From 3e5671b6f0ff9159598cdf88f22e21a1e8e7a578 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Sat, 15 Aug 2015 22:54:23 +0000 Subject: [PATCH 001/585] version update git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1221773 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- define.php | 2 +- duplicator.php | 3 ++- views/packages/new2.base.php | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/define.php b/define.php index 427dab57..82356f3f 100644 --- a/define.php +++ b/define.php @@ -1,7 +1,7 @@ '; DUP_Util::_e('Get faster builds with Duplicator Pro.'); echo ''; - echo " [" . DUP_Util::__('details') . "]"; + echo " [" . DUP_Util::__('details') . "]"; } echo ''; From 84632c144635d992843a714e47b406f212633ff1 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Sat, 15 Aug 2015 23:50:00 +0000 Subject: [PATCH 002/585] version update git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1221784 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- readme.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/readme.txt b/readme.txt index 7b23ca69..dc8664c0 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: www.lifeinthegrid.com/partner Tags: backup, restore, move, migrate, localhost, synchronize, duplicate, clone, automate, niche Requires at least: 3.8 Tested up to: 4.2 -Stable tag: 0.5.24 +Stable tag: 0.5.26 License: GPLv2 Duplicate, clone, backup, move and transfer an entire site from one location to another. @@ -24,7 +24,10 @@ http://www.youtube.com/watch?v=yZ7pHmR9JC8 This tool is great to move WordPress or backup Wordpress sites and for pulling a production site down onto your local machine for testing and validation. It also works good for developing locally and then pushing up to a production server for a first time site release. = Please Note = -This project is currently in Beta, the underlying logic to backup WordPress, move WordPress and transfer WordPress are very complex. It's impossible to know how each system is setup; this is why your feedback is important to us. Thanks for helping us to make WordPress the best blogging platform in the world. +The underlying logic to backup WordPress, move WordPress and transfer WordPress are very complex. It's impossible to know how each system is setup; this is why your feedback is important to us. Thanks for helping us to make WordPress the best blogging platform in the world. + += Duplicator Pro = +Take Duplicator to the next level with the [premium version](http://snapcreek.com/duplicator) of the plugin. = Active Contributors =
  • [Paal Joachim Romdahl](http://www.easywebdesigntutorials.com) (Training)
  • From c0e8cb2ddd82114a65de468ba9e090ac1935f07b Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Tue, 18 Aug 2015 23:24:05 +0000 Subject: [PATCH 003/585] - security patch for low profile XSS git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1224309 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- views/tools/logging.php | 393 ++++++++++++++++++++-------------------- 1 file changed, 197 insertions(+), 196 deletions(-) diff --git a/views/tools/logging.php b/views/tools/logging.php index b52064e6..8916c679 100644 --- a/views/tools/logging.php +++ b/views/tools/logging.php @@ -1,197 +1,198 @@ - 0) { - unset($logname); - } - unset($validFiles); - } - - if (!isset($logname) || !$logname) { - $logname = (count($logs) > 0) ? basename($logs[0]) : ""; - } - - $logurl = get_site_url(null, '', is_ssl() ? 'https' : 'http') . '/' . DUPLICATOR_SSDIR_NAME . '/' . $logname; - $logfound = (strlen($logname) > 0) ? true :false; - -?> - - - - - -
    - - - -
    -

    .

    - - .

    - - :
    - - .
    - - .
    - - .
    -
    - - - - - - - - -
    -
    -
     
    -
    - -
    -

    -
    - " />   -
    - - -
    -
    - -
    - -
    - {$time} - {$name}
    " - : "{$time} - {$name}
    "; - if ($count > 20) break; - } - ?> -
    -
    - - -
    + 0) { + unset($logname); + } + unset($validFiles); + } + + if (!isset($logname) || !$logname) { + $logname = (count($logs) > 0) ? basename($logs[0]) : ""; + } + + $logurl = get_site_url(null, '', is_ssl() ? 'https' : 'http') . '/' . DUPLICATOR_SSDIR_NAME . '/' . $logname; + $logfound = (strlen($logname) > 0) ? true :false; + +?> + + + + + +
    + + + +
    +

    .

    + + .

    + + :
    + - .
    + - .
    + - .
    +
    + + + + + + + + +
    +
    +
     
    +
    + +
    +

    +
    + " />   +
    + + +
    +
    + +
    + +
    + {$time} - {$name}
    " + : "{$time} - {$name}
    "; + if ($count > 20) break; + } + ?> +
    +
    + + +
    \ No newline at end of file From b5e556159ce747abcca9ab40cb73eebf8dc1df08 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Tue, 18 Aug 2015 23:30:17 +0000 Subject: [PATCH 004/585] version update git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1224317 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- define.php | 2 +- duplicator.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/define.php b/define.php index 82356f3f..d452ae46 100644 --- a/define.php +++ b/define.php @@ -1,7 +1,7 @@ Date: Tue, 18 Aug 2015 23:34:09 +0000 Subject: [PATCH 005/585] readme update git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1224325 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index dc8664c0..802559ab 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: www.lifeinthegrid.com/partner Tags: backup, restore, move, migrate, localhost, synchronize, duplicate, clone, automate, niche Requires at least: 3.8 Tested up to: 4.2 -Stable tag: 0.5.26 +Stable tag: 0.5.28 License: GPLv2 Duplicate, clone, backup, move and transfer an entire site from one location to another. From f32a6f1d50ae4ab7c6bff64e1389f135c4d54cac Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Thu, 27 Aug 2015 16:05:02 +0000 Subject: [PATCH 006/585] wp update git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1232291 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- readme.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.txt b/readme.txt index 802559ab..1646d082 100644 --- a/readme.txt +++ b/readme.txt @@ -2,8 +2,8 @@ Contributors: corylamleorg, bobriley Donate link: www.lifeinthegrid.com/partner Tags: backup, restore, move, migrate, localhost, synchronize, duplicate, clone, automate, niche -Requires at least: 3.8 -Tested up to: 4.2 +Requires at least: 3.9 +Tested up to: 4.3 Stable tag: 0.5.28 License: GPLv2 From 3c3c60dccf0e01e6aa69fd26f42662e9e9797e6a Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Wed, 2 Sep 2015 14:46:50 +0000 Subject: [PATCH 007/585] version update git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1236415 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- define.php | 120 +++++++++++++++++++++++++++-------------------------- 1 file changed, 61 insertions(+), 59 deletions(-) diff --git a/define.php b/define.php index d452ae46..5ac5c926 100644 --- a/define.php +++ b/define.php @@ -1,59 +1,61 @@ - + From 58d67dde71b1078d956bd36c2f8e410acf2f75e0 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Sun, 6 Sep 2015 00:14:35 +0000 Subject: [PATCH 008/585] Improved required file checking on database.sql file Improve readability of Duplicator error log results git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1238948 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- classes/logging.php | 15 ++--- classes/package.archive.zip.php | 1 + classes/package.database.php | 27 +++++--- classes/server.php | 10 +-- classes/ui.php | 51 +++++++-------- define.php | 2 +- duplicator.php | 8 +-- installer/build/view.step3.php | 6 +- views/packages/new1.base.php | 4 +- views/packages/new1.inc.form.php | 5 ++ views/packages/new3.base.php | 2 +- views/tools/cleanup.php | 107 ++++++++++++++++++++----------- 12 files changed, 139 insertions(+), 99 deletions(-) diff --git a/classes/logging.php b/classes/logging.php index 7747dc4d..34025538 100644 --- a/classes/logging.php +++ b/classes/logging.php @@ -53,18 +53,17 @@ static public function Error($msg, $detail) { $source = self::getStack(debug_backtrace()); $err_msg = "\n==================================================================================\n"; - $err_msg .= "!!DUPLICATOR ERROR!!\n"; - $err_msg .= "Please Try Again! If the error persists please see the Duplicator 'Support' link.\n"; + $err_msg .= "DUPLICATOR ERROR\n"; + $err_msg .= "Please try again! If the error persists see the Duplicator 'Help' menu.\n"; $err_msg .= "---------------------------------------------------------------------------------\n"; - $err_msg .= "MESSAGE:\n{$msg}\n"; + $err_msg .= "MESSAGE:\n\t{$msg}\n"; if (strlen($detail)) { - $err_msg .= "DETAILS:\n{$detail}\n"; + $err_msg .= "DETAILS:\n\t{$detail}\n"; } - $err_msg .= "---------------------------------------------------------------------------------\n"; $err_msg .= "TRACE:\n{$source}"; $err_msg .= "==================================================================================\n\n"; - @fwrite(self::$logFileHandle, "\n{$err_msg}"); - die("DUPLICATOR ERROR: Please see the duplicator log file."); + @fwrite(self::$logFileHandle, "{$err_msg}"); + die("DUPLICATOR ERROR: Please see the 'Package Log' file link below."); } @@ -77,7 +76,7 @@ public static function getStack($stacktrace) { $output = ""; $i = 1; foreach($stacktrace as $node) { - $output .= "$i. ".basename($node['file']) ." : " .$node['function'] ." (" .$node['line'].")\n"; + $output .= "\t $i. ".basename($node['file']) ." : " .$node['function'] ." (" .$node['line'].")\n"; $i++; } return $output; diff --git a/classes/package.archive.zip.php b/classes/package.archive.zip.php index 02c22c1d..18b6cebf 100644 --- a/classes/package.archive.zip.php +++ b/classes/package.archive.zip.php @@ -63,6 +63,7 @@ static public function Create(DUP_Archive $archive) { DUP_Log::Info("SIZE:\t" . self::$scanReport->ARC->Size); DUP_Log::Info("STATS:\tDirs " . self::$scanReport->ARC->DirCount . " | Files " . self::$scanReport->ARC->FileCount); + //ADD SQL $isSQLInZip = self::$zipArchive->addFile(self::$sqlPath, "database.sql"); if ($isSQLInZip) { diff --git a/classes/package.database.php b/classes/package.database.php index 6a5756f0..0a95da4b 100644 --- a/classes/package.database.php +++ b/classes/package.database.php @@ -35,25 +35,34 @@ public function Build($package) { $time_start = DUP_Util::GetMicrotime(); $this->Package->SetStatus(DUP_PackageStatus::DBSTART); + $this->dbStorePath = "{$this->Package->StorePath}/{$this->File}"; $package_mysqldump = DUP_Settings::Get('package_mysqldump'); $package_phpdump_qrylimit = DUP_Settings::Get('package_phpdump_qrylimit'); - $this->dbStorePath = "{$this->Package->StorePath}/{$this->File}"; $mysqlDumpPath = self::GetMySqlDumpPath(); $mode = ($mysqlDumpPath && $package_mysqldump) ? 'MYSQLDUMP' : 'PHP'; - $mysqlDumpSupport = ($mysqlDumpPath) ? 'Is Supported' : 'Not Supported'; + $reserved_db_filepath = DUPLICATOR_WPROOTPATH . 'database.sql'; + $log = "\n********************************************************************************\n"; $log .= "DATABASE:\n"; $log .= "********************************************************************************\n"; - $log .= "BUILD MODE: {$mode} "; + $log .= "BUILD MODE: {$mode}"; $log .= ($mode == 'PHP') ? "(query limit - {$package_phpdump_qrylimit})\n" : "\n"; - $log .= "MYSQLDUMP: {$mysqlDumpSupport}\n"; - $log .= "MYSQLTIMEOUT: " . DUPLICATOR_DB_MAX_TIME; + $log .= "MYSQLTIMEOUT: " . DUPLICATOR_DB_MAX_TIME . "\n"; + $log .= "MYSQLDUMP: "; + $log .= ($mysqlDumpPath) ? "Is Supported" : "Not Supported"; DUP_Log::Info($log); $log = null; + //Reserved file found + if (file_exists($reserved_db_filepath)) { + DUP_Log::Error("Reserverd SQL file detected", + "The file database.sql was found at [{$reserved_db_filepath}].\n" + . "\tPlease remove/rename this file to continue with the package creation."); + } + switch ($mode) { case 'MYSQLDUMP': $this->mysqlDump($mysqlDumpPath); break; case 'PHP' : $this->phpDump(); break; @@ -62,10 +71,12 @@ public function Build($package) { DUP_Log::Info("SQL CREATED: {$this->File}"); $time_end = DUP_Util::GetMicrotime(); $time_sum = DUP_Util::ElapsedTime($time_end, $time_start); - + + //File below 10k will be incomplete $sql_file_size = filesize($this->dbStorePath); - if ($sql_file_size <= 0) { - DUP_Log::Error("SQL file generated zero bytes.", "No data was written to the sql file. Check permission on file and parent directory at [{$this->dbStorePath}]"); + DUP_Log::Info('file size:' . $sql_file_size); + if ($sql_file_size < 10000) { + DUP_Log::Error("SQL file size too low.", "File does not look complete. Check permission on file and parent directory at [{$this->dbStorePath}]"); } DUP_Log::Info("SQL FILE SIZE: " . DUP_Util::ByteSize($sql_file_size)); DUP_Log::Info("SQL FILE TIME: " . date("Y-m-d H:i:s")); diff --git a/classes/server.php b/classes/server.php index a424e188..585f7207 100644 --- a/classes/server.php +++ b/classes/server.php @@ -113,11 +113,11 @@ public static function GetChecks() */ public static function InstallerFilesFound() { - - $phpFile = file_exists(DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_PHP); - $sqlFile = file_exists(DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_SQL); - $logFile = file_exists(DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_LOG); - return ($phpFile || $sqlFile || $logFile); + $phpFile = file_exists(DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_PHP); + $logFile = file_exists(DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_LOG); + $sqlFile1 = file_exists(DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_SQL); + $sqlFile2 = file_exists(DUPLICATOR_WPROOTPATH . 'database.sql'); + return ($phpFile || $logFile || $sqlFile1 || $sqlFile2); } /** diff --git a/classes/ui.php b/classes/ui.php index 304fa8d3..cc7ce5fc 100644 --- a/classes/ui.php +++ b/classes/ui.php @@ -88,37 +88,32 @@ static public function GetViewStateValue($searchKey) { * Shows a display message in the wp-admin if any researved files are found * @return type void */ - static public function ShowReservedFilesNotice() { - - if (! is_plugin_active('duplicator/duplicator.php')) - return; - - $hide = isset($_REQUEST['page']) && $_REQUEST['page'] == 'duplicator-tools' ? true : false; - $perms = (current_user_can( 'install_plugins' ) && current_user_can( 'import' )); - if (! $perms || $hide) + static public function ShowReservedFilesNotice() + { + //Show only on Duplicator pages and Dashboard when plugin is active + $dup_active = is_plugin_active('duplicator/duplicator.php'); + $dup_perm = current_user_can( 'manage_options' ); + if (! $dup_active || ! $dup_perm) return; - - $metaKey = 'dup-wpnotice01'; - if ( isset($_GET[$metaKey]) && $_GET[$metaKey] == '1') { - self::SaveViewState($metaKey, true); - } - - if ( self::GetViewStateValue($metaKey) != null) { - if (DUP_Server::InstallerFilesFound()) { - $queryStr = $_SERVER['QUERY_STRING']; - echo '

    '; - $duplicator_nonce = wp_create_nonce('duplicator_cleanup_page'); - @printf("%s
    %s | %s", - __('Reserved Duplicator install file(s) still exists in the root directory. Please delete these file(s) to avoid possible security issues.', 'wpduplicator'), - $duplicator_nonce, - __('Remove file(s) now', 'wpduplicator'), - __('Dismiss this notice', 'wpduplicator')); - echo "

    "; - } else { - self::SaveViewState($metaKey, true); + if (DUP_Server::InstallerFilesFound()) + { + $screen = get_current_screen(); + $on_active_tab = isset($_GET['tab']) && $_GET['tab'] == 'cleanup' ? true : false; + + echo '

    '; + if ($screen->id == 'duplicator_page_duplicator-tools' && $on_active_tab) + { + DUP_Util::_e('Reserved Duplicator install files have been detected in the root directory. Please delete these reserved files to avoid security issues.'); } - } + else + { + $duplicator_nonce = wp_create_nonce('duplicator_cleanup_page'); + DUP_Util::_e('Reserved Duplicator install files have been detected in the root directory. Please delete these reserved files to avoid security issues.'); + @printf("
    %s", $duplicator_nonce, DUP_Util::__('Take me to the cleanup page!')); + } + echo "

    "; + } } } diff --git a/define.php b/define.php index 5ac5c926..8976b3d8 100644 --- a/define.php +++ b/define.php @@ -3,7 +3,7 @@ if (function_exists('plugin_dir_url')) { - define('DUPLICATOR_VERSION', '0.5.28'); + define('DUPLICATOR_VERSION', '0.5.29'); define("DUPLICATOR_HOMEPAGE", "http://lifeinthegrid.com/labs/duplicator"); define("DUPLICATOR_GIVELINK", "http://lifeinthegrid.com/partner"); define("DUPLICATOR_HELPLINK", "http://lifeinthegrid.com/duplicator-docs"); diff --git a/duplicator.php b/duplicator.php index bb0c67c5..ff713c5f 100644 --- a/duplicator.php +++ b/duplicator.php @@ -3,7 +3,7 @@ Plugin Name: Duplicator Plugin URI: http://www.lifeinthegrid.com/duplicator/ Description: Create a backup of your WordPress files and database. Duplicate and move an entire site from one location to another in a few steps. Create a full snapshot of your site at any point in time. - Version: 0.5.28 + Version: 0.5.29 Author: LifeInTheGrid Author URI: http://www.lifeinthegrid.com Text Domain: wpduplicator @@ -177,15 +177,15 @@ function duplicator_menu() { $perms = 'export'; $perms = apply_filters($wpfront_caps_translator, $perms); - $page_packages = add_submenu_page('duplicator', __('Packages', 'wpduplicator'), __('Packages', 'wpduplicator'), $perms, 'duplicator', 'duplicator_get_menu'); + $page_packages = add_submenu_page('duplicator', DUP_Util::__('Packages'), DUP_Util::__('Packages'), $perms, 'duplicator', 'duplicator_get_menu'); $perms = 'manage_options'; $perms = apply_filters($wpfront_caps_translator, $perms); - $page_settings = add_submenu_page('duplicator', __('Settings', 'wpduplicator'), __('Settings', 'wpduplicator'), $perms, 'duplicator-settings', 'duplicator_get_menu'); + $page_settings = add_submenu_page('duplicator', DUP_Util::__('Settings'), DUP_Util::__('Settings'), $perms, 'duplicator-settings', 'duplicator_get_menu'); $perms = 'manage_options'; $perms = apply_filters($wpfront_caps_translator, $perms); - $page_tools = add_submenu_page('duplicator', __('Tools', 'wpduplicator'), __('Tools', 'wpduplicator'), $perms, 'duplicator-tools', 'duplicator_get_menu'); + $page_tools = add_submenu_page('duplicator', DUP_Util::__('Tools'), DUP_Util::__('Tools'), $perms, 'duplicator-tools', 'duplicator_get_menu'); $perms = 'manage_options'; $perms = apply_filters($wpfront_caps_translator, $perms); diff --git a/installer/build/view.step3.php b/installer/build/view.step3.php index 63bb8af4..88833fd2 100644 --- a/installer/build/view.step3.php +++ b/installer/build/view.step3.php @@ -30,12 +30,12 @@

    -
    IMPORTANT FINAL STEPS!
    +
    VERY IMPORTANT FINAL STEPS!
    - - +
    1. Install Report + 1. Review Install Report @@ -57,7 +57,7 @@ Validate all pages, links images and plugins
    4. File Cleanup4. Security Cleanup Removes all installer files (requires login)

    diff --git a/views/packages/new1.base.php b/views/packages/new1.base.php index 9d4d3c7e..a99f6942 100644 --- a/views/packages/new1.base.php +++ b/views/packages/new1.base.php @@ -218,12 +218,12 @@
    - +
    - +
    ' style='font-size:10px; margin-top:5px;' />
    diff --git a/views/packages/new1.inc.form.php b/views/packages/new1.inc.form.php index 1d77ecb7..612e5bbf 100644 --- a/views/packages/new1.inc.form.php +++ b/views/packages/new1.inc.form.php @@ -112,6 +112,11 @@
    +
    + + + Duplicator Pro + diff --git a/views/packages/new3.base.php b/views/packages/new3.base.php index 7337af4f..1adb7506 100644 --- a/views/packages/new3.base.php +++ b/views/packages/new3.base.php @@ -133,7 +133,7 @@
    - +

    diff --git a/views/tools/cleanup.php b/views/tools/cleanup.php index 561aae7a..7b43da96 100644 --- a/views/tools/cleanup.php +++ b/views/tools/cleanup.php @@ -2,45 +2,52 @@ require_once(DUPLICATOR_PLUGIN_PATH . '/views/javascript.php'); require_once(DUPLICATOR_PLUGIN_PATH . '/views/inc.header.php'); - $nonce = wp_create_nonce('duplicator_cleanup_page'); - + $nonce = wp_create_nonce('duplicator_cleanup_page'); $_GET['action'] = isset($_GET['action']) ? $_GET['action'] : 'display'; - - if(isset($_GET['action'])) - { - if(($_GET['action'] == 'installer') || ($_GET['action'] == 'legacy') || ($_GET['action'] == 'tmp-cache')) - { - $verify_nonce = $_REQUEST['_wpnonce']; - - if ( ! wp_verify_nonce( $verify_nonce, 'duplicator_cleanup_page' ) ) { - exit; // Get out of here, the nonce is rotten! - } - } - } + + $installer_file = DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_PHP; + $installer_bak = DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_BAK; + $installer_sql1 = DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_SQL; + $installer_sql2 = DUPLICATOR_WPROOTPATH . 'database.sql'; + $installer_log = DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_LOG; + + if(isset($_GET['action'])) + { + if(($_GET['action'] == 'installer') || ($_GET['action'] == 'legacy') || ($_GET['action'] == 'tmp-cache')) + { + $verify_nonce = $_REQUEST['_wpnonce']; + if ( ! wp_verify_nonce( $verify_nonce, 'duplicator_cleanup_page' ) ) { + exit; // Get out of here, the nonce is rotten! + } + } + } switch ($_GET['action']) { - case 'installer' : - - $action_response = __('Installer File Cleanup Ran.', 'wpduplicator'); + case 'installer' : + $action_response = __('Installer file cleanup ran!'); + $css_hide_msg = 'div.dup-header div.error {display:none}'; break; case 'legacy': DUP_Settings::LegacyClean(); - $action_response = __('Legacy data removed.', 'wpduplicator'); + $action_response = __('Legacy data removed.'); break; case 'tmp-cache': DUP_Package::TmpCleanup(true); - $action_response = __('Build cache removed.', 'wpduplicator'); + $action_response = __('Build cache removed.'); break; } ?> @@ -53,15 +60,14 @@ Successfully removed {$installer_file}" : "
    Does not exist or unable to remove file: {$installer_file}
    "; $html .= (@unlink($installer_bak)) ? "
    Successfully removed {$installer_bak}
    " : "
    Does not exist or unable to remove file: {$installer_bak}
    "; - $html .= (@unlink($installer_sql)) ? "
    Successfully removed {$installer_sql}
    " : "
    Does not exist or unable to remove file: {$installer_sql}
    "; + $html .= (@unlink($installer_sql1)) ? "
    Successfully removed {$installer_sql1}
    " : "
    Does not exist or unable to remove file: {$installer_sql1}
    "; + $html .= (@unlink($installer_sql2)) ? "
    Successfully removed {$installer_sql2}
    " : "
    Does not exist or unable to remove file: {$installer_sql2}
    "; $html .= (@unlink($installer_log)) ? "
    Successfully removed {$installer_log}
    " : "
    Does not exist or unable to remove file: {$installer_log}
    "; //No way to know exact name of archive file except from installer. @@ -85,8 +91,8 @@ ?>
    - .
    - .

    + .
    + .

    @@ -94,19 +100,42 @@ -


    +


    - - - + + + - - + + - - + +
    + + + + + + [] +
    +
    +
    " + . "
    {$installer_file}
    " + . "
    {$installer_bak}
    " + . "
    {$installer_sql1}
    " + . "
    {$installer_sql2}
    " + . "
    {$installer_log}
    "; + ?> +
    +
    []. [].
    []. [].
    @@ -119,11 +148,11 @@ Duplicator.Tools.DeleteLegacy = function () { var result = true; - var result = confirm(''); + var result = confirm(''); if (! result) return; @@ -132,7 +161,7 @@ Duplicator.Tools.ClearBuildCache = function () { var result = true; var result = confirm(''); From ebcd4197295ea64342dae2ccdcaccdc1740b7543 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Sun, 6 Sep 2015 01:42:22 +0000 Subject: [PATCH 009/585] Improved required file checking on database.sql file git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1238967 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- views/tools/cleanup.php | 96 ++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 50 deletions(-) diff --git a/views/tools/cleanup.php b/views/tools/cleanup.php index 7b43da96..52a3b8d1 100644 --- a/views/tools/cleanup.php +++ b/views/tools/cleanup.php @@ -57,45 +57,42 @@

    - - Successfully removed {$installer_file}
    " : "
    Does not exist or unable to remove file: {$installer_file}
    "; - $html .= (@unlink($installer_bak)) ? "
    Successfully removed {$installer_bak}
    " : "
    Does not exist or unable to remove file: {$installer_bak}
    "; - $html .= (@unlink($installer_sql1)) ? "
    Successfully removed {$installer_sql1}
    " : "
    Does not exist or unable to remove file: {$installer_sql1}
    "; - $html .= (@unlink($installer_sql2)) ? "
    Successfully removed {$installer_sql2}
    " : "
    Does not exist or unable to remove file: {$installer_sql2}
    "; - $html .= (@unlink($installer_log)) ? "
    Successfully removed {$installer_log}
    " : "
    Does not exist or unable to remove file: {$installer_log}
    "; + //Uncommon to see $installer_sql2 so don't display message + $html .= (@unlink($installer_file)) ? "
    Successfully removed {$installer_file}
    " : "
    Does not exist or unable to remove file: {$installer_file}
    "; + $html .= (@unlink($installer_bak)) ? "
    Successfully removed {$installer_bak}
    " : "
    Does not exist or unable to remove file: {$installer_bak}
    "; + $html .= (@unlink($installer_sql1)) ? "
    Successfully removed {$installer_sql1}
    " : "
    Does not exist or unable to remove file: {$installer_sql1}
    "; + $html .= (@unlink($installer_sql2)) ? "
    Successfully removed {$installer_sql2}
    " : "
    Does not exist or unable to remove file: {$installer_sql2}
    "; + $html .= (@unlink($installer_log)) ? "
    Successfully removed {$installer_log}
    " : "
    Does not exist or unable to remove file: {$installer_log}
    "; - //No way to know exact name of archive file except from installer. - //The only place where the package can be remove is from installer - //So just show a message if removing from plugin. - if (! empty($package_name) ){ - $path_parts = pathinfo($package_name); - $path_parts = (isset($path_parts['extension'])) ? $path_parts['extension'] : ''; - if ($path_parts == "zip" && ! is_dir($package_name)) { - $html .= (@unlink($package_name)) - ? "
    Successfully removed {$package_name}
    " - : "
    Does not exist or unable to remove archive file.
    "; + //No way to know exact name of archive file except from installer. + //The only place where the package can be remove is from installer + //So just show a message if removing from plugin. + if (! empty($package_name) ){ + $path_parts = pathinfo($package_name); + $path_parts = (isset($path_parts['extension'])) ? $path_parts['extension'] : ''; + if ($path_parts == "zip" && ! is_dir($package_name)) { + $html .= (@unlink($package_name)) + ? "
    Successfully removed {$package_name}
    " + : "
    Does not exist or unable to remove archive file.
    "; + } else { + $html .= "
    Does not exist or unable to remove archive file. Please validate that an archive file exists.
    "; + } } else { - $html .= "
    Does not exist or unable to remove archive file. Please validate that an archive file exists.
    "; + $html .= '
    It is recommended to remove your archive file from the root of your WordPress install. This will need to be done manually.
    '; } - } else { - $html .= '
    It is recommended to remove your archive file from the root of your WordPress install. This will need to be done manually.
    '; - } + echo $html; + ?> - echo $html; - ?> - -
    - .
    - .

    -
    +
    + .
    + .

    +
    - + @@ -114,17 +111,22 @@

    " - . "
    {$installer_file}
    " - . "
    {$installer_bak}
    " - . "
    {$installer_sql1}
    " - . "
    {$installer_sql2}
    " - . "
    {$installer_log}
    "; + echo "

    "; + echo $installer_file_exists ? "
    {$installer_file} [{$found}]
    " : "
    {$installer_file}
    "; + echo $installer_bak_exists ? "
    {$installer_bak} [{$found}]
    " : "
    {$installer_bak}
    "; + echo $installer_sql1_exists ? "
    {$installer_sql1} [{$found}]
    " : "
    {$installer_sql1}
    "; + echo $installer_sql2_exists ? "
    {$installer_sql2} [{$found}]
    " : "
    {$installer_sql2}
    "; + echo $installer_log_exists ? "
    {$installer_log} [{$found}]
    " : "
    {$installer_log}
    "; ?>
    @@ -133,19 +135,15 @@ []. - + []. - - From 45ca76c95f9d729385347d74d1098c4a4853045e Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Sun, 6 Sep 2015 15:42:19 +0000 Subject: [PATCH 010/585] - improved required file checking git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1239155 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- views/tools/cleanup.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/views/tools/cleanup.php b/views/tools/cleanup.php index 52a3b8d1..89b59f0b 100644 --- a/views/tools/cleanup.php +++ b/views/tools/cleanup.php @@ -47,10 +47,9 @@ table.dup-reset-opts td {padding:10px} form#dup-settings-form {padding: 0px 10px 0px 10px} a.dup-fixed-btn {min-width: 150px; text-align: center} - div#dup-tools-delete-moreinfo {display: none; padding: 5px 0 0 20px; border:1px solid silver; background-color: #fff; border-radius: 5px; padding:10px; margin:5px; width:700px } + div#dup-tools-delete-moreinfo {display: none; padding: 5px 0 0 20px; border:1px solid silver; background-color: #fff; border-radius: 5px; padding:10px; margin:5px; width:750px } -
    @@ -118,15 +117,16 @@ $installer_log_exists = file_exists(DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_LOG) ? true : false; $found = DUP_Util::__("Found"); - DUP_Util::_e("Duplicator will attempt to removed the following reserved files. These files are typically from a previous Duplicator install, " + $not_found = DUP_Util::__("Not Found"); + DUP_Util::_e("Clicking on the 'Delete Reserved Files' button will attempt to removed the following reserved files. These files are typically from a previous Duplicator install, " . "but may be from other sources. If you are unsure of the source, please validate the files. These files should never be left on " . "production systems as they can leave a security hole for your site."); echo "

    "; - echo $installer_file_exists ? "
    {$installer_file} [{$found}]
    " : "
    {$installer_file}
    "; - echo $installer_bak_exists ? "
    {$installer_bak} [{$found}]
    " : "
    {$installer_bak}
    "; - echo $installer_sql1_exists ? "
    {$installer_sql1} [{$found}]
    " : "
    {$installer_sql1}
    "; - echo $installer_sql2_exists ? "
    {$installer_sql2} [{$found}]
    " : "
    {$installer_sql2}
    "; - echo $installer_log_exists ? "
    {$installer_log} [{$found}]
    " : "
    {$installer_log}
    "; + echo $installer_file_exists ? "
    {$found} - {$installer_file}
    " : "
    {$not_found} - {$installer_file}
    "; + echo $installer_bak_exists ? "
    {$found} - {$installer_bak}
    " : "
    {$not_found} - {$installer_bak}
    "; + echo $installer_sql1_exists ? "
    {$found} - {$installer_sql1}
    " : "
    {$not_found} - {$installer_sql1}
    "; + echo $installer_sql2_exists ? "
    {$found} - {$installer_sql2}
    " : "
    {$not_found} - {$installer_sql2}
    "; + echo $installer_log_exists ? "
    {$found} - {$installer_log}
    " : "
    {$not_found} - {$installer_log}
    "; ?> From 0398ad87f867317458de6dedcf90fa93e8da0aad Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Sun, 6 Sep 2015 22:51:36 +0000 Subject: [PATCH 011/585] - improved required file checking git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1239287 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- views/tools/cleanup.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/views/tools/cleanup.php b/views/tools/cleanup.php index 89b59f0b..29dfa226 100644 --- a/views/tools/cleanup.php +++ b/views/tools/cleanup.php @@ -60,12 +60,11 @@ $html = ""; $package_name = (isset($_GET['package'])) ? DUPLICATOR_WPROOTPATH . esc_html($_GET['package']) : ''; - //Uncommon to see $installer_sql2 so don't display message - $html .= (@unlink($installer_file)) ? "
    Successfully removed {$installer_file}
    " : "
    Does not exist or unable to remove file: {$installer_file}
    "; - $html .= (@unlink($installer_bak)) ? "
    Successfully removed {$installer_bak}
    " : "
    Does not exist or unable to remove file: {$installer_bak}
    "; - $html .= (@unlink($installer_sql1)) ? "
    Successfully removed {$installer_sql1}
    " : "
    Does not exist or unable to remove file: {$installer_sql1}
    "; - $html .= (@unlink($installer_sql2)) ? "
    Successfully removed {$installer_sql2}
    " : "
    Does not exist or unable to remove file: {$installer_sql2}
    "; - $html .= (@unlink($installer_log)) ? "
    Successfully removed {$installer_log}
    " : "
    Does not exist or unable to remove file: {$installer_log}
    "; + $html .= (@unlink($installer_file)) ? "
    Successfully removed {$installer_file}
    " : ""; + $html .= (@unlink($installer_bak)) ? "
    Successfully removed {$installer_bak}
    " : ""; + $html .= (@unlink($installer_sql1)) ? "
    Successfully removed {$installer_sql1}
    " : ""; + $html .= (@unlink($installer_sql2)) ? "
    Successfully removed {$installer_sql2}
    " : ""; + $html .= (@unlink($installer_log)) ? "
    Successfully removed {$installer_log}
    " : ""; //No way to know exact name of archive file except from installer. //The only place where the package can be remove is from installer @@ -118,9 +117,8 @@ $found = DUP_Util::__("Found"); $not_found = DUP_Util::__("Not Found"); - DUP_Util::_e("Clicking on the 'Delete Reserved Files' button will attempt to removed the following reserved files. These files are typically from a previous Duplicator install, " - . "but may be from other sources. If you are unsure of the source, please validate the files. These files should never be left on " - . "production systems as they can leave a security hole for your site."); + DUP_Util::_e("Clicking on the 'Delete Reserved Files' button will remove the following reserved files. These files are typically from a previous Duplicator install. " + . "If you are unsure of the source, please validate the files. These files should never be left on production systems as they can leave a security hole for your site."); echo "

    "; echo $installer_file_exists ? "
    {$found} - {$installer_file}
    " : "
    {$not_found} - {$installer_file}
    "; echo $installer_bak_exists ? "
    {$found} - {$installer_bak}
    " : "
    {$not_found} - {$installer_bak}
    "; From 53558d4da92678486296a0e899674d998de18792 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Sun, 6 Sep 2015 22:56:57 +0000 Subject: [PATCH 012/585] - improved required file checking git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1239292 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- views/tools/cleanup.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/views/tools/cleanup.php b/views/tools/cleanup.php index 29dfa226..2cd397cd 100644 --- a/views/tools/cleanup.php +++ b/views/tools/cleanup.php @@ -60,11 +60,11 @@ $html = ""; $package_name = (isset($_GET['package'])) ? DUPLICATOR_WPROOTPATH . esc_html($_GET['package']) : ''; - $html .= (@unlink($installer_file)) ? "
    Successfully removed {$installer_file}
    " : ""; - $html .= (@unlink($installer_bak)) ? "
    Successfully removed {$installer_bak}
    " : ""; - $html .= (@unlink($installer_sql1)) ? "
    Successfully removed {$installer_sql1}
    " : ""; - $html .= (@unlink($installer_sql2)) ? "
    Successfully removed {$installer_sql2}
    " : ""; - $html .= (@unlink($installer_log)) ? "
    Successfully removed {$installer_log}
    " : ""; + $html .= (@unlink($installer_file)) ? "
    Successfully removed {$installer_file}
    " : "
    Does not exist or unable to remove file: {$installer_file}
    "; + $html .= (@unlink($installer_bak)) ? "
    Successfully removed {$installer_bak}
    " : "
    Does not exist or unable to remove file: {$installer_bak}
    "; + $html .= (@unlink($installer_sql1)) ? "
    Successfully removed {$installer_sql1}
    " : "
    Does not exist or unable to remove file: {$installer_sql1}
    "; + $html .= (@unlink($installer_sql2)) ? "
    Successfully removed {$installer_sql2}
    " : "
    Does not exist or unable to remove file: {$installer_sql2}
    "; + $html .= (@unlink($installer_log)) ? "
    Successfully removed {$installer_log}
    " : "
    Does not exist or unable to remove file: {$installer_log}
    "; //No way to know exact name of archive file except from installer. //The only place where the package can be remove is from installer From 137fe081c163b3ed57064c94fd0f6acfd65b3205 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Mon, 7 Sep 2015 00:44:20 +0000 Subject: [PATCH 013/585] - improved required file checking git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1239362 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- installer/build/view.step3.php | 2 +- views/tools/cleanup.php | 50 +++++++++++++++++++--------------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/installer/build/view.step3.php b/installer/build/view.step3.php index 88833fd2..04c09765 100644 --- a/installer/build/view.step3.php +++ b/installer/build/view.step3.php @@ -58,7 +58,7 @@ 4. Security Cleanup - Removes all installer files (requires login) + Validate installer files are removed (requires login)
    diff --git a/views/tools/cleanup.php b/views/tools/cleanup.php index 2cd397cd..fadd19a4 100644 --- a/views/tools/cleanup.php +++ b/views/tools/cleanup.php @@ -5,27 +5,36 @@ $nonce = wp_create_nonce('duplicator_cleanup_page'); $_GET['action'] = isset($_GET['action']) ? $_GET['action'] : 'display'; - $installer_file = DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_PHP; - $installer_bak = DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_BAK; - $installer_sql1 = DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_SQL; - $installer_sql2 = DUPLICATOR_WPROOTPATH . 'database.sql'; - $installer_log = DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_LOG; - if(isset($_GET['action'])) { if(($_GET['action'] == 'installer') || ($_GET['action'] == 'legacy') || ($_GET['action'] == 'tmp-cache')) { $verify_nonce = $_REQUEST['_wpnonce']; - if ( ! wp_verify_nonce( $verify_nonce, 'duplicator_cleanup_page' ) ) { + if ( ! wp_verify_nonce( $verify_nonce, 'duplicator_cleanup_page' ) ) + { exit; // Get out of here, the nonce is rotten! } } } + + $found = DUP_Util::__("Found"); + $not_found = DUP_Util::__("Not Found"); + + $installer_file = DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_PHP; + $installer_bak = DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_BAK; + $installer_sql1 = DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_SQL; + $installer_sql2 = DUPLICATOR_WPROOTPATH . 'database.sql'; + $installer_log = DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_LOG; switch ($_GET['action']) { case 'installer' : $action_response = __('Installer file cleanup ran!'); $css_hide_msg = 'div.dup-header div.error {display:none}'; + @unlink($installer_file); + @unlink($installer_bak); + @unlink($installer_sql1); + @unlink($installer_sql2); + @unlink($installer_log); break; case 'legacy': DUP_Settings::LegacyClean(); @@ -36,7 +45,12 @@ $action_response = __('Build cache removed.'); break; } - + + $installer_file_exists = file_exists($installer_file) ? true : false; + $installer_bak_exists = file_exists($installer_bak) ? true : false; + $installer_sql1_exists = file_exists($installer_sql1) ? true : false; + $installer_sql2_exists = file_exists($installer_sql2) ? true : false; + $installer_log_exists = file_exists($installer_log) ? true : false; ?> - - - - - -
    - - -
    - -
    - -
    - -

    - - -

    -

    - - -

    -
    - - -
    -
    - -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    - -
    - - -
    -
    - -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    - -
    -
    -

    - - - -

    -
    -




    - - + + + +
    + +
    +

    + + +

    +

    + + +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Feature + + Free + + Professional +
    Backup Files & Database
    Directory Filters
    Database Table Filters
    Migration Wizard
    Dropbox Storage
    Google Drive Storage
    Remote FTP Storage
    Scheduled Backups
    Enhanced Package Engine
    Email Alerts
    Custom Templates
    File Filters
    Customer Support
    + +
    +

    + + + +

    +

    +
    +

    + + \ No newline at end of file diff --git a/views/packages/new1.inc.form.php b/views/packages/new1.inc.form.php index 612e5bbf..8d341242 100644 --- a/views/packages/new1.inc.form.php +++ b/views/packages/new1.inc.form.php @@ -41,17 +41,14 @@ - -

    - - - - Duplicator Pro - -

    +
    + + + + + + Duplicator Pro +
    @@ -114,7 +111,7 @@
    - + Duplicator Pro From 26cc878a6596228d57e014d956ab02a333d3b9d7 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Mon, 12 Oct 2015 02:42:30 +0000 Subject: [PATCH 020/585] version update git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1263746 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- define.php | 2 +- duplicator.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/define.php b/define.php index 15b5fda4..f4cadf29 100644 --- a/define.php +++ b/define.php @@ -3,7 +3,7 @@ if (function_exists('plugin_dir_url')) { - define('DUPLICATOR_VERSION', '0.5.31'); + define('DUPLICATOR_VERSION', '0.5.32'); define("DUPLICATOR_HOMEPAGE", "http://lifeinthegrid.com/labs/duplicator"); define("DUPLICATOR_GIVELINK", "http://lifeinthegrid.com/partner"); define("DUPLICATOR_HELPLINK", "http://lifeinthegrid.com/duplicator-docs"); diff --git a/duplicator.php b/duplicator.php index 7e30bc1c..4ede23ce 100644 --- a/duplicator.php +++ b/duplicator.php @@ -3,7 +3,7 @@ Plugin Name: Duplicator Plugin URI: http://www.lifeinthegrid.com/duplicator/ Description: Create a backup of your WordPress files and database. Duplicate and move an entire site from one location to another in a few steps. Create a full snapshot of your site at any point in time. - Version: 0.5.31 + Version: 0.5.32 Author: LifeInTheGrid Author URI: http://www.lifeinthegrid.com Text Domain: wpduplicator From 8b0ce3f93bc46ff7b5a34629dae5ddb77ee3e9de Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Mon, 12 Oct 2015 02:46:57 +0000 Subject: [PATCH 021/585] version update git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1263753 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index ee494c55..e7ef854b 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: www.lifeinthegrid.com/partner Tags: backup, restore, move, migrate, localhost, synchronize, duplicate, clone, automate, niche Requires at least: 3.9 Tested up to: 4.3 -Stable tag: 0.5.30 +Stable tag: 0.5.32 License: GPLv2 Duplicate, clone, backup, move and transfer an entire site from one location to another. From 07eb1591942726b53983b9dd9c120e1ebc56db67 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Mon, 2 Nov 2015 15:09:17 +0000 Subject: [PATCH 022/585] Update: New Encoding lib added for better "Name Checks" on scanner Update: Removed legacy code for reported security check for code that was never called. Update: PHP version check from 5.2.17 to 5.2.9. git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1277913 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- classes/package.archive.php | 7 +- classes/server.php | 2 +- define.php | 2 +- duplicator.php | 3 +- installer/build/view.step1.php | 4 +- lib/forceutf8/Encoding.php | 349 +++++++++++++++++++++++++++++++++ lib/forceutf8/README.md | 61 ++++++ views/actions.php | 13 -- views/packages/new1.base.php | 2 +- 9 files changed, 420 insertions(+), 23 deletions(-) create mode 100644 lib/forceutf8/Encoding.php create mode 100644 lib/forceutf8/README.md diff --git a/classes/package.archive.php b/classes/package.archive.php index 80314daf..4e755e06 100644 --- a/classes/package.archive.php +++ b/classes/package.archive.php @@ -2,6 +2,7 @@ if ( ! defined( 'DUPLICATOR_VERSION' ) ) exit; // Exit if accessed directly require_once (DUPLICATOR_PLUGIN_PATH . 'classes/package.archive.zip.php'); +require_once (DUPLICATOR_PLUGIN_PATH . 'lib/forceutf8/Encoding.php'); /** * The base class for all filter types Directories/Files/Extentions @@ -210,7 +211,7 @@ private function getDirs() if ($invalid_test || preg_match('/[^\x20-\x7f]/', $name)) { - $this->FilterInfo->Dirs->Warning[] = utf8_encode($val); + $this->FilterInfo->Dirs->Warning[] = DUP_Encoding::toUTF8($val); } //Dir is not readble remove and flag @@ -251,7 +252,7 @@ private function getFiles() if ($invalid_test || preg_match('/[^\x20-\x7f]/', $fileName)) { - $this->FilterInfo->Files->Warning[] = utf8_encode($filePath); + $this->FilterInfo->Files->Warning[] = DUP_Encoding::toUTF8($filePath); } else { @@ -273,7 +274,7 @@ private function getFiles() //Older PHP logic which is more stable on older version of PHP //NOTE RecursiveIteratorIterator is problematic on some systems issues include: // - error 'too many files open' for recursion - // - $file->getExtension() is not reliable as it silently fails at least in php 5.2.17 + // - $file->getExtension() is not reliable as it silently fails at least in php 5.2.9 // - issues with when a file has a permission such as 705 and trying to get info (had to fallback to pathinfo) // - basic conclusion wait on the SPL libs untill after php 5.4 is a requiremnt // - since we are in a tight recursive loop lets remove the utiltiy call DUP_Util::SafePath("{$path}/{$file}") and diff --git a/classes/server.php b/classes/server.php index b72168fe..51b42f13 100644 --- a/classes/server.php +++ b/classes/server.php @@ -23,7 +23,7 @@ public static function GetRequirements() //PHP SUPPORT $safe_ini = strtolower(ini_get('safe_mode')); $dup_tests['PHP']['SAFE_MODE'] = $safe_ini != 'on' || $safe_ini != 'yes' || $safe_ini != 'true' || ini_get("safe_mode") != 1 ? 'Pass' : 'Fail'; - $dup_tests['PHP']['VERSION'] = version_compare(phpversion(), '5.2.17') >= 0 ? 'Pass' : 'Fail'; + $dup_tests['PHP']['VERSION'] = version_compare(phpversion(), '5.2.9') >= 0 ? 'Pass' : 'Fail'; $dup_tests['PHP']['ZIP'] = class_exists('ZipArchive') ? 'Pass' : 'Fail'; $dup_tests['PHP']['FUNC_1'] = function_exists("file_get_contents") ? 'Pass' : 'Fail'; $dup_tests['PHP']['FUNC_2'] = function_exists("file_put_contents") ? 'Pass' : 'Fail'; diff --git a/define.php b/define.php index f4cadf29..0cc894de 100644 --- a/define.php +++ b/define.php @@ -3,7 +3,7 @@ if (function_exists('plugin_dir_url')) { - define('DUPLICATOR_VERSION', '0.5.32'); + define('DUPLICATOR_VERSION', '0.5.34'); define("DUPLICATOR_HOMEPAGE", "http://lifeinthegrid.com/labs/duplicator"); define("DUPLICATOR_GIVELINK", "http://lifeinthegrid.com/partner"); define("DUPLICATOR_HELPLINK", "http://lifeinthegrid.com/duplicator-docs"); diff --git a/duplicator.php b/duplicator.php index 4ede23ce..c26702f0 100644 --- a/duplicator.php +++ b/duplicator.php @@ -3,7 +3,7 @@ Plugin Name: Duplicator Plugin URI: http://www.lifeinthegrid.com/duplicator/ Description: Create a backup of your WordPress files and database. Duplicate and move an entire site from one location to another in a few steps. Create a full snapshot of your site at any point in time. - Version: 0.5.32 + Version: 0.5.34 Author: LifeInTheGrid Author URI: http://www.lifeinthegrid.com Text Domain: wpduplicator @@ -118,7 +118,6 @@ function duplicator_meta_links($links, $file) { add_action('wp_ajax_duplicator_package_scan', 'duplicator_package_scan'); add_action('wp_ajax_duplicator_package_build', 'duplicator_package_build'); add_action('wp_ajax_duplicator_package_delete', 'duplicator_package_delete'); - add_action('wp_ajax_duplicator_package_report', 'duplicator_package_report'); add_action('wp_ajax_DUP_UI_SaveViewStateByPost', array('DUP_UI', 'SaveViewStateByPost')); add_action('admin_notices', array('DUP_UI', 'ShowReservedFilesNotice')); add_action('plugins_loaded', 'duplicator_wpfront_integrate'); diff --git a/installer/build/view.step1.php b/installer/build/view.step1.php index 46072b4f..0a017c63 100644 --- a/installer/build/view.step1.php +++ b/installer/build/view.step1.php @@ -31,7 +31,7 @@ $safe_ini = strtolower(@ini_get('safe_mode')); $req02 = $safe_ini != 'on' || $safe_ini != 'yes' || $safe_ini != 'true' || ini_get("safe_mode") != 1 ? 'Pass' : 'Fail'; $req03 = function_exists('mysqli_connect') ? 'Pass' : 'Fail'; - $php_compare = version_compare(phpversion(), '5.2.17'); + $php_compare = version_compare(phpversion(), '5.2.9'); $req04 = $php_compare >= 0 ? 'Pass' : 'Fail'; $total_req = ($req01 == 'Pass' && $req02 == 'Pass' && $req03 == 'Pass' && $req04 == 'Pass') ? 'Pass' : 'Fail'; ?> @@ -410,7 +410,7 @@ PHP Version:
    - (PHP 5.2.17+ is required) + (PHP 5.2.9+ is required) diff --git a/lib/forceutf8/Encoding.php b/lib/forceutf8/Encoding.php new file mode 100644 index 00000000..e6da9cb9 --- /dev/null +++ b/lib/forceutf8/Encoding.php @@ -0,0 +1,349 @@ + + * @package Encoding + * @version 2.0 + * @link https://github.com/neitanod/forceutf8 + * @example https://github.com/neitanod/forceutf8 + * @license Revised BSD + */ + +//namespace ForceUTF8; +if (!class_exists('DUP_Encoding')) +{ + class DUP_Encoding { + + const ICONV_TRANSLIT = "TRANSLIT"; + const ICONV_IGNORE = "IGNORE"; + const WITHOUT_ICONV = ""; + + protected static $win1252ToUtf8 = array( + 128 => "\xe2\x82\xac", + + 130 => "\xe2\x80\x9a", + 131 => "\xc6\x92", + 132 => "\xe2\x80\x9e", + 133 => "\xe2\x80\xa6", + 134 => "\xe2\x80\xa0", + 135 => "\xe2\x80\xa1", + 136 => "\xcb\x86", + 137 => "\xe2\x80\xb0", + 138 => "\xc5\xa0", + 139 => "\xe2\x80\xb9", + 140 => "\xc5\x92", + + 142 => "\xc5\xbd", + + + 145 => "\xe2\x80\x98", + 146 => "\xe2\x80\x99", + 147 => "\xe2\x80\x9c", + 148 => "\xe2\x80\x9d", + 149 => "\xe2\x80\xa2", + 150 => "\xe2\x80\x93", + 151 => "\xe2\x80\x94", + 152 => "\xcb\x9c", + 153 => "\xe2\x84\xa2", + 154 => "\xc5\xa1", + 155 => "\xe2\x80\xba", + 156 => "\xc5\x93", + + 158 => "\xc5\xbe", + 159 => "\xc5\xb8" + ); + + protected static $brokenUtf8ToUtf8 = array( + "\xc2\x80" => "\xe2\x82\xac", + + "\xc2\x82" => "\xe2\x80\x9a", + "\xc2\x83" => "\xc6\x92", + "\xc2\x84" => "\xe2\x80\x9e", + "\xc2\x85" => "\xe2\x80\xa6", + "\xc2\x86" => "\xe2\x80\xa0", + "\xc2\x87" => "\xe2\x80\xa1", + "\xc2\x88" => "\xcb\x86", + "\xc2\x89" => "\xe2\x80\xb0", + "\xc2\x8a" => "\xc5\xa0", + "\xc2\x8b" => "\xe2\x80\xb9", + "\xc2\x8c" => "\xc5\x92", + + "\xc2\x8e" => "\xc5\xbd", + + + "\xc2\x91" => "\xe2\x80\x98", + "\xc2\x92" => "\xe2\x80\x99", + "\xc2\x93" => "\xe2\x80\x9c", + "\xc2\x94" => "\xe2\x80\x9d", + "\xc2\x95" => "\xe2\x80\xa2", + "\xc2\x96" => "\xe2\x80\x93", + "\xc2\x97" => "\xe2\x80\x94", + "\xc2\x98" => "\xcb\x9c", + "\xc2\x99" => "\xe2\x84\xa2", + "\xc2\x9a" => "\xc5\xa1", + "\xc2\x9b" => "\xe2\x80\xba", + "\xc2\x9c" => "\xc5\x93", + + "\xc2\x9e" => "\xc5\xbe", + "\xc2\x9f" => "\xc5\xb8" + ); + + protected static $utf8ToWin1252 = array( + "\xe2\x82\xac" => "\x80", + + "\xe2\x80\x9a" => "\x82", + "\xc6\x92" => "\x83", + "\xe2\x80\x9e" => "\x84", + "\xe2\x80\xa6" => "\x85", + "\xe2\x80\xa0" => "\x86", + "\xe2\x80\xa1" => "\x87", + "\xcb\x86" => "\x88", + "\xe2\x80\xb0" => "\x89", + "\xc5\xa0" => "\x8a", + "\xe2\x80\xb9" => "\x8b", + "\xc5\x92" => "\x8c", + + "\xc5\xbd" => "\x8e", + + + "\xe2\x80\x98" => "\x91", + "\xe2\x80\x99" => "\x92", + "\xe2\x80\x9c" => "\x93", + "\xe2\x80\x9d" => "\x94", + "\xe2\x80\xa2" => "\x95", + "\xe2\x80\x93" => "\x96", + "\xe2\x80\x94" => "\x97", + "\xcb\x9c" => "\x98", + "\xe2\x84\xa2" => "\x99", + "\xc5\xa1" => "\x9a", + "\xe2\x80\xba" => "\x9b", + "\xc5\x93" => "\x9c", + + "\xc5\xbe" => "\x9e", + "\xc5\xb8" => "\x9f" + ); + + static function toUTF8($text){ + /** + * Function \ForceUTF8\Encoding::toUTF8 + * + * This function leaves UTF8 characters alone, while converting almost all non-UTF8 to UTF8. + * + * It assumes that the encoding of the original string is either Windows-1252 or ISO 8859-1. + * + * It may fail to convert characters to UTF-8 if they fall into one of these scenarios: + * + * 1) when any of these characters: ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞß + * are followed by any of these: ("group B") + * ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶•¸¹º»¼½¾¿ + * For example: %ABREPRESENT%C9%BB. «REPRESENTÉ» + * The "«" (%AB) character will be converted, but the "É" followed by "»" (%C9%BB) + * is also a valid unicode character, and will be left unchanged. + * + * 2) when any of these: àáâãäåæçèéêëìíîï are followed by TWO chars from group B, + * 3) when any of these: ðñòó are followed by THREE chars from group B. + * + * @name toUTF8 + * @param string $text Any string. + * @return string The same string, UTF8 encoded + * + */ + + if(is_array($text)) + { + foreach($text as $k => $v) + { + $text[$k] = self::toUTF8($v); + } + return $text; + } + + if(!is_string($text)) { + return $text; + } + + $max = self::strlen($text); + + $buf = ""; + for($i = 0; $i < $max; $i++){ + $c1 = $text{$i}; + if($c1>="\xc0"){ //Should be converted to UTF8, if it's not UTF8 already + $c2 = $i+1 >= $max? "\x00" : $text{$i+1}; + $c3 = $i+2 >= $max? "\x00" : $text{$i+2}; + $c4 = $i+3 >= $max? "\x00" : $text{$i+3}; + if($c1 >= "\xc0" & $c1 <= "\xdf"){ //looks like 2 bytes UTF8 + if($c2 >= "\x80" && $c2 <= "\xbf"){ //yeah, almost sure it's UTF8 already + $buf .= $c1 . $c2; + $i++; + } else { //not valid UTF8. Convert it. + $cc1 = (chr(ord($c1) / 64) | "\xc0"); + $cc2 = ($c1 & "\x3f") | "\x80"; + $buf .= $cc1 . $cc2; + } + } elseif($c1 >= "\xe0" & $c1 <= "\xef"){ //looks like 3 bytes UTF8 + if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf"){ //yeah, almost sure it's UTF8 already + $buf .= $c1 . $c2 . $c3; + $i = $i + 2; + } else { //not valid UTF8. Convert it. + $cc1 = (chr(ord($c1) / 64) | "\xc0"); + $cc2 = ($c1 & "\x3f") | "\x80"; + $buf .= $cc1 . $cc2; + } + } elseif($c1 >= "\xf0" & $c1 <= "\xf7"){ //looks like 4 bytes UTF8 + if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf" && $c4 >= "\x80" && $c4 <= "\xbf"){ //yeah, almost sure it's UTF8 already + $buf .= $c1 . $c2 . $c3 . $c4; + $i = $i + 3; + } else { //not valid UTF8. Convert it. + $cc1 = (chr(ord($c1) / 64) | "\xc0"); + $cc2 = ($c1 & "\x3f") | "\x80"; + $buf .= $cc1 . $cc2; + } + } else { //doesn't look like UTF8, but should be converted + $cc1 = (chr(ord($c1) / 64) | "\xc0"); + $cc2 = (($c1 & "\x3f") | "\x80"); + $buf .= $cc1 . $cc2; + } + } elseif(($c1 & "\xc0") == "\x80"){ // needs conversion + if(isset(self::$win1252ToUtf8[ord($c1)])) { //found in Windows-1252 special cases + $buf .= self::$win1252ToUtf8[ord($c1)]; + } else { + $cc1 = (chr(ord($c1) / 64) | "\xc0"); + $cc2 = (($c1 & "\x3f") | "\x80"); + $buf .= $cc1 . $cc2; + } + } else { // it doesn't need conversion + $buf .= $c1; + } + } + return $buf; + } + + static function toWin1252($text, $option = self::WITHOUT_ICONV) { + if(is_array($text)) { + foreach($text as $k => $v) { + $text[$k] = self::toWin1252($v, $option); + } + return $text; + } else if(is_string($text)) { + return self::utf8_decode($text, $option); + } else { + return $text; + } + } + + static function toISO8859($text) { + return self::toWin1252($text); + } + + static function toLatin1($text) { + return self::toWin1252($text); + } + + static function fixUTF8($text, $option = self::WITHOUT_ICONV){ + if(is_array($text)) { + foreach($text as $k => $v) { + $text[$k] = self::fixUTF8($v, $option); + } + return $text; + } + + $last = ""; + while($last <> $text){ + $last = $text; + $text = self::toUTF8(self::utf8_decode($text, $option)); + } + $text = self::toUTF8(self::utf8_decode($text, $option)); + return $text; + } + + static function UTF8FixWin1252Chars($text){ + // If you received an UTF-8 string that was converted from Windows-1252 as it was ISO8859-1 + // (ignoring Windows-1252 chars from 80 to 9F) use this function to fix it. + // See: http://en.wikipedia.org/wiki/Windows-1252 + + return str_replace(array_keys(self::$brokenUtf8ToUtf8), array_values(self::$brokenUtf8ToUtf8), $text); + } + + static function removeBOM($str=""){ + if(substr($str, 0,3) == pack("CCC",0xef,0xbb,0xbf)) { + $str=substr($str, 3); + } + return $str; + } + + protected static function strlen($text){ + return (function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload')) & 2) ? + mb_strlen($text,'8bit') : strlen($text); + } + + public static function normalizeEncoding($encodingLabel) + { + $encoding = strtoupper($encodingLabel); + $encoding = preg_replace('/[^a-zA-Z0-9\s]/', '', $encoding); + $equivalences = array( + 'ISO88591' => 'ISO-8859-1', + 'ISO8859' => 'ISO-8859-1', + 'ISO' => 'ISO-8859-1', + 'LATIN1' => 'ISO-8859-1', + 'LATIN' => 'ISO-8859-1', + 'UTF8' => 'UTF-8', + 'UTF' => 'UTF-8', + 'WIN1252' => 'ISO-8859-1', + 'WINDOWS1252' => 'ISO-8859-1' + ); + + if(empty($equivalences[$encoding])){ + return 'UTF-8'; + } + + return $equivalences[$encoding]; + } + + public static function encode($encodingLabel, $text) + { + $encodingLabel = self::normalizeEncoding($encodingLabel); + if($encodingLabel == 'ISO-8859-1') return self::toLatin1($text); + return self::toUTF8($text); + } + + protected static function utf8_decode($text, $option) + { + if ($option == self::WITHOUT_ICONV || !function_exists('iconv')) { + $o = utf8_decode( + str_replace(array_keys(self::$utf8ToWin1252), array_values(self::$utf8ToWin1252), self::toUTF8($text)) + ); + } else { + $o = iconv("UTF-8", "Windows-1252" . ($option == self::ICONV_TRANSLIT ? '//TRANSLIT' : ($option == self::ICONV_IGNORE ? '//IGNORE' : '')), $text); + } + return $o; + } + } +} \ No newline at end of file diff --git a/lib/forceutf8/README.md b/lib/forceutf8/README.md new file mode 100644 index 00000000..d2131c3d --- /dev/null +++ b/lib/forceutf8/README.md @@ -0,0 +1,61 @@ +forceutf8 +========= + +PHP Class Encoding featuring popular \ForceUTF8\Encoding::toUTF8() function --formerly known as forceUTF8()-- that fixes mixed encoded strings. + +Description +=========== + +If you apply the PHP function utf8_encode() to an already-UTF8 string it will return a garbled UTF8 string. + +This class addresses this issue and provides a handy static function called \ForceUTF8\Encoding::toUTF8(). + +You don't need to know what the encoding of your strings is. It can be Latin1 (iso 8859-1), Windows-1252 or UTF8, or the string can have a mix of them. \ForceUTF8\Encoding::toUTF8() will convert everything to UTF8. + +Sometimes you have to deal with services that are unreliable in terms of encoding, possibly mixing UTF8 and Latin1 in the same string. + +Update: + +I've included another function, \ForceUTF8\Encoding::fixUTF8(), which will fix the double (or multiple) encoded UTF8 string that looks garbled. + +Usage: +====== + + use \ForceUTF8\Encoding; + + $utf8_string = Encoding::toUTF8($utf8_or_latin1_or_mixed_string); + + $latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string); + +also: + + $utf8_string = Encoding::fixUTF8($garbled_utf8_string); + +Examples: + + use \ForceUTF8\Encoding; + + echo Encoding::fixUTF8("Fédération Camerounaise de Football\n"); + echo Encoding::fixUTF8("Fédération Camerounaise de Football\n"); + echo Encoding::fixUTF8("Fédération Camerounaise de Football\n"); + echo Encoding::fixUTF8("Fédération Camerounaise de Football\n"); + +will output: + + Fédération Camerounaise de Football + Fédération Camerounaise de Football + Fédération Camerounaise de Football + Fédération Camerounaise de Football + +Install via composer: +===================== +Edit your composer.json file to include the following: + +```json +{ + "require": { + "neitanod/forceutf8": "dev-master" + } +} +``` + diff --git a/views/actions.php b/views/actions.php index 45817c07..f07d55df 100644 --- a/views/actions.php +++ b/views/actions.php @@ -66,19 +66,6 @@ function duplicator_package_build() { die($json_response); } - -function duplicator_package_report() { - - DUP_Util::CheckPermissions('export'); - - $scanReport = $_GET['scanfile']; - header('Content-Type: application/json'); - header("Location: " . DUPLICATOR_SSDIR_URL . "/tmp/" . $scanReport); - echo DUPLICATOR_SSDIR_URL . "/tmp/" . $scanReport; - - die(); -} - /** * DUPLICATOR_PACKAGE_DELETE * Deletes the files and database record entries diff --git a/views/packages/new1.base.php b/views/packages/new1.base.php index 74da296d..041d7df5 100644 --- a/views/packages/new1.base.php +++ b/views/packages/new1.base.php @@ -160,7 +160,7 @@ - + From c0279cc50076bf2c5b4c1743d25c7f4447bcebda Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Mon, 2 Nov 2015 15:23:31 +0000 Subject: [PATCH 023/585] version update to .34 git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1277930 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index e7ef854b..b226e0d7 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: www.lifeinthegrid.com/partner Tags: backup, restore, move, migrate, localhost, synchronize, duplicate, clone, automate, niche Requires at least: 3.9 Tested up to: 4.3 -Stable tag: 0.5.32 +Stable tag: 0.5.34 License: GPLv2 Duplicate, clone, backup, move and transfer an entire site from one location to another. From 40a2074f8004bd54537627447e52dbe7a80c3d3f Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Fri, 13 Nov 2015 13:36:36 +0000 Subject: [PATCH 024/585] php error messages: https://wordpress.org/support/topic/php-warning-when-deleting-packages git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1285561 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- views/actions.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/views/actions.php b/views/actions.php index f07d55df..86c4ce66 100644 --- a/views/actions.php +++ b/views/actions.php @@ -92,6 +92,7 @@ function duplicator_package_delete() { foreach ($list as $id) { $getResult = $wpdb->get_results($wpdb->prepare("SELECT name, hash FROM `{$tblName}` WHERE id = %d", $id), ARRAY_A); + if ($getResult) { $row = $getResult[0]; $nameHash = "{$row['name']}_{$row['hash']}"; @@ -117,7 +118,9 @@ function duplicator_package_delete() { @unlink(DUP_Util::SafePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}.log")); //Unfinished Zip files $tmpZip = DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_archive.zip.*"; - array_map('unlink', glob($tmpZip)); + if ($tmpZip !== false) { + array_map('unlink', glob($tmpZip)); + } @unlink(DUP_Util::SafePath()); $delCount++; } From 2c25ec6a8965005f8ae6b9e8799f6ad77f6e4016 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Sat, 21 Nov 2015 21:39:10 +0000 Subject: [PATCH 025/585] - New: Pulling Beta Status: After 4 years - New: JSON link in scanner for quick viewing - Update: Error log cleanup code forum thread - Update: F5 Refresh on scanner page caused lose of form data - Update: language file slug from 'wpdulicator' to 'duplicator' per wp-team - Fix: Scan Warning: array_count_values(): Can only count STRING and INTEGER git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1291821 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- classes/package.php | 7 ++- classes/utility.php | 2 +- define.php | 4 +- duplicator.php | 10 +-- views/help/about.php | 20 +++--- views/help/help.php | 38 +++++------ views/packages/controller.php | 2 +- views/packages/list-nodata.php | 20 +++--- views/packages/list.base.php | 100 ++++++++++++++--------------- views/packages/new1.base.php | 64 +++++++++---------- views/packages/new1.inc.form.php | 104 +++++++++++++++---------------- views/packages/new2.base.php | 21 +++++-- views/packages/new3.base.php | 58 ++++++++--------- views/settings/controller.php | 4 +- views/settings/general.php | 78 +++++++++++------------ views/tools/controller.php | 8 +-- views/tools/diagnostics.php | 94 ++++++++++++++-------------- views/tools/logging.php | 22 +++---- 18 files changed, 335 insertions(+), 321 deletions(-) diff --git a/classes/package.php b/classes/package.php index 26ba19e9..13c8acba 100644 --- a/classes/package.php +++ b/classes/package.php @@ -132,10 +132,13 @@ public function Scan() { $report['ARC']['Status']['Size'], $report['ARC']['Status']['Names'], $report['ARC']['Status']['Big'], - $db['Status']); + $db['Status']['Size'], + $db['Status']['Rows']); - $warn_counts = array_count_values($warnings); + $warn_counts = array_count_values($warnings); + $report['RPT']['Warnings'] = $warn_counts['Warn']; + $report['RPT']['Success'] = $warn_counts['Good']; $report['RPT']['ScanTime'] = DUP_Util::ElapsedTime(DUP_Util::GetMicrotime(), $timerStart); $fp = fopen(DUPLICATOR_SSDIR_PATH_TMP . "/{$this->ScanFile}", 'w'); fwrite($fp, json_encode($report)); diff --git a/classes/utility.php b/classes/utility.php index d8d6eed9..601c1afe 100644 --- a/classes/utility.php +++ b/classes/utility.php @@ -255,7 +255,7 @@ public static function CheckPermissions($permission = 'read') { $capability = apply_filters('wpfront_user_role_editor_duplicator_translate_capability', $capability); if(!current_user_can($capability)) { - wp_die(__('You do not have sufficient permissions to access this page.', 'wpduplicator')); + wp_die(__('You do not have sufficient permissions to access this page.', 'duplicator')); return; } } diff --git a/define.php b/define.php index 0cc894de..32ff4ce9 100644 --- a/define.php +++ b/define.php @@ -3,14 +3,14 @@ if (function_exists('plugin_dir_url')) { - define('DUPLICATOR_VERSION', '0.5.34'); + define('DUPLICATOR_VERSION', '1.1.0'); define("DUPLICATOR_HOMEPAGE", "http://lifeinthegrid.com/labs/duplicator"); define("DUPLICATOR_GIVELINK", "http://lifeinthegrid.com/partner"); define("DUPLICATOR_HELPLINK", "http://lifeinthegrid.com/duplicator-docs"); define("DUPLICATOR_CERTIFIED", "http://lifeinthegrid.com/duplicator-hosts"); define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__)); define('DUPLICATOR_SITE_URL', get_site_url()); - define('DUPLICATOR_LANG_SLUG', 'wpduplicator'); + define('DUPLICATOR_LANG_SLUG', 'duplicator'); /* Paths should ALWAYS read "/" uni: /home/path/file.txt diff --git a/duplicator.php b/duplicator.php index c26702f0..7b33f55b 100644 --- a/duplicator.php +++ b/duplicator.php @@ -3,7 +3,7 @@ Plugin Name: Duplicator Plugin URI: http://www.lifeinthegrid.com/duplicator/ Description: Create a backup of your WordPress files and database. Duplicate and move an entire site from one location to another in a few steps. Create a full snapshot of your site at any point in time. - Version: 0.5.34 + Version: 1.1.0 Author: LifeInTheGrid Author URI: http://www.lifeinthegrid.com Text Domain: wpduplicator @@ -84,7 +84,7 @@ function duplicator_update() { if (DUPLICATOR_VERSION != get_option("duplicator_version_plugin")) { duplicator_activate(); } - load_plugin_textdomain('wpduplicator', FALSE, dirname(plugin_basename(__FILE__)) . '/lang/'); + load_plugin_textdomain('duplicator', FALSE, dirname(plugin_basename(__FILE__)) . '/lang/'); } /* DEACTIVATION / UNINSTALL @@ -100,8 +100,8 @@ function duplicator_meta_links($links, $file) { $plugin = plugin_basename(__FILE__); // create link if ($file == $plugin) { - $links[] = '' . __('Help', 'wpduplicator') . ''; - $links[] = '' . __('About', 'wpduplicator') . ''; + $links[] = '' . __('Help', 'duplicator') . ''; + $links[] = '' . __('About', 'duplicator') . ''; return $links; } return $links; @@ -244,7 +244,7 @@ function duplicator_manage_link($links, $file) { $this_plugin = plugin_basename(__FILE__); if ($file == $this_plugin) { - $settings_link = '' . __("Manage", 'wpduplicator') . ''; + $settings_link = '' . __("Manage", 'duplicator') . ''; array_unshift($links, $settings_link); } return $links; diff --git a/views/help/about.php b/views/help/about.php index 71de4006..fb18f603 100644 --- a/views/help/about.php +++ b/views/help/about.php @@ -38,7 +38,7 @@
    - +
    @@ -51,7 +51,7 @@ @@ -61,14 +61,14 @@ -

    +

    - +
    @@ -80,14 +80,14 @@ -
    +
    -
    +
    @@ -104,14 +104,14 @@
    - +
    @@ -128,7 +128,7 @@ diff --git a/views/help/help.php b/views/help/help.php index c665120b..d6c799cf 100644 --- a/views/help/help.php +++ b/views/help/help.php @@ -26,7 +26,7 @@
    - +
    @@ -35,7 +35,7 @@ @@ -47,17 +47,17 @@
    -
    +
    -
    +
    @@ -66,14 +66,14 @@
    -
    +
    - +

    @@ -85,13 +85,13 @@
    -
    +
    - +

    @@ -101,13 +101,13 @@
    -
    +
    - +

    diff --git a/views/packages/controller.php b/views/packages/controller.php index dc10ff4f..3dd9437f 100644 --- a/views/packages/controller.php +++ b/views/packages/controller.php @@ -73,7 +73,7 @@
    -
    -

    +
    +

    %s %s", - __("Please visit the", 'wpduplicator'), - __("help page", 'wpduplicator'), - __("for additional support", 'wpduplicator')); + __("Please visit the", 'duplicator'), + __("help page", 'duplicator'), + __("for additional support", 'duplicator')); ?> @@ -21,16 +21,16 @@
    %s %s", - __("To get an older package please visit the", 'wpduplicator'), - __("help page", 'wpduplicator'), - __("and look for the Change Log link for additional instructions.", 'wpduplicator')); + __("To get an older package please visit the", 'duplicator'), + __("help page", 'duplicator'), + __("and look for the Change Log link for additional instructions.", 'duplicator')); ?>


    diff --git a/views/packages/list.base.php b/views/packages/list.base.php index 70baf302..1fc5f37f 100644 --- a/views/packages/list.base.php +++ b/views/packages/list.base.php @@ -38,7 +38,7 @@ = 3) : ?>
    - +
    @@ -49,19 +49,19 @@
    - " onclick="Duplicator.Pack.Delete()"> + " onclick="Duplicator.Pack.Delete()">

    - ..."> + ..."> -   - +   + @@ -86,13 +86,13 @@ - - - - - + + + + + @@ -123,7 +123,7 @@ $detail_id = "duplicator-detail-row-{$rowCount}"; $plugin_version = empty($pack_version) ? 'unknown' : $pack_version; $plugin_compat = version_compare($plugin_version, '0.5.0'); - $notes = empty($pack_notes) ? __("(No Notes Taken)", 'wpduplicator') : $pack_notes; + $notes = empty($pack_notes) ? __("(No Notes Taken)", 'duplicator') : $pack_notes; //Links $uniqueid = "{$row['name']}_{$row['hash']}"; @@ -141,31 +141,31 @@ = 100) : ?> - + - + @@ -254,16 +254,16 @@ -
    " style="margin-left:15px" onclick="Duplicator.Pack.SetDeleteAll()" />" style="margin-left:15px" onclick="Duplicator.Pack.SetDeleteAll()" /> - +
    [][] -   +   - +
    - :   |   - :   |   - :
    - : + :   |   + :   |   + :
    + :
     
    -   -   - +   +   +
    - ); return false;">[]   - []
    + ); return false;">[]   + []
    @@ -186,33 +186,33 @@ ?>
    [][] - ... + ...
    - :   |   - :   |   - :
    + :   |   + :   |   + :
    -
    +
    - :
    + :
    %s", - __("This package has encountered errors. Click 'View Log' for more details. For additional support see the ", 'wpduplicator'), - __("online knowledgebase", 'wpduplicator')); + __("This package has encountered errors. Click 'View Log' for more details. For additional support see the ", 'duplicator'), + __("online knowledgebase", 'duplicator')); ?>
     
    - +
    [View Package Object]
    @@ -234,8 +234,8 @@
    - | - + | +
    - - - + + +
    - +
    -   - +   +
    @@ -114,7 +114,7 @@
    Pass
    ' : '
    Fail
    '; ?>
    @@ -123,44 +123,44 @@
    - +
    @@ -168,21 +168,21 @@
    -
    +
    - +
    %s   [%s]
    ", $dup_tests['IO']['WPROOT'], DUPLICATOR_WPROOTPATH); printf("%s   [%s]
    ", $dup_tests['IO']['SSDIR'], DUPLICATOR_SSDIR_PATH); printf("%s   [%s]
    ", $dup_tests['IO']['SSTMP'], DUPLICATOR_SSDIR_PATH_TMP); - //printf("%s: [%s]
    ", __('PHP Script Owner', 'wpduplicator'), DUP_Util::GetCurrentUser()); - //printf("%s: [%s]
    ", __('PHP Process Owner', 'wpduplicator'), DUP_Util::GetProcessOwner()); + //printf("%s: [%s]
    ", __('PHP Script Owner', 'duplicator'), DUP_Util::GetCurrentUser()); + //printf("%s: [%s]
    ", __('PHP Process Owner', 'duplicator'), DUP_Util::GetProcessOwner()); ?>
    - +
    @@ -190,24 +190,24 @@
    - +
    - + - +
    db_version()); ?>db_version()); ?>
    [" . __('more info', 'wpduplicator') . "]"; + _e("MySQL version 5.0+ or better is required and the PHP MySQLi extension (note the trailing 'i') is also required. Contact your server administrator and request that mysqli extension and MySQL Server 5.0+ be installed. Please note in future versions support for other databases and extensions will be added.", 'duplicator'); + echo " [" . __('more info', 'duplicator') . "]"; ?>
    @@ -216,17 +216,17 @@
    -
    +
    - +
    - -
    ' style='font-size:10px; margin-top:5px;' /> + +
    ' style='font-size:10px; margin-top:5px;' />
    @@ -235,7 +235,7 @@
    %s [%s]", __("For additional help please see the ", 'wpduplicator'), __("help page", 'wpduplicator')); + printf(" %s [%s]", __("For additional help please see the ", 'duplicator'), __("help page", 'duplicator')); ?>
    diff --git a/views/packages/new1.inc.form.php b/views/packages/new1.inc.form.php index 8d341242..9a27ae4f 100644 --- a/views/packages/new1.inc.form.php +++ b/views/packages/new1.inc.form.php @@ -3,14 +3,14 @@
    - +
    - +
    -
    +

    -
    +
    @@ -20,7 +20,7 @@ META-BOX: STORAGE -->
    -   +  
    @@ -28,15 +28,15 @@ - - - + + + - - + + @@ -46,7 +46,7 @@ - + Duplicator Pro @@ -60,10 +60,10 @@
    -   +   -    - +    +
    @@ -72,8 +72,8 @@
      -
    • -
    • +
    • +
    @@ -85,29 +85,29 @@ ?>
    Archive->FilterOn) ? "checked='checked'" : ""; ?> /> - +
    - +
    - +
    -
    - +
    +

    @@ -123,14 +123,14 @@
      
    - - + +
    Database->FilterOn) ? "checked='checked'" : ""; ?> />
    - [ ]   - [ ] + [ ]   + [ ]
    get_results("SHOW FULL TABLES FROM `" . DB_NAME . "` WHERE Table_Type = 'BASE TABLE' ", ARRAY_N); @@ -163,7 +163,7 @@ ?>
    - +
    @@ -176,58 +176,58 @@
    - +
    -

    +

    - + - + - + - + - + - +
    - + - +
    Installer->OptsSSLAdmin) ? "checked='checked'" : ""; ?> /> - + Installer->OptsSSLLogin) ? "checked='checked'" : ""; ?> /> - +
    Installer->OptsCacheWP) ? "checked='checked'" : ""; ?> /> - + Installer->OptsCachePath) ? "checked='checked'" : ""; ?> /> - +
    @@ -235,17 +235,17 @@

    -
    +
    - +
    - +
    @@ -254,8 +254,8 @@ diff --git a/views/packages/new2.base.php b/views/packages/new2.base.php index 000a4f0f..5c16ef86 100644 --- a/views/packages/new2.base.php +++ b/views/packages/new2.base.php @@ -1,6 +1,15 @@ window.location.href = '{$redirect}'"; + exit; + } + global $wp_version; $Package = new DUP_Package(); $Package->SaveActive($_POST); @@ -322,14 +331,16 @@ DUP_Util::_e('No file extension filters have been set.'); } ?> - - -
    + + + +
    -
    -

    diff --git a/views/packages/new3.base.php b/views/packages/new3.base.php index 1adb7506..d968b6e6 100644 --- a/views/packages/new3.base.php +++ b/views/packages/new3.base.php @@ -30,18 +30,18 @@
    - - - + + +
    - +
    -   - +   + @@ -52,42 +52,42 @@
    -

    +

    -

    -
    -
    +

    +
    +
    + + + +
    +
    +   +
    +
    + +
    + +


    @@ -379,6 +415,19 @@ } }; + Duplicator.Pack.ToggleDupArchive = function() { + var $btn = $('#dup-duparchive-btn'); + if ($('#dup-duparchive-check').is(':checked')) { + $btn.removeAttr("disabled"); + } else { + $btn.attr("disabled", true); + } + }; + + Duplicator.Pack.OpenBetaLink = function() { + window.open('http://snapcreek.com/duplicator/duplicator-lite-1-3-beta/'); + }; + //Page Init: Duplicator.UI.AnimateProgressBar('dup-progress-bar'); Duplicator.Pack.Create(); From 9ac8224812cf0d24404378c9c3413d85c6abbf67 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Wed, 6 Jun 2018 16:14:56 +0000 Subject: [PATCH 381/585] - Version Update git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1888309 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 458f5c16..0ae67a33 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Tags: migration, backup, restore, move, migrate, duplicate, transfer, clone, aut Requires at least: 4.0 Tested up to: 4.9 Requires PHP: 5.2.17 -Stable tag: 1.2.38 +Stable tag: 1.2.40 License: GPLv2 WordPress migration and backups are much easier with Duplicator! Clone, backup, move and transfer an entire site from one location to another. From ecfa398257488b6373867faf0b5b4d34ca59cf4d Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Wed, 18 Jul 2018 02:18:47 +0000 Subject: [PATCH 382/585] - Fix for mysqldump with open_basedir enabled - Sanitize fields for the installer git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1910714 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- classes/class.db.php | 20 +- define.php | 4 +- duplicator.php | 4 +- installer/build/ctrls/ctrl.step2.php | 923 ++++++++++++++------------- installer/build/ctrls/ctrl.step3.php | 19 +- installer/build/view.step4.php | 7 +- views/settings/about-info.php | 10 +- 7 files changed, 502 insertions(+), 485 deletions(-) diff --git a/classes/class.db.php b/classes/class.db.php index 0cbd5f42..b3b68da9 100644 --- a/classes/class.db.php +++ b/classes/class.db.php @@ -114,7 +114,6 @@ public static function getWindowsMySqlDumpRealPath() { */ public static function getMySqlDumpPath() { - //Is shell_exec possible if (!DUP_Util::hasShellExec()) { return false; @@ -123,7 +122,7 @@ public static function getMySqlDumpPath() $custom_mysqldump_path = DUP_Settings::Get('package_mysqldump_path'); $custom_mysqldump_path = (strlen($custom_mysqldump_path)) ? $custom_mysqldump_path : ''; - //Common Windows Paths + //COMMON WINDOWS PATHS if (DUP_Util::isWindows()) { $paths = array( $custom_mysqldump_path, @@ -137,7 +136,7 @@ public static function getMySqlDumpPath() 'C:/Program Files/MySQL/MySQL Server 5.0/bin/mysqldump', ); - //Common Linux Paths + //COMMON LINUX PATHS } else { $path1 = ''; $path2 = ''; @@ -165,11 +164,22 @@ public static function getMySqlDumpPath() ); } - // Find the one which works + //Try to find a path that works. With open_basedir enabled, the file_exists may not work on some systems + //So we fallback and try to use exec as a last resort + $exec_available = function_exists('exec'); foreach ($paths as $path) { if(file_exists($path)) { - if (DUP_Util::isExecutable($path)) + if (DUP_Util::isExecutable($path)) { + return $path; + } + } elseif ($exec_available) { + $out = array(); + $rc = -1; + $cmd = $path . ' --help'; + @exec($cmd, $out, $rc); + if ($rc === 0) { return $path; + } } } diff --git a/define.php b/define.php index beb2cef0..75656d85 100644 --- a/define.php +++ b/define.php @@ -2,8 +2,8 @@ //Prevent directly browsing to the file if (function_exists('plugin_dir_url')) { - define('DUPLICATOR_VERSION', '1.2.40'); - define('DUPLICATOR_HOMEPAGE', 'http://lifeinthegrid.com/labs/duplicator'); + define('DUPLICATOR_VERSION', '1.2.41'); + define('DUPLICATOR_HOMEPAGE', 'https://snapcreek.com/duplicator/duplicator-free/'); define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__)); define('DUPLICATOR_SITE_URL', get_site_url()); diff --git a/duplicator.php b/duplicator.php index 2f620eba..f486b99a 100644 --- a/duplicator.php +++ b/duplicator.php @@ -1,9 +1,9 @@ Success
    " : "
    Fail
    "; - $tstDB = ($dbFound) ? "
    Success
    " : "
    Fail
    "; - - $dbversion_info = DUPX_DB::getServerInfo($dbConn); - $dbversion_info = empty($dbversion_info) ? 'no connection' : $dbversion_info; - $dbversion_info_fail = version_compare(DUPX_DB::getVersion($dbConn), '5.5.3') < 0; - - $dbversion_compat = DUPX_DB::getVersion($dbConn); - $dbversion_compat = empty($dbversion_compat) ? 'no connection' : $dbversion_compat; - $dbversion_compat_fail = version_compare($dbversion_compat, $GLOBALS['FW_VERSION_DB']) < 0; - - $tstInfo = ($dbversion_info_fail) - ? "
    {$dbversion_info}
    " - : "
    {$dbversion_info}
    "; - - $tstCompat = ($dbversion_compat_fail) - ? "
    This Server: [{$dbversion_compat}] -- Package Server: [{$GLOBALS['FW_VERSION_DB']}]
    " - : "
    This Server: [{$dbversion_compat}] -- Package Server: [{$GLOBALS['FW_VERSION_DB']}]
    "; - - $html .= << - - Using Connection String:
    - Host={$_POST['dbhost']}; Database={$_POST['dbname']}; Uid={$_POST['dbuser']}; Pwd={$_POST['dbpass']}; {$port_view} -
    - - - - - - - - - - - - - - - - - -
    Host:{$tstSrv}
    Database:{$tstDB}
    Version:{$tstInfo}
    Compatibility:{$tstCompat}
    -DATA; - - //-------------------------------- - //WARNING: DB has tables with create option - if ($_POST['dbaction'] == 'create') - { - $tblcount = DUPX_DB::countTables($dbConn, $_POST['dbname']); - $html .= ($tblcount > 0) - ? "
    WARNING: " . sprintf(ERR_DBEMPTY, $_POST['dbname'], $tblcount) . "
    " - : ''; - } - - //WARNNG: Input has utf8 - $dbConnItems = array($_POST['dbhost'], $_POST['dbuser'], $_POST['dbname'],$_POST['dbpass']); - $dbUTF8_tst = false; - foreach ($dbConnItems as $value) - { - if (DUPX_U::isNonASCII($value)) { - $dbUTF8_tst = true; - break; - } - } - - //WARNING: UTF8 Data in Connection String - $html .= (! $dbConn && $dbUTF8_tst) - ? "
    WARNING: " . ERR_TESTDB_UTF8 . "
    " - : ''; - - //NOTICE: Version Too Low - $html .= ($dbversion_info_fail) - ? "
    NOTICE: " . ERR_TESTDB_VERSION_INFO . "
    " - : ''; - - //NOTICE: Version Incompatibility - $html .= ($dbversion_compat_fail) - ? "
    NOTICE: " . ERR_TESTDB_VERSION_COMPAT . "
    " - : ''; - - $html .= "
    "; - die($html); -} - -//=============================== -//ERROR MESSAGES -//=============================== -//ERR_MAKELOG -($GLOBALS['LOG_FILE_HANDLE'] != false) or DUPX_Log::error(ERR_MAKELOG); - -//ERR_MYSQLI_SUPPORT -function_exists('mysqli_connect') or DUPX_Log::error(ERR_MYSQLI_SUPPORT); - -//ERR_DBCONNECT -$dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], null, $_POST['dbport']); -@mysqli_query($dbh, "SET wait_timeout = {$GLOBALS['DB_MAX_TIME']}"); -($dbh) or DUPX_Log::error(ERR_DBCONNECT . mysqli_connect_error()); -if ($_POST['dbaction'] == 'empty') { - mysqli_select_db($dbh, $_POST['dbname']) or DUPX_Log::error(sprintf(ERR_DBCREATE, $_POST['dbname'])); -} -//ERR_DBEMPTY -if ($_POST['dbaction'] == 'create' ) { - $tblcount = DUPX_DB::countTables($dbh, $_POST['dbname']); - if ($tblcount > 0) { - DUPX_Log::error(sprintf(ERR_DBEMPTY, $_POST['dbname'], $tblcount)); - } -} - -$log = <<= $php_mem_range && $php_mem_range != 0) -{ - $db_file_size = DUPX_U::readableByteSize($db_file_size); - $msg = "\nWARNING: The database script is '{$db_file_size}' in size. The PHP memory allocation is set\n"; - $msg .= "at '{$php_mem}'. There is a high possibility that the installer script will fail with\n"; - $msg .= "a memory allocation error when trying to load the database.sql file. It is\n"; - $msg .= "recommended to increase the 'memory_limit' setting in the php.ini config file.\n"; - $msg .= "see: {$faq_url}{$utm_prefix}inst_step2_lgdbscript#faq-trouble-056-q \n"; - DUPX_Log::info($msg); -} - -@chmod("{$root_path}/database.sql", 0777); -$sql_file = file_get_contents('database.sql', true); - -//ERROR: Reading database.sql file -if ($sql_file === FALSE || strlen($sql_file) < 10) -{ - $msg = "Unable to read the database.sql file from the archive. Please check these items:
    "; - $msg .= "1. Validate permissions and/or group-owner rights on these items:
    "; - $msg .= " - File: database.sql
    - Directory: [{$root_path}]
    "; - $msg .= "see: {$faq_url}#faq-trouble-055-q
    "; - $msg .= "2. Validate the database.sql file exists and is in the root of the archive.zip file
    "; - $msg .= "see: {$faq_url}#faq-installer-020-q
    "; - DUPX_Log::error($msg); -} - -//Removes invalid space characters -//Complex Subject See: http://webcollab.sourceforge.net/unicode.html -if ($_POST['dbnbsp']) -{ - DUPX_Log::info("NOTICE: Ran fix non-breaking space characters\n"); - $sql_file = preg_replace('/\xC2\xA0/', ' ', $sql_file); -} - -//Write new contents to install-data.sql -$sql_file_copy_status = file_put_contents($GLOBALS['SQL_FILE_NAME'], $sql_file); -$sql_result_file_data = explode(";\n", $sql_file); -$sql_result_file_length = count($sql_result_file_data); -$sql_result_file_path = "{$root_path}/{$GLOBALS['SQL_FILE_NAME']}"; -$sql_file = null; -$db_collatefb_log = ''; - -if($_POST['dbcollatefb']){ - $supportedCollations = DUPX_DB::getSupportedCollationsList($dbh); - $collation_arr = array( - 'utf8mb4_unicode_520_ci', - 'utf8mb4_unicode_520', - 'utf8mb4_unicode_ci', - 'utf8mb4', - 'utf8_unicode_520_ci', - 'utf8_unicode_520', - 'utf8_unicode_ci', - 'utf8' - ); - $latest_supported_collation = ''; - $latest_supported_index = -1; - - foreach ($collation_arr as $key => $val){ - if(in_array($val,$supportedCollations)){ - $latest_supported_collation = $val; - $latest_supported_index = $key; - break; - } - } - - //No need to replace if current DB is up to date - if($latest_supported_index != 0){ - for($i=0; $i < $latest_supported_index; $i++){ - foreach ($sql_result_file_data as $index => $col_sql_query){ - if(strpos($col_sql_query,$collation_arr[$i]) !== false){ - $sql_result_file_data[$index] = str_replace($collation_arr[$i], $latest_supported_collation, $col_sql_query); - if(strpos($collation_arr[$i],'utf8mb4') !== false && strpos($latest_supported_collation,'utf8mb4') === false){ - $sql_result_file_data[$index] = str_replace('utf8mb4','utf8',$sql_result_file_data[$index]); - } - $sub_query = str_replace("\n", '', substr($col_sql_query, 0, 75)); - $db_collatefb_log .= " - Collation '{$collation_arr[$i]}' set to '{$latest_supported_collation}' on query [{$sub_query}...]\n"; - } - } - } - } -} - -//WARNING: Create installer-data.sql failed -if ($sql_file_copy_status === FALSE || filesize($sql_result_file_path) == 0 || !is_readable($sql_result_file_path)) -{ - $sql_file_size = DUPX_U::readableByteSize(filesize('database.sql')); - $msg = "\nWARNING: Unable to properly copy database.sql ({$sql_file_size}) to {$GLOBALS['SQL_FILE_NAME']}. Please check these items:\n"; - $msg .= "- Validate permissions and/or group-owner rights on database.sql and directory [{$root_path}] \n"; - $msg .= "- see: {$faq_url}{$utm_prefix}inst_step2_copydbsql#faq-trouble-055-q \n"; - DUPX_Log::info($msg); -} - -//================================= -//START DB RUN -@mysqli_query($dbh, "SET wait_timeout = {$GLOBALS['DB_MAX_TIME']}"); -@mysqli_query($dbh, "SET max_allowed_packet = {$GLOBALS['DB_MAX_PACKETS']}"); -DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']); - -//Will set mode to null only for this db handle session -//sql_mode can cause db create issues on some systems -$qry_session_custom = true; -switch ($_POST['dbmysqlmode']) { - case 'DISABLE': - @mysqli_query($dbh, "SET SESSION sql_mode = ''"); - break; - case 'CUSTOM': - $dbmysqlmode_opts = $_POST['dbmysqlmode_opts']; - $qry_session_custom = @mysqli_query($dbh, "SET SESSION sql_mode = '{$dbmysqlmode_opts}'"); - if ($qry_session_custom == false) { - $sql_error = mysqli_error($dbh); - $log = "WARNING: Trying to set a custom sql_mode setting issue has been detected:\n{$sql_error}.\n"; - $log .= "For more details visit: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html\n"; - } - break; -} - -//Set defaults in-case the variable could not be read -$dbvar_maxtime = DUPX_DB::getVariable($dbh, 'wait_timeout'); -$dbvar_maxpacks = DUPX_DB::getVariable($dbh, 'max_allowed_packet'); -$dbvar_sqlmode = DUPX_DB::getVariable($dbh, 'sql_mode'); -$dbvar_maxtime = is_null($dbvar_maxtime) ? 300 : $dbvar_maxtime; -$dbvar_maxpacks = is_null($dbvar_maxpacks) ? 1048576 : $dbvar_maxpacks; -$dbvar_sqlmode = empty($dbvar_sqlmode) ? 'NOT_SET' : $dbvar_sqlmode; -$dbvar_version = DUPX_DB::getVersion($dbh); -$sql_file_size1 = DUPX_U::readableByteSize(@filesize("database.sql")); -$sql_file_size2 = DUPX_U::readableByteSize(@filesize("{$GLOBALS['SQL_FILE_NAME']}")); -$db_collatefb = isset($_POST['dbcollatefb']) ? 'On' : 'Off'; - - -DUPX_Log::info("--------------------------------------"); -DUPX_Log::info("DATABASE ENVIRONMENT"); -DUPX_Log::info("--------------------------------------"); -DUPX_Log::info("MYSQL VERSION:\tThis Server: {$dbvar_version} -- Build Server: {$GLOBALS['FW_VERSION_DB']}"); -DUPX_Log::info("FILE SIZE:\tdatabase.sql ({$sql_file_size1}) - installer-data.sql ({$sql_file_size2})"); -DUPX_Log::info("TIMEOUT:\t{$dbvar_maxtime}"); -DUPX_Log::info("MAXPACK:\t{$dbvar_maxpacks}"); -DUPX_Log::info("SQLMODE:\t{$dbvar_sqlmode}"); -DUPX_Log::info("NEW SQL FILE:\t[{$sql_result_file_path}]"); -DUPX_Log::info("COLLATE RESET:\t{$db_collatefb}\n{$db_collatefb_log}"); - -if ($qry_session_custom == false) { - DUPX_Log::info("\n{$log}\n"); -} - -//CREATE DB -switch ($_POST['dbaction']) { - case "create": - mysqli_query($dbh, "CREATE DATABASE IF NOT EXISTS `{$_POST['dbname']}`"); - mysqli_select_db($dbh, $_POST['dbname']) - or DUPX_Log::error(sprintf(ERR_DBCONNECT_CREATE, $_POST['dbname'])); - break; - case "empty": - //DROP DB TABLES - $drop_log = "Database already empty. Ready for install."; - $sql = "SHOW FULL TABLES WHERE Table_Type != 'VIEW'"; - $found_tables = null; - if ($result = mysqli_query($dbh, $sql)) { - while ($row = mysqli_fetch_row($result)) { - $found_tables[] = $row[0]; - } - if (count($found_tables) > 0) { - foreach ($found_tables as $table_name) { - $sql = "DROP TABLE `{$_POST['dbname']}`.`{$table_name}`"; - if (!$result = mysqli_query($dbh, $sql)) { - DUPX_Log::error(sprintf(ERR_DBTRYCLEAN, $_POST['dbname'])); - } - } - } - $drop_log = count($found_tables); - } - break; -} - - -//WRITE DATA -DUPX_Log::info("--------------------------------------"); -DUPX_Log::info("DATABASE RESULTS"); -DUPX_Log::info("--------------------------------------"); -$profile_start = DUPX_U::getMicrotime(); -$fcgi_buffer_pool = 5000; -$fcgi_buffer_count = 0; -$dbquery_rows = 0; -$dbtable_rows = 1; -$dbquery_errs = 0; -$counter = 0; -@mysqli_autocommit($dbh, false); - -while ($counter < $sql_result_file_length) { - - $query_strlen = strlen(trim($sql_result_file_data[$counter])); - - if ($dbvar_maxpacks < $query_strlen) { - - DUPX_Log::info("**ERROR** Query size limit [length={$query_strlen}] [sql=" . substr($sql_result_file_data[$counter], 0, 75) . "...]"); - $dbquery_errs++; - - } elseif ($query_strlen > 0) { - - @mysqli_free_result(@mysqli_query($dbh, ($sql_result_file_data[$counter]))); - $err = mysqli_error($dbh); - - //Check to make sure the connection is alive - if (!empty($err)) { - - if (!mysqli_ping($dbh)) { - mysqli_close($dbh); - $dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], $_POST['dbname'], $_POST['dbport'] ); - // Reset session setup - @mysqli_query($dbh, "SET wait_timeout = {$GLOBALS['DB_MAX_TIME']}"); - DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']); - } - DUPX_Log::info("**ERROR** database error write '{$err}' - [sql=" . substr($sql_result_file_data[$counter], 0, 75) . "...]"); - $dbquery_errs++; - - //Buffer data to browser to keep connection open - } else { - if ($GLOBALS['DB_FCGI_FLUSH'] && $fcgi_buffer_count++ > $fcgi_buffer_pool) { - $fcgi_buffer_count = 0; - DUPX_U::fcgiFlush(); - } - $dbquery_rows++; - } - } - $counter++; -} -@mysqli_commit($dbh); -@mysqli_autocommit($dbh, true); - -DUPX_Log::info("ERRORS FOUND:\t{$dbquery_errs}"); -DUPX_Log::info("TABLES DROPPED:\t{$drop_log}"); -DUPX_Log::info("QUERIES RAN:\t{$dbquery_rows}\n"); - -$dbtable_count = 0; -if ($result = mysqli_query($dbh, "SHOW TABLES")) { - while ($row = mysqli_fetch_array($result, MYSQLI_NUM)) { - $table_rows = DUPX_DB::countTableRows($dbh, $row[0]); - $dbtable_rows += $table_rows; - DUPX_Log::info("{$row[0]}: ({$table_rows})"); - $dbtable_count++; - } - @mysqli_free_result($result); -} - -if ($dbtable_count == 0) { - DUPX_Log::error("No tables where created during step 2 of the install. Please review the installer-log.txt file for - ERROR messages. You may have to manually run the installer-data.sql with a tool like phpmyadmin to validate the data input. If you have enabled compatibility mode - during the package creation process then the database server version your using may not be compatible with this script.\n"); -} - - -//DATA CLEANUP: Perform Transient Cache Cleanup -//Remove all duplicator entries and record this one since this is a new install. -$dbdelete_count = 0; -@mysqli_query($dbh, "DELETE FROM `{$GLOBALS['FW_TABLEPREFIX']}duplicator_packages`"); -$dbdelete_count1 = @mysqli_affected_rows($dbh) or 0; -@mysqli_query($dbh, "DELETE FROM `{$GLOBALS['FW_TABLEPREFIX']}options` WHERE `option_name` LIKE ('_transient%') OR `option_name` LIKE ('_site_transient%')"); -$dbdelete_count2 = @mysqli_affected_rows($dbh) or 0; -$dbdelete_count = (abs($dbdelete_count1) + abs($dbdelete_count2)); -DUPX_Log::info("\nRemoved '{$dbdelete_count}' cache/transient rows"); -//Reset Duplicator Options -foreach ($GLOBALS['FW_OPTS_DELETE'] as $value) { - mysqli_query($dbh, "DELETE FROM `{$GLOBALS['FW_TABLEPREFIX']}options` WHERE `option_name` = '{$value}'"); -} - -@mysqli_close($dbh); - -//FINAL RESULTS -$profile_end = DUPX_U::getMicrotime(); -$ajax2_end = DUPX_U::getMicrotime(); -$ajax1_sum = DUPX_U::elapsedTime($ajax2_end, $ajax2_start); -DUPX_Log::info("\nCREATE/INSTALL RUNTIME: " . DUPX_U::elapsedTime($profile_end, $profile_start)); -DUPX_Log::info('STEP-2 COMPLETE @ ' . @date('h:i:s') . " - RUNTIME: {$ajax1_sum}"); - -$JSON['pass'] = 1; -$JSON['table_count'] = $dbtable_count; -$JSON['table_rows'] = $dbtable_rows; -$JSON['query_errs'] = $dbquery_errs; -echo json_encode($JSON); -error_reporting($ajax1_error_level); -die(''); +Success
    " : "
    Fail
    "; + $tstDB = ($dbFound) ? "
    Success
    " : "
    Fail
    "; + + $dbversion_info = DUPX_DB::getServerInfo($dbConn); + $dbversion_info = empty($dbversion_info) ? 'no connection' : $dbversion_info; + $dbversion_info_fail = version_compare(DUPX_DB::getVersion($dbConn), '5.5.3') < 0; + + $dbversion_compat = DUPX_DB::getVersion($dbConn); + $dbversion_compat = empty($dbversion_compat) ? 'no connection' : $dbversion_compat; + $dbversion_compat_fail = version_compare($dbversion_compat, $GLOBALS['FW_VERSION_DB']) < 0; + + $tstInfo = ($dbversion_info_fail) + ? "
    {$dbversion_info}
    " + : "
    {$dbversion_info}
    "; + + $tstCompat = ($dbversion_compat_fail) + ? "
    This Server: [{$dbversion_compat}] -- Package Server: [{$GLOBALS['FW_VERSION_DB']}]
    " + : "
    This Server: [{$dbversion_compat}] -- Package Server: [{$GLOBALS['FW_VERSION_DB']}]
    "; + + $html .= << + + Using Connection String:
    + Host={$_POST['dbhost']}; Database={$_POST['dbname']}; Uid={$_POST['dbuser']}; Pwd={$_POST['dbpass']}; {$port_view} +
    + + + + + + + + + + + + + + + + + +
    Host:{$tstSrv}
    Database:{$tstDB}
    Version:{$tstInfo}
    Compatibility:{$tstCompat}
    +DATA; + + //-------------------------------- + //WARNING: DB has tables with create option + if ($_POST['dbaction'] == 'create') + { + $tblcount = DUPX_DB::countTables($dbConn, $_POST['dbname']); + $html .= ($tblcount > 0) + ? "
    WARNING: " . sprintf(ERR_DBEMPTY, $_POST['dbname'], $tblcount) . "
    " + : ''; + } + + //WARNNG: Input has utf8 + $dbConnItems = array($_POST['dbhost'], $_POST['dbuser'], $_POST['dbname'],$_POST['dbpass']); + $dbUTF8_tst = false; + foreach ($dbConnItems as $value) + { + if (DUPX_U::isNonASCII($value)) { + $dbUTF8_tst = true; + break; + } + } + + //WARNING: UTF8 Data in Connection String + $html .= (! $dbConn && $dbUTF8_tst) + ? "
    WARNING: " . ERR_TESTDB_UTF8 . "
    " + : ''; + + //NOTICE: Version Too Low + $html .= ($dbversion_info_fail) + ? "
    NOTICE: " . ERR_TESTDB_VERSION_INFO . "
    " + : ''; + + //NOTICE: Version Incompatibility + $html .= ($dbversion_compat_fail) + ? "
    NOTICE: " . ERR_TESTDB_VERSION_COMPAT . "
    " + : ''; + + $html .= "
    "; + die($html); +} + +//=============================== +//ERROR MESSAGES +//=============================== +//ERR_MAKELOG +($GLOBALS['LOG_FILE_HANDLE'] != false) or DUPX_Log::error(ERR_MAKELOG); + +//ERR_MYSQLI_SUPPORT +function_exists('mysqli_connect') or DUPX_Log::error(ERR_MYSQLI_SUPPORT); + +//ERR_DBCONNECT +$dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], null, $_POST['dbport']); +@mysqli_query($dbh, "SET wait_timeout = {$GLOBALS['DB_MAX_TIME']}"); +($dbh) or DUPX_Log::error(ERR_DBCONNECT . mysqli_connect_error()); +if ($_POST['dbaction'] == 'empty') { + mysqli_select_db($dbh, $_POST['dbname']) or DUPX_Log::error(sprintf(ERR_DBCREATE, $_POST['dbname'])); +} +//ERR_DBEMPTY +if ($_POST['dbaction'] == 'create' ) { + $tblcount = DUPX_DB::countTables($dbh, $_POST['dbname']); + if ($tblcount > 0) { + DUPX_Log::error(sprintf(ERR_DBEMPTY, $_POST['dbname'], $tblcount)); + } +} + +$log = <<= $php_mem_range && $php_mem_range != 0) +{ + $db_file_size = DUPX_U::readableByteSize($db_file_size); + $msg = "\nWARNING: The database script is '{$db_file_size}' in size. The PHP memory allocation is set\n"; + $msg .= "at '{$php_mem}'. There is a high possibility that the installer script will fail with\n"; + $msg .= "a memory allocation error when trying to load the database.sql file. It is\n"; + $msg .= "recommended to increase the 'memory_limit' setting in the php.ini config file.\n"; + $msg .= "see: {$faq_url}{$utm_prefix}inst_step2_lgdbscript#faq-trouble-056-q \n"; + DUPX_Log::info($msg); +} + +@chmod("{$root_path}/database.sql", 0777); +$sql_file = file_get_contents('database.sql', true); + +//ERROR: Reading database.sql file +if ($sql_file === FALSE || strlen($sql_file) < 10) +{ + $msg = "Unable to read the database.sql file from the archive. Please check these items:
    "; + $msg .= "1. Validate permissions and/or group-owner rights on these items:
    "; + $msg .= " - File: database.sql
    - Directory: [{$root_path}]
    "; + $msg .= "see: {$faq_url}#faq-trouble-055-q
    "; + $msg .= "2. Validate the database.sql file exists and is in the root of the archive.zip file
    "; + $msg .= "see: {$faq_url}#faq-installer-020-q
    "; + DUPX_Log::error($msg); +} + +//Removes invalid space characters +//Complex Subject See: http://webcollab.sourceforge.net/unicode.html +if ($_POST['dbnbsp']) +{ + DUPX_Log::info("NOTICE: Ran fix non-breaking space characters\n"); + $sql_file = preg_replace('/\xC2\xA0/', ' ', $sql_file); +} + +//Write new contents to install-data.sql +$sql_file_copy_status = file_put_contents($GLOBALS['SQL_FILE_NAME'], $sql_file); +$sql_result_file_data = explode(";\n", $sql_file); +$sql_result_file_length = count($sql_result_file_data); +$sql_result_file_path = "{$root_path}/{$GLOBALS['SQL_FILE_NAME']}"; +$sql_file = null; +$db_collatefb_log = ''; + +if($_POST['dbcollatefb']){ + $supportedCollations = DUPX_DB::getSupportedCollationsList($dbh); + $collation_arr = array( + 'utf8mb4_unicode_520_ci', + 'utf8mb4_unicode_520', + 'utf8mb4_unicode_ci', + 'utf8mb4', + 'utf8_unicode_520_ci', + 'utf8_unicode_520', + 'utf8_unicode_ci', + 'utf8' + ); + $latest_supported_collation = ''; + $latest_supported_index = -1; + + foreach ($collation_arr as $key => $val){ + if(in_array($val,$supportedCollations)){ + $latest_supported_collation = $val; + $latest_supported_index = $key; + break; + } + } + + //No need to replace if current DB is up to date + if($latest_supported_index != 0){ + for($i=0; $i < $latest_supported_index; $i++){ + foreach ($sql_result_file_data as $index => $col_sql_query){ + if(strpos($col_sql_query,$collation_arr[$i]) !== false){ + $sql_result_file_data[$index] = str_replace($collation_arr[$i], $latest_supported_collation, $col_sql_query); + if(strpos($collation_arr[$i],'utf8mb4') !== false && strpos($latest_supported_collation,'utf8mb4') === false){ + $sql_result_file_data[$index] = str_replace('utf8mb4','utf8',$sql_result_file_data[$index]); + } + $sub_query = str_replace("\n", '', substr($col_sql_query, 0, 75)); + $db_collatefb_log .= " - Collation '{$collation_arr[$i]}' set to '{$latest_supported_collation}' on query [{$sub_query}...]\n"; + } + } + } + } +} + +//WARNING: Create installer-data.sql failed +if ($sql_file_copy_status === FALSE || filesize($sql_result_file_path) == 0 || !is_readable($sql_result_file_path)) +{ + $sql_file_size = DUPX_U::readableByteSize(filesize('database.sql')); + $msg = "\nWARNING: Unable to properly copy database.sql ({$sql_file_size}) to {$GLOBALS['SQL_FILE_NAME']}. Please check these items:\n"; + $msg .= "- Validate permissions and/or group-owner rights on database.sql and directory [{$root_path}] \n"; + $msg .= "- see: {$faq_url}{$utm_prefix}inst_step2_copydbsql#faq-trouble-055-q \n"; + DUPX_Log::info($msg); +} + +//================================= +//START DB RUN +@mysqli_query($dbh, "SET wait_timeout = {$GLOBALS['DB_MAX_TIME']}"); +@mysqli_query($dbh, "SET max_allowed_packet = {$GLOBALS['DB_MAX_PACKETS']}"); +DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']); + +//Will set mode to null only for this db handle session +//sql_mode can cause db create issues on some systems +$qry_session_custom = true; +switch ($_POST['dbmysqlmode']) { + case 'DISABLE': + @mysqli_query($dbh, "SET SESSION sql_mode = ''"); + break; + case 'CUSTOM': + $dbmysqlmode_opts = $_POST['dbmysqlmode_opts']; + $qry_session_custom = @mysqli_query($dbh, "SET SESSION sql_mode = '{$dbmysqlmode_opts}'"); + if ($qry_session_custom == false) { + $sql_error = mysqli_error($dbh); + $log = "WARNING: Trying to set a custom sql_mode setting issue has been detected:\n{$sql_error}.\n"; + $log .= "For more details visit: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html\n"; + } + break; +} + +//Set defaults in-case the variable could not be read +$dbvar_maxtime = DUPX_DB::getVariable($dbh, 'wait_timeout'); +$dbvar_maxpacks = DUPX_DB::getVariable($dbh, 'max_allowed_packet'); +$dbvar_sqlmode = DUPX_DB::getVariable($dbh, 'sql_mode'); +$dbvar_maxtime = is_null($dbvar_maxtime) ? 300 : $dbvar_maxtime; +$dbvar_maxpacks = is_null($dbvar_maxpacks) ? 1048576 : $dbvar_maxpacks; +$dbvar_sqlmode = empty($dbvar_sqlmode) ? 'NOT_SET' : $dbvar_sqlmode; +$dbvar_version = DUPX_DB::getVersion($dbh); +$sql_file_size1 = DUPX_U::readableByteSize(@filesize("database.sql")); +$sql_file_size2 = DUPX_U::readableByteSize(@filesize("{$GLOBALS['SQL_FILE_NAME']}")); +$db_collatefb = isset($_POST['dbcollatefb']) ? 'On' : 'Off'; + + +DUPX_Log::info("--------------------------------------"); +DUPX_Log::info("DATABASE ENVIRONMENT"); +DUPX_Log::info("--------------------------------------"); +DUPX_Log::info("MYSQL VERSION:\tThis Server: {$dbvar_version} -- Build Server: {$GLOBALS['FW_VERSION_DB']}"); +DUPX_Log::info("FILE SIZE:\tdatabase.sql ({$sql_file_size1}) - installer-data.sql ({$sql_file_size2})"); +DUPX_Log::info("TIMEOUT:\t{$dbvar_maxtime}"); +DUPX_Log::info("MAXPACK:\t{$dbvar_maxpacks}"); +DUPX_Log::info("SQLMODE:\t{$dbvar_sqlmode}"); +DUPX_Log::info("NEW SQL FILE:\t[{$sql_result_file_path}]"); +DUPX_Log::info("COLLATE RESET:\t{$db_collatefb}\n{$db_collatefb_log}"); + +if ($qry_session_custom == false) { + DUPX_Log::info("\n{$log}\n"); +} + +//CREATE DB +switch ($_POST['dbaction']) { + case "create": + mysqli_query($dbh, "CREATE DATABASE IF NOT EXISTS `{$_POST['dbname']}`"); + mysqli_select_db($dbh, $_POST['dbname']) + or DUPX_Log::error(sprintf(ERR_DBCONNECT_CREATE, $_POST['dbname'])); + break; + case "empty": + //DROP DB TABLES + $drop_log = "Database already empty. Ready for install."; + $sql = "SHOW FULL TABLES WHERE Table_Type != 'VIEW'"; + $found_tables = null; + if ($result = mysqli_query($dbh, $sql)) { + while ($row = mysqli_fetch_row($result)) { + $found_tables[] = $row[0]; + } + if (count($found_tables) > 0) { + foreach ($found_tables as $table_name) { + $sql = "DROP TABLE `{$_POST['dbname']}`.`{$table_name}`"; + if (!$result = mysqli_query($dbh, $sql)) { + DUPX_Log::error(sprintf(ERR_DBTRYCLEAN, $_POST['dbname'])); + } + } + } + $drop_log = count($found_tables); + } + break; +} + + +//WRITE DATA +DUPX_Log::info("--------------------------------------"); +DUPX_Log::info("DATABASE RESULTS"); +DUPX_Log::info("--------------------------------------"); +$profile_start = DUPX_U::getMicrotime(); +$fcgi_buffer_pool = 5000; +$fcgi_buffer_count = 0; +$dbquery_rows = 0; +$dbtable_rows = 1; +$dbquery_errs = 0; +$counter = 0; +@mysqli_autocommit($dbh, false); + +while ($counter < $sql_result_file_length) { + + $query_strlen = strlen(trim($sql_result_file_data[$counter])); + + if ($dbvar_maxpacks < $query_strlen) { + + DUPX_Log::info("**ERROR** Query size limit [length={$query_strlen}] [sql=" . substr($sql_result_file_data[$counter], 0, 75) . "...]"); + $dbquery_errs++; + + } elseif ($query_strlen > 0) { + + @mysqli_free_result(@mysqli_query($dbh, ($sql_result_file_data[$counter]))); + $err = mysqli_error($dbh); + + //Check to make sure the connection is alive + if (!empty($err)) { + + if (!mysqli_ping($dbh)) { + mysqli_close($dbh); + $dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], $_POST['dbname'], $_POST['dbport'] ); + // Reset session setup + @mysqli_query($dbh, "SET wait_timeout = {$GLOBALS['DB_MAX_TIME']}"); + DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']); + } + DUPX_Log::info("**ERROR** database error write '{$err}' - [sql=" . substr($sql_result_file_data[$counter], 0, 75) . "...]"); + $dbquery_errs++; + + //Buffer data to browser to keep connection open + } else { + if ($GLOBALS['DB_FCGI_FLUSH'] && $fcgi_buffer_count++ > $fcgi_buffer_pool) { + $fcgi_buffer_count = 0; + DUPX_U::fcgiFlush(); + } + $dbquery_rows++; + } + } + $counter++; +} +@mysqli_commit($dbh); +@mysqli_autocommit($dbh, true); + +DUPX_Log::info("ERRORS FOUND:\t{$dbquery_errs}"); +DUPX_Log::info("TABLES DROPPED:\t{$drop_log}"); +DUPX_Log::info("QUERIES RAN:\t{$dbquery_rows}\n"); + +$dbtable_count = 0; +if ($result = mysqli_query($dbh, "SHOW TABLES")) { + while ($row = mysqli_fetch_array($result, MYSQLI_NUM)) { + $table_rows = DUPX_DB::countTableRows($dbh, $row[0]); + $dbtable_rows += $table_rows; + DUPX_Log::info("{$row[0]}: ({$table_rows})"); + $dbtable_count++; + } + @mysqli_free_result($result); +} + +if ($dbtable_count == 0) { + DUPX_Log::error("No tables where created during step 2 of the install. Please review the installer-log.txt file for + ERROR messages. You may have to manually run the installer-data.sql with a tool like phpmyadmin to validate the data input. If you have enabled compatibility mode + during the package creation process then the database server version your using may not be compatible with this script.\n"); +} + + +//DATA CLEANUP: Perform Transient Cache Cleanup +//Remove all duplicator entries and record this one since this is a new install. +$dbdelete_count = 0; +@mysqli_query($dbh, "DELETE FROM `{$GLOBALS['FW_TABLEPREFIX']}duplicator_packages`"); +$dbdelete_count1 = @mysqli_affected_rows($dbh) or 0; +@mysqli_query($dbh, "DELETE FROM `{$GLOBALS['FW_TABLEPREFIX']}options` WHERE `option_name` LIKE ('_transient%') OR `option_name` LIKE ('_site_transient%')"); +$dbdelete_count2 = @mysqli_affected_rows($dbh) or 0; +$dbdelete_count = (abs($dbdelete_count1) + abs($dbdelete_count2)); +DUPX_Log::info("\nRemoved '{$dbdelete_count}' cache/transient rows"); +//Reset Duplicator Options +foreach ($GLOBALS['FW_OPTS_DELETE'] as $value) { + mysqli_query($dbh, "DELETE FROM `{$GLOBALS['FW_TABLEPREFIX']}options` WHERE `option_name` = '{$value}'"); +} + +@mysqli_close($dbh); + +//FINAL RESULTS +$profile_end = DUPX_U::getMicrotime(); +$ajax2_end = DUPX_U::getMicrotime(); +$ajax1_sum = DUPX_U::elapsedTime($ajax2_end, $ajax2_start); +DUPX_Log::info("\nCREATE/INSTALL RUNTIME: " . DUPX_U::elapsedTime($profile_end, $profile_start)); +DUPX_Log::info('STEP-2 COMPLETE @ ' . @date('h:i:s') . " - RUNTIME: {$ajax1_sum}"); + +$JSON['pass'] = 1; +$JSON['table_count'] = $dbtable_count; +$JSON['table_rows'] = $dbtable_rows; +$JSON['query_errs'] = $dbquery_errs; +echo json_encode($JSON); +error_reporting($ajax1_error_level); +die(''); ?> \ No newline at end of file diff --git a/installer/build/ctrls/ctrl.step3.php b/installer/build/ctrls/ctrl.step3.php index d2dac34f..90eb18df 100644 --- a/installer/build/ctrls/ctrl.step3.php +++ b/installer/build/ctrls/ctrl.step3.php @@ -15,14 +15,11 @@ $ajax2_start = DUPX_U::getMicrotime(); -//MYSQL CONNECTION -$dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], html_entity_decode($_POST['dbpass']), $_POST['dbname'], $_POST['dbport']); -$charset_server = @mysqli_character_set_name($dbh); -@mysqli_query($dbh, "SET wait_timeout = {$GLOBALS['DB_MAX_TIME']}"); -DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']); - //POST PARAMS -$_POST['blogname'] = mysqli_real_escape_string($dbh, $_POST['blogname']); +$_POST['dbhost'] = isset($_POST['dbhost']) ? DUPX_U::sanitize(trim($_POST['dbhost'])) : null; +$_POST['dbname'] = isset($_POST['dbname']) ? DUPX_U::sanitize(trim($_POST['dbname'])) : null; +$_POST['dbuser'] = isset($_POST['dbuser']) ? DUPX_U::sanitize($_POST['dbuser']) : null; +$_POST['blogname'] = isset($_POST['blogname']) ? DUPX_U::sanitize(trim($_POST['blogname'])): ''; $_POST['postguid'] = isset($_POST['postguid']) && $_POST['postguid'] == 1 ? 1 : 0; $_POST['fullsearch'] = isset($_POST['fullsearch']) && $_POST['fullsearch'] == 1 ? 1 : 0; $_POST['path_old'] = isset($_POST['path_old']) ? trim($_POST['path_old']) : null; @@ -33,6 +30,14 @@ $_POST['url_new'] = isset($_POST['url_new']) ? rtrim(trim($_POST['url_new']), '/') : null; $_POST['retain_config'] = (isset($_POST['retain_config']) && $_POST['retain_config'] == '1') ? true : false; $_POST['exe_safe_mode'] = isset($_POST['exe_safe_mode']) ? $_POST['exe_safe_mode'] : 0; + +//MYSQL CONNECTION +$dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], html_entity_decode($_POST['dbpass']), $_POST['dbname'], $_POST['dbport']); +$charset_server = @mysqli_character_set_name($dbh); +@mysqli_query($dbh, "SET wait_timeout = {$GLOBALS['DB_MAX_TIME']}"); +DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']); + + //LOGGING $POST_LOG = $_POST; unset($POST_LOG['tables']); diff --git a/installer/build/view.step4.php b/installer/build/view.step4.php index 0eb3175a..1a45fffd 100644 --- a/installer/build/view.step4.php +++ b/installer/build/view.step4.php @@ -67,12 +67,17 @@

    - Additional Notes: + Final Steps:
    • Review the front-end or re-run installer at ">step 1
    • +
    • Finalize installation by logging into the WordPress Admin Login and removing installation files
    • +
    + + Additional Notes: +
    • The .htaccess file was reset. Resave plugins that write to this file.
    • Visit the troubleshoot section or diff --git a/views/settings/about-info.php b/views/settings/about-info.php index 87f7433d..e9852709 100644 --- a/views/settings/about-info.php +++ b/views/settings/about-info.php @@ -141,7 +141,7 @@
    - + @@ -161,14 +161,6 @@


    - - - -



    From bcad10bc2f11e9db1156beef4440cf50602bd3e6 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Wed, 18 Jul 2018 23:14:35 +0000 Subject: [PATCH 383/585] - Fix for mysqldump with open_basedir enabled git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1911257 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- classes/class.db.php | 56 +++--- views/settings/packages.php | 366 ++++++++++++++++++------------------ 2 files changed, 207 insertions(+), 215 deletions(-) diff --git a/classes/class.db.php b/classes/class.db.php index b3b68da9..7e162b31 100644 --- a/classes/class.db.php +++ b/classes/class.db.php @@ -78,36 +78,38 @@ public static function getVersion($full = false) * * @return boolean|string */ - public static function getWindowsMySqlDumpRealPath() { - if(function_exists('php_ini_loaded_file')) - { - $get_php_ini_path = php_ini_loaded_file(); - if(file_exists($get_php_ini_path)) - { - $search = array( - dirname(dirname($get_php_ini_path)).'/mysql/bin/mysqldump.exe', - dirname(dirname(dirname($get_php_ini_path))).'/mysql/bin/mysqldump.exe', - dirname(dirname($get_php_ini_path)).'/mysql/bin/mysqldump', - dirname(dirname(dirname($get_php_ini_path))).'/mysql/bin/mysqldump', - ); - - foreach($search as $mysqldump) - { - if(file_exists($mysqldump)) - { - return str_replace("\\","/",$mysqldump); + public static function getWindowsMySqlDumpRealPath() + { + try { + if (function_exists('php_ini_loaded_file')) { + $get_php_ini_path = php_ini_loaded_file(); + if (@file_exists($get_php_ini_path)) { + $search = array( + dirname(dirname($get_php_ini_path)).'/mysql/bin/mysqldump.exe', + dirname(dirname(dirname($get_php_ini_path))).'/mysql/bin/mysqldump.exe', + dirname(dirname($get_php_ini_path)).'/mysql/bin/mysqldump', + dirname(dirname(dirname($get_php_ini_path))).'/mysql/bin/mysqldump', + ); + + foreach ($search as $mysqldump) { + if (@file_exists($mysqldump)) { + return str_replace("\\", "/", $mysqldump); + } } } } - } - unset($search); - unset($get_php_ini_path); + unset($search); + unset($get_php_ini_path); - return false; + return false; + + } catch(Exception $ex) { + return false; + } } - /** + /** * Returns the mysqldump path if the server is enabled to execute it otherwise false * * @return boolean|string @@ -126,14 +128,13 @@ public static function getMySqlDumpPath() if (DUP_Util::isWindows()) { $paths = array( $custom_mysqldump_path, - self::getWindowsMySqlDumpRealPath(), + self::getWindowsMySqlDumpRealPath(), 'C:/xampp/mysql/bin/mysqldump.exe', 'C:/Program Files/xampp/mysql/bin/mysqldump', 'C:/Program Files/MySQL/MySQL Server 6.0/bin/mysqldump', 'C:/Program Files/MySQL/MySQL Server 5.5/bin/mysqldump', 'C:/Program Files/MySQL/MySQL Server 5.4/bin/mysqldump', - 'C:/Program Files/MySQL/MySQL Server 5.1/bin/mysqldump', - 'C:/Program Files/MySQL/MySQL Server 5.0/bin/mysqldump', + 'C:/wamp64/bin/mysql/mysql5.7.21/bin', ); //COMMON LINUX PATHS @@ -160,7 +161,6 @@ public static function getMySqlDumpPath() '/usr/bin/mysqldump', '/opt/local/lib/mysql6/bin/mysqldump', '/opt/local/lib/mysql5/bin/mysqldump', - '/opt/local/lib/mysql4/bin/mysqldump', ); } @@ -168,7 +168,7 @@ public static function getMySqlDumpPath() //So we fallback and try to use exec as a last resort $exec_available = function_exists('exec'); foreach ($paths as $path) { - if(file_exists($path)) { + if(@file_exists($path)) { if (DUP_Util::isExecutable($path)) { return $path; } diff --git a/views/settings/packages.php b/views/settings/packages.php index 1e219314..1a02a707 100644 --- a/views/settings/packages.php +++ b/views/settings/packages.php @@ -2,8 +2,9 @@ global $wp_version; global $wpdb; -$action_updated = null; -$action_response = __("Package Settings Saved", 'duplicator'); +$action_updated = null; +$action_response = __("Package Settings Saved", 'duplicator'); +$mysqldump_exe_file = ''; //SAVE RESULTS if (isset($_POST['action']) && $_POST['action'] == 'save') { @@ -12,37 +13,33 @@ if (! isset( $_POST['dup_settings_save_nonce_field'] ) || ! wp_verify_nonce( $_POST['dup_settings_save_nonce_field'], 'dup_settings_save' )) { die('Invalid token permissions to perform this request.'); } - //Package - $mysqldump_enabled = isset($_POST['package_dbmode']) && $_POST['package_dbmode'] == 'mysql' ? "1" : "0"; - $mysqldump_exe_file = isset($_POST['package_mysqldump_path']) - ? trim(DUP_DB::escSQL(strip_tags($_POST['package_mysqldump_path']), true)) - : null; - $mysqldump_path_valid = is_file($mysqldump_exe_file) ? true : false; - + $mysqldump_enabled = isset($_POST['package_dbmode']) && $_POST['package_dbmode'] == 'mysql' ? "1" : "0"; + if (isset($_POST['package_mysqldump_path'])) { + $mysqldump_exe_file = DUP_Util::safePath(stripslashes(trim($_POST['package_mysqldump_path']))); + $mysqldump_exe_file = DUP_DB::escSQL(strip_tags($mysqldump_exe_file), true); + } + DUP_Settings::Set('last_updated', date('Y-m-d-H-i-s')); DUP_Settings::Set('package_zip_flush', isset($_POST['package_zip_flush']) ? "1" : "0"); DUP_Settings::Set('package_mysqldump', $mysqldump_enabled ? "1" : "0"); DUP_Settings::Set('package_phpdump_qrylimit', isset($_POST['package_phpdump_qrylimit']) ? $_POST['package_phpdump_qrylimit'] : "100"); - if ($mysqldump_path_valid) { - $mysqldump_exe_file = DUP_Util::isWindows() ? realpath($mysqldump_exe_file) : $mysqldump_exe_file; - DUP_Settings::Set('package_mysqldump_path', $mysqldump_exe_file); - } + DUP_Settings::Set('package_mysqldump_path', $mysqldump_exe_file); DUP_Settings::Set('package_ui_created', $_POST['package_ui_created']); $action_updated = DUP_Settings::Save(); DUP_Util::initSnapshotDirectory(); } -$package_zip_flush = DUP_Settings::Get('package_zip_flush'); -$phpdump_chunkopts = array("20", "100", "500", "1000", "2000"); -$phpdump_qrylimit = DUP_Settings::Get('package_phpdump_qrylimit'); -$package_mysqldump = DUP_Settings::Get('package_mysqldump'); +//GET RESULTS +$phpdump_chunkopts = array("20", "100", "500", "1000", "2000"); +$package_zip_flush = DUP_Settings::Get('package_zip_flush'); +$phpdump_qrylimit = DUP_Settings::Get('package_phpdump_qrylimit'); +$package_mysqldump = DUP_Settings::Get('package_mysqldump'); $package_mysqldump_path = trim(DUP_Settings::Get('package_mysqldump_path')); -$package_ui_created = is_numeric(DUP_Settings::Get('package_ui_created')) ? DUP_Settings::Get('package_ui_created') : 1; -$mysqlDumpPath = DUP_DB::getMySqlDumpPath(); -$mysqlDumpFound = ($mysqlDumpPath) ? true : false; - +$package_ui_created = is_numeric(DUP_Settings::Get('package_ui_created')) ? DUP_Settings::Get('package_ui_created') : 1; +$mysqlDumpPath = DUP_DB::getMySqlDumpPath(); +$mysqlDumpFound = ($mysqlDumpPath) ? true : false; ?>
    - - - - - -

    - - -

    -
    - - - - - -
    - -

    -
    - -

    -
    - -

    -
    - - - - + + + + + +
    - - - -

    - -
    - - " - data-tooltip=""> - - %s %s", - __("Please visit our recommended", 'duplicator'), - __("host list", 'duplicator'), - __("for reliable access to mysqldump", 'duplicator')); - ?> - - -

    -

    - - /> - - ()
    - -
    - -
    - -   - -

    - -
    - - %s %s", - __("See the", 'duplicator'), - __("host list", 'duplicator'), - __("for reliable access to mysqldump.", 'duplicator')); - - ?> -

    - - - - " - data-tooltip=""> -
    - " /> -
    - The custom path provided is not recognized as a valid mysqldump file:
    ', 'duplicator'); - $mysqldump_path = esc_html($mysqldump_path); - echo "'{$mysqldump_path}'"; - } - } - ?> -
    -

    -
    - - - - - - - - /> - - -   + + + + + +

    + + +

    +
    + + + + + +
    + +

    +
    + +

    +
    + +

    +
    + + + + - - - - - -
    + + + +

    + +
    + + " + data-tooltip=""> + + %s %s", + __("Please visit our recommended", 'duplicator'), + __("host list", 'duplicator'), + __("for reliable access to mysqldump", 'duplicator')); + ?> + + +

    +

    + + /> +
    + +
    + +   + +

    + +
    + + %s %s", + __("See the", 'duplicator'), + __("host list", 'duplicator'), + __("for reliable access to mysqldump.", 'duplicator')); + ?> +

    + + + " - data-tooltip=""> -   - -

    -
    - /> - - () -

    - -

    -
    - - -

    -
    - " style="display: inline-block;" /> -

    + data-tooltip-title="" + data-tooltip=""> +
    + " /> +
    + The custom path provided is not recognized as a valid mysqldump file:
    ', 'duplicator'); + $mysqldump_path = esc_html($package_mysqldump_path); + echo "'{$mysqldump_path}'"; + } + ?> +
    +

    + + + + + + + + + /> + + +   + +
    + " + data-tooltip=""> +   + +

    +
    + /> + + () +

    + +

    +
    + + +

    +
    + " style="display: inline-block;" /> +

    From 4aa3636aea9e286ff9e40e427823989d45d00399 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Fri, 20 Jul 2018 20:07:38 +0000 Subject: [PATCH 384/585] - Fixes for input sanitization git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1912505 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- installer/build/classes/class.logging.php | 130 +++++++++++----------- installer/build/ctrls/ctrl.step2.php | 20 ++++ installer/build/ctrls/ctrl.step3.php | 3 + installer/build/main.installer.php | 15 +-- 4 files changed, 96 insertions(+), 72 deletions(-) diff --git a/installer/build/classes/class.logging.php b/installer/build/classes/class.logging.php index 17124752..2e3d3557 100644 --- a/installer/build/classes/class.logging.php +++ b/installer/build/classes/class.logging.php @@ -1,66 +1,66 @@ -
  • Empty this root directory except for the package and installer and try again.
  • Delete just the wp-config.php file and try again. This will over-write all other files in the directory.
  • Check the "Manual package extraction" checkbox under advanced options to skip extraction
  • '); -define('ERR_ZIPNOTFOUND', 'The packaged zip file was not found. Be sure the zip package is in the same directory as the installer file and as the correct permissions. If you are trying to reinstall a package you can copy the package from the "' . DUPLICATOR_SSDIR_NAME . '" directory back up to your root which is the same location as your installer.php file.'); -define('ERR_ZIPOPEN', 'Failed to open zip archive file. Please be sure the archive is completely downloaded before running the installer. Try to extract the archive manually to make sure the file is not corrupted.'); -define('ERR_ZIPEXTRACTION', 'Errors extracting zip file. Portions or part of the zip archive did not extract correctly. Try to extract the archive manually with a client side program like unzip/win-zip/winrar or your hosts cPanel to make sure the file is not corrupted. If the file extracts correctly then there is an invalid file or directory that PHP is unable to extract. This can happen if your moving from one operating system to another where certain naming conventions work on one environment and not another.

    Workarounds:
    1. Create a new package and be sure to exclude any directories that have invalid names or files in them. This warning will be displayed on the scan results under "Name Checks".
    2. Manually extract the zip file with a client side program or your hosts cPanel. Then under options in step 1 of this installer check the "Manual Archive Extraction" option and perform the install.'); -define('ERR_ZIPMANUAL', 'When choosing manual package extraction, the contents of the package must already be extracted and the wp-config.php and database.sql files must be present in the same directory as the installer.php for the process to continue. Please manually extract the package into the current directory before continuing in manual extraction mode. Also validate that the wp-config.php and database.sql files are present.'); -define('ERR_MAKELOG', 'PHP is having issues writing to the log file ' . DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']) . '\installer-log.txt . In order for the Duplicator to proceed validate your owner/group and permission settings for PHP on this path. Try temporarily setting you permissions to 777 to see if the issue gets resolved. If you are on a shared hosting environment please contact your hosting company and tell them you are getting errors writing files to the path above when using PHP.'); -define('ERR_ZIPARCHIVE', 'In order to extract the archive.zip file the PHP ZipArchive module must be installed. Please read the FAQ for more details. You can still install this package but you will need to check the Manual package extraction checkbox found in the Advanced Options. Please read the online user guide for details in performing a manual package extraction.'); -define('ERR_MYSQLI_SUPPORT', 'In order to complete an install the mysqli extension for PHP is required. If you are on a hosted server please contact your host and request that mysqli be enabled. For more information visit: http://php.net/manual/en/mysqli.installation.php'); -define('ERR_DBCONNECT', 'DATABASE CONNECTION FAILED!
    '); -define('ERR_DBCONNECT_CREATE', 'DATABASE CREATION FAILURE!
    Unable to create database "%s". Check to make sure the user has "Create" privileges. Some hosts will restrict creation of a database only through the cpanel. Try creating the database manually to proceed with installation. If the database already exists then check the radio button labeled "Connect and Remove All Data" which will remove all existing tables.'); -define('ERR_DBTRYCLEAN', 'DATABASE CREATION FAILURE!
    Unable to remove all tables from database "%s".
    Please remove all tables from this database and try the installation again.'); -define('ERR_DBCREATE', 'The database "%s" does not exists.
    Change mode to create in order to create a new database.'); -define('ERR_DBEMPTY', 'The database "%s" has "%s" tables. The Duplicator only works with an EMPTY database. Enable the action "Connect and Remove All Data" radio button to remove all tables and or create a new database. Some hosting providers do not allow table removal from scripts. In this case you will need to login to your hosting providers control panel and remove the tables manually. Please contact your hosting provider for further details. Always backup all your data before proceeding!'); -define('ERR_TESTDB_UTF8', 'UTF8 Characters were detected as part of the database connection string. If your connection fails be sure to update the MySQL my.ini configuration file setting to support UTF8 characters by enabling this option [character_set_server=utf8] and restarting the database server.'); -define('ERR_TESTDB_VERSION_INFO', 'The current version detected was released prior to MySQL 5.5.3 which had a release date of April 8th 2010. WordPress 4.2 included support for utf8mb4 which is only supported in MySQL server 5.5.3+. It is highly recommended to upgrade your version of MySQL server on this server to be more compatible with recent releases of WordPress and avoid issues with install errors.'); -define('ERR_TESTDB_VERSION_COMPAT', 'In order to avoid database incompatibility issues make sure the database versions between the build and installer servers are as close as possible. If the package was created on a newer database version than where it is being installed then you might run into issues.

    It is best to make sure the server where the installer is running has the same or higher version number than where it was built. If the major and minor version are the same or close for example [5.7 to 5.6], then the migration should work without issues. A version pair of [5.7 to 5.1] is more likely to cause issues unless you have a very simple setup. If the versions are too far apart work with your hosting provider to upgrade the MySQL engine on this server.

    MariaDB: If see a version of 10.N.N then the database distribution is a MariaDB flavor of MySQL. While the distributions are very close there are some subtle differences. Some operating systems will report the version such as "5.5.5-10.1.21-MariaDB" showing the correlation of both. Please visit the online MariaDB versus MySQL - Compatibility page for more details.

    Please note these messages are simply notices. It is highly recommended that you continue with the install process and closely monitor the installer-log.txt file along with the install report found on step 3 of the installer. Be sure to look for any notices/warnings/errors in these locations to validate the install process did not detect any errors. If any issues are found please visit the FAQ pages and see the question What if I get database errors or general warnings on the install report?.'); - - -/** - * Class used to log information to the installer-log.txt file - * - * Standard: PSR-2 - * @link http://www.php-fig.org/psr/psr-2 Full Documentation - * - * @package SC\DUPX\Log - * - */ -class DUPX_Log -{ - - /** - * Used to write debug info to the text log file - * - * @param string $msg Any text data - * @param int $loglevel Log level - * - * @return string Write info to both the log and browser - */ - public static function info($msg, $logging = 1) - { - if ($logging <= $GLOBALS["LOGGING"]) { - @fwrite($GLOBALS["LOG_FILE_HANDLE"], "{$msg}\n"); - } - } - - /** - * Used to write errors to the text log file - * - * @param string $msg Any text data - * @param int $loglevel Log level - * - * @return string Write errors to both the log and browser - */ - public static function error($msg) - { - $breaks = array("
    ","
    ","
    "); - $log_msg = str_ireplace($breaks, "\r\n", $msg); - $log_msg = strip_tags($log_msg); - @fwrite($GLOBALS["LOG_FILE_HANDLE"], "\nINSTALLER ERROR:\n{$log_msg}\n"); - @fclose($GLOBALS["LOG_FILE_HANDLE"]); - die("

    INSTALL ERROR!
    {$msg}
    "); - } -} +
  • Empty this root directory except for the package and installer and try again.
  • Delete just the wp-config.php file and try again. This will over-write all other files in the directory.
  • Check the "Manual package extraction" checkbox under advanced options to skip extraction
  • '); +define('ERR_ZIPNOTFOUND', 'The packaged zip file was not found. Be sure the zip package is in the same directory as the installer file and as the correct permissions. If you are trying to reinstall a package you can copy the package from the "' . DUPLICATOR_SSDIR_NAME . '" directory back up to your root which is the same location as your installer.php file.'); +define('ERR_ZIPOPEN', 'Failed to open zip archive file. Please be sure the archive is completely downloaded before running the installer. Try to extract the archive manually to make sure the file is not corrupted.'); +define('ERR_ZIPEXTRACTION', 'Errors extracting zip file. Portions or part of the zip archive did not extract correctly. Try to extract the archive manually with a client side program like unzip/win-zip/winrar or your hosts cPanel to make sure the file is not corrupted. If the file extracts correctly then there is an invalid file or directory that PHP is unable to extract. This can happen if your moving from one operating system to another where certain naming conventions work on one environment and not another.

    Workarounds:
    1. Create a new package and be sure to exclude any directories that have invalid names or files in them. This warning will be displayed on the scan results under "Name Checks".
    2. Manually extract the zip file with a client side program or your hosts cPanel. Then under options in step 1 of this installer check the "Manual Archive Extraction" option and perform the install.'); +define('ERR_ZIPMANUAL', 'When choosing manual package extraction, the contents of the package must already be extracted and the wp-config.php and database.sql files must be present in the same directory as the installer.php for the process to continue. Please manually extract the package into the current directory before continuing in manual extraction mode. Also validate that the wp-config.php and database.sql files are present.'); +define('ERR_MAKELOG', 'PHP is having issues writing to the log file ' . DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']) . '\installer-log.txt . In order for the Duplicator to proceed validate your owner/group and permission settings for PHP on this path. Try temporarily setting you permissions to 777 to see if the issue gets resolved. If you are on a shared hosting environment please contact your hosting company and tell them you are getting errors writing files to the path above when using PHP.'); +define('ERR_ZIPARCHIVE', 'In order to extract the archive.zip file the PHP ZipArchive module must be installed. Please read the FAQ for more details. You can still install this package but you will need to check the Manual package extraction checkbox found in the Advanced Options. Please read the online user guide for details in performing a manual package extraction.'); +define('ERR_MYSQLI_SUPPORT', 'In order to complete an install the mysqli extension for PHP is required. If you are on a hosted server please contact your host and request that mysqli be enabled. For more information visit: http://php.net/manual/en/mysqli.installation.php'); +define('ERR_DBCONNECT', 'DATABASE CONNECTION FAILED!
    '); +define('ERR_DBCONNECT_CREATE', 'DATABASE CREATION FAILURE!
    Unable to create database "%s". Check to make sure the user has "Create" privileges. Some hosts will restrict creation of a database only through the cpanel. Try creating the database manually to proceed with installation. If the database already exists then check the radio button labeled "Connect and Remove All Data" which will remove all existing tables.'); +define('ERR_DBTRYCLEAN', 'DATABASE CREATION FAILURE!
    Unable to remove all tables from database "%s".
    Please remove all tables from this database and try the installation again.'); +define('ERR_DBCREATE', 'The database "%s" does not exists.
    Change mode to create in order to create a new database.'); +define('ERR_DBEMPTY', 'The database "%s" has "%s" tables. The Duplicator only works with an EMPTY database. Enable the action "Connect and Remove All Data" radio button to remove all tables and or create a new database. Some hosting providers do not allow table removal from scripts. In this case you will need to login to your hosting providers control panel and remove the tables manually. Please contact your hosting provider for further details. Always backup all your data before proceeding!'); +define('ERR_TESTDB_UTF8', 'UTF8 Characters were detected as part of the database connection string. If your connection fails be sure to update the MySQL my.ini configuration file setting to support UTF8 characters by enabling this option [character_set_server=utf8] and restarting the database server.'); +define('ERR_TESTDB_VERSION_INFO', 'The current version detected was released prior to MySQL 5.5.3 which had a release date of April 8th 2010. WordPress 4.2 included support for utf8mb4 which is only supported in MySQL server 5.5.3+. It is highly recommended to upgrade your version of MySQL server on this server to be more compatible with recent releases of WordPress and avoid issues with install errors.'); +define('ERR_TESTDB_VERSION_COMPAT', 'In order to avoid database incompatibility issues make sure the database versions between the build and installer servers are as close as possible. If the package was created on a newer database version than where it is being installed then you might run into issues.

    It is best to make sure the server where the installer is running has the same or higher version number than where it was built. If the major and minor version are the same or close for example [5.7 to 5.6], then the migration should work without issues. A version pair of [5.7 to 5.1] is more likely to cause issues unless you have a very simple setup. If the versions are too far apart work with your hosting provider to upgrade the MySQL engine on this server.

    MariaDB: If see a version of 10.N.N then the database distribution is a MariaDB flavor of MySQL. While the distributions are very close there are some subtle differences. Some operating systems will report the version such as "5.5.5-10.1.21-MariaDB" showing the correlation of both. Please visit the online MariaDB versus MySQL - Compatibility page for more details.

    Please note these messages are simply notices. It is highly recommended that you continue with the install process and closely monitor the installer-log.txt file along with the install report found on step 3 of the installer. Be sure to look for any notices/warnings/errors in these locations to validate the install process did not detect any errors. If any issues are found please visit the FAQ pages and see the question What if I get database errors or general warnings on the install report?.'); +define('ERR_NON_SECURE_PASSWORD', 'The database password provided contains a single quote! For security reasons this character is not valid. You have two options:
    1. Remove the single quote character from your password.
    2. Open the installer.php and set the variable $GLOBALS[DUPX_DBPASS_CHECK] = false'); + +/** + * Class used to log information to the installer-log.txt file + * + * Standard: PSR-2 + * @link http://www.php-fig.org/psr/psr-2 Full Documentation + * + * @package SC\DUPX\Log + * + */ +class DUPX_Log +{ + + /** + * Used to write debug info to the text log file + * + * @param string $msg Any text data + * @param int $loglevel Log level + * + * @return string Write info to both the log and browser + */ + public static function info($msg, $logging = 1) + { + if ($logging <= $GLOBALS["LOGGING"]) { + @fwrite($GLOBALS["LOG_FILE_HANDLE"], "{$msg}\n"); + } + } + + /** + * Used to write errors to the text log file + * + * @param string $msg Any text data + * @param int $loglevel Log level + * + * @return string Write errors to both the log and browser + */ + public static function error($msg) + { + $breaks = array("
    ","
    ","
    "); + $log_msg = str_ireplace($breaks, "\r\n", $msg); + $log_msg = strip_tags($log_msg); + @fwrite($GLOBALS["LOG_FILE_HANDLE"], "\nINSTALLER ERROR:\n{$log_msg}\n"); + @fclose($GLOBALS["LOG_FILE_HANDLE"]); + die("

    INSTALL ERROR!
    {$msg}
    "); + } +} ?> \ No newline at end of file diff --git a/installer/build/ctrls/ctrl.step2.php b/installer/build/ctrls/ctrl.step2.php index caafd6c0..07d82e8c 100644 --- a/installer/build/ctrls/ctrl.step2.php +++ b/installer/build/ctrls/ctrl.step2.php @@ -4,6 +4,7 @@ $_POST['dbhost'] = isset($_POST['dbhost']) ? DUPX_U::sanitize(trim($_POST['dbhost'])) : null; $_POST['dbname'] = isset($_POST['dbname']) ? DUPX_U::sanitize(trim($_POST['dbname'])) : null; $_POST['dbuser'] = isset($_POST['dbuser']) ? DUPX_U::sanitize($_POST['dbuser']) : null; +$_POST['dbpass'] = isset($_POST['dbpass']) ? $_POST['dbpass'] : null; $_POST['dbcharset'] = isset($_POST['dbcharset']) ? DUPX_U::sanitize(trim($_POST['dbcharset'])) : $GLOBALS['DBCHARSET_DEFAULT']; $_POST['dbcollate'] = isset($_POST['dbcollate']) ? DUPX_U::sanitize(trim($_POST['dbcollate'])) : $GLOBALS['DBCOLLATE_DEFAULT']; $_POST['dbnbsp'] = (isset($_POST['dbnbsp']) && $_POST['dbnbsp'] == '1') ? true : false; @@ -132,9 +133,26 @@ //=============================== //ERROR MESSAGES //=============================== + //ERR_MAKELOG ($GLOBALS['LOG_FILE_HANDLE'] != false) or DUPX_Log::error(ERR_MAKELOG); +//ERR_NON_SECURE_PASSWORD +if ($GLOBALS['DUPX_DBPASS_CHECK']) { + $dbpass_test_chars = array("'"); + $dbpass_char_found = false; + $dbpass_sent = urldecode($_POST['dbpass']); + foreach ($dbpass_test_chars as $value) { + if (strpos($dbpass_sent, $value)) { + $dbpass_char_found = true; + break; + } + } + if ($dbpass_char_found) { + DUPX_Log::error(ERR_NON_SECURE_PASSWORD); + } +} + //ERR_MYSQLI_SUPPORT function_exists('mysqli_connect') or DUPX_Log::error(ERR_MYSQLI_SUPPORT); @@ -153,6 +171,8 @@ function_exists('mysqli_connect') or DUPX_Log::error(ERR_MYSQLI_SUPPORT); } } + + $log = << Date: Sat, 4 Aug 2018 22:12:57 +0000 Subject: [PATCH 385/585] - new parsley lib - new installer password option git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1919900 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- assets/css/parsley.css | 37 + assets/css/style.css | 157 +-- assets/js/parsley.min.js | 11 + classes/class.crypt.php | 57 ++ classes/package/class.pack.installer.php | 20 +- classes/package/class.pack.php | 10 +- classes/utilities/class.u.php | 34 +- define.php | 2 +- duplicator.php | 12 +- installer/build/assets/inc.css.php | 472 ++++----- installer/build/classes/class.http.php | 205 ++++ installer/build/main.installer.php | 37 +- installer/build/view.help.php | 1098 +++++++++++--------- installer/build/view.init1.php | 103 ++ installer/build/view.step1.php | 2 + installer/build/view.step2.php | 850 ++++++++-------- installer/build/view.step3.php | 678 ++++++------- views/packages/details/detail.php | 52 +- views/packages/main/packages.php | 4 +- views/packages/main/s1.setup2.php | 1172 ++++++++++++---------- 20 files changed, 2863 insertions(+), 2150 deletions(-) create mode 100644 assets/css/parsley.css create mode 100644 assets/js/parsley.min.js create mode 100644 classes/class.crypt.php create mode 100644 installer/build/classes/class.http.php create mode 100644 installer/build/view.init1.php diff --git a/assets/css/parsley.css b/assets/css/parsley.css new file mode 100644 index 00000000..e30094ca --- /dev/null +++ b/assets/css/parsley.css @@ -0,0 +1,37 @@ +div.parsley-success, +input.parsley-success, +select.parsley-success, +textarea.parsley-success { + color: #468847; + background-color: #DFF0D8; + border: 1px solid #D6E9C6; +} + +div.parsley-error, +input.parsley-error, +select.parsley-error, +textarea.parsley-error { + color: #B94A48; + background-color: #F2DEDE; + border: 1px solid #EED3D7; +} + +.parsley-errors-list { + margin: 2px 0 3px; + padding: 0; + list-style-type: none; + font-size: 0.9em; + line-height: 0.9em; + opacity: 0; + -moz-opacity: 0; + -webkit-opacity: 0; + + transition: all .3s ease-in; + -o-transition: all .3s ease-in; + -moz-transition: all .3s ease-in; + -webkit-transition: all .3s ease-in; +} + +.parsley-errors-list.filled { + opacity: 1; +} diff --git a/assets/css/style.css b/assets/css/style.css index 30dbb1af..e192af8f 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -1,78 +1,79 @@ -/* ================================================ - * DUPLICATOR STYLE - * Common elements shared across the duplicator plugin - * ================================================ */ - -/*Global Elements*/ -input[type=button]{cursor:pointer;padding:5px;cursor:pointer;} -input[type=submit]{cursor:pointer;padding:5px;cursor:pointer;} -fieldset {border:1px solid gray; padding:0px 5px 5px 5px; } -label {font-size:13px} -.no-select {user-select:none; -o-user-select:none; -moz-user-select:none; -khtml-user-select:none; -webkit-user-select:none;} -hr {border:0; border-top:1px solid #ddd; border-bottom:1px solid #fafafa; margin:10px 0px 2px 0px;} -i[data-tooltip].fa-question-circle {cursor:pointer; color:#C3C3C3} -i[data-tooltip].fa-lightbulb-o {cursor:pointer; color:gray} -span.btn-separator {content: ''; display: inline-block; background: silver; margin: 2px 3px; height: 25px; width: 1px; vertical-align: top;} -a.grey-icon i.fa {color:#777} -i.grey-icon {color:#777} - - -/*TABS*/ -ul.category-tabs li {cursor: pointer} - -/*BOXES: Expandable sections */ -div.dup-box {padding:0px; display: block; background-color: #fff; border: 1px solid #e5e5e5; box-shadow: 0 1px 1px rgba(0,0,0,.04);} -div.dup-box-title {font-size: 16px; padding: 10px 0 0 10px; font-weight: bold; cursor: pointer; height:27px; margin:0px; color:#000 } -div.dup-box-title:hover {background-color: #FCFCFC;} -div.dup-box-arrow {text-decoration:none!important; float:right; width:27px; height:30px; font-size:16px; cursor:pointer; padding:1px 0 0 0; white-space: nowrap} -div.dup-box-panel {padding:10px 15px 10px 15px; border-top:1px solid #EEEEEE; margin:-1px 0 0 0;} -div.dup-redirect {font-size:16px; font-weight: bold; padding: 10px} - -/*PANELS: Boxes that do not exapand */ -div.dup-panel {padding:0px; display: block; background-color: #fff; border: 1px solid #e5e5e5; box-shadow: 0 1px 1px rgba(0,0,0,.04);} -div.dup-panel-title {font-size: 14px; padding: 10px 0 0 15px; font-weight: 600; height:28px; margin:0px; color:#000; } -div.dup-panel-panel {padding:10px 15px 10px 15px; border-top:1px solid #EEEEEE; margin:-1px 0 0 0;} - -/*INFO-BOX:Simple box with no title */ -div.dup-info-box {padding:8px; border:1px solid #ccc; border-radius:4px; background-color:#F7FCFE; margin:0px 0px 5px 20px; line-height:16px} -div.dup-info-box small {margin-top:10px; display:block} - -/*PACKAGE:Progress Boxes */ -div#dup-progress-bar-area {width:500px; margin:40px auto 0px auto; padding:25px 50px 35px 50px; border:1px solid #ccc; box-shadow:0 8px 6px -6px #999; text-align:center; border-radius:4px; color:#000;} -div#dup-progress-bar-area h2 {margin-bottom:15px} - -/*HEADER MESSAGES*/ -div.dup-hdr-success {color:green; font-size:22px; font-weight:bold} -div.dup-hdr-error {color:#A62426; font-size:22px; font-weight:bold} - -/*DIALOGS: THICKBOX */ -#TB_title { padding-bottom: 3px!important; margin-bottom:5px!important; font-size:16px!important;} -div.dup-dlg-alert-txt {padding:10px 0; font-size:16px} -div.dup-dlg-alert-btns {position:absolute; bottom:20px; right:20px;} -div.dup-dlg-confirm-txt {padding:10px 0; font-size:16px} -div.dup-dlg-confirm-btns {position:absolute; bottom:20px; right:20px;} -div.dup-dlg-confirm-progress {display:none} - -/*ADMIN: NOTICES */ -div#dup-global-error-reserved-files p {font-size:14px} -div#dup-global-error-reserved-files b.pass-msg {color:green; font-size:20px} -div#dup-global-error-reserved-files p.pass-lnks {line-height:24px; margin:-7px 0 0 5px} -div#dup-global-error-reserved-files div.pass-msg {padding:5px 0 0 10px; font-size:11px; color:#999; font-style: italic} -div.dup-wpnotice-box {display:none;} - -/*================================================ -PARSLEY:Overrides*/ -input.parsley-error, textarea.parsley-error { - color:#B94A48 !important; - background-color:#F2DEDE !important; - border:1px solid #EED3D7 !important; -} -div.qtip-content {line-height:16px} -ul.parsley-error-list {margin:1px 0px -7px 0px} -div.notice-safemode {color: maroon;} -div.cleanup-notice b.title {color: green;font-size: 20px;} - -/*SCREEN TABS*/ -div.dup-screen-hlp-info {line-height:26px; padding:10px 0 10px 0} -#screen-meta-links .button { font-size:13px !important; height:auto !important;font-weight: normal; padding: 3px 6px 3px 16px !important;min-width:72px !important} - +/* ================================================ + * DUPLICATOR STYLE + * Common elements shared across the duplicator plugin + * ================================================ */ + +/*Global Elements*/ +input[type=button]{cursor:pointer;padding:5px;cursor:pointer;} +input[type=submit]{cursor:pointer;padding:5px;cursor:pointer;} +fieldset {border:1px solid gray; padding:0px 5px 5px 5px; } +label {font-size:13px} +.no-select {user-select:none; -o-user-select:none; -moz-user-select:none; -khtml-user-select:none; -webkit-user-select:none;} +hr {border:0; border-top:1px solid #ddd; border-bottom:1px solid #fafafa; margin:10px 0px 2px 0px;} +i[data-tooltip].fa-question-circle {cursor:pointer; color:#C3C3C3} +i[data-tooltip].fa-lightbulb-o {cursor:pointer; color:gray} +span.btn-separator {content: ''; display: inline-block; background: silver; margin: 2px 3px; height: 25px; width: 1px; vertical-align: top;} +a.grey-icon i.fa {color:#777} +i.grey-icon {color:#777} + + +/*TABS*/ +ul.category-tabs li {cursor: pointer} + +/*BOXES: Expandable sections */ +div.dup-box {padding:0px; display: block; background-color: #fff; border: 1px solid #e5e5e5; box-shadow: 0 1px 1px rgba(0,0,0,.04);} +div.dup-box-title {font-size: 16px; padding: 10px 0 0 10px; font-weight: bold; cursor: pointer; height:27px; margin:0px; color:#000 } +div.dup-box-title:hover {background-color: #FCFCFC;} +div.dup-box-arrow {text-decoration:none!important; float:right; width:27px; height:30px; font-size:16px; cursor:pointer; padding:1px 0 0 0; white-space: nowrap} +div.dup-box-panel {padding:10px 15px 10px 15px; border-top:1px solid #EEEEEE; margin:-1px 0 0 0;} +div.dup-redirect {font-size:16px; font-weight: bold; padding: 10px} + +/*PANELS: Boxes that do not exapand */ +div.dup-panel {padding:0px; display: block; background-color: #fff; border: 1px solid #e5e5e5; box-shadow: 0 1px 1px rgba(0,0,0,.04);} +div.dup-panel-title {font-size: 14px; padding: 10px 0 0 15px; font-weight: 600; height:28px; margin:0px; color:#000; } +div.dup-panel-panel {padding:10px 15px 10px 15px; border-top:1px solid #EEEEEE; margin:-1px 0 0 0;} + +/*INFO-BOX:Simple box with no title */ +div.dup-info-box {padding:8px; border:1px solid #ccc; border-radius:4px; background-color:#F7FCFE; margin:0px 0px 5px 20px; line-height:16px} +div.dup-info-box small {margin-top:10px; display:block} + +/*PACKAGE:Progress Boxes */ +div#dup-progress-bar-area {width:500px; margin:40px auto 0px auto; padding:25px 50px 35px 50px; border:1px solid #ccc; box-shadow:0 8px 6px -6px #999; text-align:center; border-radius:4px; color:#000;} +div#dup-progress-bar-area h2 {margin-bottom:15px} + +/*HEADER MESSAGES*/ +div.dup-hdr-success {color:green; font-size:22px; font-weight:bold} +div.dup-hdr-error {color:#A62426; font-size:22px; font-weight:bold} + +/*DIALOGS: THICKBOX */ +#TB_title { padding-bottom: 3px!important; margin-bottom:5px!important; font-size:16px!important;} +div.dup-dlg-alert-txt {padding:10px 0; font-size:16px} +div.dup-dlg-alert-btns {position:absolute; bottom:20px; right:20px;} +div.dup-dlg-confirm-txt {padding:10px 0; font-size:16px} +div.dup-dlg-confirm-btns {position:absolute; bottom:20px; right:20px;} +div.dup-dlg-confirm-progress {display:none} + +/*ADMIN: NOTICES */ +div#dup-global-error-reserved-files p {font-size:14px} +div#dup-global-error-reserved-files b.pass-msg {color:green; font-size:20px} +div#dup-global-error-reserved-files p.pass-lnks {line-height:24px; margin:-7px 0 0 5px} +div#dup-global-error-reserved-files div.pass-msg {padding:5px 0 0 10px; font-size:11px; color:#999; font-style: italic} +div.dup-wpnotice-box {display:none;} + +/*================================================ +PARSLEY:Overrides*/ +input.parsley-error, textarea.parsley-error { + color:#B94A48 !important; + background-color:#F2DEDE !important; + border:1px solid #EED3D7 !important; +} +div.qtip-content {line-height:16px} +ul.parsley-errors-list {margin:0 0 -7px 0; font-style: italic} + +div.notice-safemode {color: maroon;} +div.cleanup-notice b.title {color: green;font-size: 20px;} + +/*SCREEN TABS*/ +div.dup-screen-hlp-info {line-height:26px; padding:10px 0 10px 0} +#screen-meta-links .button { font-size:13px !important; height:auto !important;font-weight: normal; padding: 3px 6px 3px 16px !important;min-width:72px !important} + diff --git a/assets/js/parsley.min.js b/assets/js/parsley.min.js new file mode 100644 index 00000000..836699c6 --- /dev/null +++ b/assets/js/parsley.min.js @@ -0,0 +1,11 @@ +/*! +* Parsley.js +* Version 2.3.5 - built Sun, Feb 28th 2016, 6:25 am +* http://parsleyjs.org +* Guillaume Potier - +* Marc-Andre Lafortune - +* MIT Licensed +*/ +function _toConsumableArray(e){if(Array.isArray(e)){for(var t=0,i=Array(e.length);t1)throw Error("Second argument not supported");if("object"!=typeof t)throw TypeError("Argument must be an object");e.prototype=t;var i=new e;return e.prototype=null,i}}()},a=s,o={namespace:"data-parsley-",inputs:"input, textarea, select",excluded:"input[type=button], input[type=submit], input[type=reset], input[type=hidden]",priorityEnabled:!0,multiple:null,group:null,uiEnabled:!0,validationThreshold:3,focus:"first",trigger:!1,triggerAfterFailure:"input",errorClass:"parsley-error",successClass:"parsley-success",classHandler:function(e){},errorsContainer:function(e){},errorsWrapper:'
      ',errorTemplate:"
    • "},l=function(){};l.prototype={asyncSupport:!0,actualizeOptions:function(){return a.attr(this.$element,this.options.namespace,this.domOptions),this.parent&&this.parent.actualizeOptions&&this.parent.actualizeOptions(),this},_resetOptions:function(e){this.domOptions=a.objectCreate(this.parent.options),this.options=a.objectCreate(this.domOptions);for(var t in e)e.hasOwnProperty(t)&&(this.options[t]=e[t]);this.actualizeOptions()},_listeners:null,on:function(e,t){this._listeners=this._listeners||{};var i=this._listeners[e]=this._listeners[e]||[];return i.push(t),this},subscribe:function(t,i){e.listenTo(this,t.toLowerCase(),i)},off:function(e,t){var i=this._listeners&&this._listeners[e];if(i)if(t)for(var n=i.length;n--;)i[n]===t&&i.splice(n,1);else delete this._listeners[e];return this},unsubscribe:function(t,i){e.unsubscribeTo(this,t.toLowerCase())},trigger:function(e,t,i){t=t||this;var n,r=this._listeners&&this._listeners[e];if(r)for(var s=r.length;s--;)if(n=r[s].call(t,t,i),n===!1)return n;return this.parent?this.parent.trigger(e,t,i):!0},reset:function(){if("ParsleyForm"!==this.__class__)return this._resetUI(),this._trigger("reset");for(var e=0;e3&&(i=[].slice.call(arguments,1,-1)),this.fn.call(this,t,i);if(e.isArray(t)){if(!this.validateMultiple)throw"Validator `"+this.name+"` does not handle multiple values";return this.validateMultiple.apply(this,arguments)}if(this.validateNumber)return isNaN(t)?!1:(arguments[0]=parseFloat(arguments[0]),this.validateNumber.apply(this,arguments));if(this.validateString)return this.validateString.apply(this,arguments);throw"Validator `"+this.name+"` only handles multiple values"},parseRequirements:function(t,i){if("string"!=typeof t)return e.isArray(t)?t:[t];var n=this.requirementType;if(e.isArray(n)){for(var r=d(t,n.length),s=0;s0},validateString:function(e){return/\S/.test(e)},priority:512},type:{validateString:function(e,t){var i=arguments.length<=2||void 0===arguments[2]?{}:arguments[2],n=i.step,r=void 0===n?"1":n,s=i.base,a=void 0===s?0:s,o=m[t];if(!o)throw new Error("validator type `"+t+"` is not supported");if(!o.test(e))return!1;if("number"===t&&!/^any$/i.test(r||"")){var l=Number(e),u=Math.max(g(r),g(a));if(g(l)>u)return!1;var d=function(e){return Math.round(e*Math.pow(10,u))};if((d(l)-d(a))%d(r)!=0)return!1}return!0},requirementType:{"":"string",step:"string",base:"number"},priority:256},pattern:{validateString:function(e,t){return t.test(e)},requirementType:"regexp",priority:64},minlength:{validateString:function(e,t){return e.length>=t},requirementType:"integer",priority:30},maxlength:{validateString:function(e,t){return e.length<=t},requirementType:"integer",priority:30},length:{validateString:function(e,t,i){return e.length>=t&&e.length<=i},requirementType:["integer","integer"],priority:30},mincheck:{validateMultiple:function(e,t){return e.length>=t},requirementType:"integer",priority:30},maxcheck:{validateMultiple:function(e,t){return e.length<=t},requirementType:"integer",priority:30},check:{validateMultiple:function(e,t,i){return e.length>=t&&e.length<=i},requirementType:["integer","integer"],priority:30},min:{validateNumber:function(e,t){return e>=t},requirementType:"number",priority:30},max:{validateNumber:function(e,t){return t>=e},requirementType:"number",priority:30},range:{validateNumber:function(e,t,i){return e>=t&&i>=e},requirementType:["number","number"],priority:30},equalto:{validateString:function(t,i){var n=e(i);return n.length?t===n.val():t===i},priority:256}}};var y={},v=function T(e,t,i){for(var n=[],r=[],s=0;s0&&"undefined"==typeof t.options.noFocus&&(this._focusedField=t.$element,"first"===this.options.focus))break}return null===this._focusedField?null:this._focusedField.focus()},_destroyUI:function(){this.$element.off(".Parsley")}},y.Field={_reflowUI:function(){if(this._buildUI(),this._ui){var e=v(this.validationResult,this._ui.lastValidationResult);this._ui.lastValidationResult=this.validationResult,this._manageStatusClass(),this._manageErrorsMessages(e),this._actualizeTriggers(),!e.kept.length&&!e.added.length||this._failedOnce||(this._failedOnce=!0,this._actualizeTriggers())}},getErrorsMessages:function(){if(!0===this.validationResult)return[];for(var e=[],t=0;t0?this._errorClass():this._resetClass()},_manageErrorsMessages:function(t){if("undefined"==typeof this.options.errorsMessagesDisabled){if("undefined"!=typeof this.options.errorMessage)return t.added.length||t.kept.length?(this._insertErrorWrapper(),0===this._ui.$errorsWrapper.find(".parsley-custom-error-message").length&&this._ui.$errorsWrapper.append(e(this.options.errorTemplate).addClass("parsley-custom-error-message")),this._ui.$errorsWrapper.addClass("filled").find(".parsley-custom-error-message").html(this.options.errorMessage)):this._ui.$errorsWrapper.removeClass("filled").find(".parsley-custom-error-message").remove();for(var i=0;i').appendTo(this.$element)),i.attr({name:t.attr("name"),value:t.attr("value")})}this.$element.trigger(e.extend(e.Event("submit"),{parsley:!0}))}},validate:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling validate on a parsley form without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1],s=i[2];t={group:n,force:r,event:s}}return w[this.whenValidate(t).state()]},whenValidate:function(){var t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.group,r=i.force,s=i.event;this.submitEvent=s,s&&(this.submitEvent=e.extend({},s,{preventDefault:function(){a.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`"),t.validationResult=!1}})),this.validationResult=!0,this._trigger("validate"),this._refreshFields();var o=this._withoutReactualizingFormOptions(function(){return e.map(t.fields,function(e){return e.whenValidate({force:r,group:n})})}),l=function(){var i=e.Deferred();return!1===t.validationResult&&i.reject(),i.resolve().promise()};return e.when.apply(e,_toConsumableArray(o)).done(function(){t._trigger("success")}).fail(function(){t.validationResult=!1,t.focus(),t._trigger("error")}).always(function(){t._trigger("validated")}).pipe(l,l)},isValid:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling isValid on a parsley form without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1];t={group:n,force:r}}return w[this.whenValid(t).state()]},whenValid:function(){var t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.group,r=i.force;this._refreshFields();var s=this._withoutReactualizingFormOptions(function(){return e.map(t.fields,function(e){return e.whenValid({group:n,force:r})})});return e.when.apply(e,_toConsumableArray(s))},_refreshFields:function(){return this.actualizeOptions()._bindFields()},_bindFields:function(){var t=this,i=this.fields;return this.fields=[],this.fieldsMappedById={},this._withoutReactualizingFormOptions(function(){t.$element.find(t.options.inputs).not(t.options.excluded).each(function(e,i){var n=new window.Parsley.Factory(i,{},t);"ParsleyField"!==n.__class__&&"ParsleyFieldMultiple"!==n.__class__||!0===n.options.excluded||"undefined"==typeof t.fieldsMappedById[n.__class__+"-"+n.__id__]&&(t.fieldsMappedById[n.__class__+"-"+n.__id__]=n,t.fields.push(n))}),e(i).not(t.fields).each(function(e,t){t._trigger("reset")})}),this},_withoutReactualizingFormOptions:function(e){var t=this.actualizeOptions;this.actualizeOptions=function(){return this};var i=e();return this.actualizeOptions=t,i},_trigger:function(e){return this.trigger("form:"+e)}};var b=function(t,i,n,r,s){if(!/ParsleyField/.test(t.__class__))throw new Error("ParsleyField or ParsleyFieldMultiple instance expected");var a=window.Parsley._validatorRegistry.validators[i],o=new f(a);e.extend(this,{validator:o,name:i,requirements:n,priority:r||t.options[i+"Priority"]||o.priority,isDomConstraint:!0===s}),this._parseRequirements(t.options)},F=function(e){var t=e[0].toUpperCase();return t+e.slice(1)};b.prototype={validate:function(e,t){var i=this.requirementList.slice(0);return i.unshift(e),i.push(t),this.validator.validate.apply(this.validator,i)},_parseRequirements:function(e){var t=this;this.requirementList=this.validator.parseRequirements(this.requirements,function(i){return e[t.name+F(i)]})}};var C=function(t,i,n,r){this.__class__="ParsleyField",this.__id__=a.generateID(),this.$element=e(t),"undefined"!=typeof r&&(this.parent=r),this.options=n,this.domOptions=i,this.constraints=[],this.constraintsByName={},this.validationResult=[],this._bindConstraints()},$={pending:null,resolved:!0,rejected:!1};C.prototype={validate:function(t){arguments.length>=1&&!e.isPlainObject(t)&&(a.warnOnce("Calling validate on a parsley field without passing arguments as an object is deprecated."),t={options:t});var i=this.whenValidate(t);if(!i)return!0;switch(i.state()){case"pending":return null;case"resolved":return!0;case"rejected":return this.validationResult}},whenValidate:function(){var e=this,t=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],i=t.force,n=t.group;return this.refreshConstraints(),!n||this._isInGroup(n)?(this.value=this.getValue(),this._trigger("validate"),this.whenValid({force:i,value:this.value,_refreshed:!0}).always(function(){e._reflowUI()}).done(function(){e._trigger("success")}).fail(function(){e._trigger("error")}).always(function(){e._trigger("validated")})):void 0},hasConstraints:function(){return 0!==this.constraints.length},needsValidation:function(e){return"undefined"==typeof e&&(e=this.getValue()),e.length||this._isRequired()||"undefined"!=typeof this.options.validateIfEmpty?!0:!1},_isInGroup:function(t){return e.isArray(this.options.group)?-1!==e.inArray(t,this.options.group):this.options.group===t},isValid:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling isValid on a parsley field without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1];t={force:n,value:r}}var s=this.whenValid(t);return s?$[s.state()]:!0},whenValid:function(){var t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.force,r=void 0===n?!1:n,s=i.value,a=i.group,o=i._refreshed;if(o||this.refreshConstraints(),!a||this._isInGroup(a)){if(this.validationResult=!0,!this.hasConstraints())return e.when();if(("undefined"==typeof s||null===s)&&(s=this.getValue()),!this.needsValidation(s)&&!0!==r)return e.when();var l=this._getGroupedConstraints(),u=[];return e.each(l,function(i,n){var r=e.when.apply(e,_toConsumableArray(e.map(n,function(e){return t._validateConstraint(s,e)})));return u.push(r),"rejected"===r.state()?!1:void 0}),e.when.apply(e,u)}},_validateConstraint:function(t,i){var n=this,r=i.validate(t,this);return!1===r&&(r=e.Deferred().reject()),e.when(r).fail(function(e){!0===n.validationResult&&(n.validationResult=[]),n.validationResult.push({assert:i,errorMessage:"string"==typeof e&&e})})},getValue:function(){var e;return e="function"==typeof this.options.value?this.options.value(this):"undefined"!=typeof this.options.value?this.options.value:this.$element.val(),"undefined"==typeof e||null===e?"":this._handleWhitespace(e)},refreshConstraints:function(){return this.actualizeOptions()._bindConstraints()},addConstraint:function(e,t,i,n){if(window.Parsley._validatorRegistry.validators[e]){var r=new b(this,e,t,i,n);"undefined"!==this.constraintsByName[r.name]&&this.removeConstraint(r.name),this.constraints.push(r),this.constraintsByName[r.name]=r}return this},removeConstraint:function(e){for(var t=0;t1){var i=[];return this.each(function(){i.push(e(this).parsley(t))}),i}return e(this).length?new E(this,t):void a.warn("You must bind Parsley on an existing element.")},"undefined"==typeof window.ParsleyExtend&&(window.ParsleyExtend={}),M.options=e.extend(a.objectCreate(o),window.ParsleyConfig),window.ParsleyConfig=M.options,window.Parsley=window.psly=M,window.ParsleyUtils=a;var O=window.Parsley._validatorRegistry=new c(window.ParsleyConfig.validators,window.ParsleyConfig.i18n);window.ParsleyValidator={},e.each("setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator".split(" "),function(t,i){window.Parsley[i]=e.proxy(O,i),window.ParsleyValidator[i]=function(){var e;return a.warnOnce("Accessing the method '"+i+"' through ParsleyValidator is deprecated. Simply call 'window.Parsley."+i+"(...)'"),(e=window.Parsley)[i].apply(e,arguments)}}),window.Parsley.UI=y,window.ParsleyUI={removeError:function(e,t,i){var n=!0!==i;return a.warnOnce("Accessing ParsleyUI is deprecated. Call 'removeError' on the instance directly. Please comment in issue 1073 as to your need to call this method."),e.removeError(t,{updateClass:n})},getErrorsMessages:function(e){return a.warnOnce("Accessing ParsleyUI is deprecated. Call 'getErrorsMessages' on the instance directly."),e.getErrorsMessages()}},e.each("addError updateError".split(" "),function(e,t){window.ParsleyUI[t]=function(e,i,n,r,s){var o=!0!==s;return a.warnOnce("Accessing ParsleyUI is deprecated. Call '"+t+"' on the instance directly. Please comment in issue 1073 as to your need to call this method."),e[t](i,{message:n,assert:r,updateClass:o})}}),/firefox/i.test(navigator.userAgent)&&e(document).on("change","select",function(t){e(t.target).trigger("input")}),!1!==window.ParsleyConfig.autoBind&&e(function(){e("[data-parsley-validate]").length&&e("[data-parsley-validate]").parsley()});var A=e({}),R=function(){a.warnOnce("Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley")},D="parsley:";e.listen=function(e,n){var r;if(R(),"object"==typeof arguments[1]&&"function"==typeof arguments[2]&&(r=arguments[1],n=arguments[2]),"function"!=typeof n)throw new Error("Wrong parameters");window.Parsley.on(i(e),t(n,r))},e.listenTo=function(e,n,r){if(R(),!(e instanceof x||e instanceof _))throw new Error("Must give Parsley instance");if("string"!=typeof n||"function"!=typeof r)throw new Error("Wrong parameters");e.on(i(n),t(r))},e.unsubscribe=function(e,t){if(R(),"string"!=typeof e||"function"!=typeof t)throw new Error("Wrong arguments");window.Parsley.off(i(e),t.parsleyAdaptedCallback)},e.unsubscribeTo=function(e,t){if(R(),!(e instanceof x||e instanceof _))throw new Error("Must give Parsley instance");e.off(i(t))},e.unsubscribeAll=function(t){R(),window.Parsley.off(i(t)),e("form,input,textarea,select").each(function(){var n=e(this).data("Parsley");n&&n.off(i(t))})},e.emit=function(e,t){var n;R();var r=t instanceof x||t instanceof _,s=Array.prototype.slice.call(arguments,r?2:1);s.unshift(i(e)),r||(t=window.Parsley),(n=t).trigger.apply(n,_toConsumableArray(s))};e.extend(!0,M,{asyncValidators:{"default":{fn:function(e){return e.status>=200&&e.status<300},url:!1},reverse:{fn:function(e){return e.status<200||e.status>=300},url:!1}},addAsyncValidator:function(e,t,i,n){return M.asyncValidators[e]={fn:t,url:i||!1,options:n||{}},this}}),M.addValidator("remote",{requirementType:{"":"string",validator:"string",reverse:"boolean",options:"object"},validateString:function(t,i,n,r){var s,a,o={},l=n.validator||(!0===n.reverse?"reverse":"default");if("undefined"==typeof M.asyncValidators[l])throw new Error("Calling an undefined async validator: `"+l+"`");i=M.asyncValidators[l].url||i,i.indexOf("{value}")>-1?i=i.replace("{value}",encodeURIComponent(t)):o[r.$element.attr("name")||r.$element.attr("id")]=t;var u=e.extend(!0,n.options||{},M.asyncValidators[l].options);s=e.extend(!0,{},{url:i,data:o,type:"GET"},u),r.trigger("field:ajaxoptions",r,s),a=e.param(s),"undefined"==typeof M._remoteCache&&(M._remoteCache={});var d=M._remoteCache[a]=M._remoteCache[a]||e.ajax(s),h=function(){var t=M.asyncValidators[l].fn.call(r,d,i,n);return t||(t=e.Deferred().reject()),e.when(t)};return d.then(h,h)},priority:-1}),M.on("form:submit",function(){M._remoteCache={}}),window.ParsleyExtend.addAsyncValidator=function(){return ParsleyUtils.warnOnce("Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`"),M.addAsyncValidator.apply(M,arguments)},M.addMessages("en",{defaultMessage:"This value seems to be invalid.",type:{email:"This value should be a valid email.",url:"This value should be a valid url.",number:"This value should be a valid number.",integer:"This value should be a valid integer.",digits:"This value should be digits.",alphanum:"This value should be alphanumeric."},notblank:"This value should not be blank.",required:"This value is required.",pattern:"This value seems to be invalid.",min:"This value should be greater than or equal to %s.",max:"This value should be lower than or equal to %s.",range:"This value should be between %s and %s.",minlength:"This value is too short. It should have %s characters or more.",maxlength:"This value is too long. It should have %s characters or fewer.",length:"This value length is invalid. It should be between %s and %s characters long.",mincheck:"You must select at least %s choices.",maxcheck:"You must select %s choices or fewer.",check:"You must select between %s and %s choices.",equalto:"This value should be the same."}),M.setLocale("en");var q=M;return q}); +//# sourceMappingURL=parsley.min.js.map \ No newline at end of file diff --git a/classes/class.crypt.php b/classes/class.crypt.php new file mode 100644 index 00000000..e99406a3 --- /dev/null +++ b/classes/class.crypt.php @@ -0,0 +1,57 @@ + "@@CLASS.DB.PHP@@", "classes/class.logging.php" => "@@CLASS.LOGGING.PHP@@", "classes/class.engine.php" => "@@CLASS.ENGINE.PHP@@", + "classes/class.http.php" => "@@CLASS.HTTP.PHP@@", "classes/config/class.conf.wp.php" => "@@CLASS.CONF.WP.PHP@@", "classes/config/class.conf.srv.php" => "@@CLASS.CONF.SRV.PHP@@", "ctrls/ctrl.step1.php" => "@@CTRL.STEP1.PHP@@", "ctrls/ctrl.step2.php" => "@@CTRL.STEP2.PHP@@", "ctrls/ctrl.step3.php" => "@@CTRL.STEP3.PHP@@", + "view.init1.php" => "@@VIEW.INIT1.PHP@@", "view.step1.php" => "@@VIEW.STEP1.PHP@@", "view.step2.php" => "@@VIEW.STEP2.PHP@@", "view.step3.php" => "@@VIEW.STEP3.PHP@@", @@ -151,13 +155,15 @@ private function createFromTemplate($template) "fwrite_url_old" => get_option('siteurl'), "fwrite_archive_name" => "{$this->Package->NameHash}_archive.zip", "fwrite_archive_onlydb" => $this->Package->Archive->ExportOnlyDB, - "fwrite_package_notes" => $this->Package->Notes, - "fwrite_package_size" => $this->Package->Archive->Size, - "fwrite_secure_name" => $this->Package->NameHash, - "fwrite_dbhost" => $this->Package->Installer->OptsDBHost, - "fwrite_dbport" => $this->Package->Installer->OptsDBPort, - "fwrite_dbname" => $this->Package->Installer->OptsDBName, - "fwrite_dbuser" => $this->Package->Installer->OptsDBUser, + "fwrite_package_notes" => $this->Package->Notes, + "fwrite_package_size" => $this->Package->Archive->Size, + "fwrite_secure_name" => $this->Package->NameHash, + "fwrite_dbhost" => $this->Package->Installer->OptsDBHost, + "fwrite_dbport" => $this->Package->Installer->OptsDBPort, + "fwrite_dbname" => $this->Package->Installer->OptsDBName, + "fwrite_dbuser" => $this->Package->Installer->OptsDBUser, + "fwrite_secureon" => $this->Package->Installer->OptsSecureOn, + "fwrite_securepass" => $this->Package->Installer->OptsSecurePass, "fwrite_dbpass" => '', "fwrite_wp_tableprefix" => $wpdb->prefix, "fwrite_opts_delete" => json_encode($deleteOpts), diff --git a/classes/package/class.pack.php b/classes/package/class.pack.php index faa3386c..9010b06c 100644 --- a/classes/package/class.pack.php +++ b/classes/package/class.pack.php @@ -335,10 +335,12 @@ public function saveActive($post = null) $this->Archive->FilterFiles = DUP_Util::escSanitizeTextAreaField($filter_files); $this->Archive->FilterExts = str_replace(array('.', ' '), '', DUP_Util::escSanitizeTextAreaField($filter_exts)); //INSTALLER - $this->Installer->OptsDBHost = DUP_Util::escSanitizeTextField($post['dbhost']); - $this->Installer->OptsDBPort = DUP_Util::escSanitizeTextField($post['dbport']); - $this->Installer->OptsDBName = DUP_Util::escSanitizeTextField($post['dbname']); - $this->Installer->OptsDBUser = DUP_Util::escSanitizeTextField($post['dbuser']); + $this->Installer->OptsDBHost = DUP_Util::escSanitizeTextField($post['dbhost']); + $this->Installer->OptsDBPort = DUP_Util::escSanitizeTextField($post['dbport']); + $this->Installer->OptsDBName = DUP_Util::escSanitizeTextField($post['dbname']); + $this->Installer->OptsDBUser = DUP_Util::escSanitizeTextField($post['dbuser']); + $this->Installer->OptsSecureOn = isset($post['secure-on']) ? 1 : 0; + $this->Installer->OptsSecurePass = DUP_Util::installerScramble($post['secure-pass']); //DATABASE $this->Database->FilterOn = isset($post['dbfilter-on']) ? 1 : 0; $this->Database->FilterTables = esc_html($tablelist); diff --git a/classes/utilities/class.u.php b/classes/utilities/class.u.php index 0b542f6b..ab226bc3 100644 --- a/classes/utilities/class.u.php +++ b/classes/utilities/class.u.php @@ -18,6 +18,8 @@ exit; } +require_once (DUPLICATOR_PLUGIN_PATH.'classes/class.crypt.php'); + class DUP_Util { /** @@ -132,7 +134,7 @@ public static function array_group_by(array $array, $key) /** * PHP_SAPI for fcgi requires a data flush of at least 256 - * bytes every 40 seconds or else it forces a script hault + * bytes every 40 seconds or else it forces a script halt * * @return string A series of 256 space characters */ @@ -154,7 +156,7 @@ public static function snapshotURL() } /** - * Returns the last N lines of a file. Equivelent to tail command + * Returns the last N lines of a file. equivalent to tail command * * @param string $filepath The full path to the file to be tailed * @param int $lines The number of lines to return with each tail call @@ -480,8 +482,34 @@ public static function getProcessOwner() } } + /** + * Wrap to prevent malware scanners from reporting false/positive + * Switched from our old method to avoid WordFence reporting a false positive + * + * @param string $string The string to decrypt i.e. base64_decode + * + * @return string Returns the string base64 decoded + */ + public static function installerUnscramble($string) + { + return base64_decode($string); + } + + /** + * Wrap to prevent malware scanners from reporting false/positive + * Switched from our old method to avoid WordFence reporting a false positive + * + * @param string $string The string to decrypt i.e. base64_encode + * + * @return string Returns the string base64 encode + */ + public static function installerScramble($string) + { + return base64_encode($string); + } + /** - * Creates the snapshot directory if it doesn't already exisit + * Creates the snapshot directory if it doesn't already exist * * @return null */ diff --git a/define.php b/define.php index 75656d85..66ddb81a 100644 --- a/define.php +++ b/define.php @@ -2,7 +2,7 @@ //Prevent directly browsing to the file if (function_exists('plugin_dir_url')) { - define('DUPLICATOR_VERSION', '1.2.41'); + define('DUPLICATOR_VERSION', '1.2.42'); define('DUPLICATOR_HOMEPAGE', 'https://snapcreek.com/duplicator/duplicator-free/'); define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__)); define('DUPLICATOR_SITE_URL', get_site_url()); diff --git a/duplicator.php b/duplicator.php index f486b99a..0d11bebf 100644 --- a/duplicator.php +++ b/duplicator.php @@ -3,7 +3,7 @@ Plugin Name: Duplicator Plugin URI: https://snapcreek.com/duplicator/duplicator-free/ Description: Migrate and backup a copy of your WordPress files and database. Duplicate and move a site from one location to another quickly. - Version: 1.2.41 + Version: 1.2.42 Author: Snap Creek Author URI: http://www.snapcreek.com/duplicator/ Text Domain: duplicator @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA SOURCE CONTRIBUTORS: - David Coveney of Interconnect IT Ltd https://github.com/interconnectit/Search-Replace-DB/ ================================================================================ */ @@ -109,8 +108,8 @@ function duplicator_update() } /** - * Hooked into `register_deactivation_hook`. Routines used to deactivae the plugin - * For uninstall see uninstall.php Wordpress by default will call the uninstall.php file + * Hooked into `register_deactivation_hook`. Routines used to deactivate the plugin + * For uninstall see uninstall.php WordPress by default will call the uninstall.php file * * @access global * @return null @@ -163,9 +162,10 @@ function duplicator_init() wp_register_style('dup-font-awesome', DUPLICATOR_PLUGIN_URL . 'assets/css/font-awesome.min.css', null, '4.7.0'); wp_register_style('dup-plugin-style', DUPLICATOR_PLUGIN_URL . 'assets/css/style.css', null, DUPLICATOR_VERSION); wp_register_style('dup-jquery-qtip',DUPLICATOR_PLUGIN_URL . 'assets/js/jquery.qtip/jquery.qtip.min.css', null, '2.2.1'); + wp_register_style('dup-parsley-style', DUPLICATOR_PLUGIN_URL . 'assets/css/style.css', null, '2.3.5'); /* JS */ wp_register_script('dup-handlebars', DUPLICATOR_PLUGIN_URL . 'assets/js/handlebars.min.js', array('jquery'), '4.0.10'); - wp_register_script('dup-parsley', DUPLICATOR_PLUGIN_URL . 'assets/js/parsley-standalone.min.js', array('jquery'), '1.1.18'); + wp_register_script('dup-parsley', DUPLICATOR_PLUGIN_URL . 'assets/js/parsley.min.js', array('jquery'), '2.3.5'); wp_register_script('dup-jquery-qtip', DUPLICATOR_PLUGIN_URL . 'assets/js/jquery.qtip/jquery.qtip.min.js', array('jquery'), '2.2.1'); } @@ -265,7 +265,6 @@ function duplicator_scripts() wp_enqueue_script('jquery-ui-progressbar'); wp_enqueue_script('dup-parsley'); wp_enqueue_script('dup-jquery-qtip'); - } /** @@ -280,6 +279,7 @@ function duplicator_styles() wp_enqueue_style('dup-font-awesome'); wp_enqueue_style('dup-plugin-style'); wp_enqueue_style('dup-jquery-qtip'); + wp_enqueue_style('dup-parsley-style'); } diff --git a/installer/build/assets/inc.css.php b/installer/build/assets/inc.css.php index bb60b95a..5d8cb2c3 100644 --- a/installer/build/assets/inc.css.php +++ b/installer/build/assets/inc.css.php @@ -1,228 +1,246 @@ - \ No newline at end of file diff --git a/installer/build/classes/class.http.php b/installer/build/classes/class.http.php new file mode 100644 index 00000000..24c5d2fc --- /dev/null +++ b/installer/build/classes/class.http.php @@ -0,0 +1,205 @@ + 'value1', 'key2' => 'value2') + * generated hidden form elements + * @return string An html form that will automatically post itself + */ + public static function post_with_html($url, $data) + { + $id = uniqid(); + $html = "
      \n"; + foreach ($data as $name => $value) + { + $html .= "\n"; + } + $html .= "
      \n"; + $html .= ""; + echo $html; + } + + /** + * Do an http post request with curl or php code + * @param string $url A URL to post to + * @param string $params A valid key/pair combo $data = array('key1' => 'value1', 'key2' => 'value2'); + * @param string $headers Optional header elements + * @return a string or FALSE on failure. + */ + public static function post($url, $params = array(), $headers = null) + { + //PHP POST + if (!function_exists('curl_init')) + { + return self::php_get_post($url, $params, $headers = null, 'POST'); + } + + //CURL POST + $headers_on = isset($headers) && array_count_values($headers); + $params = http_build_query($params); + $ch = curl_init(); + + // Return contents of transfer on curl_exec + // Allow self-signed certs + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HEADER, $headers_on); + + if ($headers_on) + { + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + } + curl_setopt($ch, CURLOPT_POST, count($params)); + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + $response = curl_exec($ch); + curl_close($ch); + return $response; + } + + /** + * Do an http post request with curl or php code + * @param string $url A URL to get. If $params is not null then all query strings will be removed. + * @param string $params A valid key/pair combo $data = array('key1' => 'value1', 'key2' => 'value2'); + * @param string $headers Optional header elements + * @return a string or FALSE on failure. + */ + public static function get($url, $params = array(), $headers = null) + { + //PHP GET + if (!function_exists('curl_init')) + { + return self::php_get_post($url, $params, $headers = null, 'GET'); + } + + //Remove query string if $params are passed + $full_url = $url; + if (count($params)) + { + $url = preg_replace('/\?.*/', '', $url); + $full_url = $url . '?' . http_build_query($params); + } + $headers_on = isset($headers) && array_count_values($headers); + $ch = curl_init(); + + // Return contents of transfer on curl_exec + // Allow self-signed certs + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_URL, $full_url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HEADER, $headers_on); + if ($headers_on) + { + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + } + $response = curl_exec($ch); + curl_close($ch); + return $response; + } + + /** + * Gets the URL of the current request + * @param bool $show_query Include the query string in the URL + * @return string A URL + */ + public static function get_request_uri($show_query = true) + { + $isSecure = false; + + if((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || ($_SERVER['SERVER_PORT'] == 443)) + { + $isSecure = true; + } + elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') + { + $isSecure = true; + } + $protocol = $isSecure ? 'https' : 'http'; + $url = "{$protocol}://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"; + $url = ($show_query) ? $url : preg_replace('/\?.*/', '', $url); + return $url; + } + + /** + * Check to see if the internet is accessible + * @param string $url A URL e.g without prefix "ajax.googleapis.com" + * @param string $port A valid port number + * @return bool + */ + public static function is_url_active($url, $port, $timeout = 5) + { + if (function_exists('fsockopen')) + { + $port = isset($port) && is_integer($port) ? $port : 80; + $connected = @fsockopen($url, $port, $errno, $errstr, $timeout); //website and port + if ($connected) + { + $is_conn = true; + @fclose($connected); + } + else + { + $is_conn = false; + } + return $is_conn; + } + else + { + return false; + } + } + + public static function parse_host($url) + { + $url = parse_url(trim($url)); + if ($url == false) + { + return null; + } + return trim($url['host'] ? $url['host'] : array_shift(explode('/', $url['path'], 2))); + } + + //PHP POST or GET requets + private static function php_get_post($url, $params, $headers = null, $method) + { + $full_url = $url; + if ($method == 'GET' && count($params)) + { + $url = preg_replace('/\?.*/', '', $url); + $full_url = $url . '?' . http_build_query($params); + } + + $data = array('http' => array( + 'method' => $method, + 'content' => http_build_query($params))); + + if ($headers !== null) + { + $data['http']['header'] = $headers; + } + $ctx = stream_context_create($data); + $fp = @fopen($full_url, 'rb', false, $ctx); + if (!$fp) + { + throw new Exception("Problem with $full_url, $php_errormsg"); + } + $response = @stream_get_contents($fp); + if ($response === false) + { + throw new Exception("Problem reading data from $full_url, $php_errormsg"); + } + return $response; + } + +} +?> diff --git a/installer/build/main.installer.php b/installer/build/main.installer.php index 8ddd771c..6c753567 100644 --- a/installer/build/main.installer.php +++ b/installer/build/main.installer.php @@ -103,6 +103,8 @@ $GLOBALS['FW_DBNAME'] = '%fwrite_dbname%'; $GLOBALS['FW_DBUSER'] = '%fwrite_dbuser%'; $GLOBALS['FW_DBPASS'] = '%fwrite_dbpass%'; +$GLOBALS['FW_SECUREON'] = '%fwrite_secureon%'; +$GLOBALS['FW_SECUREPASS'] = '%fwrite_securepass%'; $GLOBALS['FW_BLOGNAME'] = '%fwrite_blogname%'; $GLOBALS['FW_WPROOT'] = '%fwrite_wproot%'; $GLOBALS['FW_WPLOGIN_URL'] = '%fwrite_wplogin_url%'; @@ -142,7 +144,13 @@ define("DUPLICATOR_SSDIR_NAME", 'wp-snapshots'); //This should match DUPLICATOR_SSDIR_NAME in duplicator.php //SHARED POST PARMS -$_POST['action_step'] = isset($_POST['action_step']) ? $_POST['action_step'] : "1"; +$_POST['action_step'] = isset($_POST['action_step']) ? $_POST['action_step'] : "0"; +$_POST['secure-pass'] = isset($_POST['secure-pass']) ? $_POST['secure-pass'] : ""; +if ($GLOBALS['FW_SECUREON']) { + if (base64_decode($GLOBALS['FW_SECUREPASS']) != $_POST['secure-pass']) { + $_POST['action_step'] = 0; + } +} /** Host has several combinations : localhost | localhost:55 | localhost: | http://localhost | http://localhost:55 */ @@ -182,9 +190,16 @@ @@CLASS.ENGINE.PHP@@ @@CLASS.CONF.WP.PHP@@ @@CLASS.CONF.SRV.PHP@@ +@@CLASS.HTTP.PHP@@
      » info » help + '; + echo ($GLOBALS['FW_SECUREON']) ? 'locked' : 'unlocked'; + + ?> + - -
      -
      Database Only Mode
      +
      +
      +
      - +
      @@ -253,6 +277,9 @@ if (! isset($_GET['help'])) { switch ($_POST['action_step']) { + case "0" : + ?> @@VIEW.INIT1.PHP@@ @@VIEW.STEP1.PHP@@ -
      -
      - For additional help visit the
      Online Knowledge-Base
      - Features available only in Duplicator Pro are flagged with a pro tag. -
      - -

      Installer Security

      - -
      - The installer security screen pro will allow for basic password protection on the installer. The password is set at package creation time. The password - input on this screen must be entered before proceeding with an install. This setting is optional and can be turned on/off via the package creation screens. -

      - - If you do not recall the password then login to the site where the package was created and click the details of the package to view the original password. - To validate the password just typed you can toggle the view by clicking on the lock icon. -

      -
      - - - -

      Step 1 of 4: Deployment

      -
      - The "Extract Archive" screen is separated into four sections: -

      - -

      Archive

      - This is the archive file the installer must use in order to extract the web site files and database. The 'Name' is a unique key that - ties both the archive and installer together. The installer needs the archive file name to match the 'Name' value exactly character for character in order - for this section to get a pass status. -

      - If the archive name is ever changed then it should be renamed back to the 'Name' value in order for the installer to properly identify it as part of a - complete package. Additional information such as the archive size and the package notes are mentioned in this section. -

      - -

      Validation

      - This section shows the installers system requirements and notices. All requirements must pass in order to proceed to Step 2. Each requirement will show - a Pass/Fail status. Notices on the other hand are not required in order to continue with the install. -

      - - Notices are simply checks that will help you identify any possible issues that might occur. If this section shows a - Good/Warn for various checks. Click on the title link and read the overview for how to solve the test. -

      - -

      MultiSite pro

      - The multisite option allows users with a pro Business or Gold license to perform additional multi-site tasks. All licenses can backup & migrate standalone sites - and full multisite networks. Multisite Plus+ (business and above) adds the ability to install a subsite as a standalone site. -

      - -

      Options

      - The options for step 1 can help better prepare your site should your server need additional settings beyond most general configuration. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      OptionDetails
      General Options
      Extraction - Manual Archive Extraction
      - Set the Extraction value to "Manual Archive Extraction" when the archive file has already been manually extracted on the server. This can be done through your hosts - control panel such as cPanel or by your host directly. This setting can be helpful if you have a large archive files or are having issues with the installer extracting - the file due to timeout issues. -

      - - PHP ZipArchive
      - This extraction method will use the PHP ZipArchive code to extract the archive zip file. -

      - - Shell-Exec Unzip pro
      - This extraction method will use the PHP shell_exec to call the system unzip - command on the server. This is the default mode that is used if its avail on the server. -

      - -
      Permissions pro - All Files: Check the 'All Files' check-box and enter in the desired chmod command - to recursively set the octal value on all the files being extracted. Typically this value is 644 on most servers and hosts. -

      - - All Directories: Check the 'All Directories' check-box and enter in the desired chmod command - to recursively set octal value on all the directories being extracted. Typically this value is 755 on most servers and hosts. -
      Advanced Options
      Safe Mode - Safe mode is designed to configure the site with specific options at install time to help over come issues that may happen during the install were the site - is having issues. These options should only be used if you run into issues after you have tried to run an install. -

      - Basic: This safe mode option will disable all the plugins at install time. When this option is set you will need to re-enable all plugins after the - install has full ran. -

      - - Advanced: This option applies all settings used in basic and will also de-activate and reactivate your theme when logging in for the first time. This - options should be used only if the Basic option did not work. -
      Config Files pro - Inside the archive.zip should be a copy of the original .htaccess (Apache) or the web.config (IIS) files that were setup with your packaged site. - When the installer runs it will backup and then reset all .htaccess, user.ini, and web.config files. It will then create blank copies of - both files. This is needed because the original files that were archived in most cases will not play well in the new environment. -

      - - There are cases where users do not want these files over-written after the installer runs. If that is the case then check the checkbox for this setting - to retain the original web server configuration files you had on the original site that was archived. This is an advanced feature and requires that you - know how to properly configure either the .htaccess or web.config files on your server. -
      File TimesWhen the archive is extracted should it show the current date-time or keep the original time it had when it was built. This setting will be applied to - all files and directories.
      Logging - The level of detail that will be sent to the log file (installer-log.txt). The recommend setting for most installs should be 'Light'. - Note if you use Debug the amount of data written can be very large. Debug is only recommended for support. -
      -

      - -

      Notices

      - To proceed with the install users must check the checkbox labeled " I have read and accept all terms & notices". This means you accept the term of using the software - and are aware of any notices. -

      - -
      -
      - - - - -

      Step 2 of 4: Install Database

      -
      - -

      Basic/cPanel:

      - There are currently two options you can use to perform the database setup. The "Basic" option requires knowledge about the existing server and on most hosts - will require that the database be setup ahead of time. The cPanel option is for hosts that support cPanel Software. - This option will automatically show you the existing databases and users on your cPanel server and allow you to create new databases directly - from the installer. -

      - -

      cPanel Login pro

      - The cPanel connectivity option is only available for Duplicator Pro. - - - - - - - - - - - - - - - - - - - - - -
      OptionDetails
      HostThis should be the primary domain account URL that is associated with your host. Most hosts will require you to register a primary domain name. - This should be the URL that you place in the host field. For example if your primary domain name is "mysite.com" then you would enter in - "https://mysite.com:2083". The port 2038 is the common port number that cPanel works on. If you do not know your primary domain name please contact your - hosting provider or server administrator.
      UsernameThe cPanel username used to login to your cPanel account. This is not the same thing as your WordPress administrator account. - If your unsure of this name please contact your hosting provider or server administrator.
      PasswordThe password of the cPanel user
      Troubleshoot - Common cPanel Connection Issues:
      - - Your host does not use cPanel Software
      - - Your host has disabled cPanel API access
      - - Your host has configured cPanel to work differently (please contact your host)
      - - View a list of valid cPanel Supported Hosts -
      -

      - - -

      Setup

      - The database setup options allow you to connect to an existing database or in the case of cPanel connect or create a new database. - - - - - - - - - - - - - - - - - - - - - - - - - - -
      OptionDetails
      Action - Create New Database: Will attempt to create a new database if it does not exist. When using the 'Basic' option this option will not work on many - hosting providers as the ability to create new databases is normally locked down. If the database does not exist then you will need to login to your - control panel and create the database. If your host supports 'cPanel' then you can use this option to create a new database after logging in via your - cPanel account. -

      - - Connect and Remove All Data: This options will DELETE all tables in the database you are connecting to. Please make sure you have - backups of all your data before using an portion of the installer, as this option WILL remove all data. -

      - - Connect and Backup Any Existing Data:pro This options will RENAME all tables in the database you are connecting to with a prefix of - "". -

      - - Manual SQL Execution:pro This options requires that you manually run your own SQL import to an existing database before running the installer. - When this action is selected the database.sql file found inside the archive.zip file will NOT be ran. The database your connecting to should already - be a valid WordPress installed database. This option is viable when you need to run advanced search and replace options on the database. -

      - -
      HostThe name of the host server that the database resides on. Many times this will be 'localhost', however each hosting provider will have it's own naming - convention please check with your server administrator or host to valid for sure the name needed. To add a port number just append it to the host i.e. - 'localhost:3306'.
      DatabaseThe name of the database to which this installation will connect and install the new tables and data into. Some hosts will require a prefix while others - do not. Be sure to know exactly how your host requires the database name to be entered.
      UserThe name of a MySQL database server user. This is special account that has privileges to access a database and can read from or write to that database. - This is not the same thing as your WordPress administrator account.
      PasswordThe password of the MySQL database server user.
      -

      - - -

      Options

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      OptionDetails
      Prefixpro*By default, databases are prefixed with the cPanel account's username (for example, myusername_databasename). However you can ignore this option if - your host does not use the default cPanel username prefix schema. Check the 'Ignore cPanel Prefix' and the username prefixes will be ignored. - This will still require you to enter in the cPanels required setup prefix if they require one. The checkbox will be set to read-only if your host has - disabled prefix settings. Please see your host full requirements when using the cPanel options.
      LegacyWhen creating a database table, the Mysql version being used may not support the collation type of the Mysql version where the table was created. - In this scenario, the installer will fallback to a legacy collation type to try and create the table. This value should only be checked if you receive an error when - testing the database. -

      - For example, if the database was created on MySQL 5.7 and the tables collation type was 'utf8mb4_unicode_520_ci', however your trying to run the installer - on an older MySQL 5.5 engine that does not support that type then an error will be thrown. If this option is checked then the legacy setting will try to - use 'utf8mb4_unicode_520', then 'utf8mb4', then 'utf8' and so on until it runs out of options. -

      - For more information about this feature see the online FAQ question titled - "What is compatibility mode & 'unknown collation' errors" -
      SpacingThe process will remove utf8 characters represented as 'xC2' 'xA0' and replace with a uniform space. Use this option if you find strange question - marks in you posts
      ModeThe MySQL mode option will allow you to set the mode for this session. It is very useful when running into conversion issues. For a full overview please - see the MySQL mode documentation specific to your version.
      CharsetWhen the database is populated from the SQL script it will use this value as part of its connection. Only change this value if you know what your - databases character set should be.
      CollationWhen the database is populated from the SQL script it will use this value as part of its connection. Only change this value if you know what your - databases collation set should be.
      - *cPanel Only Option -

      - -

      Validation

      - Testing the database connection is important and can help isolate possible issues that may arise with database version and compatibility issues. - - - - - - - - - - - - - - -
      OptionDetails
      Test
      Database
      - The 'Test Database' button will help validate if the connection parameters are correct for this server and help with details about any issues - that may arise. -
      Troubleshoot - Common Database Connection Issues:
      - - Double check case sensitive values 'User', 'Password' & the 'Database Name'
      - - Validate the database and database user exist on this server
      - - Check if the database user has the correct permission levels to this database
      - - The host 'localhost' may not work on all hosting providers
      - - Contact your hosting provider for the exact required parameters
      - - Visit the online resources 'Common FAQ page'
      - -
      -

      -

      - - - - -

      Step 3 of 4: Update Data

      -
      - - -

      New Settings

      - These are the new values (URL, Path and Title) you can update for the new location at which your site will be installed at. -

      - -

      Replace pro

      - This section will allow you to add as many custom search and replace items that you would like. For example you can search for other URLs to replace. Please use high - caution when using this feature as it can have unintended consequences as it will search the entire database. It is recommended to only use highly unique items such as - full URL or file paths with this option. -

      - - -

      Options

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      OptionDetails
      New Admin Account
      UsernameA new WordPress username to create. This will create a new WordPress administrator account. Please note that usernames are not changeable from the within the UI.
      PasswordThe new password for the new user. Must be at least 6 characters long.
      Scan Options
      Cleanup proThe checkbox labeled Remove schedules & storage endpoints will empty the Duplicator schedule and storage settings. This is recommended to keep enabled so that you do not have unwanted schedules and storage options enabled.
      Old URLThe old URL of the original values that the package was created with. These values should not be changed, unless you know the underlying reasons
      Old PathThe old path of the original values that the package was created with. These values should not be changed, unless you know the underlying reasons
      Site URL For details see WordPress Site URL & Alternate Directory. If you're not sure about this value then leave it the same as the new settings URL.
      Scan TablesSelect the tables to be updated. This process will update all of the 'Old Settings' with the 'New Settings'. Hold down the 'ctrl key' to select/deselect multiple.
      Activate PluginsThese plug-ins are the plug-ins that were activated when the package was created and represent the plug-ins that will be activated after the install.
      Full SearchFull search forces a scan of every single cell in the database. If it is not checked then only text based columns are searched which makes the update process much faster. - Use this option if you have issues with data not updating correctly.
      Post GUIDIf your moving a site keep this value checked. For more details see the notes on GUIDS. Changing values in the posts table GUID column can change RSS readers to evaluate that the posts are new and may show them in feeds again.
      WP-Config File
      Config SSLTurn off SSL support for WordPress. This sets FORCE_SSL_ADMIN in your wp-config file to false if true, otherwise it will create the setting if not set. The "Enforce on Login" - will turn off SSL support for WordPress Logins.
      Config CacheTurn off Cache support for WordPress. This sets WP_CACHE in your wp-config file to false if true, otherwise it will create the setting if not set. The "Keep Home Path" - sets WPCACHEHOME in your wp-config file to nothing if true, otherwise nothing is changed.
      -

      -

      - - - - -

      Step 4 of 4: Test Site

      -
      -

      Final Steps

      - - Review Install Report
      - The install report is designed to give you a synopsis of the possible errors and warnings that may exist after the installation is completed. -

      - - Test Site
      - After the install is complete run through your entire site and test all pages and posts. -

      - - Security Cleanup
      - When you're completed with the installation please delete all installation files. Leaving these files on your server can impose a security risk! -

      - -
      - - - -

      Troubleshooting Tips

      -
      - -
      - Common Quick Fix Issues: -
        -
      • Use an approved hosting provider
      • -
      • Validate directory and file permissions (see below)
      • -
      • Validate web server configuration file (see below)
      • -
      • Clear your browsers cache
      • -
      • Deactivate and reactivate all plugins
      • -
      • Resave a plugins settings if it reports errors
      • -
      • Make sure your root directory is empty
      • -
      - - Permissions:
      - Not all operating systems are alike. Therefore, when you move a package (zip file) from one location to another the file and directory permissions may not always stick. If this is the case then check your WordPress directories and make sure it's permissions are set to 755. For files make sure the permissions are set to 644 (this does not apply to windows servers). Also pay attention to the owner/group attributes. For a full overview of the correct file changes see the WordPress permissions codex -

      - - Web server configuration files:
      - For Apache web server the root .htaccess file was copied to .htaccess.orig. A new stripped down .htaccess file was created to help simplify access issues. For IIS web server the web.config file was copied to web.config.orig, however no new web.config file was created. If you have not altered this file manually then resaving your permalinks and resaving your plugins should resolve most all changes that were made to the root web configuration file. If your still experiencing issues then open the .orig file and do a compare to see what changes need to be made.

      Plugin Notes:
      It's impossible to know how all 3rd party plugins function. The Duplicator attempts to fix the new install URL for settings stored in the WordPress options table. Please validate that all plugins retained there settings after installing. If you experience issues try to bulk deactivate all plugins then bulk reactivate them on your new duplicated site. If you run into issues were a plugin does not retain its data then try to resave the plugins settings. -

      - - Cache Systems:
      - Any type of cache system such as Super Cache, W3 Cache, etc. should be emptied before you create a package. Another alternative is to include the cache directory in the directory exclusion path list found in the options dialog. Including a directory such as \pathtowordpress\wp-content\w3tc\ (the w3 Total Cache directory) will exclude this directory from being packaged. In is highly recommended to always perform a cache empty when you first fire up your new site even if you excluded your cache directory. -

      - - Trying Again:
      - If you need to retry and reinstall this package you can easily run the process again by deleting all files except the installer and package file and then browse to the installer again. -

      - - Additional Notes:
      - If you have made changes to your PHP files directly this might have an impact on your duplicated site. Be sure all changes made will correspond to the sites new location. - Only the package (zip file) and the installer (php file) should be in the directory where you are installing the site. Please read through our knowledge base before submitting any issues. - If you have a large log file that needs evaluated please email the file, or attach it to a help ticket. -

      - -
      - -
      - -
      For additional help please visit the online resources
      - -

      -
      - + + +
      +

      + For complete help visit the + Online Knowledge-Base
      + Features available only in Duplicator Pro are flagged with a pro tag. +
      + +

      Installer Security

      + +
      + The installer security screen will allow for basic password protection on the installer. The password is set at package creation time. The password + input on this screen must be entered before proceeding with an install. This setting is optional and can be turned on/off via the package creation screens. +

      + + If you do not recall the password then login to the site where the package was created and click the details of the package to view the original password. + To validate the password just typed you can toggle the view by clicking on the lock icon. For detail on how to override this setting visit the online FAQ for + more details. + + + + + + + + + + + + + + +
      OptionDetails
      Locked + "Locked" means a password is protecting each step of the installer. This option is recommended on all installers + that are accessible via a public URL but not required. +
      Unlocked + "Unlocked" means that if your installer is on a public server that anyone can access it. This is a less secure way to run your installer. If you are running the + installer very quickly then removing all the installer files, then the chances of exposing it is going to be low depending on your sites access history. +

      + + While it is not required to have a password set it is recommended. If your URL has little to no traffic or has never been the target of an attack + then running the installer without a password is going to be relatively safe if ran quickly. However, a password is always a good idea. Also, it is + absolutely required and recommended to remove all installer files after installation is completed by logging into the WordPress admin and + following the Duplicator prompts. +
      +
      + + + +

      Step 1 of 4: Deployment

      +
      + There are currently several modes that the installer can be in. The mode will be shown at the top of each screen. Below is an overview of the various modes. + + + + + + + + + + + + + + + + + + + + + + + + +
      OptionDetails
      Standard Install + This mode indicates that the installer and archive have been placed into an empty directory and the site is ready for a fresh/new redeployment. + This is the most common mode and the mode that has been around the longest. +
      Standard Install
      Database Only
      + This mode indicates that the installer and archive were manually moved or transferred to a location and that only the Database will be installed + at this location. +
      Overwrite Install + This mode indicates that the installer was started in a location that contains an existing site -or- the archive file was imported into an existing site using + Duplicator Pro on the destination site (see Duplicator Pro > Tools > Import). In both cases the existing site will be overwritten. +
      Overwrite Install
      Database Only
      + This mode indicates that the installer was started in a location that contains an existing site -or- the archive file was imported into an existing site using + Duplicator Pro on the destination site (see Duplicator Pro > Tools > Import). In both cases the existing site's database will be overwritten. +
      +

      + + + The "Extract Archive" screen is separated into four sections: +

      + +

      Archive

      + This is the archive file the installer must use in order to extract the web site files and database. The 'Name' is a unique key that + ties both the archive and installer together. The installer needs the archive file name to match the 'Name' value exactly character for character in order + for this section to get a pass status. +

      + If the archive name is ever changed then it should be renamed back to the 'Name' value in order for the installer to properly identify it as part of a + complete package. Additional information such as the archive size and the package notes are mentioned in this section. +

      + +

      Validation

      + This section shows the installers system requirements and notices. All requirements must pass in order to proceed to Step 2. Each requirement will show + a Pass/Fail status. Notices on the other hand are not required in order to continue with the install. +

      + + Notices are simply checks that will help you identify any possible issues that might occur. If this section shows a + Good/Warn for various checks. Click on the title link and read the overview for how to solve the test. +

      + +

      Multisite pro

      + The multisite option allows users with a Pro Business or Gold license to perform additional multi-site tasks. All licenses can backup & migrate standalone sites + and full multisite networks. Multisite Plus+ (business and above) adds the ability to install a subsite as a standalone site. +

      + +

      Options

      + The options for step 1 can help better prepare your site should your server need additional settings beyond most general configuration. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      OptionDetails
      General Options
      Extraction + Manual Archive Extraction
      + Set the Extraction value to "Manual Archive Extraction" when the archive file has already been manually extracted on the server. This can be done through your hosts + control panel such as cPanel or by your host directly. This setting can be helpful if you have a large archive files or are having issues with the installer extracting + the file due to timeout issues. +

      + + PHP ZipArchive
      + This extraction method will use the PHP ZipArchive code to extract the archive zip file. +

      + + Shell-Exec Unzip
      + This extraction method will use the PHP shell_exec to call the system unzip + command on the server. This is the default mode that is used if its avail on the server. +

      + +
      Permissions + All Files: Check the 'All Files' check-box and enter in the desired chmod command + to recursively set the octal value on all the files being extracted. Typically this value is 644 on most servers and hosts. +

      + + All Directories: Check the 'All Directories' check-box and enter in the desired chmod command + to recursively set octal value on all the directories being extracted. Typically this value is 755 on most servers and hosts. +
      Advanced Options
      Safe Mode + Safe mode is designed to configure the site with specific options at install time to help over come issues that may happen during the install were the site + is having issues. These options should only be used if you run into issues after you have tried to run an install. +

      + Basic: This safe mode option will disable all the plugins at install time. When this option is set you will need to re-enable all plugins after the + install has full ran. +

      + + Advanced: This option applies all settings used in basic and will also de-activate and reactivate your theme when logging in for the first time. This + options should be used only if the Basic option did not work. +
      Config Files + When dealing with configuration files (.htaccess, web.config and .user.ini) the installer can apply different modes: +

      + + Create New: This is the default recommended option which will create either a new .htaccess or web.config file. The new file is streamlined to help + guarantee no conflicts are created during install. The config files generated with this mode will be simple and basic. The WordFence .user.ini file if + present will be removed. +

      + + Restore Original: This option simply renames the htaccess.orig or web.config.orig files to .htaccess or web.config. The *.orig files come from the original + web server where the package was built. Please note this option will cause issues with the install process if the configuration files are not properly setup to + handle the new server environment. This is an advanced option and should only be used if you know how to properly configure your web servers configuration. +

      + + + + + Additional Notes: + Inside the archive.zip will be a copy of the original .htaccess (Apache) or the web.config (IIS) files that were setup with your packaged site. They are both + renamed to htaccess.orig and web.config.orig. Using either Create New or Restore Original if any existing config files exist for the extraction process they will + be backed up with a .bak extension. +

      +
      File TimesWhen the archive is extracted should it show the current date-time or keep the original time it had when it was built. This setting will be applied to + all files and directories.
      Logging + The level of detail that will be sent to the log file (installer-log.txt). The recommend setting for most installs should be 'Light'. + Note if you use Debug the amount of data written can be very large. Debug is only recommended for support. +
      +

      + +

      Notices

      + To proceed with the install users must check the checkbox labeled " I have read and accept all terms & notices". This means you accept the term of using the software + and are aware of any notices. +

      + +
      +
      + + + + +

      Step 2 of 4: Install Database

      +
      + +

      Basic/cPanel:

      + There are currently two options you can use to perform the database setup. The "Basic" option requires knowledge about the existing server and on most hosts + will require that the database be setup ahead of time. The cPanel option is for hosts that support cPanel Software. + This option will automatically show you the existing databases and users on your cPanel server and allow you to create new databases directly + from the installer. +

      + +

      cPanel Login pro

      + The cPanel connectivity option is only available for Duplicator Pro. + + + + + + + + + + + + + + + + + + + + + +
      OptionDetails
      HostThis should be the primary domain account URL that is associated with your host. Most hosts will require you to register a primary domain name. + This should be the URL that you place in the host field. For example if your primary domain name is "mysite.com" then you would enter in + "https://mysite.com:2083". The port 2038 is the common port number that cPanel works on. If you do not know your primary domain name please contact your + hosting provider or server administrator.
      UsernameThe cPanel username used to login to your cPanel account. This is not the same thing as your WordPress administrator account. + If your unsure of this name please contact your hosting provider or server administrator.
      PasswordThe password of the cPanel user
      Troubleshoot + Common cPanel Connection Issues:
      + - Your host does not use cPanel Software
      + - Your host has disabled cPanel API access
      + - Your host has configured cPanel to work differently (please contact your host)
      + - View a list of valid cPanel Supported Hosts +
      +

      + + +

      Setup

      + The database setup options allow you to connect to an existing database or in the case of cPanel connect or create a new database. + + + + + + + + + + + + + + + + + + + + + + + + + + +
      OptionDetails
      Action + Create New Database: Will attempt to create a new database if it does not exist. When using the 'Basic' option this option will not work on many + hosting providers as the ability to create new databases is normally locked down. If the database does not exist then you will need to login to your + control panel and create the database. If your host supports 'cPanel' then you can use this option to create a new database after logging in via your + cPanel account. +

      + + Connect and Remove All Data: This options will DELETE all tables in the database you are connecting to. Please make sure you have + backups of all your data before using an portion of the installer, as this option WILL remove all data. +

      + + Connect and Backup Any Existing Data:pro This options will RENAME all tables in the database you are connecting to with a prefix of + "". +

      + + Manual SQL Execution:pro This options requires that you manually run your own SQL import to an existing database before running the installer. + When this action is selected the dup-database__[hash].sql file found inside the dup-installer folder of the archive.zip file will NOT be ran. The database your connecting to should already + be a valid WordPress installed database. This option is viable when you need to run advanced search and replace options on the database. +

      + +
      HostThe name of the host server that the database resides on. Many times this will be 'localhost', however each hosting provider will have it's own naming + convention please check with your server administrator or host to valid for sure the name needed. To add a port number just append it to the host i.e. + 'localhost:3306'.
      DatabaseThe name of the database to which this installation will connect and install the new tables and data into. Some hosts will require a prefix while others + do not. Be sure to know exactly how your host requires the database name to be entered.
      UserThe name of a MySQL database server user. This is special account that has privileges to access a database and can read from or write to that database. + This is not the same thing as your WordPress administrator account.
      PasswordThe password of the MySQL database server user.
      +

      + + +

      Options

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      OptionDetails
      Prefixpro*By default, databases are prefixed with the cPanel account's username (for example, myusername_databasename). However you can ignore this option if + your host does not use the default cPanel username prefix schema. Check the 'Ignore cPanel Prefix' and the username prefixes will be ignored. + This will still require you to enter in the cPanels required setup prefix if they require one. The checkbox will be set to read-only if your host has + disabled prefix settings. Please see your host full requirements when using the cPanel options.
      LegacyWhen creating a database table, the Mysql version being used may not support the collation type of the Mysql version where the table was created. + In this scenario, the installer will fallback to a legacy collation type to try and create the table. This value should only be checked if you receive an error when + testing the database. +

      + For example, if the database was created on MySQL 5.7 and the tables collation type was 'utf8mb4_unicode_520_ci', however your trying to run the installer + on an older MySQL 5.5 engine that does not support that type then an error will be thrown. If this option is checked then the legacy setting will try to + use 'utf8mb4_unicode_520', then 'utf8mb4', then 'utf8' and so on until it runs out of options. +

      + For more information about this feature see the online FAQ question titled + "What is compatibility mode & 'unknown collation' errors" +
      SpacingThe process will remove utf8 characters represented as 'xC2' 'xA0' and replace with a uniform space. Use this option if you find strange question + marks in you posts
      ModeThe MySQL mode option will allow you to set the mode for this session. It is very useful when running into conversion issues. For a full overview please + see the MySQL mode documentation specific to your version.
      CharsetWhen the database is populated from the SQL script it will use this value as part of its connection. Only change this value if you know what your + databases character set should be.
      CollationWhen the database is populated from the SQL script it will use this value as part of its connection. Only change this value if you know what your + databases collation set should be.
      + *cPanel Only Option +

      + +

      Validation

      + Testing the database connection is important and can help isolate possible issues that may arise with database version and compatibility issues. + + + + + + + + + + + + + + +
      OptionDetails
      Test
      Database
      + The 'Test Database' button will help validate if the connection parameters are correct for this server and help with details about any issues + that may arise. +
      Troubleshoot + Common Database Connection Issues:
      + - Double check case sensitive values 'User', 'Password' & the 'Database Name'
      + - Validate the database and database user exist on this server
      + - Check if the database user has the correct permission levels to this database
      + - The host 'localhost' may not work on all hosting providers
      + - Contact your hosting provider for the exact required parameters
      + - Visit the online resources 'Common FAQ page'
      + +
      +

      +

      + + + + +

      Step 3 of 4: Update Data

      +
      + + +

      New Settings

      + These are the new values (URL, Path and Title) you can update for the new location at which your site will be installed at. +

      + +

      Replace pro

      + This section will allow you to add as many custom search and replace items that you would like. For example you can search for other URLs to replace. Please use high + caution when using this feature as it can have unintended consequences as it will search the entire database. It is recommended to only use highly unique items such as + full URL or file paths with this option. +

      + + +

      Options

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      OptionDetails
      New Admin Account
      UsernameA new WordPress username to create. This will create a new WordPress administrator account. Please note that usernames are not changeable from the within the UI.
      PasswordThe new password for the new user. Must be at least 6 characters long.
      Scan Options
      Cleanup proThe checkbox labeled Remove schedules & storage endpoints will empty the Duplicator schedule and storage settings. This is recommended to keep enabled so that you do not have unwanted schedules and storage options enabled.
      Old URLThe old URL of the original values that the package was created with. These values should not be changed, unless you know the underlying reasons
      Old PathThe old path of the original values that the package was created with. These values should not be changed, unless you know the underlying reasons
      Site URL For details see WordPress Site URL & Alternate Directory. If you're not sure about this value then leave it the same as the new settings URL.
      Scan TablesSelect the tables to be updated. This process will update all of the 'Old Settings' with the 'New Settings'. Hold down the 'ctrl key' to select/deselect multiple.
      Activate PluginsThese plug-ins are the plug-ins that were activated when the package was created and represent the plug-ins that will be activated after the install.
      Full SearchFull search forces a scan of every single cell in the database. If it is not checked then only text based columns are searched which makes the update process much faster. + Use this option if you have issues with data not updating correctly.
      Post GUIDIf your moving a site keep this value checked. For more details see the notes on GUIDS. Changing values in the posts table GUID column can change RSS readers to evaluate that the posts are new and may show them in feeds again.
      WP-Config File
      Config SSLTurn off SSL support for WordPress. This sets FORCE_SSL_ADMIN in your wp-config file to false if true, otherwise it will create the setting if not set. The "Enforce on Login" + will turn off SSL support for WordPress Logins.
      Config CacheTurn off Cache support for WordPress. This sets WP_CACHE in your wp-config file to false if true, otherwise it will create the setting if not set. The "Keep Home Path" + sets WPCACHEHOME in your wp-config file to nothing if true, otherwise nothing is changed.
      +

      +

      + + + + +

      Step 4 of 4: Test Site

      +
      +

      Final Steps

      + + Review Install Report
      + The install report is designed to give you a synopsis of the possible errors and warnings that may exist after the installation is completed. +

      + + Test Site
      + After the install is complete run through your entire site and test all pages and posts. +

      + + Final Security Cleanup
      + When completed with the installation please delete all installation files. Leaving these files on your server can impose a security risk! You can remove + all the security files by logging into your WordPress admin and following the remove notification links. Be sure these files/directories are removed. Optionally + it is also recommended to remove the archive.zip/daf file. +
        +
      • dup-installer
      • +
      • installer.php
      • +
      • installer-backup.php
      • +
      • installer-bootlog.txt
      • +
      • archive.zip/daf
      • +
      +

      + +
      + + + +

      Troubleshooting Tips

      +
      + +
      + Common Quick Fix Issues: +
        +
      • Use an approved hosting provider
      • +
      • Validate directory and file permissions (see below)
      • +
      • Validate web server configuration file (see below)
      • +
      • Clear your browsers cache
      • +
      • Deactivate and reactivate all plugins
      • +
      • Resave a plugins settings if it reports errors
      • +
      • Make sure your root directory is empty
      • +
      + + Permissions:
      + Not all operating systems are alike. Therefore, when you move a package (zip file) from one location to another the file and directory permissions may not always stick. If this is the case then check your WordPress directories and make sure it's permissions are set to 755. For files make sure the permissions are set to 644 (this does not apply to windows servers). Also pay attention to the owner/group attributes. For a full overview of the correct file changes see the WordPress permissions codex +

      + + Web server configuration files:
      + For Apache web server the root .htaccess file was copied to htaccess.orig. A new stripped down .htaccess file was created to help simplify access issues. For IIS web server the web.config file was copied to web.config.orig, however no new web.config file was created. If you have not altered this file manually then resaving your permalinks and resaving your plugins should resolve most all changes that were made to the root web configuration file. If your still experiencing issues then open the .orig file and do a compare to see what changes need to be made.

      Plugin Notes:
      It's impossible to know how all 3rd party plugins function. The Duplicator attempts to fix the new install URL for settings stored in the WordPress options table. Please validate that all plugins retained there settings after installing. If you experience issues try to bulk deactivate all plugins then bulk reactivate them on your new duplicated site. If you run into issues were a plugin does not retain its data then try to resave the plugins settings. +

      + + Cache Systems:
      + Any type of cache system such as Super Cache, W3 Cache, etc. should be emptied before you create a package. Another alternative is to include the cache directory in the directory exclusion path list found in the options dialog. Including a directory such as \pathtowordpress\wp-content\w3tc\ (the w3 Total Cache directory) will exclude this directory from being packaged. In is highly recommended to always perform a cache empty when you first fire up your new site even if you excluded your cache directory. +

      + + Trying Again:
      + If you need to retry and reinstall this package you can easily run the process again by deleting all files except the installer and package file and then browse to the installer again. +

      + + Additional Notes:
      + If you have made changes to your PHP files directly this might have an impact on your duplicated site. Be sure all changes made will correspond to the sites new location. + Only the package (zip file) and the installer (php file) should be in the directory where you are installing the site. Please read through our knowledge base before submitting any issues. + If you have a large log file that needs evaluated please email the file, or attach it to a help ticket. +

      + +
      + +
      + +
      For additional help please visit the online resources
      + +

      +
      + diff --git a/installer/build/view.init1.php b/installer/build/view.init1.php new file mode 100644 index 00000000..863f4b4f --- /dev/null +++ b/installer/build/view.init1.php @@ -0,0 +1,103 @@ + '1')); + exit; +} + +//POSTBACK: valid password +if ($_POST['secure-pass'] == $user_pass ) { + DUPX_HTTP::post_with_html($page_url, + array( + 'action_step' => '1', + 'secure-pass' => $_POST['secure-pass'])); + exit; +} + +//ERROR: invalid password +if ($_POST['secure-try'] && $_POST['secure-pass'] != $user_pass ) { + $page_err = 1; +} +?> + + +
      + + + +
      + Installer Password +
      + + +
      +

      Invalid Password! Please try again. If the problem persists see the more details link below.

      +
      + + +
      + This file was password protected when it was created. If you do not remember the password check the details of the package on the site where it was created or visit + the online FAQ for more details. +


      + +
      + +
      +
      +
      + + +
      +
      +
      + +
      +
      +
      +
      + + + \ No newline at end of file diff --git a/installer/build/view.step1.php b/installer/build/view.step1.php index cef74726..8777a2f9 100644 --- a/installer/build/view.step1.php +++ b/installer/build/view.step1.php @@ -97,6 +97,7 @@ +
      Step 1 of 4: Deployment @@ -629,6 +630,7 @@
      + diff --git a/installer/build/view.step2.php b/installer/build/view.step2.php index 91e59e53..a84553f6 100644 --- a/installer/build/view.step2.php +++ b/installer/build/view.step2.php @@ -1,424 +1,426 @@ - - - - -
      - - - - - - -
      - Step 2 of 4: Install Database -
      - -
      - - -
      - - - -
      -
      - Setup -
      -
      - - - - - - - - - - - - - - - - - - - - - -
      Action: - -
      Host: - - - - - -
      - - -
      -
      Database: - -
      - -
      -
      User:
      Password:
      -
      -
      - - - -
      -
      -

      cPanel Connectivity

      - - - - -
      - This server does not appear to support cPanel!
      - Consider upgrading to a host that does.
      -
      - - - -
      - Want even easier installs? - Duplicator Pro - allows the following right from the installer: -
      -
        -
      • Directly login to cPanel
      • -
      • Instantly create new databases & users
      • -
      • Preview and select existing databases & users
      • -
      - - Note: Hosts that support cPanel provide remote access to server resources, allowing operations such as direct database and user creation. - Since the Duplicator Pro - installer can directly access cPanel, it dramatically speeds up your workflow. - -
      -
      - - -
      - -
      - - -
      - - - - -


      -


      - - - -
      - - - - - - - - - - - - + + + + +
      + + + + + + + +
      + Step 2 of 4: Install Database +
      + +
      + + +
      + + + +
      +
      + Setup +
      +
      + + + + + + + + + + + + + + + + + + + + + +
      Action: + +
      Host: + + + + + +
      + + +
      +
      Database: + +
      + +
      +
      User:
      Password:
      +
      +
      + + + +
      +
      +

      cPanel Connectivity

      + + + + +
      + This server does not appear to support cPanel!
      + Consider upgrading to a host that does.
      +
      + + + +
      + Want even easier installs? + Duplicator Pro + allows the following right from the installer: +
      +
        +
      • Directly login to cPanel
      • +
      • Instantly create new databases & users
      • +
      • Preview and select existing databases & users
      • +
      + + Note: Hosts that support cPanel provide remote access to server resources, allowing operations such as direct database and user creation. + Since the Duplicator Pro + installer can directly access cPanel, it dramatically speeds up your workflow. + +
      +
      + + +
      + +
      + + +
      + + + + +


      +


      + + + +
      + + + + + + + + + + + + diff --git a/installer/build/view.step3.php b/installer/build/view.step3.php index d4829deb..98c29adc 100644 --- a/installer/build/view.step3.php +++ b/installer/build/view.step3.php @@ -1,339 +1,341 @@ - - - - -
      - - - - - - - - - - - - - - - - - - -
      - Step 3 of 4: Update Data -
      - - - -
      - - - - - - - - - - - - - -
      URL: - - get -
      Path:
      Title:
      -
      -

      - - - - - - -
      - - - - - - \ No newline at end of file diff --git a/views/packages/details/detail.php b/views/packages/details/detail.php index a022ba57..d780e359 100644 --- a/views/packages/details/detail.php +++ b/views/packages/details/detail.php @@ -16,6 +16,8 @@ $mysqlcompat_on = isset($package->Database->Compatible) && strlen($package->Database->Compatible); $mysqlcompat_on = ($mysqldump_on && $mysqlcompat_on) ? true : false; $dbbuild_mode = ($mysqldump_on) ? 'mysqldump' : 'PHP'; +$dup_install_secure_on = isset($package->Installer->OptsSecureOn) ? $package->Installer->OptsSecureOn : 0; +$dup_install_secure_pass = isset($package->Installer->OptsSecurePass) ? DUP_Util::installerUnscramble($package->Installer->OptsSecurePass) : ''; ?> @@ -315,6 +323,32 @@
      + + + + + + + + + + + +
      + : + +
      +
      + + +
      +
      +

      + + + + + @@ -326,7 +360,7 @@ - +
      : Installer->OptsDBHost) ? $package->Installer->OptsDBHost : __('- not set -', 'duplicator') ?>
      : Installer->OptsDBUser) ? $package->Installer->OptsDBUser : __('- not set -', 'duplicator') ?>
      @@ -380,5 +414,21 @@ $( this ).find('div.dup-box-title').trigger("click"); }); }; + + /** + * Submits the password for validation + */ + Duplicator.Pack.TogglePassword = function() + { + var $input = $('#secure-pass'); + var $button = $('#secure-btn'); + if (($input).attr('type') == 'text') { + $input.attr('type', 'password'); + $button.html(''); + } else { + $input.attr('type', 'text'); + $button.html(''); + } + } }); \ No newline at end of file diff --git a/views/packages/main/packages.php b/views/packages/main/packages.php index 9d4aa173..28b4fe48 100644 --- a/views/packages/main/packages.php +++ b/views/packages/main/packages.php @@ -25,11 +25,11 @@ table.dup-pack-table {word-break:break-all;} table.dup-pack-table th {white-space:nowrap !important;} table.dup-pack-table td.pack-name {text-overflow:ellipsis; white-space:nowrap} - table.dup-pack-table td.pack-name sup {font-style:italic;font-size:10px; cursor: pointer } + table.dup-pack-table td.pack-name sup {font-style:italic;font-size:10px; cursor: pointer; display:inline-block; margin-top: -5px } table.dup-pack-table input[name="delete_confirm"] {margin-left:15px} table.dup-pack-table td.fail {border-left: 4px solid #d54e21;} table.dup-pack-table td.pass {border-left: 4px solid #2ea2cc;} - tr.dup-pack-info td {white-space:nowrap; padding:12px 30px 0px 7px;} + tr.dup-pack-info td {white-space:nowrap; padding:10px 30px 0px 7px;} tr.dup-pack-info td.get-btns {text-align:right; padding:3px 5px 6px 0px !important;} tr.dup-pack-info td.get-btns button {box-shadow:none} textarea.dup-pack-debug {width:98%; height:300px; font-size:11px; display:none} diff --git a/views/packages/main/s1.setup2.php b/views/packages/main/s1.setup2.php index 911a79d8..24427673 100644 --- a/views/packages/main/s1.setup2.php +++ b/views/packages/main/s1.setup2.php @@ -1,555 +1,619 @@ - - -
      " data-validate="parsley"> - - - -
      - - -
      -
      -
      -
      - -
      -
      -
      - - -
      -
      -   -
      -
      -
      - - - - - - - - - - - - - - - - - - -
       
      -
      - - - - - - - - - " - data-tooltip=""> - - -
      -
      -
      -

      - - - -
      -
      -   - -    - - - -
      -
      -
      - - - -
      -
        -
      • -
      • -
      - - -
      - - Archive->FilterDirs) ? count(explode(";", $Package->Archive->FilterDirs)) -1 : 0; - $filter_file_count = isset($Package->Archive->FilterFiles) ? count(explode(";", $Package->Archive->FilterFiles)) -1 : 0; - ?> - - Archive->ExportOnlyDB) ? "checked='checked'" :""; ?> /> - - -
      - Archive->FilterOn) ? "checked='checked'" :""; ?> /> - - " - data-tooltip=""> - - -
      - - -
      - - - - - - - - - -
      -
      - -
      -
      -
      - -
      - '; - _e("This option has automatically been checked because you have opted for a Two-Part Install Process. Please complete the package build and continue with the ", 'duplicator'); - printf('%s %s.', - __('', 'duplicator'), - __('Quick Start Two-Part Install Instructions', 'duplicator')); - echo '

      '; - } - - _e("Overview:
      This advanced option excludes all files from the archive. Only the database and a copy of the installer.php " - . "will be included in the archive.zip file. The option can be used for backing up and moving only the database.", 'duplicator'); - - echo '

      '; - - _e(" Notice:
      ", 'duplicator'); - - _e("Please use caution when installing only the database over an existing site and be sure the correct files correspond with the database. For example, " - . "if WordPress 4.6 is on this site and you copy the database to a host that has WordPress 4.8 files then the source code of the files will not be " - . "in sync with the database causing possible errors. If you’re immediately moving the source files with the database then you can ignore this notice. " - . "Please use this advanced feature with caution!", 'duplicator'); - ?> -

      -
      - -
      - - -
      - - - - - - - - -
      - -
      Database->FilterOn) ? "checked='checked'" :""; ?> /> - - " - data-tooltip=""> - -
      -
      - [ ]   - [ ] -
      - get_results("SHOW FULL TABLES FROM `" . DB_NAME . "` WHERE Table_Type = 'BASE TABLE' ", ARRAY_N); - $num_rows = count($tables); - $next_row = round($num_rows / 4, 0); - $counter = 0; - $tableList = explode(',', $Package->Database->FilterTables); - - echo '
      '; - foreach ($tables as $table) { - - if (in_array($table[0], $coreTables)) { - $core_css = 'core-table'; - $core_note = '*'; - } else { - $core_css = 'non-core-table'; - $core_note = ''; - } - - if (in_array($table[0], $tableList)) { - $checked = 'checked="checked"'; - $css = 'text-decoration:line-through'; - } else { - $checked = ''; - $css = ''; - } - echo "
      "; - $counter++; - if ($next_row <= $counter) { - echo '
      '; - $counter = 0; - } - } - echo '
      '; - ?> -
      -
      - -
      - excluded from the database script. ", 'duplicator'); - _e("Excluding certain tables can cause your site or plugins to not work correctly after install!
      ", 'duplicator'); - _e(" Use caution when excluding tables! It is highly recommended to not exclude WordPress core tables*, unless you know the impact.", 'duplicator'); - ?> -
      - -
      -   - " - data-tooltip=""> -   - - [] - -
      - - - Database->Compatible); - $is_mysql40 = in_array('mysql40', $modes); - $is_no_table = in_array('no_table_options', $modes); - $is_no_key = in_array('no_key_options', $modes); - $is_no_field = in_array('no_field_options', $modes); - ?> - - - - - - - -
      - > - - - > - - - > - - - > - -
      - - - - -
      -
      -
      -

      - - -
      -
      - -
      -
      - -
      - -
      - .
      - - " - data-tooltip=""> - -
      - - - - - - - - - - - - - - - - - - - - - -

      - -
      - - - - - " - data-tooltip=""> - - -
      - -
      -

      - - - - -
      - - -title = __('Reset Package Settings?', 'duplicator'); - $confirm1->message = __('This will clear and reset all of the current package settings. Would you like to continue?', 'duplicator'); - $confirm1->jscallback = 'Duplicator.Pack.ResetSettings()'; - $confirm1->initConfirm(); - - $default_name1 = DUP_Package::getDefaultName(); - $default_name2 = DUP_Package::getDefaultName(false); - -?> - \ No newline at end of file From 9babb9842e3a6fb96eaddbb01085d1a9b5567280 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Thu, 9 Aug 2018 00:20:30 +0000 Subject: [PATCH 386/585] - refactor, improve UI feedback, update wording git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1921896 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- classes/package/class.pack.database.php | 2 -- installer/build/classes/class.logging.php | 2 +- views/packages/main/s1.setup2.php | 3 +++ 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/classes/package/class.pack.database.php b/classes/package/class.pack.database.php index 7a09b304..6c51a0c4 100644 --- a/classes/package/class.pack.database.php +++ b/classes/package/class.pack.database.php @@ -227,7 +227,6 @@ private function mysqlDump($exePath) $tables = $wpdb->get_col('SHOW TABLES'); $filterTables = isset($this->FilterTables) ? explode(',', $this->FilterTables) : null; $tblAllCount = count($tables); - $tblFilterOn = ($this->FilterOn) ? 'ON' : 'OFF'; if (is_array($filterTables) && $this->FilterOn) { foreach ($tables as $key => $val) { @@ -290,7 +289,6 @@ private function phpDump() $filterTables = isset($this->FilterTables) ? explode(',', $this->FilterTables) : null; $tblAllCount = count($tables); - $tblFilterOn = ($this->FilterOn) ? 'ON' : 'OFF'; $qryLimit = DUP_Settings::Get('package_phpdump_qrylimit'); if (is_array($filterTables) && $this->FilterOn) { diff --git a/installer/build/classes/class.logging.php b/installer/build/classes/class.logging.php index 2e3d3557..d52a75a5 100644 --- a/installer/build/classes/class.logging.php +++ b/installer/build/classes/class.logging.php @@ -14,7 +14,7 @@ define('ERR_DBCREATE', 'The database "%s" does not exists.
      Change mode to create in order to create a new database.'); define('ERR_DBEMPTY', 'The database "%s" has "%s" tables. The Duplicator only works with an EMPTY database. Enable the action "Connect and Remove All Data" radio button to remove all tables and or create a new database. Some hosting providers do not allow table removal from scripts. In this case you will need to login to your hosting providers control panel and remove the tables manually. Please contact your hosting provider for further details. Always backup all your data before proceeding!'); define('ERR_TESTDB_UTF8', 'UTF8 Characters were detected as part of the database connection string. If your connection fails be sure to update the MySQL my.ini configuration file setting to support UTF8 characters by enabling this option [character_set_server=utf8] and restarting the database server.'); -define('ERR_TESTDB_VERSION_INFO', 'The current version detected was released prior to MySQL 5.5.3 which had a release date of April 8th 2010. WordPress 4.2 included support for utf8mb4 which is only supported in MySQL server 5.5.3+. It is highly recommended to upgrade your version of MySQL server on this server to be more compatible with recent releases of WordPress and avoid issues with install errors.'); +define('ERR_TESTDB_VERSION_INFO', 'If the current version detected was released prior to MySQL 5.5.3 which had a release date of April 8th 2010. WordPress 4.2 included support for utf8mb4 which is only supported in MySQL server 5.5.3+. It is highly recommended to upgrade your version of MySQL server on this server to be more compatible with recent releases of WordPress and avoid issues with install errors.'); define('ERR_TESTDB_VERSION_COMPAT', 'In order to avoid database incompatibility issues make sure the database versions between the build and installer servers are as close as possible. If the package was created on a newer database version than where it is being installed then you might run into issues.

      It is best to make sure the server where the installer is running has the same or higher version number than where it was built. If the major and minor version are the same or close for example [5.7 to 5.6], then the migration should work without issues. A version pair of [5.7 to 5.1] is more likely to cause issues unless you have a very simple setup. If the versions are too far apart work with your hosting provider to upgrade the MySQL engine on this server.

      MariaDB: If see a version of 10.N.N then the database distribution is a MariaDB flavor of MySQL. While the distributions are very close there are some subtle differences. Some operating systems will report the version such as "5.5.5-10.1.21-MariaDB" showing the correlation of both. Please visit the online MariaDB versus MySQL - Compatibility page for more details.

      Please note these messages are simply notices. It is highly recommended that you continue with the install process and closely monitor the installer-log.txt file along with the install report found on step 3 of the installer. Be sure to look for any notices/warnings/errors in these locations to validate the install process did not detect any errors. If any issues are found please visit the FAQ pages and see the question What if I get database errors or general warnings on the install report?.'); define('ERR_NON_SECURE_PASSWORD', 'The database password provided contains a single quote! For security reasons this character is not valid. You have two options:
      1. Remove the single quote character from your password.
      2. Open the installer.php and set the variable $GLOBALS[DUPX_DBPASS_CHECK] = false'); diff --git a/views/packages/main/s1.setup2.php b/views/packages/main/s1.setup2.php index 24427673..24d0d590 100644 --- a/views/packages/main/s1.setup2.php +++ b/views/packages/main/s1.setup2.php @@ -580,14 +580,17 @@ Duplicator.Pack.EnableInstallerPassword = function () { + var $button = $('#secure-btn'); if ($('#secure-on').is(':checked')) { $('#secure-pass').attr('readonly', false); $('#secure-pass').attr('required', 'true').focus(); $('#dup-installer-secure').show(); + $button.removeAttr('disabled'); } else { $('#secure-pass').removeAttr('required'); $('#secure-pass').attr('readonly', true); $('#dup-installer-secure').hide(); + $button.attr('disabled', 'true'); } }; From ef48fadbaabe4abdb8e44c026d3032ca5167edfb Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Tue, 14 Aug 2018 15:59:11 +0000 Subject: [PATCH 387/585] - improved password enhancements - improve db connection messages git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1924732 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- classes/class.password.php | 228 +++++++++++++++++ classes/package/class.pack.installer.php | 7 +- classes/utilities/class.u.php | 4 +- installer/build/assets/inc.css.php | 2 +- installer/build/classes/class.logging.php | 6 +- installer/build/classes/class.password.php | 229 ++++++++++++++++++ .../build/classes/config/class.conf.wp.php | 7 +- installer/build/ctrls/ctrl.step2.php | 30 +-- installer/build/ctrls/ctrl.step3.php | 7 +- installer/build/main.installer.php | 13 +- installer/build/view.init1.php | 10 +- views/packages/main/controller.php | 96 ++++---- 12 files changed, 545 insertions(+), 94 deletions(-) create mode 100644 classes/class.password.php create mode 100644 installer/build/classes/class.password.php diff --git a/classes/class.password.php b/classes/class.password.php new file mode 100644 index 00000000..2175e17d --- /dev/null +++ b/classes/class.password.php @@ -0,0 +1,228 @@ + in 2004-2006 and placed in +# the public domain. Revised in subsequent years, still public domain. +# +# There's absolutely no warranty. +# +# The homepage URL for this framework is: +# +# http://www.openwall.com/phpass/ +# +# Please be sure to update the Version line if you edit this file in any way. +# It is suggested that you leave the main version number intact, but indicate +# your project name (after the slash) and add your own revision information. +# +# Please do not change the "private" password hashing method implemented in +# here, thereby making your hashes incompatible. However, if you must, please +# change the hash type identifier (the "$P$") to something different. +# +# Obviously, since this code is in the public domain, the above are not +# requirements (there can be none), but merely suggestions. +# +class DUP_PasswordHash +{ + + var $itoa64; + var $iteration_count_log2; + var $portable_hashes; + var $random_state; + + function __construct($iteration_count_log2, $portable_hashes) + { + $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + + if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) + $iteration_count_log2 = 8; + $this->iteration_count_log2 = $iteration_count_log2; + + $this->portable_hashes = $portable_hashes; + + $this->random_state = microtime(); + if (function_exists('getmypid')) + $this->random_state .= getmypid(); + } + + function PasswordHash($iteration_count_log2, $portable_hashes) + { + self::__construct($iteration_count_log2, $portable_hashes); + } + + function get_random_bytes($count) + { + $output = ''; + if (@is_readable('/dev/urandom') && + ($fh = @fopen('/dev/urandom', 'rb'))) { + $output = fread($fh, $count); + fclose($fh); + } + + if (strlen($output) < $count) { + $output = ''; + for ($i = 0; $i < $count; $i += 16) { + $this->random_state = + md5(microtime() . $this->random_state); + $output .= md5($this->random_state, TRUE); + } + $output = substr($output, 0, $count); + } + + return $output; + } + + function encode64($input, $count) + { + $output = ''; + $i = 0; + do { + $value = ord($input[$i++]); + $output .= $this->itoa64[$value & 0x3f]; + if ($i < $count) + $value |= ord($input[$i]) << 8; + $output .= $this->itoa64[($value >> 6) & 0x3f]; + if ($i++ >= $count) + break; + if ($i < $count) + $value |= ord($input[$i]) << 16; + $output .= $this->itoa64[($value >> 12) & 0x3f]; + if ($i++ >= $count) + break; + $output .= $this->itoa64[($value >> 18) & 0x3f]; + } while ($i < $count); + + return $output; + } + + function gensalt_private($input) + { + $output = '$P$'; + $output .= $this->itoa64[min($this->iteration_count_log2 + + ((PHP_VERSION >= '5') ? 5 : 3), 30)]; + $output .= $this->encode64($input, 6); + + return $output; + } + + function crypt_private($password, $setting) + { + $output = '*0'; + if (substr($setting, 0, 2) === $output) + $output = '*1'; + + $id = substr($setting, 0, 3); + # We use "$P$", phpBB3 uses "$H$" for the same thing + if ($id !== '$P$' && $id !== '$H$') + return $output; + + $count_log2 = strpos($this->itoa64, $setting[3]); + if ($count_log2 < 7 || $count_log2 > 30) + return $output; + + $count = 1 << $count_log2; + + $salt = substr($setting, 4, 8); + if (strlen($salt) !== 8) + return $output; + + # We were kind of forced to use MD5 here since it's the only + # cryptographic primitive that was available in all versions + # of PHP in use. To implement our own low-level crypto in PHP + # would have resulted in much worse performance and + # consequently in lower iteration counts and hashes that are + # quicker to crack (by non-PHP code). + $hash = md5($salt . $password, TRUE); + do { + $hash = md5($hash . $password, TRUE); + } while (--$count); + + $output = substr($setting, 0, 12); + $output .= $this->encode64($hash, 16); + + return $output; + } + + function gensalt_blowfish($input) + { + # This one needs to use a different order of characters and a + # different encoding scheme from the one in encode64() above. + # We care because the last character in our encoded string will + # only represent 2 bits. While two known implementations of + # bcrypt will happily accept and correct a salt string which + # has the 4 unused bits set to non-zero, we do not want to take + # chances and we also do not want to waste an additional byte + # of entropy. + $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + + $output = '$2a$'; + $output .= chr(ord('0') + $this->iteration_count_log2 / 10); + $output .= chr(ord('0') + $this->iteration_count_log2 % 10); + $output .= '$'; + + $i = 0; + do { + $c1 = ord($input[$i++]); + $output .= $itoa64[$c1 >> 2]; + $c1 = ($c1 & 0x03) << 4; + if ($i >= 16) { + $output .= $itoa64[$c1]; + break; + } + + $c2 = ord($input[$i++]); + $c1 |= $c2 >> 4; + $output .= $itoa64[$c1]; + $c1 = ($c2 & 0x0f) << 2; + + $c2 = ord($input[$i++]); + $c1 |= $c2 >> 6; + $output .= $itoa64[$c1]; + $output .= $itoa64[$c2 & 0x3f]; + } while (1); + + return $output; + } + + function HashPassword($password) + { + $random = ''; + + if (CRYPT_BLOWFISH === 1 && !$this->portable_hashes) { + $random = $this->get_random_bytes(16); + $hash = + crypt($password, $this->gensalt_blowfish($random)); + if (strlen($hash) === 60) + return $hash; + } + + if (strlen($random) < 6) + $random = $this->get_random_bytes(6); + $hash = + $this->crypt_private($password, + $this->gensalt_private($random)); + if (strlen($hash) === 34) + return $hash; + + # Returning '*' on error is safe here, but would _not_ be safe + # in a crypt(3)-like function used _both_ for generating new + # hashes and for validating passwords against existing hashes. + return '*'; + } + + function CheckPassword($password, $stored_hash) + { + $hash = $this->crypt_private($password, $stored_hash); + if ($hash[0] === '*') + $hash = crypt($password, $stored_hash); + + # This is not constant-time. In order to keep the code simple, + # for timing safety we currently rely on the salts being + # unpredictable, which they are at least in the non-fallback + # cases (that is, when we use /dev/urandom and bcrypt). + return $hash === $stored_hash; + } +} + diff --git a/classes/package/class.pack.installer.php b/classes/package/class.pack.installer.php index ef2ed2f0..f83a63a4 100644 --- a/classes/package/class.pack.installer.php +++ b/classes/package/class.pack.installer.php @@ -1,5 +1,6 @@ "@@CLASS.HTTP.PHP@@", "classes/config/class.conf.wp.php" => "@@CLASS.CONF.WP.PHP@@", "classes/config/class.conf.srv.php" => "@@CLASS.CONF.SRV.PHP@@", + "classes/class.password.php" => "@@CLASS.PASSWORD.PHP@@", "ctrls/ctrl.step1.php" => "@@CTRL.STEP1.PHP@@", "ctrls/ctrl.step2.php" => "@@CTRL.STEP2.PHP@@", "ctrls/ctrl.step3.php" => "@@CTRL.STEP3.PHP@@", @@ -143,6 +145,9 @@ private function createFromTemplate($template) DUP_Log::Info("PACK SIZE: {$this->Package->Size}"); + $hasher = new DUP_PasswordHash(8, FALSE); + $pass_hash = $hasher->HashPassword($this->Package->Installer->OptsSecurePass); + $replace_items = Array( //COMPARE VALUES "fwrite_created" => $this->Package->Created, @@ -163,7 +168,7 @@ private function createFromTemplate($template) "fwrite_dbname" => $this->Package->Installer->OptsDBName, "fwrite_dbuser" => $this->Package->Installer->OptsDBUser, "fwrite_secureon" => $this->Package->Installer->OptsSecureOn, - "fwrite_securepass" => $this->Package->Installer->OptsSecurePass, + "fwrite_securepass" => $pass_hash, "fwrite_dbpass" => '', "fwrite_wp_tableprefix" => $wpdb->prefix, "fwrite_opts_delete" => json_encode($deleteOpts), diff --git a/classes/utilities/class.u.php b/classes/utilities/class.u.php index ab226bc3..f88c4e98 100644 --- a/classes/utilities/class.u.php +++ b/classes/utilities/class.u.php @@ -6,7 +6,7 @@ * @link http://www.php-fig.org/psr/psr-2 * * @package Duplicator - * @subpackage classes/utilites + * @subpackage classes/utilities * @copyright (c) 2017, Snapcreek LLC * @since 1.1.0 * @@ -18,7 +18,7 @@ exit; } -require_once (DUPLICATOR_PLUGIN_PATH.'classes/class.crypt.php'); +//require_once (DUPLICATOR_PLUGIN_PATH.'classes/class.crypt.php'); class DUP_Util { diff --git a/installer/build/assets/inc.css.php b/installer/build/assets/inc.css.php index 5d8cb2c3..b910e6f2 100644 --- a/installer/build/assets/inc.css.php +++ b/installer/build/assets/inc.css.php @@ -138,7 +138,7 @@ table.s2-db-test-dtls {text-align: left; margin: auto} table.s2-db-test-dtls td:first-child {font-weight: bold} div#s2-dbconn-test-msg {font-size:12px} - div#s2-dbconn-status {border:1px solid silver; border-radius:3px; background-color:#f9f9f9; padding:2px 5px; margin-top:10px; height:175px; overflow-y: scroll} + div#s2-dbconn-status {border:1px solid silver; border-radius:3px; background-color:#f9f9f9; padding:2px 5px; margin-top:10px; height:200px; overflow-y: scroll} div#s2-dbconn-status div.warn-msg {text-align: left; padding:5px; margin:10px 0 10px 0} div#s2-dbconn-status div.warn-msg b{color:maroon} diff --git a/installer/build/classes/class.logging.php b/installer/build/classes/class.logging.php index d52a75a5..7050cf94 100644 --- a/installer/build/classes/class.logging.php +++ b/installer/build/classes/class.logging.php @@ -9,14 +9,14 @@ define('ERR_ZIPARCHIVE', 'In order to extract the archive.zip file the PHP ZipArchive module must be installed. Please read the FAQ for more details. You can still install this package but you will need to check the Manual package extraction checkbox found in the Advanced Options. Please read the online user guide for details in performing a manual package extraction.'); define('ERR_MYSQLI_SUPPORT', 'In order to complete an install the mysqli extension for PHP is required. If you are on a hosted server please contact your host and request that mysqli be enabled. For more information visit: http://php.net/manual/en/mysqli.installation.php'); define('ERR_DBCONNECT', 'DATABASE CONNECTION FAILED!
      '); +define('ERR_DBCONNECT_INFO', 'DATABASE CONNECTION FAILED!
      If the problem persists see the online FAQ for recommended fixes.'); define('ERR_DBCONNECT_CREATE', 'DATABASE CREATION FAILURE!
      Unable to create database "%s". Check to make sure the user has "Create" privileges. Some hosts will restrict creation of a database only through the cpanel. Try creating the database manually to proceed with installation. If the database already exists then check the radio button labeled "Connect and Remove All Data" which will remove all existing tables.'); define('ERR_DBTRYCLEAN', 'DATABASE CREATION FAILURE!
      Unable to remove all tables from database "%s".
      Please remove all tables from this database and try the installation again.'); define('ERR_DBCREATE', 'The database "%s" does not exists.
      Change mode to create in order to create a new database.'); define('ERR_DBEMPTY', 'The database "%s" has "%s" tables. The Duplicator only works with an EMPTY database. Enable the action "Connect and Remove All Data" radio button to remove all tables and or create a new database. Some hosting providers do not allow table removal from scripts. In this case you will need to login to your hosting providers control panel and remove the tables manually. Please contact your hosting provider for further details. Always backup all your data before proceeding!'); define('ERR_TESTDB_UTF8', 'UTF8 Characters were detected as part of the database connection string. If your connection fails be sure to update the MySQL my.ini configuration file setting to support UTF8 characters by enabling this option [character_set_server=utf8] and restarting the database server.'); -define('ERR_TESTDB_VERSION_INFO', 'If the current version detected was released prior to MySQL 5.5.3 which had a release date of April 8th 2010. WordPress 4.2 included support for utf8mb4 which is only supported in MySQL server 5.5.3+. It is highly recommended to upgrade your version of MySQL server on this server to be more compatible with recent releases of WordPress and avoid issues with install errors.'); -define('ERR_TESTDB_VERSION_COMPAT', 'In order to avoid database incompatibility issues make sure the database versions between the build and installer servers are as close as possible. If the package was created on a newer database version than where it is being installed then you might run into issues.

      It is best to make sure the server where the installer is running has the same or higher version number than where it was built. If the major and minor version are the same or close for example [5.7 to 5.6], then the migration should work without issues. A version pair of [5.7 to 5.1] is more likely to cause issues unless you have a very simple setup. If the versions are too far apart work with your hosting provider to upgrade the MySQL engine on this server.

      MariaDB: If see a version of 10.N.N then the database distribution is a MariaDB flavor of MySQL. While the distributions are very close there are some subtle differences. Some operating systems will report the version such as "5.5.5-10.1.21-MariaDB" showing the correlation of both. Please visit the online MariaDB versus MySQL - Compatibility page for more details.

      Please note these messages are simply notices. It is highly recommended that you continue with the install process and closely monitor the installer-log.txt file along with the install report found on step 3 of the installer. Be sure to look for any notices/warnings/errors in these locations to validate the install process did not detect any errors. If any issues are found please visit the FAQ pages and see the question What if I get database errors or general warnings on the install report?.'); -define('ERR_NON_SECURE_PASSWORD', 'The database password provided contains a single quote! For security reasons this character is not valid. You have two options:
      1. Remove the single quote character from your password.
      2. Open the installer.php and set the variable $GLOBALS[DUPX_DBPASS_CHECK] = false'); +define('ERR_TESTDB_VERSION_INFO', 'If the current version detected is below 5.5.3 (release on April 8th 2010) then support for utf8mb4 tables will not work. The utf8mb4 format is only supported in MySQL server 5.5.3+. It is highly recommended to upgrade your version of MySQL server on this server to be more compatible with recent releases of WordPress and avoid issues with install errors.'); +define('ERR_TESTDB_VERSION_COMPAT', 'In order to avoid database incompatibility issues make sure the database versions between the build and installer servers are as close as possible. If the package was created on a newer database version than where it is being installed then you might run into issues.

      It is best to make sure the server where the installer is running has the same or higher version number than where it was built. If the major and minor version are the same or close for example [5.7 to 5.6], then the migration should work without issues. A version pair of [5.7 to 5.1] is more likely to cause issues unless you have a very simple setup. If the versions are too far apart work with your hosting provider to upgrade the MySQL engine on this server.

      MariaDB: If a version of 10.N.N shows then the database distribution is a MariaDB flavor of MySQL. While the distributions are very close there are some subtle differences. Some operating systems will report the version such as "5.5.5-10.1.21-MariaDB" showing the correlation of both. Please visit the online MariaDB versus MySQL - Compatibility page for more details.

      Please note these messages are simply notices. It is highly recommended that you continue with the install process and closely monitor the installer-log.txt file along with the install report found on step 3 of the installer. Be sure to look for any notices/warnings/errors in these locations to validate the install process did not detect any errors. If any issues are found please visit the FAQ pages and see the question What if I get database errors or general warnings on the install report?.'); /** * Class used to log information to the installer-log.txt file diff --git a/installer/build/classes/class.password.php b/installer/build/classes/class.password.php new file mode 100644 index 00000000..b1a5f75f --- /dev/null +++ b/installer/build/classes/class.password.php @@ -0,0 +1,229 @@ + in 2004-2006 and placed in +# the public domain. Revised in subsequent years, still public domain. +# +# There's absolutely no warranty. +# +# The homepage URL for this framework is: +# +# http://www.openwall.com/phpass/ +# +# Please be sure to update the Version line if you edit this file in any way. +# It is suggested that you leave the main version number intact, but indicate +# your project name (after the slash) and add your own revision information. +# +# Please do not change the "private" password hashing method implemented in +# here, thereby making your hashes incompatible. However, if you must, please +# change the hash type identifier (the "$P$") to something different. +# +# Obviously, since this code is in the public domain, the above are not +# requirements (there can be none), but merely suggestions. +# +class DUPX_PasswordHash +{ + + var $itoa64; + var $iteration_count_log2; + var $portable_hashes; + var $random_state; + + function __construct($iteration_count_log2, $portable_hashes) + { + $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + + if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) + $iteration_count_log2 = 8; + $this->iteration_count_log2 = $iteration_count_log2; + + $this->portable_hashes = $portable_hashes; + + $this->random_state = microtime(); + if (function_exists('getmypid')) + $this->random_state .= getmypid(); + } + + function PasswordHash($iteration_count_log2, $portable_hashes) + { + self::__construct($iteration_count_log2, $portable_hashes); + } + + function get_random_bytes($count) + { + $output = ''; + if (@is_readable('/dev/urandom') && + ($fh = @fopen('/dev/urandom', 'rb'))) { + $output = fread($fh, $count); + fclose($fh); + } + + if (strlen($output) < $count) { + $output = ''; + for ($i = 0; $i < $count; $i += 16) { + $this->random_state = + md5(microtime() . $this->random_state); + $output .= md5($this->random_state, TRUE); + } + $output = substr($output, 0, $count); + } + + return $output; + } + + function encode64($input, $count) + { + $output = ''; + $i = 0; + do { + $value = ord($input[$i++]); + $output .= $this->itoa64[$value & 0x3f]; + if ($i < $count) + $value |= ord($input[$i]) << 8; + $output .= $this->itoa64[($value >> 6) & 0x3f]; + if ($i++ >= $count) + break; + if ($i < $count) + $value |= ord($input[$i]) << 16; + $output .= $this->itoa64[($value >> 12) & 0x3f]; + if ($i++ >= $count) + break; + $output .= $this->itoa64[($value >> 18) & 0x3f]; + } while ($i < $count); + + return $output; + } + + function gensalt_private($input) + { + $output = '$P$'; + $output .= $this->itoa64[min($this->iteration_count_log2 + + ((PHP_VERSION >= '5') ? 5 : 3), 30)]; + $output .= $this->encode64($input, 6); + + return $output; + } + + function crypt_private($password, $setting) + { + $output = '*0'; + if (substr($setting, 0, 2) === $output) + $output = '*1'; + + $id = substr($setting, 0, 3); + # We use "$P$", phpBB3 uses "$H$" for the same thing + if ($id !== '$P$' && $id !== '$H$') + return $output; + + $count_log2 = strpos($this->itoa64, $setting[3]); + if ($count_log2 < 7 || $count_log2 > 30) + return $output; + + $count = 1 << $count_log2; + + $salt = substr($setting, 4, 8); + if (strlen($salt) !== 8) + return $output; + + # We were kind of forced to use MD5 here since it's the only + # cryptographic primitive that was available in all versions + # of PHP in use. To implement our own low-level crypto in PHP + # would have resulted in much worse performance and + # consequently in lower iteration counts and hashes that are + # quicker to crack (by non-PHP code). + $hash = md5($salt . $password, TRUE); + do { + $hash = md5($hash . $password, TRUE); + } while (--$count); + + $output = substr($setting, 0, 12); + $output .= $this->encode64($hash, 16); + + return $output; + } + + function gensalt_blowfish($input) + { + # This one needs to use a different order of characters and a + # different encoding scheme from the one in encode64() above. + # We care because the last character in our encoded string will + # only represent 2 bits. While two known implementations of + # bcrypt will happily accept and correct a salt string which + # has the 4 unused bits set to non-zero, we do not want to take + # chances and we also do not want to waste an additional byte + # of entropy. + $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + + $output = '$2a$'; + $output .= chr(ord('0') + $this->iteration_count_log2 / 10); + $output .= chr(ord('0') + $this->iteration_count_log2 % 10); + $output .= '$'; + + $i = 0; + do { + $c1 = ord($input[$i++]); + $output .= $itoa64[$c1 >> 2]; + $c1 = ($c1 & 0x03) << 4; + if ($i >= 16) { + $output .= $itoa64[$c1]; + break; + } + + $c2 = ord($input[$i++]); + $c1 |= $c2 >> 4; + $output .= $itoa64[$c1]; + $c1 = ($c2 & 0x0f) << 2; + + $c2 = ord($input[$i++]); + $c1 |= $c2 >> 6; + $output .= $itoa64[$c1]; + $output .= $itoa64[$c2 & 0x3f]; + } while (1); + + return $output; + } + + function HashPassword($password) + { + $random = ''; + + if (CRYPT_BLOWFISH === 1 && !$this->portable_hashes) { + $random = $this->get_random_bytes(16); + $hash = + crypt($password, $this->gensalt_blowfish($random)); + if (strlen($hash) === 60) + return $hash; + } + + if (strlen($random) < 6) + $random = $this->get_random_bytes(6); + $hash = + $this->crypt_private($password, + $this->gensalt_private($random)); + if (strlen($hash) === 34) + return $hash; + + # Returning '*' on error is safe here, but would _not_ be safe + # in a crypt(3)-like function used _both_ for generating new + # hashes and for validating passwords against existing hashes. + return '*'; + } + + function CheckPassword($password, $stored_hash) + { + $hash = $this->crypt_private($password, $stored_hash); + if ($hash[0] === '*') + $hash = crypt($password, $stored_hash); + + # This is not constant-time. In order to keep the code simple, + # for timing safety we currently rely on the salts being + # unpredictable, which they are at least in the non-fallback + # cases (that is, when we use /dev/urandom and bcrypt). + return $hash === $stored_hash; + } +} + +?> diff --git a/installer/build/classes/config/class.conf.wp.php b/installer/build/classes/config/class.conf.wp.php index 7c27149c..388433e4 100644 --- a/installer/build/classes/config/class.conf.wp.php +++ b/installer/build/classes/config/class.conf.wp.php @@ -13,7 +13,7 @@ class DUPX_WPConfig { /** - * Updates the web server config files in Step 1 + * Updates the web server config files in Step 3 * * @return null */ @@ -23,6 +23,7 @@ public static function updateStandard() $root_path = DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']); $wpconfig = @file_get_contents('wp-config.php', true); + $_POST['dbpass'] = isset($_POST['dbpass']) ? str_replace("'", "\'", $_POST['dbpass']) : null; $patterns = array( "/'DB_NAME',\s*'.*?'/", @@ -35,7 +36,7 @@ public static function updateStandard() $replace = array( "'DB_NAME', ".'\''.$_POST['dbname'].'\'', "'DB_USER', ".'\''.$_POST['dbuser'].'\'', - "'DB_PASSWORD', ".'\''.DUPX_U::pregReplacementQuote($_POST['dbpass']).'\'', + "'DB_PASSWORD', " . '\'' . DUPX_U::pregReplacementQuote($_POST['dbpass']) . '\'', "'DB_HOST', ".'\''.$db_host.'\''); //SSL CHECKS @@ -76,7 +77,7 @@ public static function updateStandard() } /** - * Updates the web server config files in Step 1 + * Updates the web server config files in Step 3 * * @return null */ diff --git a/installer/build/ctrls/ctrl.step2.php b/installer/build/ctrls/ctrl.step2.php index 07d82e8c..95d80699 100644 --- a/installer/build/ctrls/ctrl.step2.php +++ b/installer/build/ctrls/ctrl.step2.php @@ -50,11 +50,11 @@ $dbversion_info = DUPX_DB::getServerInfo($dbConn); $dbversion_info = empty($dbversion_info) ? 'no connection' : $dbversion_info; - $dbversion_info_fail = version_compare(DUPX_DB::getVersion($dbConn), '5.5.3') < 0; + $dbversion_info_fail = $dbConn && version_compare(DUPX_DB::getVersion($dbConn), '5.5.3') < 0; $dbversion_compat = DUPX_DB::getVersion($dbConn); $dbversion_compat = empty($dbversion_compat) ? 'no connection' : $dbversion_compat; - $dbversion_compat_fail = version_compare($dbversion_compat, $GLOBALS['FW_VERSION_DB']) < 0; + $dbversion_compat_fail = $dbConn && version_compare($dbversion_compat, $GLOBALS['FW_VERSION_DB']) < 0; $tstInfo = ($dbversion_info_fail) ? "
      {$dbversion_info}
      " @@ -91,6 +91,11 @@ DATA; //-------------------------------- + //WARNING: Unable to connect + $html .= (!$dbConn || !$dbFound) + ? "
      " . ERR_DBCONNECT_INFO . "
      " + : ''; + //WARNING: DB has tables with create option if ($_POST['dbaction'] == 'create') { @@ -103,8 +108,7 @@ //WARNNG: Input has utf8 $dbConnItems = array($_POST['dbhost'], $_POST['dbuser'], $_POST['dbname'],$_POST['dbpass']); $dbUTF8_tst = false; - foreach ($dbConnItems as $value) - { + foreach ($dbConnItems as $value) { if (DUPX_U::isNonASCII($value)) { $dbUTF8_tst = true; break; @@ -112,7 +116,7 @@ } //WARNING: UTF8 Data in Connection String - $html .= (! $dbConn && $dbUTF8_tst) + $html .= (!$dbConn && $dbUTF8_tst) ? "
      WARNING: " . ERR_TESTDB_UTF8 . "
      " : ''; @@ -137,22 +141,6 @@ //ERR_MAKELOG ($GLOBALS['LOG_FILE_HANDLE'] != false) or DUPX_Log::error(ERR_MAKELOG); -//ERR_NON_SECURE_PASSWORD -if ($GLOBALS['DUPX_DBPASS_CHECK']) { - $dbpass_test_chars = array("'"); - $dbpass_char_found = false; - $dbpass_sent = urldecode($_POST['dbpass']); - foreach ($dbpass_test_chars as $value) { - if (strpos($dbpass_sent, $value)) { - $dbpass_char_found = true; - break; - } - } - if ($dbpass_char_found) { - DUPX_Log::error(ERR_NON_SECURE_PASSWORD); - } -} - //ERR_MYSQLI_SUPPORT function_exists('mysqli_connect') or DUPX_Log::error(ERR_MYSQLI_SUPPORT); diff --git a/installer/build/ctrls/ctrl.step3.php b/installer/build/ctrls/ctrl.step3.php index 00392d19..730948bc 100644 --- a/installer/build/ctrls/ctrl.step3.php +++ b/installer/build/ctrls/ctrl.step3.php @@ -30,9 +30,8 @@ $_POST['url_new'] = isset($_POST['url_new']) ? rtrim(trim($_POST['url_new']), '/') : null; $_POST['retain_config'] = (isset($_POST['retain_config']) && $_POST['retain_config'] == '1') ? true : false; $_POST['exe_safe_mode'] = isset($_POST['exe_safe_mode']) ? $_POST['exe_safe_mode'] : 0; -if ($GLOBALS['DUPX_DBPASS_CHECK']) { - $_POST['dbpass'] = isset($_POST['dbpass']) ? str_replace("'", '', $_POST['dbpass']) : null; -} +$_POST['dbpass'] = isset($_POST['dbpass']) ? $_POST['dbpass'] : null; + //MYSQL CONNECTION $dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], html_entity_decode($_POST['dbpass']), $_POST['dbname'], $_POST['dbport']); @@ -332,8 +331,6 @@ function _dupx_array_rtrim(&$value) { mysqli_close($dbh); - - $ajax2_end = DUPX_U::getMicrotime(); $ajax2_sum = DUPX_U::elapsedTime($ajax2_end, $ajax2_start); DUPX_Log::info("\nSTEP 3 COMPLETE @ " . @date('h:i:s') . " - RUNTIME: {$ajax2_sum}\n\n"); diff --git a/installer/build/main.installer.php b/installer/build/main.installer.php index 6c753567..3ef1e9dc 100644 --- a/installer/build/main.installer.php +++ b/installer/build/main.installer.php @@ -145,9 +145,12 @@ //SHARED POST PARMS $_POST['action_step'] = isset($_POST['action_step']) ? $_POST['action_step'] : "0"; -$_POST['secure-pass'] = isset($_POST['secure-pass']) ? $_POST['secure-pass'] : ""; +$_POST['secure-pass'] = isset($_POST['secure-pass']) ? $_POST['secure-pass'] : ''; + if ($GLOBALS['FW_SECUREON']) { - if (base64_decode($GLOBALS['FW_SECUREPASS']) != $_POST['secure-pass']) { + $pass_hasher = new DUPX_PasswordHash(8, FALSE); + $pass_check = $pass_hasher->CheckPassword(base64_encode($_POST['secure-pass']), $GLOBALS['FW_SECUREPASS']); + if (! $pass_check) { $_POST['action_step'] = 0; } } @@ -191,11 +194,14 @@ @@CLASS.CONF.WP.PHP@@ @@CLASS.CONF.SRV.PHP@@ @@CLASS.HTTP.PHP@@ +@@CLASS.PASSWORD.PHP@@ CheckPassword(base64_encode($_POST['secure-pass']), $GLOBALS['FW_SECUREPASS']); + if (! $pass_check) { die("Unauthorized Access: Please provide a password!"); } } @@ -220,7 +226,6 @@ endif; ?> - diff --git a/installer/build/view.init1.php b/installer/build/view.init1.php index 863f4b4f..e2bcef56 100644 --- a/installer/build/view.init1.php +++ b/installer/build/view.init1.php @@ -2,15 +2,13 @@ /** IDE HELPERS */ /* @var $GLOBALS['DUPX_AC'] DUPX_ArchiveConfig */ -//require_once($GLOBALS['DUPX_INIT'] . '/classes/class.crypt.php'); - - $_POST['secure-pass'] = isset($_POST['secure-pass']) ? $_POST['secure-pass'] : '' ; $_POST['secure-try'] = isset($_POST['secure-try']) ? 1 : 0 ; $_GET['debug'] = isset($_GET['debug']) ? $_GET['debug'] : 0; $page_url = DUPX_HTTP::get_request_uri(); $page_err = 0; -$user_pass = base64_decode($GLOBALS['FW_SECUREPASS']); +$pass_hasher = new DUPX_PasswordHash(8, FALSE); +$pass_check = $pass_hasher->CheckPassword(base64_encode($_POST['secure-pass']), $GLOBALS['FW_SECUREPASS']); //FORWARD: password not enabled if (! $GLOBALS['FW_SECUREON'] && ! $_GET['debug']) { @@ -19,7 +17,7 @@ } //POSTBACK: valid password -if ($_POST['secure-pass'] == $user_pass ) { +if ($pass_check) { DUPX_HTTP::post_with_html($page_url, array( 'action_step' => '1', @@ -28,7 +26,7 @@ } //ERROR: invalid password -if ($_POST['secure-try'] && $_POST['secure-pass'] != $user_pass ) { +if ($_POST['secure-try'] && ! $pass_check) { $page_err = 1; } ?> diff --git a/views/packages/main/controller.php b/views/packages/main/controller.php index 16beb45f..cc5e3bf0 100644 --- a/views/packages/main/controller.php +++ b/views/packages/main/controller.php @@ -1,49 +1,49 @@ - - - - - + + + + \ No newline at end of file From eb729324fce5fbf191309b3d0c6f1efd35d79b64 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Wed, 15 Aug 2018 16:46:58 +0000 Subject: [PATCH 388/585] - improved password setup git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1925343 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- views/packages/main/s1.setup2.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/views/packages/main/s1.setup2.php b/views/packages/main/s1.setup2.php index 24d0d590..afca4b0c 100644 --- a/views/packages/main/s1.setup2.php +++ b/views/packages/main/s1.setup2.php @@ -18,7 +18,8 @@ select#archive-format {min-width:100px; margin:1px 0 4px 0} span#dup-archive-filter-file {color:#A62426; display:none} span#dup-archive-filter-db {color:#A62426; display:none} - span#dup-installer-secure {color:#A62426; display:none; font-size:14px} + span#dup-installer-secure-lock {color:#A62426; display:none; font-size:14px} + span#dup-installer-secure-unlock {color:#A62426; display:none; font-size:14px} span#dup-archive-db-only {color:#A62426; display:none} div#dup-file-filter-items, div#dup-db-filter-items {padding:5px 0;} div#dup-db-filter-items {font-stretch:ultra-condensed; font-family:Calibri; } @@ -365,7 +366,8 @@
        - + +
      @@ -584,12 +586,14 @@ if ($('#secure-on').is(':checked')) { $('#secure-pass').attr('readonly', false); $('#secure-pass').attr('required', 'true').focus(); - $('#dup-installer-secure').show(); + $('#dup-installer-secure-lock').show(); + $('#dup-installer-secure-unlock').hide(); $button.removeAttr('disabled'); } else { $('#secure-pass').removeAttr('required'); $('#secure-pass').attr('readonly', true); - $('#dup-installer-secure').hide(); + $('#dup-installer-secure-lock').hide(); + $('#dup-installer-secure-unlock').show(); $button.attr('disabled', 'true'); } }; From cdd754533c3b553a49077935748e2a0fa3d67fd8 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Tue, 21 Aug 2018 02:10:19 +0000 Subject: [PATCH 389/585] - spelling fixes - new feature suggest button git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1927719 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- classes/ui/class.ui.notice.php | 4 ++-- readme.txt | 4 ++-- views/packages/details/detail.php | 4 ++-- views/packages/main/s1.setup2.php | 4 ++-- views/packages/main/s3.build.php | 4 ++-- views/settings/about-info.php | 34 +++++++++++++---------------- views/tools/diagnostics/support.php | 4 ++-- 7 files changed, 27 insertions(+), 31 deletions(-) diff --git a/classes/ui/class.ui.notice.php b/classes/ui/class.ui.notice.php index bec5312b..a8cb6f29 100644 --- a/classes/ui/class.ui.notice.php +++ b/classes/ui/class.ui.notice.php @@ -47,7 +47,7 @@ public static function showReservedFilesNotice() if(get_option("duplicator_exe_safe_mode", 0) > 0 ){ $safe_msg1 = __('Safe Mode:', 'duplicator'); $safe_msg2 = __('During the install safe mode was enabled deactivating all plugins.
      Please be sure to ', 'duplicator'); - $safe_msg3 = __('re-activate the plugins', 'duplicator'); + $safe_msg3 = __('reactivate the plugins', 'duplicator'); $safe_html = "
      {$safe_msg1}
      {$safe_msg2} {$safe_msg3}!

      "; } @@ -94,4 +94,4 @@ public static function redirect($location) echo ""; die(__('Invalid token permissions to perform this request.', 'duplicator')); } -} \ No newline at end of file +} diff --git a/readme.txt b/readme.txt index 0ae67a33..660981a4 100644 --- a/readme.txt +++ b/readme.txt @@ -33,7 +33,7 @@ Duplicator enables you to: Duplicator creates a package that bundles all the site's plugins, themes, content, database and WordPress files into a simple zip file called a package. This package can then be used to easily migrate a WordPress site to any location you wish. Move on the same server, across servers and pretty much any location a WordPress site can be hosted. *WordPress is not required for installation* since the package contains all site files. = Improve Your Workflow with Pre-Bundled Sites = -Duplicator lets you make your own pre-configured sites to eliminate rework. Instead of manually configuring your favorite theme, set of plugins or content over and over, now just configure a single site and bundle it up into a Duplicator package. Once you have the bundled site, you can migrate the WordPress site over and over to different locations to instantly create many pre-configured sites! +Duplicator lets you make your own preconfigured sites to eliminate rework. Instead of manually configuring your favorite theme, set of plugins or content over and over, now just configure a single site and bundle it up into a Duplicator package. Once you have the bundled site, you can migrate the WordPress site over and over to different locations to instantly create many preconfigured sites! = Duplicator Pro = Duplicator Pro takes Duplicator to the next level with features you'll really appreciate, such as: @@ -103,4 +103,4 @@ Please see the following url: == Upgrade Notice == -Please use our ticketing system when submitting your logs. Please do not post to the forums. \ No newline at end of file +Please use our ticketing system when submitting your logs. Please do not post to the forums. diff --git a/views/packages/details/detail.php b/views/packages/details/detail.php index d780e359..531671cb 100644 --- a/views/packages/details/detail.php +++ b/views/packages/details/detail.php @@ -56,7 +56,7 @@ -

      +

      @@ -431,4 +431,4 @@ } } }); - \ No newline at end of file + diff --git a/views/packages/main/s1.setup2.php b/views/packages/main/s1.setup2.php index afca4b0c..c1747b53 100644 --- a/views/packages/main/s1.setup2.php +++ b/views/packages/main/s1.setup2.php @@ -353,7 +353,7 @@ - +
      @@ -623,4 +623,4 @@ Duplicator.Pack.EnableInstallerPassword(); }); - \ No newline at end of file + diff --git a/views/packages/main/s3.build.php b/views/packages/main/s3.build.php index a383de95..2d7168fc 100644 --- a/views/packages/main/s3.build.php +++ b/views/packages/main/s3.build.php @@ -317,7 +317,7 @@
      1. -
      2. +

      @@ -433,4 +433,4 @@ Duplicator.Pack.Create(); }); - \ No newline at end of file + diff --git a/views/settings/about-info.php b/views/settings/about-info.php index e9852709..818f2468 100644 --- a/views/settings/about-info.php +++ b/views/settings/about-info.php @@ -16,7 +16,7 @@ } table.dup-support-hlp-hdrs td img{margin-left:7px} div.dup-support-hlp-txt{padding:10px 4px 4px 4px; text-align:center} - div.dup-support-give-area {width:400px; height:185px; float:left; border:1px solid #dfdfdf; border-radius:4px; margin:10px; line-height:18px;box-shadow: 0 8px 6px -6px #ccc;} + div.dup-support-give-area {width:400px; height:165px; float:left; border:1px solid #dfdfdf; border-radius:4px; margin:10px; line-height:18px;box-shadow: 0 8px 6px -6px #ccc;} div.dup-spread-word {display:inline-block; border:1px solid red; text-align:center} img#dup-support-approved { -webkit-animation:approve-keyframe 12s 1s infinite alternate backwards} @@ -32,13 +32,8 @@ #mc-embedded-subscribe { height: 35px; font-size: 16px; font-weight: bold} div.mce_inline_error {width:300px; margin: auto !important} div#mce-responses {margin: auto; padding: 10px; width:500px; font-weight: bold;} - - - - -
      @@ -82,23 +77,19 @@
      - +
      - -
      - > - > - > - > - > -

      + +
      + +
      + +


      @@ -167,6 +158,11 @@ \ No newline at end of file + From f4dbddf908f8ff52c6a8b91ef77034f82c93bbe2 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Thu, 23 Aug 2018 01:09:13 +0000 Subject: [PATCH 390/585] improved input escaping git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1928889 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- .../build/classes/config/class.conf.wp.php | 34 +++++++++++++------ installer/build/classes/utilities/class.u.php | 18 ++++++++-- installer/build/ctrls/ctrl.step2.php | 4 +-- installer/build/ctrls/ctrl.step3.php | 7 ++-- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/installer/build/classes/config/class.conf.wp.php b/installer/build/classes/config/class.conf.wp.php index 388433e4..6cf02335 100644 --- a/installer/build/classes/config/class.conf.wp.php +++ b/installer/build/classes/config/class.conf.wp.php @@ -21,23 +21,28 @@ public static function updateStandard() { if (!file_exists('wp-config.php')) return; - $root_path = DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']); - $wpconfig = @file_get_contents('wp-config.php', true); - $_POST['dbpass'] = isset($_POST['dbpass']) ? str_replace("'", "\'", $_POST['dbpass']) : null; + $root_path = DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']); + $wpconfig = @file_get_contents('wp-config.php', true); + + $db_port = is_int($_POST['dbport']) ? $_POST['dbport'] : 3306; + $db_host = ($db_port == 3306) ? $_POST['dbhost'] : "{$_POST['dbhost']}:{$db_port}"; + $db_name = isset($_POST['dbname']) ? DUPX_U::safeQuote($_POST['dbname']) : null; + $db_user = isset($_POST['dbuser']) ? DUPX_U::safeQuote($_POST['dbuser']) : null; + $db_pass = isset($_POST['dbpass']) ? DUPX_U::safeQuote($_POST['dbpass']) : null; $patterns = array( "/'DB_NAME',\s*'.*?'/", "/'DB_USER',\s*'.*?'/", "/'DB_PASSWORD',\s*'.*?'/", - "/'DB_HOST',\s*'.*?'/"); - - $db_host = ($_POST['dbport'] == 3306) ? $_POST['dbhost'] : "{$_POST['dbhost']}:{$_POST['dbport']}"; + "/'DB_HOST',\s*'.*?'/" + ); $replace = array( - "'DB_NAME', ".'\''.$_POST['dbname'].'\'', - "'DB_USER', ".'\''.$_POST['dbuser'].'\'', - "'DB_PASSWORD', " . '\'' . DUPX_U::pregReplacementQuote($_POST['dbpass']) . '\'', - "'DB_HOST', ".'\''.$db_host.'\''); + "'DB_NAME', " . "'{$db_name}'", + "'DB_USER', " . "'{$db_user}'", + "'DB_PASSWORD', " . "'{$db_pass}'", + "'DB_HOST', " . "'{$db_host}'" + ); //SSL CHECKS if ($_POST['ssl_admin']) { @@ -71,11 +76,18 @@ public static function updateStandard() } } - $wpconfig = preg_replace($patterns, $replace, $wpconfig); + $replace = array_map('self::customEscape', $replace); + $wpconfig = preg_replace($patterns, $replace, $wpconfig); + file_put_contents('wp-config.php', $wpconfig); $wpconfig = null; } + public static function customEscape($str) + { + return str_replace('\\', '\\\\', $str); + } + /** * Updates the web server config files in Step 3 * diff --git a/installer/build/classes/utilities/class.u.php b/installer/build/classes/utilities/class.u.php index 0526a523..dd1bd955 100644 --- a/installer/build/classes/utilities/class.u.php +++ b/installer/build/classes/utilities/class.u.php @@ -10,7 +10,6 @@ */ class DUPX_U { - /** * Adds a slash to the end of a file or directory path * @@ -162,11 +161,11 @@ public static function isJSON($string) * same characters that are special in the pattern. Allows for '$' to be safely passed. * * @param string $str The string to replace on - */ - public static function pregReplacementQuote($str) + public static function pregSpecialChars($str) { return preg_replace('/(\$|\\\\)(?=\d)/', '\\\\\1', $str); } + * */ /** * Display human readable byte sizes @@ -273,6 +272,19 @@ public static function sanitize($input) return filter_var($input, FILTER_SANITIZE_STRING); } + /** + * Filter the string to escape the quote + * + * @param string $val The value to escape quote + * + * @return string Returns the input value escaped + */ + public static function safeQuote($val) + { + $val = addslashes($val); + return $val; + } + /** * Check PHP version * diff --git a/installer/build/ctrls/ctrl.step2.php b/installer/build/ctrls/ctrl.step2.php index 95d80699..350adb1d 100644 --- a/installer/build/ctrls/ctrl.step2.php +++ b/installer/build/ctrls/ctrl.step2.php @@ -2,8 +2,8 @@ //POST PARAMS $_POST['dbaction'] = isset($_POST['dbaction']) ? $_POST['dbaction'] : 'create'; $_POST['dbhost'] = isset($_POST['dbhost']) ? DUPX_U::sanitize(trim($_POST['dbhost'])) : null; -$_POST['dbname'] = isset($_POST['dbname']) ? DUPX_U::sanitize(trim($_POST['dbname'])) : null; -$_POST['dbuser'] = isset($_POST['dbuser']) ? DUPX_U::sanitize($_POST['dbuser']) : null; +$_POST['dbname'] = isset($_POST['dbname']) ? trim($_POST['dbname']) : null; +$_POST['dbuser'] = isset($_POST['dbuser']) ? $_POST['dbuser'] : null; $_POST['dbpass'] = isset($_POST['dbpass']) ? $_POST['dbpass'] : null; $_POST['dbcharset'] = isset($_POST['dbcharset']) ? DUPX_U::sanitize(trim($_POST['dbcharset'])) : $GLOBALS['DBCHARSET_DEFAULT']; $_POST['dbcollate'] = isset($_POST['dbcollate']) ? DUPX_U::sanitize(trim($_POST['dbcollate'])) : $GLOBALS['DBCOLLATE_DEFAULT']; diff --git a/installer/build/ctrls/ctrl.step3.php b/installer/build/ctrls/ctrl.step3.php index 730948bc..e145ac2d 100644 --- a/installer/build/ctrls/ctrl.step3.php +++ b/installer/build/ctrls/ctrl.step3.php @@ -17,8 +17,9 @@ //POST PARAMS $_POST['dbhost'] = isset($_POST['dbhost']) ? DUPX_U::sanitize(trim($_POST['dbhost'])) : null; -$_POST['dbname'] = isset($_POST['dbname']) ? DUPX_U::sanitize(trim($_POST['dbname'])) : null; -$_POST['dbuser'] = isset($_POST['dbuser']) ? DUPX_U::sanitize($_POST['dbuser']) : null; +$_POST['dbname'] = isset($_POST['dbname']) ? trim($_POST['dbname']) : null; +$_POST['dbuser'] = isset($_POST['dbuser']) ? $_POST['dbuser'] : null; +$_POST['dbpass'] = isset($_POST['dbpass']) ? $_POST['dbpass'] : null; $_POST['blogname'] = isset($_POST['blogname']) ? DUPX_U::sanitize(trim($_POST['blogname'])): ''; $_POST['postguid'] = isset($_POST['postguid']) && $_POST['postguid'] == 1 ? 1 : 0; $_POST['fullsearch'] = isset($_POST['fullsearch']) && $_POST['fullsearch'] == 1 ? 1 : 0; @@ -30,7 +31,7 @@ $_POST['url_new'] = isset($_POST['url_new']) ? rtrim(trim($_POST['url_new']), '/') : null; $_POST['retain_config'] = (isset($_POST['retain_config']) && $_POST['retain_config'] == '1') ? true : false; $_POST['exe_safe_mode'] = isset($_POST['exe_safe_mode']) ? $_POST['exe_safe_mode'] : 0; -$_POST['dbpass'] = isset($_POST['dbpass']) ? $_POST['dbpass'] : null; + //MYSQL CONNECTION From d58d01cdb1bfbce5db9fd82d905b1cf51af11fa8 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Thu, 23 Aug 2018 01:19:25 +0000 Subject: [PATCH 391/585] - improve input escapes git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1928890 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- .../build/classes/config/class.conf.wp.php | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/installer/build/classes/config/class.conf.wp.php b/installer/build/classes/config/class.conf.wp.php index 6cf02335..fd0ea538 100644 --- a/installer/build/classes/config/class.conf.wp.php +++ b/installer/build/classes/config/class.conf.wp.php @@ -1,5 +1,4 @@ \ No newline at end of file From 3cb78cf807782751fc892002ef07af4a37311970 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Thu, 23 Aug 2018 23:58:39 +0000 Subject: [PATCH 392/585] about page updates git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1929433 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- views/settings/about-info.php | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/views/settings/about-info.php b/views/settings/about-info.php index 818f2468..081a8b29 100644 --- a/views/settings/about-info.php +++ b/views/settings/about-info.php @@ -24,7 +24,8 @@ form#dup-donate-form input:hover {opacity:1.0;} img#dup-img-5stars {opacity:0.7;} img#dup-img-5stars:hover {opacity:1.0;} - + div.social-item {float:right; width: 170px; padding:10px 10px 20px 0px; border:0px solid red; text-align: left; font-size:20px} + /* EMAIL AREA */ div.dup-support-email-area {width:825px; height:355px; border:1px solid #dfdfdf; border-radius:4px; margin:10px; line-height:18px;box-shadow: 0 8px 6px -6px #ccc;} #mce-EMAIL {font-size:20px; height:40px; width:500px} @@ -51,7 +52,7 @@
      - +
      @@ -65,7 +66,7 @@ @@ -77,22 +78,29 @@
      - +
      - +
      - -
      - -
      - - +


      +
      From 16773f4dbddd9b758a6a4ec78fa6527ca15649f6 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Fri, 24 Aug 2018 20:26:01 +0000 Subject: [PATCH 393/585] - version update git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1929928 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 660981a4..c64ef1f3 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Tags: migration, backup, restore, move, migrate, duplicate, transfer, clone, aut Requires at least: 4.0 Tested up to: 4.9 Requires PHP: 5.2.17 -Stable tag: 1.2.40 +Stable tag: 1.2.42 License: GPLv2 WordPress migration and backups are much easier with Duplicator! Clone, backup, move and transfer an entire site from one location to another. From 32e7d96683923964decc6d0971cd2e7f8971995e Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Tue, 11 Sep 2018 04:21:49 +0000 Subject: [PATCH 394/585] - improve remove installer files message git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1939038 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- classes/ui/class.ui.notice.php | 194 ++++++++++++++--------------- define.php | 2 +- duplicator.php | 2 +- installer/build/assets/inc.css.php | 9 +- installer/build/main.installer.php | 7 +- installer/build/view.help.php | 11 +- installer/build/view.step4.php | 56 ++++----- uninstall.php | 2 +- 8 files changed, 137 insertions(+), 146 deletions(-) diff --git a/classes/ui/class.ui.notice.php b/classes/ui/class.ui.notice.php index a8cb6f29..d912ec04 100644 --- a/classes/ui/class.ui.notice.php +++ b/classes/ui/class.ui.notice.php @@ -1,97 +1,97 @@ -

      '; - - //Safe Mode Notice - $safe_html = ''; - if(get_option("duplicator_exe_safe_mode", 0) > 0 ){ - $safe_msg1 = __('Safe Mode:', 'duplicator'); - $safe_msg2 = __('During the install safe mode was enabled deactivating all plugins.
      Please be sure to ', 'duplicator'); - $safe_msg3 = __('reactivate the plugins', 'duplicator'); - $safe_html = "

      {$safe_msg1}
      {$safe_msg2} {$safe_msg3}!

      "; - } - - //On Tools > Cleanup Page - if ($screen->id == 'duplicator_page_duplicator-tools' && ($on_active_tab == "info" || $on_active_tab == '') ) { - - $title = __('This site has been successfully migrated!', 'duplicator'); - $msg1 = __('Final step(s):', 'duplicator'); - $msg2 = __('This message will be removed after all installer files are removed. Installer files must be removed to maintain a secure site.
      ' - . 'Click the link above or button below to remove all installer files and complete the migration.', 'duplicator'); - - echo " {$title}
      {$safe_html} {$msg1}
      "; - printf("1. %s
      ", __('Optionally, Review Duplicator at WordPress.org...', 'duplicator')); - printf("2. %s
      ", __('Remove Installation Files Now!', 'duplicator')); - echo "
      {$msg2}
      "; - - //All other Pages - } else { - - $title = __('Migration Almost Complete!', 'duplicator'); - $msg = __('Reserved Duplicator installation files have been detected in the root directory. Please delete these installation files to ' - . 'avoid security issues.
      Go to:Duplicator > Tools > Information >Stored Data and click the "Remove Installation Files" button', 'duplicator'); - - $nonce = wp_create_nonce('duplicator_cleanup_page'); - $url = self_admin_url('admin.php?page=duplicator-tools&tab=diagnostics§ion=info&_wpnonce='.$nonce); - echo "{$title}
      {$safe_html} {$msg}"; - @printf("
      %s", __('Take me there now!', 'duplicator')); - - } - echo "

      "; - } - } - - /** - * Shows a message for redirecting a page - * - * @return string The location to redirect to - */ - public static function redirect($location) - { - echo '
      '; - __('Redirecting Please Wait...', 'duplicator'); - echo '
      '; - echo ""; - die(__('Invalid token permissions to perform this request.', 'duplicator')); - } -} +

      '; + + //Safe Mode Notice + $safe_html = ''; + if(get_option("duplicator_exe_safe_mode", 0) > 0 ){ + $safe_msg1 = __('Safe Mode:', 'duplicator'); + $safe_msg2 = __('During the install safe mode was enabled deactivating all plugins.
      Please be sure to ', 'duplicator'); + $safe_msg3 = __('reactivate the plugins', 'duplicator'); + $safe_html = "

      {$safe_msg1}
      {$safe_msg2} {$safe_msg3}!

      "; + } + + //On Tools > Cleanup Page + if ($screen->id == 'duplicator_page_duplicator-tools' && ($on_active_tab == "info" || $on_active_tab == '') ) { + + $title = __('This site has been successfully migrated!', 'duplicator'); + $msg1 = __('Final step(s):', 'duplicator'); + $msg2 = __('This message will be removed after all installer files are removed. Installer files must be removed to maintain a secure site.
      ' + . 'Click the link above or button below to remove all installer files and complete the migration.', 'duplicator'); + + echo " {$title}
      {$safe_html} {$msg1}
      "; + printf("1. %s
      ", __('Optionally, Review Duplicator at WordPress.org...', 'duplicator')); + printf("2. %s
      ", __('Remove Installation Files Now!', 'duplicator')); + echo "
      {$msg2}
      "; + + //All other Pages + } else { + + $title = __('Migration Almost Complete!', 'duplicator'); + $msg = __('Reserved Duplicator installation files have been detected in the root directory. Please delete these installation files to ' + . 'avoid security issues.
      Go to:Duplicator > Tools > Information >Stored Data and click the "Remove Installation Files" button', 'duplicator'); + + $nonce = wp_create_nonce('duplicator_cleanup_page'); + $url = self_admin_url('admin.php?page=duplicator-tools&tab=diagnostics§ion=info&_wpnonce='.$nonce); + echo "{$title}
      {$safe_html} {$msg}"; + @printf("
      %s", __('Take me there now!', 'duplicator')); + + } + echo "

      "; + } + } + + /** + * Shows a message for redirecting a page + * + * @return string The location to redirect to + */ + public static function redirect($location) + { + echo '
      '; + __('Redirecting Please Wait...', 'duplicator'); + echo '
      '; + echo ""; + die(__('Invalid token permissions to perform this request.', 'duplicator')); + } +} diff --git a/define.php b/define.php index 66ddb81a..fa8a8564 100644 --- a/define.php +++ b/define.php @@ -2,7 +2,7 @@ //Prevent directly browsing to the file if (function_exists('plugin_dir_url')) { - define('DUPLICATOR_VERSION', '1.2.42'); + define('DUPLICATOR_VERSION', '1.2.44'); define('DUPLICATOR_HOMEPAGE', 'https://snapcreek.com/duplicator/duplicator-free/'); define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__)); define('DUPLICATOR_SITE_URL', get_site_url()); diff --git a/duplicator.php b/duplicator.php index 0d11bebf..b3b206d0 100644 --- a/duplicator.php +++ b/duplicator.php @@ -3,7 +3,7 @@ Plugin Name: Duplicator Plugin URI: https://snapcreek.com/duplicator/duplicator-free/ Description: Migrate and backup a copy of your WordPress files and database. Duplicate and move a site from one location to another quickly. - Version: 1.2.42 + Version: 1.2.44 Author: Snap Creek Author URI: http://www.snapcreek.com/duplicator/ Text Domain: duplicator diff --git a/installer/build/assets/inc.css.php b/installer/build/assets/inc.css.php index b910e6f2..4137e9a6 100644 --- a/installer/build/assets/inc.css.php +++ b/installer/build/assets/inc.css.php @@ -197,11 +197,10 @@ table.s4-final-step {width:100%;} table.s4-final-step td {padding:5px 15px 5px 5px} table.s4-final-step td:first-child {white-space:nowrap;} - div.s4-go-back {border-top:1px dotted #dfdfdf; margin:auto; font-style:italic; font-size:10px; color:#333} - a.s4-final-btns {display: block; width:145px; padding:5px; line-height: 1.4; background-color:#F1F1F1; border:1px solid silver; - color: #000; box-shadow: 5px 5px 5px -5px #949494; text-decoration: none; text-align: center; border-radius: 4px; - } - a.s4-final-btns:hover {background-color: #dfdfdf;} + div.s4-go-back {border-top:1px dotted #dfdfdf; margin:auto; font-style:italic; font-size:11px; color:#333; padding-top:4px} + div.s4-go-back ul {line-height:18px} + button.s4-final-btns {cursor:pointer; color:#fff; font-size:16px; border-radius:5px; padding:7px; background-color:#13659C; border:1px solid gray; width:165px;} + button.s4-final-btns:hover {background-color: #dfdfdf;} div.s4-gopro-btn {text-align:center; font-size:14px; margin:auto; width:200px; font-style: italic; font-weight:bold} div.s4-gopro-btn a{color:green} diff --git a/installer/build/main.installer.php b/installer/build/main.installer.php index 3ef1e9dc..9b8fb8e4 100644 --- a/installer/build/main.installer.php +++ b/installer/build/main.installer.php @@ -253,15 +253,12 @@
      - version:
      - » info - » help + version:
      + help '; echo ($GLOBALS['FW_SECUREON']) ? 'locked' : 'unlocked'; - ?> - diff --git a/installer/build/view.help.php b/installer/build/view.help.php index 005c3e3d..c8636c8c 100644 --- a/installer/build/view.help.php +++ b/installer/build/view.help.php @@ -535,14 +535,15 @@ Final Security Cleanup
      When completed with the installation please delete all installation files. Leaving these files on your server can impose a security risk! You can remove - all the security files by logging into your WordPress admin and following the remove notification links. Be sure these files/directories are removed. Optionally - it is also recommended to remove the archive.zip/daf file. + all the security files by logging into your WordPress admin and following the remove notification links. Be sure all these files are removed. Optionally + it is also recommended to remove the archive.zip file.
        -
      • dup-installer
      • installer.php
      • +
      • installer-data.sql
      • installer-backup.php
      • -
      • installer-bootlog.txt
      • -
      • archive.zip/daf
      • +
      • installer-log.txt
      • +
      • database.sql
      • +
      • [a-hash-code]_archive.zip (optional)


      diff --git a/installer/build/view.step4.php b/installer/build/view.step4.php index 1a45fffd..3c134b48 100644 --- a/installer/build/view.step4.php +++ b/installer/build/view.step4.php @@ -1,5 +1,4 @@ @@ -36,9 +34,11 @@ - + - - - -
      Site Login + + - Login to finalize the setup + Click the Admin Login button to login and finalize this install.

      Update of Permalinks required see: Admin > Settings > Permalinks > Save @@ -52,37 +52,31 @@
      Show Report - Optionally review the migration report
      - - Install Notices: ()   - Update Notices: ()     - General Notices: () - -
      -

      + + IMPORTANT FINAL STEPS: Login into the WordPress Admin to remove all installation files + and keep this site secure. This install is not complete until the installer files are removed! + +


      - Final Steps: + Additional Notes:
      • - Review the front-end or - re-run installer at ">step 1 + Review Migration Report
        +     + + Install Notices: ()   + Update Notices: ()     + General Notices: () +
      • -
      • Finalize installation by logging into the WordPress Admin Login and removing installation files
      • -
      - - Additional Notes: -
        -
      • The .htaccess file was reset. Resave plugins that write to this file.
      • - Visit the troubleshoot section or - online FAQs for additional help. + Review this sites front-end or + re-run the installer and ">go back to step 1.
      • +
      • If the .htaccess file was reset some plugin settings might need to be re-saved.
      • +
      • For additional help and questions visit the online FAQs.
      diff --git a/uninstall.php b/uninstall.php index 8405c3dc..8e683acf 100644 --- a/uninstall.php +++ b/uninstall.php @@ -15,7 +15,7 @@ $DUP_Settings = new DUP_Settings(); $table_name = $wpdb->prefix . "duplicator_packages"; -$wpdb->query("DROP TABLE `{$table_name}`"); +$wpdb->query("DROP TABLE IF EXISTS `{$table_name}`"); delete_option('duplicator_version_plugin'); From 527d1585c172e4133ab426ea990e7da85a0c5464 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Fri, 14 Sep 2018 16:49:42 +0000 Subject: [PATCH 395/585] - improve file cleanup messages git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@1941467 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- installer/build/view.help.php | 3 +++ installer/build/view.step4.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/installer/build/view.help.php b/installer/build/view.help.php index c8636c8c..cf7700d4 100644 --- a/installer/build/view.help.php +++ b/installer/build/view.help.php @@ -49,6 +49,9 @@ +
      + Note: Even though the installer has a password protection feature, it should only be used for the short term while the installer is being used. All installer files should and + must be removed after the install is completed. Files should not to be left on the server for any long duration of time to prevent any security related issues.
      -
      - -
      No Params
      -
      - diff --git a/define.php b/define.php index fa8a8564..18f703fe 100644 --- a/define.php +++ b/define.php @@ -2,7 +2,7 @@ //Prevent directly browsing to the file if (function_exists('plugin_dir_url')) { - define('DUPLICATOR_VERSION', '1.2.44'); + define('DUPLICATOR_VERSION', '1.2.46'); define('DUPLICATOR_HOMEPAGE', 'https://snapcreek.com/duplicator/duplicator-free/'); define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__)); define('DUPLICATOR_SITE_URL', get_site_url()); @@ -26,10 +26,6 @@ define('DUPLICATOR_SSDIR_URL', DUPLICATOR_SITE_URL . "/" . DUPLICATOR_SSDIR_NAME); define('DUPLICATOR_INSTALL_PHP', 'installer.php'); define('DUPLICATOR_INSTALL_BAK', 'installer-backup.php'); - define('DUPLICATOR_INSTALL_SQL', 'installer-data.sql'); - define('DUPLICATOR_INSTALL_LOG', 'installer-log.txt'); - define('DUPLICATOR_INSTALL_DB', 'database.sql'); - //GENERAL CONSTRAINTS define('DUPLICATOR_PHP_MAX_MEMORY', '2048M'); diff --git a/duplicator.php b/duplicator.php index b3b206d0..2b07b53c 100644 --- a/duplicator.php +++ b/duplicator.php @@ -3,7 +3,7 @@ Plugin Name: Duplicator Plugin URI: https://snapcreek.com/duplicator/duplicator-free/ Description: Migrate and backup a copy of your WordPress files and database. Duplicate and move a site from one location to another quickly. - Version: 1.2.44 + Version: 1.2.46 Author: Snap Creek Author URI: http://www.snapcreek.com/duplicator/ Text Domain: duplicator diff --git a/installer/build/classes/class.logging.php b/installer/build/classes/class.logging.php index 7050cf94..1685d32d 100644 --- a/installer/build/classes/class.logging.php +++ b/installer/build/classes/class.logging.php @@ -4,8 +4,8 @@ define('ERR_ZIPNOTFOUND', 'The packaged zip file was not found. Be sure the zip package is in the same directory as the installer file and as the correct permissions. If you are trying to reinstall a package you can copy the package from the "' . DUPLICATOR_SSDIR_NAME . '" directory back up to your root which is the same location as your installer.php file.'); define('ERR_ZIPOPEN', 'Failed to open zip archive file. Please be sure the archive is completely downloaded before running the installer. Try to extract the archive manually to make sure the file is not corrupted.'); define('ERR_ZIPEXTRACTION', 'Errors extracting zip file. Portions or part of the zip archive did not extract correctly. Try to extract the archive manually with a client side program like unzip/win-zip/winrar or your hosts cPanel to make sure the file is not corrupted. If the file extracts correctly then there is an invalid file or directory that PHP is unable to extract. This can happen if your moving from one operating system to another where certain naming conventions work on one environment and not another.

      Workarounds:
      1. Create a new package and be sure to exclude any directories that have invalid names or files in them. This warning will be displayed on the scan results under "Name Checks".
      2. Manually extract the zip file with a client side program or your hosts cPanel. Then under options in step 1 of this installer check the "Manual Archive Extraction" option and perform the install.'); -define('ERR_ZIPMANUAL', 'When choosing manual package extraction, the contents of the package must already be extracted and the wp-config.php and database.sql files must be present in the same directory as the installer.php for the process to continue. Please manually extract the package into the current directory before continuing in manual extraction mode. Also validate that the wp-config.php and database.sql files are present.'); -define('ERR_MAKELOG', 'PHP is having issues writing to the log file ' . DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']) . '\installer-log.txt . In order for the Duplicator to proceed validate your owner/group and permission settings for PHP on this path. Try temporarily setting you permissions to 777 to see if the issue gets resolved. If you are on a shared hosting environment please contact your hosting company and tell them you are getting errors writing files to the path above when using PHP.'); +define('ERR_ZIPMANUAL', "When choosing manual package extraction, the contents of the package must already be extracted and the wp-config.php and dup-database__{$GLOBALS['PACKAGE_HASH']}.sql files must be present in the same directory as the installer.php for the process to continue. Please manually extract the package into the current directory before continuing in manual extraction mode. Also validate that the wp-config.php and dup-database__{$GLOBALS['PACKAGE_HASH']}.sql files are present."); +define('ERR_MAKELOG', 'PHP is having issues writing to the log file ' . DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']) . '\".$GLOBALS["LOG_FILE_NAME"]." . In order for the Duplicator to proceed validate your owner/group and permission settings for PHP on this path. Try temporarily setting you permissions to 777 to see if the issue gets resolved. If you are on a shared hosting environment please contact your hosting company and tell them you are getting errors writing files to the path above when using PHP.'); define('ERR_ZIPARCHIVE', 'In order to extract the archive.zip file the PHP ZipArchive module must be installed. Please read the FAQ for more details. You can still install this package but you will need to check the Manual package extraction checkbox found in the Advanced Options. Please read the online user guide for details in performing a manual package extraction.'); define('ERR_MYSQLI_SUPPORT', 'In order to complete an install the mysqli extension for PHP is required. If you are on a hosted server please contact your host and request that mysqli be enabled. For more information visit: http://php.net/manual/en/mysqli.installation.php'); define('ERR_DBCONNECT', 'DATABASE CONNECTION FAILED!
      '); @@ -16,7 +16,7 @@ define('ERR_DBEMPTY', 'The database "%s" has "%s" tables. The Duplicator only works with an EMPTY database. Enable the action "Connect and Remove All Data" radio button to remove all tables and or create a new database. Some hosting providers do not allow table removal from scripts. In this case you will need to login to your hosting providers control panel and remove the tables manually. Please contact your hosting provider for further details. Always backup all your data before proceeding!'); define('ERR_TESTDB_UTF8', 'UTF8 Characters were detected as part of the database connection string. If your connection fails be sure to update the MySQL my.ini configuration file setting to support UTF8 characters by enabling this option [character_set_server=utf8] and restarting the database server.'); define('ERR_TESTDB_VERSION_INFO', 'If the current version detected is below 5.5.3 (release on April 8th 2010) then support for utf8mb4 tables will not work. The utf8mb4 format is only supported in MySQL server 5.5.3+. It is highly recommended to upgrade your version of MySQL server on this server to be more compatible with recent releases of WordPress and avoid issues with install errors.'); -define('ERR_TESTDB_VERSION_COMPAT', 'In order to avoid database incompatibility issues make sure the database versions between the build and installer servers are as close as possible. If the package was created on a newer database version than where it is being installed then you might run into issues.

      It is best to make sure the server where the installer is running has the same or higher version number than where it was built. If the major and minor version are the same or close for example [5.7 to 5.6], then the migration should work without issues. A version pair of [5.7 to 5.1] is more likely to cause issues unless you have a very simple setup. If the versions are too far apart work with your hosting provider to upgrade the MySQL engine on this server.

      MariaDB: If a version of 10.N.N shows then the database distribution is a MariaDB flavor of MySQL. While the distributions are very close there are some subtle differences. Some operating systems will report the version such as "5.5.5-10.1.21-MariaDB" showing the correlation of both. Please visit the online MariaDB versus MySQL - Compatibility page for more details.

      Please note these messages are simply notices. It is highly recommended that you continue with the install process and closely monitor the installer-log.txt file along with the install report found on step 3 of the installer. Be sure to look for any notices/warnings/errors in these locations to validate the install process did not detect any errors. If any issues are found please visit the FAQ pages and see the question What if I get database errors or general warnings on the install report?.'); +define('ERR_TESTDB_VERSION_COMPAT', 'In order to avoid database incompatibility issues make sure the database versions between the build and installer servers are as close as possible. If the package was created on a newer database version than where it is being installed then you might run into issues.

      It is best to make sure the server where the installer is running has the same or higher version number than where it was built. If the major and minor version are the same or close for example [5.7 to 5.6], then the migration should work without issues. A version pair of [5.7 to 5.1] is more likely to cause issues unless you have a very simple setup. If the versions are too far apart work with your hosting provider to upgrade the MySQL engine on this server.

      MariaDB: If a version of 10.N.N shows then the database distribution is a MariaDB flavor of MySQL. While the distributions are very close there are some subtle differences. Some operating systems will report the version such as "5.5.5-10.1.21-MariaDB" showing the correlation of both. Please visit the online MariaDB versus MySQL - Compatibility page for more details.

      Please note these messages are simply notices. It is highly recommended that you continue with the install process and closely monitor the file along with the install report found on step 3 of the installer. Be sure to look for any notices/warnings/errors in these locations to validate the install process did not detect any errors. If any issues are found please visit the FAQ pages and see the question What if I get database errors or general warnings on the install report?.'); /** * Class used to log information to the installer-log.txt file diff --git a/installer/build/ctrls/ctrl.step1.php b/installer/build/ctrls/ctrl.step1.php index 18cb2db8..c0012c50 100644 --- a/installer/build/ctrls/ctrl.step1.php +++ b/installer/build/ctrls/ctrl.step1.php @@ -37,7 +37,7 @@ if (!$GLOBALS['FW_ARCHIVE_ONLYDB']) { //ERR_ZIPMANUAL if ($_POST['archive_engine'] == 'manual') { - if (!file_exists("wp-config.php") && !file_exists("database.sql")) { + if (!file_exists("wp-config.php") && !file_exists("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql")) { DUPX_Log::error(ERR_ZIPMANUAL); } } else { diff --git a/installer/build/ctrls/ctrl.step2.php b/installer/build/ctrls/ctrl.step2.php index 350adb1d..2a163711 100644 --- a/installer/build/ctrls/ctrl.step2.php +++ b/installer/build/ctrls/ctrl.step2.php @@ -183,7 +183,7 @@ function_exists('mysqli_connect') or DUPX_Log::error(ERR_MYSQLI_SUPPORT); $log = ''; $faq_url = $GLOBALS['FAQ_URL']; $utm_prefix = '?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content='; -$db_file_size = filesize('database.sql'); +$db_file_size = filesize("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql"); $php_mem = $GLOBALS['PHP_MEMORY_LIMIT']; $php_mem_range = DUPX_U::getBytes($GLOBALS['PHP_MEMORY_LIMIT']); $php_mem_range = $php_mem_range == null ? 0 : $php_mem_range - 5000000; //5 MB Buffer @@ -195,23 +195,23 @@ function_exists('mysqli_connect') or DUPX_Log::error(ERR_MYSQLI_SUPPORT); $db_file_size = DUPX_U::readableByteSize($db_file_size); $msg = "\nWARNING: The database script is '{$db_file_size}' in size. The PHP memory allocation is set\n"; $msg .= "at '{$php_mem}'. There is a high possibility that the installer script will fail with\n"; - $msg .= "a memory allocation error when trying to load the database.sql file. It is\n"; + $msg .= "a memory allocation error when trying to load the dup-database__{$GLOBALS['PACKAGE_HASH']}.sql file. It is\n"; $msg .= "recommended to increase the 'memory_limit' setting in the php.ini config file.\n"; $msg .= "see: {$faq_url}{$utm_prefix}inst_step2_lgdbscript#faq-trouble-056-q \n"; DUPX_Log::info($msg); } -@chmod("{$root_path}/database.sql", 0777); -$sql_file = file_get_contents('database.sql', true); +@chmod("{$root_path}/dup-database__{$GLOBALS['PACKAGE_HASH']}.sql", 0777); +$sql_file = file_get_contents("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql", true); //ERROR: Reading database.sql file if ($sql_file === FALSE || strlen($sql_file) < 10) { - $msg = "Unable to read the database.sql file from the archive. Please check these items:
      "; + $msg = "Unable to read the dup-database__{$GLOBALS['PACKAGE_HASH']}.sql file from the archive. Please check these items:
      "; $msg .= "1. Validate permissions and/or group-owner rights on these items:
      "; - $msg .= " - File: database.sql
      - Directory: [{$root_path}]
      "; + $msg .= " - File: dup-database__{$GLOBALS['PACKAGE_HASH']}.sql
      - Directory: [{$root_path}]
      "; $msg .= "see: {$faq_url}#faq-trouble-055-q
      "; - $msg .= "2. Validate the database.sql file exists and is in the root of the archive.zip file
      "; + $msg .= "2. Validate the dup-database__{$GLOBALS['PACKAGE_HASH']}.sql file exists and is in the root of the archive.zip file
      "; $msg .= "see: {$faq_url}#faq-installer-020-q
      "; DUPX_Log::error($msg); } @@ -275,9 +275,9 @@ function_exists('mysqli_connect') or DUPX_Log::error(ERR_MYSQLI_SUPPORT); //WARNING: Create installer-data.sql failed if ($sql_file_copy_status === FALSE || filesize($sql_result_file_path) == 0 || !is_readable($sql_result_file_path)) { - $sql_file_size = DUPX_U::readableByteSize(filesize('database.sql')); - $msg = "\nWARNING: Unable to properly copy database.sql ({$sql_file_size}) to {$GLOBALS['SQL_FILE_NAME']}. Please check these items:\n"; - $msg .= "- Validate permissions and/or group-owner rights on database.sql and directory [{$root_path}] \n"; + $sql_file_size = DUPX_U::readableByteSize(filesize("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql")); + $msg = "\nWARNING: Unable to properly copy dup-database__{$GLOBALS['PACKAGE_HASH']}.sql ({$sql_file_size}) to {$GLOBALS['SQL_FILE_NAME']}. Please check these items:\n"; + $msg .= "- Validate permissions and/or group-owner rights on dup-database__{$GLOBALS['PACKAGE_HASH']}.sql and directory [{$root_path}] \n"; $msg .= "- see: {$faq_url}{$utm_prefix}inst_step2_copydbsql#faq-trouble-055-q \n"; DUPX_Log::info($msg); } @@ -314,7 +314,7 @@ function_exists('mysqli_connect') or DUPX_Log::error(ERR_MYSQLI_SUPPORT); $dbvar_maxpacks = is_null($dbvar_maxpacks) ? 1048576 : $dbvar_maxpacks; $dbvar_sqlmode = empty($dbvar_sqlmode) ? 'NOT_SET' : $dbvar_sqlmode; $dbvar_version = DUPX_DB::getVersion($dbh); -$sql_file_size1 = DUPX_U::readableByteSize(@filesize("database.sql")); +$sql_file_size1 = DUPX_U::readableByteSize(@filesize("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql")); $sql_file_size2 = DUPX_U::readableByteSize(@filesize("{$GLOBALS['SQL_FILE_NAME']}")); $db_collatefb = isset($_POST['dbcollatefb']) ? 'On' : 'Off'; @@ -323,7 +323,7 @@ function_exists('mysqli_connect') or DUPX_Log::error(ERR_MYSQLI_SUPPORT); DUPX_Log::info("DATABASE ENVIRONMENT"); DUPX_Log::info("--------------------------------------"); DUPX_Log::info("MYSQL VERSION:\tThis Server: {$dbvar_version} -- Build Server: {$GLOBALS['FW_VERSION_DB']}"); -DUPX_Log::info("FILE SIZE:\tdatabase.sql ({$sql_file_size1}) - installer-data.sql ({$sql_file_size2})"); +DUPX_Log::info("FILE SIZE:\tdup-database__{$GLOBALS['PACKAGE_HASH']}.sql ({$sql_file_size1}) - dup-installer-data__{$GLOBALS['PACKAGE_HASH']}.sql ({$sql_file_size2})"); DUPX_Log::info("TIMEOUT:\t{$dbvar_maxtime}"); DUPX_Log::info("MAXPACK:\t{$dbvar_maxpacks}"); DUPX_Log::info("SQLMODE:\t{$dbvar_sqlmode}"); @@ -434,8 +434,8 @@ function_exists('mysqli_connect') or DUPX_Log::error(ERR_MYSQLI_SUPPORT); } if ($dbtable_count == 0) { - DUPX_Log::error("No tables where created during step 2 of the install. Please review the installer-log.txt file for - ERROR messages. You may have to manually run the installer-data.sql with a tool like phpmyadmin to validate the data input. If you have enabled compatibility mode + DUPX_Log::error("No tables where created during step 2 of the install. Please review the ".$GLOBALS["LOG_FILE_NAME"]." file for + ERROR messages. You may have to manually run the installer-data__{$GLOBALS['PACKAGE_HASH']}.sql with a tool like phpmyadmin to validate the data input. If you have enabled compatibility mode during the package creation process then the database server version your using may not be compatible with this script.\n"); } diff --git a/installer/build/main.installer.php b/installer/build/main.installer.php index 9b8fb8e4..bdf85423 100644 --- a/installer/build/main.installer.php +++ b/installer/build/main.installer.php @@ -111,6 +111,7 @@ $GLOBALS['FW_OPTS_DELETE'] = json_decode("%fwrite_opts_delete%", true); $GLOBALS['FW_DUPLICATOR_VERSION'] = '%fwrite_duplicator_version%'; $GLOBALS['FW_ARCHIVE_ONLYDB'] = '%fwrite_archive_onlydb%'; +$GLOBALS['PACKAGE_HASH'] = '%package_hash%'; //DATABASE SETUP: all time in seconds $GLOBALS['DB_MAX_TIME'] = 5000; @@ -166,8 +167,9 @@ $_POST['dbcollate'] = isset($_POST['dbcollate']) ? trim($_POST['dbcollate']) : $GLOBALS['DBCOLLATE_DEFAULT']; //GLOBALS -$GLOBALS['SQL_FILE_NAME'] = "installer-data.sql"; -$GLOBALS['LOG_FILE_NAME'] = "installer-log.txt"; +// Constants which are dependent on the $GLOBALS['DUPX_AC'] +$GLOBALS['SQL_FILE_NAME'] = "dup-installer-data__{$GLOBALS['PACKAGE_HASH']}.sql"; +$GLOBALS['LOG_FILE_NAME'] = "dup-installer-log__{$GLOBALS['PACKAGE_HASH']}.txt"; $GLOBALS['LOGGING'] = isset($_POST['logging']) ? $_POST['logging'] : 1; $GLOBALS['CURRENT_ROOT_PATH'] = dirname(__FILE__); $GLOBALS['CHOWN_ROOT_PATH'] = @chmod("{$GLOBALS['CURRENT_ROOT_PATH']}", 0755); diff --git a/installer/build/view.help.php b/installer/build/view.help.php index cf7700d4..bd2b0306 100644 --- a/installer/build/view.help.php +++ b/installer/build/view.help.php @@ -222,7 +222,7 @@ Logging - The level of detail that will be sent to the log file (installer-log.txt). The recommend setting for most installs should be 'Light'. + The level of detail that will be sent to the log file (). The recommend setting for most installs should be 'Light'. Note if you use Debug the amount of data written can be very large. Debug is only recommended for support. @@ -542,10 +542,10 @@ it is also recommended to remove the archive.zip file.
      • installer.php
      • -
      • installer-data.sql
      • +
      • dup-installer-data__.sql
      • installer-backup.php
      • -
      • installer-log.txt
      • -
      • database.sql
      • +
      • +
      • dup-database__.sql
      • [a-hash-code]_archive.zip (optional)


      diff --git a/installer/build/view.step1.php b/installer/build/view.step1.php index cc3958da..fa8ff1fb 100644 --- a/installer/build/view.step1.php +++ b/installer/build/view.step1.php @@ -23,7 +23,7 @@ //until further reports are discovered, removed on 04-06-2018 //$badFiles = array('__MACOSX', $arcFilePath); $badFiles = array('', $arcFilePath); - $goodFiles = array('database.sql', 'installer-backup.php'); + $goodFiles = array("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql", 'installer-backup.php'); $goodFilesFound = true; $badFilesFound = false; @@ -223,7 +223,7 @@ the issue. Please check the contents of the zip archive and be sure its contents match the layout of your site.

      - Files such as database.sql and wp-config.php should be at the root of the archive. For more details see the FAQ article + Files such as dup-database__.sql and wp-config.php should be at the root of the archive. For more details see the FAQ article The archive format is changing on my Mac what might be the problem? @@ -558,10 +558,10 @@ After Install: When you are done with the installation you must remove these files/directories:
      • installer.php
      • -
      • installer-data.sql
      • +
      • dup-installer-data__.sql
      • installer-backup.php
      • -
      • installer-log.txt
      • -
      • database.sql
      • +
      • +
      • dup-database__.sql
      These files contain sensitive information and should not remain on a production system for system integrity and security protection. @@ -622,7 +622,7 @@ ========================================= --> @@ -93,12 +99,13 @@
      -
      +
      - +

      @@ -106,18 +113,18 @@



      \ No newline at end of file From c02a264a9b707f153a37f36d64b5ed78c40fab0d Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Wed, 9 Jan 2019 17:39:50 +0000 Subject: [PATCH 430/585] - Installer: Missing validation on tls connections - Installer: Do not generate exception if wp-config does not exist git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@2009313 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- define.php | 2 +- installer/dup-installer/assets/inc.css.php | 4 +- .../dup-installer/assets/inc.libs.css.php | 26 +- .../dup-installer/assets/inc.libs.js.php | 77 +++-- .../dup-installer/classes/class.http.php | 144 --------- .../classes/config/class.constants.php | 1 - .../classes/utilities/class.u.php | 17 -- installer/dup-installer/ctrls/ctrl.s3.php | 277 ++++++++++-------- installer/dup-installer/main.installer.php | 1 - installer/dup-installer/views/view.s3.php | 38 ++- installer/dup-installer/views/view.s4.php | 2 +- installer/installer.tpl | 40 ++- lib/snaplib/class.snaplib.u.url.php | 54 ---- views/settings/general.php | 9 +- 14 files changed, 262 insertions(+), 430 deletions(-) diff --git a/define.php b/define.php index 78790368..4a121e74 100644 --- a/define.php +++ b/define.php @@ -3,7 +3,7 @@ if (function_exists('plugin_dir_url')) { define('DUPLICATOR_VERSION', '1.3.3'); - define('DUPLICATOR_VERSION_BUILD', '2019-01-07_20:16'); + define('DUPLICATOR_VERSION_BUILD', '2019-01-09_09:30'); define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__)); define('DUPLICATOR_SITE_URL', get_site_url()); diff --git a/installer/dup-installer/assets/inc.css.php b/installer/dup-installer/assets/inc.css.php index e697ec20..67da40d0 100644 --- a/installer/dup-installer/assets/inc.css.php +++ b/installer/dup-installer/assets/inc.css.php @@ -60,11 +60,11 @@ /*Adv Opts */ table.dupx-opts {width:100%; border:0px;} - table.dupx-opts td{white-space:nowrap; padding:3px;} + table.dupx-opts td{padding:3px;} table.dupx-opts td:first-child{width:125px; font-weight: bold} table.dupx-advopts td:first-child{width:125px;} table.dupx-advopts label.radio {width:50px; display:inline-block} - table.dupx-advopts label {cursor:pointer} + table.dupx-advopts label {white-space:nowrap; cursor:pointer} table.dupx-advopts-space {line-height:24px} div.error-pane {border:1px solid #efefef; border-left:4px solid #D54E21; padding:0 0 0 10px; margin:2px 0 10px 0} diff --git a/installer/dup-installer/assets/inc.libs.css.php b/installer/dup-installer/assets/inc.libs.css.php index b3a237a9..e7f524a7 100644 --- a/installer/dup-installer/assets/inc.libs.css.php +++ b/installer/dup-installer/assets/inc.libs.css.php @@ -1,24 +1,18 @@ + - + TODO: When updating replace: [url("images/] with: []url("assets/images/] +*/ +.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;font-size:100%}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-button{padding:.4em 1em;display:inline-block;position:relative;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2em;box-sizing:border-box;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-button-icon-only{text-indent:0}.ui-button-icon-only .ui-icon{position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px}.ui-button.ui-icon-notext .ui-icon{padding:0;width:2.1em;height:2.1em;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-icon-notext .ui-icon{width:auto;height:auto;text-indent:0;white-space:normal;padding:.4em 1em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-controlgroup{vertical-align:middle;display:inline-block}.ui-controlgroup > .ui-controlgroup-item{float:left;margin-left:0;margin-right:0}.ui-controlgroup > .ui-controlgroup-item:focus,.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus{z-index:9999}.ui-controlgroup-vertical > .ui-controlgroup-item{display:block;float:none;width:100%;margin-top:0;margin-bottom:0;text-align:left}.ui-controlgroup-vertical .ui-controlgroup-item{box-sizing:border-box}.ui-controlgroup .ui-controlgroup-label{padding:.4em 1em}.ui-controlgroup .ui-controlgroup-label span{font-size:80%}.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item{border-left:none}.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item{border-top:none}.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content{border-right:none}.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content{border-bottom:none}.ui-controlgroup-vertical .ui-spinner-input{width:75%;width:calc( 100% - 2.4em )}.ui-controlgroup-vertical .ui-spinner .ui-spinner-up{border-top-style:solid}.ui-checkboxradio-label .ui-icon-background{box-shadow:inset 1px 1px 1px #ccc;border-radius:.12em;border:none}.ui-checkboxradio-radio-label .ui-icon-background{width:16px;height:16px;border-radius:1em;overflow:visible;border:none}.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon{background-image:none;width:8px;height:8px;border-width:4px;border-style:solid}.ui-checkboxradio-disabled{pointer-events:none}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;left:.5em;top:.3em}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-n{height:2px;top:0}.ui-dialog .ui-resizable-e{width:2px;right:0}.ui-dialog .ui-resizable-s{height:2px;bottom:0}.ui-dialog .ui-resizable-w{width:2px;left:0}.ui-dialog .ui-resizable-se,.ui-dialog .ui-resizable-sw,.ui-dialog .ui-resizable-ne,.ui-dialog .ui-resizable-nw{width:7px;height:7px}.ui-dialog .ui-resizable-se{right:0;bottom:0}.ui-dialog .ui-resizable-sw{left:0;bottom:0}.ui-dialog .ui-resizable-ne{right:0;top:0}.ui-dialog .ui-resizable-nw{left:0;top:0}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,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");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-text{display:block;margin-right:20px;overflow:hidden;text-overflow:ellipsis}.ui-selectmenu-button.ui-button{text-align:left;white-space:nowrap;width:14em}.ui-selectmenu-icon.ui-icon{float:right;margin-top:0}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:.222em 0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:2em}.ui-spinner-button{width:1.6em;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top-style:none;border-bottom-style:none;border-right-style:none}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #d3d3d3}.ui-widget-content{border:1px solid #aaa;background:#fff;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url("assets/images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #d3d3d3;background:#e6e6e6 url("assets/images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #999;background:#dadada url("assets/images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#212121;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #aaa;background:#fff url("assets/images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-icon-background,.ui-state-active .ui-icon-background{border:#aaa;background-color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url("assets/images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;color:#363636}.ui-state-checked{border:1px solid #fcefa1;background:#fbf9ee}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url("assets/images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("assets/images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("assets/images/ui-icons_222222_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("assets/images/ui-icons_454545_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("assets/images/ui-icons_454545_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("assets/images/ui-icons_2e83ff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("assets/images/ui-icons_cd0a0a_256x240.png")}.ui-button .ui-icon{background-image:url("assets/images/ui-icons_888888_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:-8px -8px 8px #aaa;box-shadow:-8px -8px 8px #aaa} -").appendTo(o)),a.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",a.opacity)),a.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",a.zIndex)),this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this._addClass(this.helper,"ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,o,a=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY=0;i--)if(s=this.items[i],n=s.item[0],o=this._intersectsWithPointer(s),o&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===o?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===o?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),o=this.options.axis,a={};o&&"x"!==o||(a.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollLeft)),o&&"y"!==o||(a.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(a,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp(new t.Event("mouseup",{target:null})),"original"===this.options.helper?(this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,o=t.left,a=o+t.width,r=t.top,l=r+t.height,h=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+h>r&&l>s+h,d="y"===this.options.axis||e+c>o&&a>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>o&&a>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&l>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var e,i,s="x"===this.options.axis||this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top,t.height),n="y"===this.options.axis||this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left,t.width),o=s&&n;return o?(e=this._getDragVerticalDirection(),i=this._getDragHorizontalDirection(),this.floating?"right"===i||"down"===e?2:1:e&&("down"===e?2:1)):!1},_intersectsWithSides:function(t){var e=this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),i=this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),s=this._getDragVerticalDirection(),n=this._getDragHorizontalDirection();return this.floating&&n?"right"===n&&i||"left"===n&&!i:s&&("down"===s&&e||"up"===s&&!e)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this._setHandleClassName(),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){function i(){r.push(this)}var s,n,o,a,r=[],l=[],h=this._connectWith();if(h&&e)for(s=h.length-1;s>=0;s--)for(o=t(h[s],this.document[0]),n=o.length-1;n>=0;n--)a=t.data(o[n],this.widgetFullName),a&&a!==this&&!a.options.disabled&&l.push([t.isFunction(a.options.items)?a.options.items.call(a.element):t(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a]);for(l.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),s=l.length-1;s>=0;s--)l[s][0].each(i);return t(r)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,o,a,r,l,h,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i],this.document[0]),s=n.length-1;s>=0;s--)o=t.data(n[s],this.widgetFullName),o&&o!==this&&!o.options.disabled&&(u.push([t.isFunction(o.options.items)?o.options.items.call(o.element[0],e,{item:this.currentItem}):t(o.options.items,o.element),o]),this.containers.push(o));for(i=u.length-1;i>=0;i--)for(a=u[i][1],r=u[i][0],s=0,h=r.length;h>s;s++)l=t(r[s]),l.data(this.widgetName+"-item",a),c.push({item:l,instance:a,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.floating=this.items.length?"x"===this.options.axis||this._isFloating(this.items[0].item):!1,this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,o;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),o=n.offset(),s.left=o.left,s.top=o.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)o=this.containers[i].element.offset(),this.containers[i].containerCache.left=o.left,this.containers[i].containerCache.top=o.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]);return e._addClass(n,"ui-sortable-placeholder",i||e.currentItem[0].className)._removeClass(n,"ui-sortable-helper"),"tbody"===s?e._createTrPlaceholder(e.currentItem.find("tr").eq(0),t("",e.document[0]).appendTo(n)):"tr"===s?e._createTrPlaceholder(e.currentItem,n):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_createTrPlaceholder:function(e,i){var s=this;e.children().each(function(){t(" ",s.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(i)})},_contactContainers:function(e){var i,s,n,o,a,r,l,h,c,u,d=null,p=null;for(i=this.containers.length-1;i>=0;i--)if(!t.contains(this.currentItem[0],this.containers[i].element[0]))if(this._intersectsWith(this.containers[i].containerCache)){if(d&&t.contains(this.containers[i].element[0],d.element[0]))continue;d=this.containers[i],p=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",e,this._uiHash(this)),this.containers[i].containerCache.over=0);if(d)if(1===this.containers.length)this.containers[p].containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1);else{for(n=1e4,o=null,c=d.floating||this._isFloating(this.currentItem),a=c?"left":"top",r=c?"width":"height",u=c?"pageX":"pageY",s=this.items.length-1;s>=0;s--)t.contains(this.containers[p].element[0],this.items[s].item[0])&&this.items[s].item[0]!==this.currentItem[0]&&(l=this.items[s].item.offset()[a],h=!1,e[u]-l>this.items[s][r]/2&&(h=!0),n>Math.abs(e[u]-l)&&(n=Math.abs(e[u]-l),o=this.items[s],this.direction=h?"up":"down"));if(!o&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[p])return this.currentContainer.containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash()),this.currentContainer.containerCache.over=1),void 0;o?this._rearrange(e,o,null,!0):this._rearrange(e,null,this.containers[p].element,!0),this._trigger("change",e,this._uiHash()),this.containers[p]._trigger("change",e,this._uiHash(this)),this.currentContainer=this.containers[p],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===this.document[0].body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,"document"===n.containment?this.document.width():this.window.width()-this.helperProportions.width-this.margins.left,("document"===n.containment?this.document.height()||document.body.parentNode.scrollHeight:this.window.height()||this.document[0].body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())*s}},_generatePosition:function(e){var i,s,n=this.options,o=e.pageX,a=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,l=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.leftthis.containment[2]&&(o=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(a=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((a-this.originalPageY)/n.grid[1])*n.grid[1],a=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((o-this.originalPageX)/n.grid[0])*n.grid[0],o=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():l?0:r.scrollTop()),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():l?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){function i(t,e,i){return function(s){i._trigger(t,s,e._uiHash(e))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&n.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||n.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(n.push(function(t){this._trigger("remove",t,this._uiHash())}),n.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)e||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!e){for(s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!this.cancelHelperRemoval},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}}),t.widget("ui.accordion",{version:"1.12.1",options:{active:0,animate:{},classes:{"ui-accordion-header":"ui-corner-top","ui-accordion-header-collapsed":"ui-corner-all","ui-accordion-content":"ui-corner-bottom"},collapsible:!1,event:"click",header:"> li > :first-child, > :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var e=this.options;this.prevShow=this.prevHide=t(),this._addClass("ui-accordion","ui-widget ui-helper-reset"),this.element.attr("role","tablist"),e.collapsible||e.active!==!1&&null!=e.active||(e.active=0),this._processPanels(),0>e.active&&(e.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():t()}},_createIcons:function(){var e,i,s=this.options.icons;s&&(e=t(""),this._addClass(e,"ui-accordion-header-icon","ui-icon "+s.header),e.prependTo(this.headers),i=this.active.children(".ui-accordion-header-icon"),this._removeClass(i,s.header)._addClass(i,null,s.activeHeader)._addClass(this.headers,"ui-accordion-icons")) - },_destroyIcons:function(){this._removeClass(this.headers,"ui-accordion-icons"),this.headers.children(".ui-accordion-header-icon").remove()},_destroy:function(){var t;this.element.removeAttr("role"),this.headers.removeAttr("role aria-expanded aria-selected aria-controls tabIndex").removeUniqueId(),this._destroyIcons(),t=this.headers.next().css("display","").removeAttr("role aria-hidden aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&t.css("height","")},_setOption:function(t,e){return"active"===t?(this._activate(e),void 0):("event"===t&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(e)),this._super(t,e),"collapsible"!==t||e||this.options.active!==!1||this._activate(0),"icons"===t&&(this._destroyIcons(),e&&this._createIcons()),void 0)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t),this._toggleClass(null,"ui-state-disabled",!!t),this._toggleClass(this.headers.add(this.headers.next()),null,"ui-state-disabled",!!t)},_keydown:function(e){if(!e.altKey&&!e.ctrlKey){var i=t.ui.keyCode,s=this.headers.length,n=this.headers.index(e.target),o=!1;switch(e.keyCode){case i.RIGHT:case i.DOWN:o=this.headers[(n+1)%s];break;case i.LEFT:case i.UP:o=this.headers[(n-1+s)%s];break;case i.SPACE:case i.ENTER:this._eventHandler(e);break;case i.HOME:o=this.headers[0];break;case i.END:o=this.headers[s-1]}o&&(t(e.target).attr("tabIndex",-1),t(o).attr("tabIndex",0),t(o).trigger("focus"),e.preventDefault())}},_panelKeyDown:function(e){e.keyCode===t.ui.keyCode.UP&&e.ctrlKey&&t(e.currentTarget).prev().trigger("focus")},refresh:function(){var e=this.options;this._processPanels(),e.active===!1&&e.collapsible===!0||!this.headers.length?(e.active=!1,this.active=t()):e.active===!1?this._activate(0):this.active.length&&!t.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(e.active=!1,this.active=t()):this._activate(Math.max(0,e.active-1)):e.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var t=this.headers,e=this.panels;this.headers=this.element.find(this.options.header),this._addClass(this.headers,"ui-accordion-header ui-accordion-header-collapsed","ui-state-default"),this.panels=this.headers.next().filter(":not(.ui-accordion-content-active)").hide(),this._addClass(this.panels,"ui-accordion-content","ui-helper-reset ui-widget-content"),e&&(this._off(t.not(this.headers)),this._off(e.not(this.panels)))},_refresh:function(){var e,i=this.options,s=i.heightStyle,n=this.element.parent();this.active=this._findActive(i.active),this._addClass(this.active,"ui-accordion-header-active","ui-state-active")._removeClass(this.active,"ui-accordion-header-collapsed"),this._addClass(this.active.next(),"ui-accordion-content-active"),this.active.next().show(),this.headers.attr("role","tab").each(function(){var e=t(this),i=e.uniqueId().attr("id"),s=e.next(),n=s.uniqueId().attr("id");e.attr("aria-controls",n),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(i.event),"fill"===s?(e=n.height(),this.element.siblings(":visible").each(function(){var i=t(this),s=i.css("position");"absolute"!==s&&"fixed"!==s&&(e-=i.outerHeight(!0))}),this.headers.each(function(){e-=t(this).outerHeight(!0)}),this.headers.next().each(function(){t(this).height(Math.max(0,e-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===s&&(e=0,this.headers.next().each(function(){var i=t(this).is(":visible");i||t(this).show(),e=Math.max(e,t(this).css("height","").height()),i||t(this).hide()}).height(e))},_activate:function(e){var i=this._findActive(e)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return"number"==typeof e?this.headers.eq(e):t()},_setupEvents:function(e){var i={keydown:"_keydown"};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(e){var i,s,n=this.options,o=this.active,a=t(e.currentTarget),r=a[0]===o[0],l=r&&n.collapsible,h=l?t():a.next(),c=o.next(),u={oldHeader:o,oldPanel:c,newHeader:l?t():a,newPanel:h};e.preventDefault(),r&&!n.collapsible||this._trigger("beforeActivate",e,u)===!1||(n.active=l?!1:this.headers.index(a),this.active=r?t():a,this._toggle(u),this._removeClass(o,"ui-accordion-header-active","ui-state-active"),n.icons&&(i=o.children(".ui-accordion-header-icon"),this._removeClass(i,null,n.icons.activeHeader)._addClass(i,null,n.icons.header)),r||(this._removeClass(a,"ui-accordion-header-collapsed")._addClass(a,"ui-accordion-header-active","ui-state-active"),n.icons&&(s=a.children(".ui-accordion-header-icon"),this._removeClass(s,null,n.icons.header)._addClass(s,null,n.icons.activeHeader)),this._addClass(a.next(),"ui-accordion-content-active")))},_toggle:function(e){var i=e.newPanel,s=this.prevShow.length?this.prevShow:e.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=s,this.options.animate?this._animate(i,s,e):(s.hide(),i.show(),this._toggleComplete(e)),s.attr({"aria-hidden":"true"}),s.prev().attr({"aria-selected":"false","aria-expanded":"false"}),i.length&&s.length?s.prev().attr({tabIndex:-1,"aria-expanded":"false"}):i.length&&this.headers.filter(function(){return 0===parseInt(t(this).attr("tabIndex"),10)}).attr("tabIndex",-1),i.attr("aria-hidden","false").prev().attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_animate:function(t,e,i){var s,n,o,a=this,r=0,l=t.css("box-sizing"),h=t.length&&(!e.length||t.index()",delay:300,options:{icons:{submenu:"ui-icon-caret-1-e"},items:"> *",menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().attr({role:this.options.role,tabIndex:0}),this._addClass("ui-menu","ui-widget ui-widget-content"),this._on({"mousedown .ui-menu-item":function(t){t.preventDefault()},"click .ui-menu-item":function(e){var i=t(e.target),s=t(t.ui.safeActiveElement(this.document[0]));!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(e),e.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(e):!this.element.is(":focus")&&s.closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(e){if(!this.previousFilter){var i=t(e.target).closest(".ui-menu-item"),s=t(e.currentTarget);i[0]===s[0]&&(this._removeClass(s.siblings().children(".ui-state-active"),null,"ui-state-active"),this.focus(e,s))}},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this.element.find(this.options.items).eq(0);e||this.focus(t,i)},blur:function(e){this._delay(function(){var i=!t.contains(this.element[0],t.ui.safeActiveElement(this.document[0]));i&&this.collapseAll(e)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){this._closeOnDocumentClick(t)&&this.collapseAll(t),this.mouseHandled=!1}})},_destroy:function(){var e=this.element.find(".ui-menu-item").removeAttr("role aria-disabled"),i=e.children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled tabIndex").removeUniqueId().show(),i.children().each(function(){var e=t(this);e.data("ui-menu-submenu-caret")&&e.remove()})},_keydown:function(e){var i,s,n,o,a=!0;switch(e.keyCode){case t.ui.keyCode.PAGE_UP:this.previousPage(e);break;case t.ui.keyCode.PAGE_DOWN:this.nextPage(e);break;case t.ui.keyCode.HOME:this._move("first","first",e);break;case t.ui.keyCode.END:this._move("last","last",e);break;case t.ui.keyCode.UP:this.previous(e);break;case t.ui.keyCode.DOWN:this.next(e);break;case t.ui.keyCode.LEFT:this.collapse(e);break;case t.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(e);break;case t.ui.keyCode.ENTER:case t.ui.keyCode.SPACE:this._activate(e);break;case t.ui.keyCode.ESCAPE:this.collapse(e);break;default:a=!1,s=this.previousFilter||"",o=!1,n=e.keyCode>=96&&105>=e.keyCode?""+(e.keyCode-96):String.fromCharCode(e.keyCode),clearTimeout(this.filterTimer),n===s?o=!0:n=s+n,i=this._filterMenuItems(n),i=o&&-1!==i.index(this.active.next())?this.active.nextAll(".ui-menu-item"):i,i.length||(n=String.fromCharCode(e.keyCode),i=this._filterMenuItems(n)),i.length?(this.focus(e,i),this.previousFilter=n,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}a&&e.preventDefault()},_activate:function(t){this.active&&!this.active.is(".ui-state-disabled")&&(this.active.children("[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var e,i,s,n,o,a=this,r=this.options.icons.submenu,l=this.element.find(this.options.menus);this._toggleClass("ui-menu-icons",null,!!this.element.find(".ui-icon").length),s=l.filter(":not(.ui-menu)").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var e=t(this),i=e.prev(),s=t("").data("ui-menu-submenu-caret",!0);a._addClass(s,"ui-menu-icon","ui-icon "+r),i.attr("aria-haspopup","true").prepend(s),e.attr("aria-labelledby",i.attr("id"))}),this._addClass(s,"ui-menu","ui-widget ui-widget-content ui-front"),e=l.add(this.element),i=e.find(this.options.items),i.not(".ui-menu-item").each(function(){var e=t(this);a._isDivider(e)&&a._addClass(e,"ui-menu-divider","ui-widget-content")}),n=i.not(".ui-menu-item, .ui-menu-divider"),o=n.children().not(".ui-menu").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),this._addClass(n,"ui-menu-item")._addClass(o,"ui-menu-item-wrapper"),i.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!t.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){if("icons"===t){var i=this.element.find(".ui-menu-icon");this._removeClass(i,null,this.options.icons.submenu)._addClass(i,null,e.submenu)}this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t+""),this._toggleClass(null,"ui-state-disabled",!!t)},focus:function(t,e){var i,s,n;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),s=this.active.children(".ui-menu-item-wrapper"),this._addClass(s,null,"ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),n=this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper"),this._addClass(n,null,"ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=e.children(".ui-menu"),i.length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(e){var i,s,n,o,a,r;this._hasScroll()&&(i=parseFloat(t.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(t.css(this.activeMenu[0],"paddingTop"))||0,n=e.offset().top-this.activeMenu.offset().top-i-s,o=this.activeMenu.scrollTop(),a=this.activeMenu.height(),r=e.outerHeight(),0>n?this.activeMenu.scrollTop(o+n):n+r>a&&this.activeMenu.scrollTop(o+n-a+r))},blur:function(t,e){e||clearTimeout(this.timer),this.active&&(this._removeClass(this.active.children(".ui-menu-item-wrapper"),null,"ui-state-active"),this._trigger("blur",t,{item:this.active}),this.active=null)},_startOpening:function(t){clearTimeout(this.timer),"true"===t.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(t)},this.delay))},_open:function(e){var i=t.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(e.parents(".ui-menu")).hide().attr("aria-hidden","true"),e.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(e,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:t(e&&e.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(e),this._removeClass(s.find(".ui-state-active"),null,"ui-state-active"),this.activeMenu=s},this.delay)},_close:function(t){t||(t=this.active?this.active.parent():this.element),t.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false")},_closeOnDocumentClick:function(e){return!t(e.target).closest(".ui-menu").length},_isDivider:function(t){return!/[^\-\u2014\u2013\s]/.test(t.text())},collapse:function(t){var e=this.active&&this.active.parent().closest(".ui-menu-item",this.element);e&&e.length&&(this._close(),this.focus(t,e))},expand:function(t){var e=this.active&&this.active.children(".ui-menu ").find(this.options.items).first();e&&e.length&&(this._open(e.parent()),this._delay(function(){this.focus(t,e)}))},next:function(t){this._move("next","first",t)},previous:function(t){this._move("prev","last",t)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(t,e,i){var s;this.active&&(s="first"===t||"last"===t?this.active["first"===t?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[t+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.find(this.options.items)[e]()),this.focus(i,s)},nextPage:function(e){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=t(this),0>i.offset().top-s-n}),this.focus(e,i)):this.focus(e,this.activeMenu.find(this.options.items)[this.active?"last":"first"]())),void 0):(this.next(e),void 0)},previousPage:function(e){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=t(this),i.offset().top-s+n>0}),this.focus(e,i)):this.focus(e,this.activeMenu.find(this.options.items).first())),void 0):(this.next(e),void 0)},_hasScroll:function(){return this.element.outerHeight()",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var e,i,s,n=this.element[0].nodeName.toLowerCase(),o="textarea"===n,a="input"===n;this.isMultiLine=o||!a&&this._isContentEditable(this.element),this.valueMethod=this.element[o||a?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return e=!0,s=!0,i=!0,void 0;e=!1,s=!1,i=!1;var o=t.ui.keyCode;switch(n.keyCode){case o.PAGE_UP:e=!0,this._move("previousPage",n);break;case o.PAGE_DOWN:e=!0,this._move("nextPage",n);break;case o.UP:e=!0,this._keyEvent("previous",n);break;case o.DOWN:e=!0,this._keyEvent("next",n);break;case o.ENTER:this.menu.active&&(e=!0,n.preventDefault(),this.menu.select(n));break;case o.TAB:this.menu.active&&this.menu.select(n);break;case o.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(e)return e=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),void 0;if(!i){var n=t.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(t){return s?(s=!1,t.preventDefault(),void 0):(this._searchTimeout(t),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(t),this._change(t),void 0)}}),this._initSource(),this.menu=t("",{class:"select2-results__options select2-results__options--nested"});p.append(l),s.append(a),s.append(p)}else this.template(e,t);return f.StoreData(t,"data",e),t},r.prototype.bind=function(t,e){var l=this,n=t.id+"-results";this.$results.attr("id",n),t.on("results:all",function(e){l.clear(),l.append(e.data),t.isOpen()&&(l.setClasses(),l.highlightFirstItem())}),t.on("results:append",function(e){l.append(e.data),t.isOpen()&&l.setClasses()}),t.on("query",function(e){l.hideMessages(),l.showLoading(e)}),t.on("select",function(){t.isOpen()&&(l.setClasses(),l.options.get("scrollAfterSelect")&&l.highlightFirstItem())}),t.on("unselect",function(){t.isOpen()&&(l.setClasses(),l.options.get("scrollAfterSelect")&&l.highlightFirstItem())}),t.on("open",function(){l.$results.attr("aria-expanded","true"),l.$results.attr("aria-hidden","false"),l.setClasses(),l.ensureHighlightVisible()}),t.on("close",function(){l.$results.attr("aria-expanded","false"),l.$results.attr("aria-hidden","true"),l.$results.removeAttr("aria-activedescendant")}),t.on("results:toggle",function(){var e=l.getHighlightedResults();0!==e.length&&e.trigger("mouseup")}),t.on("results:select",function(){var e=l.getHighlightedResults();if(0!==e.length){var t=f.GetData(e[0],"data");"true"==e.attr("aria-selected")?l.trigger("close",{}):l.trigger("select",{data:t})}}),t.on("results:previous",function(){var e=l.getHighlightedResults(),t=l.$results.find("[aria-selected]"),n=t.index(e);if(!(n<=0)){var r=n-1;0===e.length&&(r=0);var i=t.eq(r);i.trigger("mouseenter");var o=l.$results.offset().top,s=i.offset().top,a=l.$results.scrollTop()+(s-o);0===r?l.$results.scrollTop(0):s-o<0&&l.$results.scrollTop(a)}}),t.on("results:next",function(){var e=l.getHighlightedResults(),t=l.$results.find("[aria-selected]"),n=t.index(e)+1;if(!(n>=t.length)){var r=t.eq(n);r.trigger("mouseenter");var i=l.$results.offset().top+l.$results.outerHeight(!1),o=r.offset().top+r.outerHeight(!1),s=l.$results.scrollTop()+o-i;0===n?l.$results.scrollTop(0):ithis.$results.outerHeight()||o<0)&&this.$results.scrollTop(i)}},r.prototype.template=function(e,t){var n=this.options.get("templateResult"),r=this.options.get("escapeMarkup"),i=n(e,t);null==i?t.style.display="none":"string"==typeof i?t.innerHTML=r(i):h(t).append(i)},r}),e.define("select2/keys",[],function(){return{BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46}}),e.define("select2/selection/base",["jquery","../utils","../keys"],function(n,r,i){function o(e,t){this.$element=e,this.options=t,o.__super__.constructor.call(this)}return r.Extend(o,r.Observable),o.prototype.render=function(){var e=n('');return this._tabindex=0,null!=r.GetData(this.$element[0],"old-tabindex")?this._tabindex=r.GetData(this.$element[0],"old-tabindex"):null!=this.$element.attr("tabindex")&&(this._tabindex=this.$element.attr("tabindex")),e.attr("title",this.$element.attr("title")),e.attr("tabindex",this._tabindex),e.attr("aria-disabled","false"),this.$selection=e},o.prototype.bind=function(e,t){var n=this,r=e.id+"-results";this.container=e,this.$selection.on("focus",function(e){n.trigger("focus",e)}),this.$selection.on("blur",function(e){n._handleBlur(e)}),this.$selection.on("keydown",function(e){n.trigger("keypress",e),e.which===i.SPACE&&e.preventDefault()}),e.on("results:focus",function(e){n.$selection.attr("aria-activedescendant",e.data._resultId)}),e.on("selection:update",function(e){n.update(e.data)}),e.on("open",function(){n.$selection.attr("aria-expanded","true"),n.$selection.attr("aria-owns",r),n._attachCloseHandler(e)}),e.on("close",function(){n.$selection.attr("aria-expanded","false"),n.$selection.removeAttr("aria-activedescendant"),n.$selection.removeAttr("aria-owns"),n.$selection.trigger("focus"),n._detachCloseHandler(e)}),e.on("enable",function(){n.$selection.attr("tabindex",n._tabindex),n.$selection.attr("aria-disabled","false")}),e.on("disable",function(){n.$selection.attr("tabindex","-1"),n.$selection.attr("aria-disabled","true")})},o.prototype._handleBlur=function(e){var t=this;window.setTimeout(function(){document.activeElement==t.$selection[0]||n.contains(t.$selection[0],document.activeElement)||t.trigger("blur",e)},1)},o.prototype._attachCloseHandler=function(e){n(document.body).on("mousedown.select2."+e.id,function(e){var t=n(e.target).closest(".select2");n(".select2.select2-container--open").each(function(){this!=t[0]&&r.GetData(this,"element").select2("close")})})},o.prototype._detachCloseHandler=function(e){n(document.body).off("mousedown.select2."+e.id)},o.prototype.position=function(e,t){t.find(".selection").append(e)},o.prototype.destroy=function(){this._detachCloseHandler(this.container)},o.prototype.update=function(e){throw new Error("The `update` method must be defined in child classes.")},o.prototype.isEnabled=function(){return!this.isDisabled()},o.prototype.isDisabled=function(){return this.options.get("disabled")},o}),e.define("select2/selection/single",["jquery","./base","../utils","../keys"],function(e,t,n,r){function i(){i.__super__.constructor.apply(this,arguments)}return n.Extend(i,t),i.prototype.render=function(){var e=i.__super__.render.call(this);return e.addClass("select2-selection--single"),e.html(''),e},i.prototype.bind=function(t,e){var n=this;i.__super__.bind.apply(this,arguments);var r=t.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",r).attr("role","textbox").attr("aria-readonly","true"),this.$selection.attr("aria-labelledby",r),this.$selection.on("mousedown",function(e){1===e.which&&n.trigger("toggle",{originalEvent:e})}),this.$selection.on("focus",function(e){}),this.$selection.on("blur",function(e){}),t.on("focus",function(e){t.isOpen()||n.$selection.trigger("focus")})},i.prototype.clear=function(){var e=this.$selection.find(".select2-selection__rendered");e.empty(),e.removeAttr("title")},i.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},i.prototype.selectionContainer=function(){return e("")},i.prototype.update=function(e){if(0!==e.length){var t=e[0],n=this.$selection.find(".select2-selection__rendered"),r=this.display(t,n);n.empty().append(r);var i=t.title||t.text;i?n.attr("title",i):n.removeAttr("title")}else this.clear()},i}),e.define("select2/selection/multiple",["jquery","./base","../utils"],function(i,e,l){function n(e,t){n.__super__.constructor.apply(this,arguments)}return l.Extend(n,e),n.prototype.render=function(){var e=n.__super__.render.call(this);return e.addClass("select2-selection--multiple"),e.html('
        '),e},n.prototype.bind=function(e,t){var r=this;n.__super__.bind.apply(this,arguments),this.$selection.on("click",function(e){r.trigger("toggle",{originalEvent:e})}),this.$selection.on("click",".select2-selection__choice__remove",function(e){if(!r.isDisabled()){var t=i(this).parent(),n=l.GetData(t[0],"data");r.trigger("unselect",{originalEvent:e,data:n})}})},n.prototype.clear=function(){var e=this.$selection.find(".select2-selection__rendered");e.empty(),e.removeAttr("title")},n.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},n.prototype.selectionContainer=function(){return i('
      • ×
      • ')},n.prototype.update=function(e){if(this.clear(),0!==e.length){for(var t=[],n=0;n×
        ');a.StoreData(r[0],"data",t),this.$selection.find(".select2-selection__rendered").prepend(r)}},e}),e.define("select2/selection/search",["jquery","../utils","../keys"],function(r,a,l){function e(e,t,n){e.call(this,t,n)}return e.prototype.render=function(e){var t=r('');this.$searchContainer=t,this.$search=t.find("input");var n=e.call(this);return this._transferTabIndex(),n},e.prototype.bind=function(e,t,n){var r=this,i=t.id+"-results";e.call(this,t,n),t.on("open",function(){r.$search.attr("aria-controls",i),r.$search.trigger("focus")}),t.on("close",function(){r.$search.val(""),r.$search.removeAttr("aria-controls"),r.$search.removeAttr("aria-activedescendant"),r.$search.trigger("focus")}),t.on("enable",function(){r.$search.prop("disabled",!1),r._transferTabIndex()}),t.on("disable",function(){r.$search.prop("disabled",!0)}),t.on("focus",function(e){r.$search.trigger("focus")}),t.on("results:focus",function(e){e.data._resultId?r.$search.attr("aria-activedescendant",e.data._resultId):r.$search.removeAttr("aria-activedescendant")}),this.$selection.on("focusin",".select2-search--inline",function(e){r.trigger("focus",e)}),this.$selection.on("focusout",".select2-search--inline",function(e){r._handleBlur(e)}),this.$selection.on("keydown",".select2-search--inline",function(e){if(e.stopPropagation(),r.trigger("keypress",e),r._keyUpPrevented=e.isDefaultPrevented(),e.which===l.BACKSPACE&&""===r.$search.val()){var t=r.$searchContainer.prev(".select2-selection__choice");if(0this.maximumInputLength?this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:t.term,params:t}}):e.call(this,t,n)},e}),e.define("select2/data/maximumSelectionLength",[],function(){function e(e,t,n){this.maximumSelectionLength=n.get("maximumSelectionLength"),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var r=this;e.call(this,t,n),t.on("select",function(){r._checkIfMaximumSelected()})},e.prototype.query=function(e,t,n){var r=this;this._checkIfMaximumSelected(function(){e.call(r,t,n)})},e.prototype._checkIfMaximumSelected=function(e,n){var r=this;this.current(function(e){var t=null!=e?e.length:0;0=r.maximumSelectionLength?r.trigger("results:message",{message:"maximumSelected",args:{maximum:r.maximumSelectionLength}}):n&&n()})},e}),e.define("select2/dropdown",["jquery","./utils"],function(t,e){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return e.Extend(n,e.Observable),n.prototype.render=function(){var e=t('');return e.attr("dir",this.options.get("dir")),this.$dropdown=e},n.prototype.bind=function(){},n.prototype.position=function(e,t){},n.prototype.destroy=function(){this.$dropdown.remove()},n}),e.define("select2/dropdown/search",["jquery","../utils"],function(o,e){function t(){}return t.prototype.render=function(e){var t=e.call(this),n=o('');return this.$searchContainer=n,this.$search=n.find("input"),t.prepend(n),t},t.prototype.bind=function(e,t,n){var r=this,i=t.id+"-results";e.call(this,t,n),this.$search.on("keydown",function(e){r.trigger("keypress",e),r._keyUpPrevented=e.isDefaultPrevented()}),this.$search.on("input",function(e){o(this).off("keyup")}),this.$search.on("keyup input",function(e){r.handleSearch(e)}),t.on("open",function(){r.$search.attr("tabindex",0),r.$search.attr("aria-controls",i),r.$search.trigger("focus"),window.setTimeout(function(){r.$search.trigger("focus")},0)}),t.on("close",function(){r.$search.attr("tabindex",-1),r.$search.removeAttr("aria-controls"),r.$search.removeAttr("aria-activedescendant"),r.$search.val(""),r.$search.trigger("blur")}),t.on("focus",function(){t.isOpen()||r.$search.trigger("focus")}),t.on("results:all",function(e){null!=e.query.term&&""!==e.query.term||(r.showSearch(e)?r.$searchContainer.removeClass("select2-search--hide"):r.$searchContainer.addClass("select2-search--hide"))}),t.on("results:focus",function(e){e.data._resultId?r.$search.attr("aria-activedescendant",e.data._resultId):r.$search.removeAttr("aria-activedescendant")})},t.prototype.handleSearch=function(e){if(!this._keyUpPrevented){var t=this.$search.val();this.trigger("query",{term:t})}this._keyUpPrevented=!1},t.prototype.showSearch=function(e,t){return!0},t}),e.define("select2/dropdown/hidePlaceholder",[],function(){function e(e,t,n,r){this.placeholder=this.normalizePlaceholder(n.get("placeholder")),e.call(this,t,n,r)}return e.prototype.append=function(e,t){t.results=this.removePlaceholder(t.results),e.call(this,t)},e.prototype.normalizePlaceholder=function(e,t){return"string"==typeof t&&(t={id:"",text:t}),t},e.prototype.removePlaceholder=function(e,t){for(var n=t.slice(0),r=t.length-1;0<=r;r--){var i=t[r];this.placeholder.id===i.id&&n.splice(r,1)}return n},e}),e.define("select2/dropdown/infiniteScroll",["jquery"],function(n){function e(e,t,n,r){this.lastParams={},e.call(this,t,n,r),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return e.prototype.append=function(e,t){this.$loadingMore.remove(),this.loading=!1,e.call(this,t),this.showLoadingMore(t)&&(this.$results.append(this.$loadingMore),this.loadMoreIfNeeded())},e.prototype.bind=function(e,t,n){var r=this;e.call(this,t,n),t.on("query",function(e){r.lastParams=e,r.loading=!0}),t.on("query:append",function(e){r.lastParams=e,r.loading=!0}),this.$results.on("scroll",this.loadMoreIfNeeded.bind(this))},e.prototype.loadMoreIfNeeded=function(){var e=n.contains(document.documentElement,this.$loadingMore[0]);if(!this.loading&&e){var t=this.$results.offset().top+this.$results.outerHeight(!1);this.$loadingMore.offset().top+this.$loadingMore.outerHeight(!1)<=t+50&&this.loadMore()}},e.prototype.loadMore=function(){this.loading=!0;var e=n.extend({},{page:1},this.lastParams);e.page++,this.trigger("query:append",e)},e.prototype.showLoadingMore=function(e,t){return t.pagination&&t.pagination.more},e.prototype.createLoadingMore=function(){var e=n('
      • '),t=this.options.get("translations").get("loadingMore");return e.html(t(this.lastParams)),e},e}),e.define("select2/dropdown/attachBody",["jquery","../utils"],function(f,a){function e(e,t,n){this.$dropdownParent=f(n.get("dropdownParent")||document.body),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var r=this;e.call(this,t,n),t.on("open",function(){r._showDropdown(),r._attachPositioningHandler(t),r._bindContainerResultHandlers(t)}),t.on("close",function(){r._hideDropdown(),r._detachPositioningHandler(t)}),this.$dropdownContainer.on("mousedown",function(e){e.stopPropagation()})},e.prototype.destroy=function(e){e.call(this),this.$dropdownContainer.remove()},e.prototype.position=function(e,t,n){t.attr("class",n.attr("class")),t.removeClass("select2"),t.addClass("select2-container--open"),t.css({position:"absolute",top:-999999}),this.$container=n},e.prototype.render=function(e){var t=f(""),n=e.call(this);return t.append(n),this.$dropdownContainer=t},e.prototype._hideDropdown=function(e){this.$dropdownContainer.detach()},e.prototype._bindContainerResultHandlers=function(e,t){if(!this._containerResultsHandlersBound){var n=this;t.on("results:all",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("results:append",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("results:message",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("select",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("unselect",function(){n._positionDropdown(),n._resizeDropdown()}),this._containerResultsHandlersBound=!0}},e.prototype._attachPositioningHandler=function(e,t){var n=this,r="scroll.select2."+t.id,i="resize.select2."+t.id,o="orientationchange.select2."+t.id,s=this.$container.parents().filter(a.hasScroll);s.each(function(){a.StoreData(this,"select2-scroll-position",{x:f(this).scrollLeft(),y:f(this).scrollTop()})}),s.on(r,function(e){var t=a.GetData(this,"select2-scroll-position");f(this).scrollTop(t.y)}),f(window).on(r+" "+i+" "+o,function(e){n._positionDropdown(),n._resizeDropdown()})},e.prototype._detachPositioningHandler=function(e,t){var n="scroll.select2."+t.id,r="resize.select2."+t.id,i="orientationchange.select2."+t.id;this.$container.parents().filter(a.hasScroll).off(n),f(window).off(n+" "+r+" "+i)},e.prototype._positionDropdown=function(){var e=f(window),t=this.$dropdown.hasClass("select2-dropdown--above"),n=this.$dropdown.hasClass("select2-dropdown--below"),r=null,i=this.$container.offset();i.bottom=i.top+this.$container.outerHeight(!1);var o={height:this.$container.outerHeight(!1)};o.top=i.top,o.bottom=i.top+o.height;var s=this.$dropdown.outerHeight(!1),a=e.scrollTop(),l=e.scrollTop()+e.height(),c=ai.bottom+s,d={left:i.left,top:o.bottom},p=this.$dropdownParent;"static"===p.css("position")&&(p=p.offsetParent());var h={top:0,left:0};(f.contains(document.body,p[0])||p[0].isConnected)&&(h=p.offset()),d.top-=h.top,d.left-=h.left,t||n||(r="below"),u||!c||t?!c&&u&&t&&(r="below"):r="above",("above"==r||t&&"below"!==r)&&(d.top=o.top-h.top-s),null!=r&&(this.$dropdown.removeClass("select2-dropdown--below select2-dropdown--above").addClass("select2-dropdown--"+r),this.$container.removeClass("select2-container--below select2-container--above").addClass("select2-container--"+r)),this.$dropdownContainer.css(d)},e.prototype._resizeDropdown=function(){var e={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(e.minWidth=e.width,e.position="relative",e.width="auto"),this.$dropdown.css(e)},e.prototype._showDropdown=function(e){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},e}),e.define("select2/dropdown/minimumResultsForSearch",[],function(){function e(e,t,n,r){this.minimumResultsForSearch=n.get("minimumResultsForSearch"),this.minimumResultsForSearch<0&&(this.minimumResultsForSearch=1/0),e.call(this,t,n,r)}return e.prototype.showSearch=function(e,t){return!(function e(t){for(var n=0,r=0;r
        ');return e.attr("dir",this.options.get("dir")),this.$container=e,this.$container.addClass("select2-container--"+this.options.get("theme")),u.StoreData(e[0],"element",this.$element),e},d}),e.define("jquery-mousewheel",["jquery"],function(e){return e}),e.define("jquery.select2",["jquery","jquery-mousewheel","./select2/core","./select2/defaults","./select2/utils"],function(i,e,o,t,s){if(null==i.fn.select2){var a=["open","close","destroy"];i.fn.select2=function(t){if("object"==typeof(t=t||{}))return this.each(function(){var e=i.extend(!0,{},t);new o(i(this),e)}),this;if("string"!=typeof t)throw new Error("Invalid arguments for Select2: "+t);var n,r=Array.prototype.slice.call(arguments,1);return this.each(function(){var e=s.GetData(this,"select2");null==e&&window.console&&console.error&&console.error("The select2('"+t+"') method was called on an element that is not using Select2."),n=e[t].apply(e,r)}),-1setHTTPHeaders(); + $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; -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@@'; - - public $hasZipArchive = false; - public $hasShellExecUnzip = false; - public $mainInstallerURL; - public $installerContentsPath; - public $installerExtractPath; - public $archiveExpectedSize = 0; - public $archiveActualSize = 0; - public $activeRatio = 0; - - /** - * Instantiate the Bootstrap Object - * - * @return null - */ - public function __construct() - { - // clean log file - self::log('', true); - - //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(self::ARCHIVE_FILENAME) ? @filesize(self::ARCHIVE_FILENAME) : false; - $archiveActualSize = ($archiveActualSize !== false) ? $archiveActualSize : 0; - $this->hasZipArchive = class_exists('ZipArchive'); - $this->hasShellExecUnzip = $this->getUnzipFilePath() != null ? true : false; - $this->installerContentsPath = str_replace("\\", '/', (dirname(__FILE__). '/' .self::INSTALLER_DIR_NAME)); - $this->installerExtractPath = str_replace("\\", '/', (dirname(__FILE__))); - $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; + if ($this->archiveExpectedSize > 0) { + $this->archiveRatio = (((1.0) * $this->archiveActualSize) / $this->archiveExpectedSize) * 100; + } else { + $this->archiveRatio = 100; + } } - $this->overwriteMode = (isset($_GET['mode']) && ($_GET['mode'] == 'overwrite')); - } - - /** - * 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 - - self::log('==DUPLICATOR INSTALLER BOOTSTRAP v@@VERSION@@=='); - self::log('----------------------------------------------------'); - self::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; - self::log("[ERROR] Installer and archive mismatch detected."); - } - } else { - self::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; - $installer_directory = dirname(__FILE__).'/'.self::INSTALLER_DIR_NAME; - $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)); - $manual_extract_found = ( - file_exists($installer_directory."/main.installer.php") - && - file_exists($installer_directory."/dup-archive__".self::PACKAGE_HASH.".txt") - && - file_exists($installer_directory."/dup-database__".self::PACKAGE_HASH.".sql") - ); - - $isZip = ($archive_extension == 'zip'); - - //MANUAL EXTRACTION NOT FOUND - if (! $manual_extract_found) { - - //MISSING ARCHIVE FILE - if (! file_exists($archive_filepath)) { - self::log("[ERROR] Archive file not found!"); - $error = "" - . "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->installerExtractPath}/
        "; - - return $error; - } - - // Sometimes the self::ARCHIVE_SIZE is ''. - $archive_size = self::ARCHIVE_SIZE; - - if (!empty($archive_size) && !self::checkInputVaslidInt($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.'.'
        '; - self::log('[ERROR] '.$error); - $error .= 'Possibibles solutions:
        '; - $error .= '- Use the file filters to get your package lower to support this server or try the package on a Linux server.'.'
        '; - $error .= '- Perform a Manual Extract Install'.'
        '; - - 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'.'
        '; - break; - case 64: - $error .= '- Ask your host to upgrade the server to 128-bit PHP or install on another system has 128-bit PHP'.'
        '; - break; + /** + * + * @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; + } + ?> + + + + + Duplicator - issue + + +
        +

        DUPLICATOR ISSUE: PHP REQUIRED

        +

        + This server is running PHP: . A minimum of PHP + is required.

        + Contact your hosting provider or server administrator and let them know you would like to upgrade your PHP version. +

        +
        + + + Windows DupArchive extractor to extract all files from the archive.'.'
        '; + /** + * 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; - } + } - //SIZE CHECK ERROR - if (($this->archiveRatio < 90) && ($this->archiveActualSize > 0) && ($this->archiveExpectedSize > 0)) { - self::log("ERROR: The expected archive size should be around [{$archiveExpectedEasy}]. The actual size is currently [{$archiveActualEasy}]."); - self::log("ERROR: The archive file may not have fully been downloaded to the server"); - $percent = round($this->archiveRatio); + $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 = "
          "; + foreach ($archive_candidates as $archive_candidate) { + $candidate_html .= '
        1. ' . $this->compareStrings($archive_filename, $archive_candidate) . '
        2. '; + } + $candidate_html .= "
        "; + } - $autochecked = isset($_POST['auto-fresh']) ? "checked='true'" : ''; - $error = "Archive file size warning.
        The expected archive size should be around [{$archiveExpectedEasy}]. " - . "The actual size is currently [{$archiveActualEasy}]. The archive file may not have fully been downloaded to the server. " - . "Please validate that the file sizes are close to the same size and that the file has been completely downloaded to the destination server. If the archive is still " - . "downloading then refresh this page to get an update on the download size.

        "; + $error = "" + . "Archive not found! The required archive file must be present in the 'Extraction Path' below. " + . "When the archive file name was created it was named with a secure 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:
        " + . ""; + + return $error; + } - 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.' . '
        '; + $this->log('[ERROR] ' . $error); + $error .= 'Possibibles solutions:
        '; + $error .= '- Use the file filters to get your package lower to support this server or try the package on a Linux server.' . '
        '; + $error .= '- Perform a ' . + 'Manual Extract Install' . '
        '; + + 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' . '
        '; + break; + case 64: + $error .= '- Ask your host to upgrade the server to 128-bit PHP or install on another system has 128-bit PHP' . '
        '; + break; + } - } + if (self::isWindows()) { + $error .= '- ' . + 'Windows DupArchive extractor to extract all files from the archive.' . '
        '; + } + return $error; + } - // OLD COMPATIBILITY MODE - if (isset($_GET['extract-installer']) && !isset($_GET['force-extract-installer'])) { - $_GET['force-extract-installer'] = $_GET['extract-installer']; - } - - if ($manual_extract_found) { - // INSTALL DIRECTORY: Check if its setup correctly AND we are not in overwrite mode - if (isset($_GET['force-extract-installer']) && ('1' == $_GET['force-extract-installer'] || 'enable' == $_GET['force-extract-installer'] || 'false' == $_GET['force-extract-installer'])) { - self::log("Manual extract found with force extract installer get parametr"); - $extract_installer = true; - } else { - $extract_installer = false; - self::log("Manual extract found so not going to extract dup-installer dir"); - } - } else { - $extract_installer = true; - } - - if ($extract_installer && file_exists($installer_directory)) { - self::log("EXTRACT dup-installer dir"); - $scanned_directory = array_diff(scandir($installer_directory), array('..', '.')); - foreach ($scanned_directory as $object) { - $object_file_path = $installer_directory.'/'.$object; - if (is_file($object_file_path)) { - if (unlink($object_file_path)) { - self::log('Successfully deleted the file '.$object_file_path); - } else { - $error .= '[ERROR] Error deleting the file '.$object_file_path.' Please manually delete it and try again.'; - self::log($error); - } - } - } - } - - //ATTEMPT EXTRACTION: - //ZipArchive and Shell Exec - if ($extract_installer) { - self::log("Ready to extract the installer"); - - self::log("Checking permission of destination folder"); - $destination = dirname(__FILE__); - if (!is_writable($destination)) { - self::log("destination folder for extraction is not writable"); - if (self::chmod($destination, 'u+rwx')) { - self::log("Permission of destination folder changed to u+rwx"); - } else { - self::log("[ERROR] Permission of destination folder failed to change to u+rwx"); - } - } - - if (!is_writable($destination)) { - self::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 .= "writable {$destination} directory on this server.
        "; - return $error; - } - - if ($isZip) { - $zip_mode = $this->getZipMode(); - - if (($zip_mode == DUPX_Bootstrap_Zip_Mode::AutoUnzip) || ($zip_mode == DUPX_Bootstrap_Zip_Mode::ZipArchive) && class_exists('ZipArchive')) { - if ($this->hasZipArchive) { - self::log("ZipArchive exists so using that"); - $extract_success = $this->extractInstallerZipArchive($archive_filepath); - - if ($extract_success) { - self::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 dup-installer directory. Please make sure you are attempting to install the original archive and not one that has been reconstructed."; - self::log($error); - return $error; - } else { - $error = '[ERROR] Error extracting with ZipArchive. '; - self::log($error); - } - } - } else { - self::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 .= "ZipArchive on this server.
        "; - } - } - - if (!$extract_success) { - if (($zip_mode == DUPX_Bootstrap_Zip_Mode::AutoUnzip) || ($zip_mode == DUPX_Bootstrap_Zip_Mode::ShellExec)) { - $unzip_filepath = $this->getUnzipFilePath(); - if ($unzip_filepath != null) { - $extract_success = $this->extractInstallerShellexec($archive_filepath); - if ($extract_success) { - self::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.'; - self::log($error); - } - } else { - self::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 .= "Shell Exec 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 == DUPX_Bootstrap_Zip_Mode::AutoUnzip) { - $unzip_filepath = $this->getUnzipFilePath(); - if (!class_exists('ZipArchive') && empty($unzip_filepath)) { - self::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 .= "ZipArchive or Shell Exec on this server or manually extract archive then choose Advanced > Manual Extract in installer."; - } - } - } else { - DupArchiveMiniExpander::init("DUPX_Bootstrap::log"); - try { - DupArchiveMiniExpander::expandDirectory($archive_filepath, self::INSTALLER_DIR_NAME, dirname(__FILE__)); - } catch (Exception $ex) { - self::log("[ERROR] Error expanding installer subdirectory:".$ex->getMessage()); - throw $ex; - } - } - - $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) { - self::log("SAPI: FPM"); - if ($is_apache) { - self::log('Server: Apache'); - } elseif ($is_nginx) { - self::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 = dirname(__FILE__).'/dup-installer/.htaccess'; - self::log("creating {$htaccess_file_path} with the content:"); - self::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) { - self::log("SAPI: CGI"); - } else { - self::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 = dirname(__FILE__).'/dup-installer/.user.ini'; - self::log("creating {$ini_file_path} with the content:"); - self::log($ini_text); - @file_put_contents($ini_file_path, $ini_text); - } else{ - self::log("No need to create dup-installer/.htaccess or dup-installer/.user.ini"); - } - } else { - self::log("No need to create dup-installer/.htaccess or dup-installer/.user.ini"); - self::log("ERROR: SAPI: Unrecognized"); - } - } else { - self::log("ERROR: Didn't need to extract the installer."); - } - - if (empty($error)) { - $config_files = glob('./dup-installer/dup-archive__*.txt'); - $config_file_absolute_path = array_pop($config_files); - if (!file_exists($config_file_absolute_path)) { - $error = 'Archive config file not found in dup-installer folder.

        '; - return $error; - } - } - - $is_https = $this->isHttps(); - - if($is_https) { - $current_url = 'https://'; - } else { - $current_url = 'http://'; - } - - if(($_SERVER['SERVER_PORT'] == 80) && ($is_https)) { - // Fixing what appears to be a bad server setting - $server_port = 443; - } else { - $server_port = $_SERVER['SERVER_PORT']; - } - - // for ngrok url and Local by Flywheel Live URL - 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 - } - $current_url .= $host; - if(strpos($current_url,':') === false) { - $current_url = $current_url.':'.$server_port; + //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 = "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." + . "
          " + . "
        • Download the whole archive from the source website (open WordPress Admin > Duplicator > Packages) " + . "and validate that the file size is close to the expected size.
        • " + . "
        • Make sure to upload the whole archive file to the destination server.
        • " + . "
        • If the archive file is still uploading then please refresh this page to get an update on the currently uploaded file size.
        • " + . "
        "; + return $error; } - - $current_url .= $_SERVER['REQUEST_URI']; - $uri_start = dirname($current_url); + } - $encoded_archive_path = urlencode($archive_filepath); + 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 ($error === null) { - $error = $this->postExtractProcessing(); + // 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); + } + } + } + } + } + } - if($error == null) { + //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"); + } + } - $bootloader_name = basename(__FILE__); - $this->mainInstallerURL = $uri_start.'/'.self::INSTALLER_DIR_NAME.'/main.installer.php'; + 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 .= "" . + "writable {$destination} directory on this server.
        "; + return $error; + } - $this->fixInstallerPerms($this->mainInstallerURL); + 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 .= "" . + "ZipArchive on this server.
        "; + } + } - $this->archive = $archive_filepath; - $this->bootloader = $bootloader_name; + 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 .= "Shell Exec " . + "on this server or manually extract archive then choose Advanced > Manual Extract in installer."; + } + } + } - if (isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING'])) { - $this->mainInstallerURL .= '?'.$_SERVER['QUERY_STRING']; + // 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 .= "ZipArchive " . + "or Shell Exec " . + "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; + } + } - self::log("DONE: No detected errors so redirecting to the main installer. Main Installer URI = {$this->mainInstallerURL}"); + 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'); } } - return $error; - } - - public function postExtractProcessing() - { - $dproInstallerDir = dirname(__FILE__) . '/dup-installer'; - $libDir = $dproInstallerDir . '/lib'; - $fileopsDir = $libDir . '/fileops'; - - if(!file_exists($dproInstallerDir)) { - - return 'Can\'t extract installer directory. See this FAQ item for details on how to resolve.'; - } + $htaccessToRemove = $this->targetDupInst.'/.htaccess'; + if (is_file($htaccessToRemove) && is_writable($htaccessToRemove)) { + $this->log("Remove Htaccess in dup-installer folder"); + @unlink($htaccessToRemove); + } - $sourceFilepath = "{$fileopsDir}/fileops.ppp"; - $destFilepath = "{$fileopsDir}/fileops.php"; - - if(file_exists($sourceFilepath) && (!file_exists($destFilepath))) { - if(@rename($sourceFilepath, $destFilepath) === false) { - return "Error renaming {$sourceFilepath}"; - } - } - } - - /** - * Indicates if site is running https or not - * - * @return bool Returns true if https, false if not - */ - public function isHttps() - { - $retVal = true; - if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { - $_SERVER ['HTTPS'] = 'on'; - } - if (isset($_SERVER['HTTPS'])) { - $retVal = ($_SERVER['HTTPS'] !== 'off'); - } else { - $retVal = ($_SERVER['SERVER_PORT'] == 443); + $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."); } - return $retVal; - } - - /** - * Fetches current URL via php - * - * @param bool $queryString If true the query string will also be returned. - * @param int $getParentDirLevel if 0 get current script name or parent folder, if 1 parent folder if 2 parent of parent folder ... - * - * @returns The current page url - */ - 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 - } + if (empty($error)) { + if ($this->isCustomDupFolder && file_exists($this->extractionTmpFolder)) { + rmdir($this->extractionTmpFolder); + } - // *** 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'; + $config_files = glob($this->targetDupInst . '/dup-archive__*.txt'); + $config_file_absolute_path = array_pop($config_files); + if (!file_exists($config_file_absolute_path)) { + $error = 'Archive config file not found in ' . $this->targetDupInstFolder . ' folder.

        '; + return $error; + } + } + + $uri_start = self::getCurrentUrl(false, false, 1); + if ($error === null) { + if (!file_exists($this->targetDupInst)) { + $error = 'Can\'t extract installer directory. ' . + 'See this FAQ item' . + ' for details on how to resolve.'; + } + + 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; } - if (isset($_SERVER['HTTP_CF_VISITOR'])) { - $visitor = json_decode($_SERVER['HTTP_CF_VISITOR']); - if ($visitor->scheme == 'https') { + + /** + * 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'; } - } - $protocol = 'http'.((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) === 'on') ? 's' : ''); + 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); + 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'] : ''; + // *** QUERY STRING + $query = ($queryString && isset($_SERVER['QUERY_STRING']) && strlen($_SERVER['QUERY_STRING']) > 0 ) ? '?' . $_SERVER['QUERY_STRING'] : ''; - return $protocol.'://'.$host.$serverUrlSelf.$query; - } + 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'; + /** + * 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); + } - $installer_dir_path = $this->installerContentsPath; + /** + * 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); + } - $this->setPerms($installer_dir_path, $dir_perms, false); - $this->setPerms($installer_dir_path, $file_perms, true); - } + $item_names = array_diff(scandir($directory), array('.', '..')); - /** - * 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) { - self::log("ERROR: Couldn't set permissions of $path
        "); - } else { - self::log("Set permissions of $path
        "); + 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); + } + } } - return $result; - } - /** - * Compare two strings and return html text which represts diff - * - * @param string $oldString - * @param string $newString - * - * @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 .= '' . $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; - } + /** + * 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
        "); + } else { + $this->log("Set permissions of $path
        "); + } + return $result; + } - /** - * Logs a string to the dup-installer-bootlog__[HASH].txt file - * - * @param string $s The string to log to the log file - * - * @return boog|int // This function returns the number of bytes that were written to the file, or FALSE on failure. - */ - public static function log($s, $deleteOld = false) - { - static $logfile = null; - if (is_null($logfile)) { - $logfile = self::getBootLogFilePath(); + /** + * 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 .= '' . $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; } - if ($deleteOld && file_exists($logfile)) { - @unlink($logfile); + + /** + * 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); } - $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 static function getBootLogFilePath() { - return dirname(__FILE__).'/dup-installer-bootlog__'.self::SECONDARY_PACKAGE_HASH.'.txt'; - } - - protected static function postprocessLog($str) { - return str_replace(array( - self::getArchiveFileHash(), - self::PACKAGE_HASH, - self::SECONDARY_PACKAGE_HASH - ), '[HASH]' , $str); - } - - - 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); + + /** + * 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'; } - return $fileHash; - } - - /** - * Extracts only the 'dup-installer' files using ZipArchive - * - * @param string $archive_filepath The path to the archive file. - * - * @return bool Returns true if the data was properly extracted - */ - private function extractInstallerZipArchive($archive_filepath, $checkSubFolder = false) - { - $success = true; - $zipArchive = new ZipArchive(); - $subFolderArchiveList = array(); - - if (($zipOpenRes = $zipArchive->open($archive_filepath)) === true) { - self::log("Successfully opened archive file."); - $destination = dirname(__FILE__); - $folder_prefix = self::INSTALLER_DIR_NAME.'/'; - self::log("Extracting all files from archive within ".self::INSTALLER_DIR_NAME); - - $this->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)) { - $this->installer_files_found++; - - if (!empty($tmpSubFolder) && !in_array($tmpSubFolder , $subFolderArchiveList)) { - $subFolderArchiveList[] = $tmpSubFolder; - } - - if ($zipArchive->extractTo($destination, $filename) === true) { - self::log("Success: {$filename} >>> {$destination}"); - } else { - self::log("[ERROR] Error extracting {$filename} from archive archive file"); - $success = false; - break; - } - } - } - - if ($checkSubFolder && count($subFolderArchiveList) !== 1) { - self::log("Error: Multiple dup subfolder archive"); - $success = false; - } else { - if ($checkSubFolder) { - $this->moveUpfromSubFolder(dirname(__FILE__).'/'.$subFolderArchiveList[0] , true); - } - - $lib_directory = dirname(__FILE__).'/'.self::INSTALLER_DIR_NAME.'/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)) { - $this->installer_files_found++; - - if ($zipArchive->extractTo($destination, $filename) === true) { - self::log("Success: {$filename} >>> {$destination}"); - } else { - self::log("[ERROR] Error extracting {$filename} from archive archive file"); - $success = false; - break; - } - } - } - } - } - - if ($zipArchive->close() === true) { - self::log("Successfully closed archive file"); - } else { - self::log("[ERROR] Problem closing archive file"); - $success = false; - } - - if ($success != false && $this->installer_files_found < 10) { - if ($checkSubFolder) { - self::log("[ERROR] Couldn't find the installer directory in the archive!"); - $success = false; - } else { - self::log("[ERROR] Couldn't find the installer directory in archive root! Check subfolder"); - $this->extractInstallerZipArchive($archive_filepath, true); - } - } - } else { - self::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'); + + /** + * 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 $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; + /** + * 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 { - // for PHP < 5.3.0 - $maxPath = self::isWindows() ? 260 : 4096; + $this->log("[ERROR] Couldn't open archive archive file with ZipArchive CODE[" . $zipOpenRes . "]"); + $success = false; } + + return $success; } - return $maxPath; - } - - /** - * 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 - * @param int|string $mode - * @return boolean - */ - public static function chmod($file, $mode) - { - if (!file_exists($file)) { - return false; + + /** + * 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; } - $octalMode = 0; + /** + * @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 (is_int($mode)) { - $octalMode = $mode; - } else if (is_string($mode)) { - $mode = trim($mode); - if (preg_match('/([0-7]{1,3})/', $mode)) { - $octalMode = intval(('0'.$mode), 8); - } else if (preg_match_all('/(a|[ugo]{1,3})([-=+])([rwx]{1,3})/', $mode, $gMatch, PREG_SET_ORDER)) { - if (!function_exists('fileperms')) { - return false; + if ($item->isDir()) { + self::chmod($item->getPathname(), $defaultDirPermission); } + } + } - // start by file permission - $octalMode = (fileperms($file) & 0777); + /** + * 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; + } - foreach ($gMatch as $matches) { - // [ugo] or a = ugo - $group = $matches[1]; - if ($group === 'a') { - $group = 'ugo'; + $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; } - // 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; - } + + // start by file permission + $octalMode = (fileperms($file) & 0777); + + foreach ($gMatch as $matches) { + // [ugo] or a = ugo + $group = $matches[1]; + if ($group === 'a') { + $group = 'ugo'; } - // 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 + // 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 'o': - $octalGroupMode = $octalGroupMode | $subPerm; // mask 000000xxx + case '-': + $octalMode = $octalMode & ~$octalGroupMode; 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 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); } - if (!function_exists('chmod')) { - return false; + /** + * 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)); } - return @chmod($file, $octalMode); - } - - public static function checkInputVaslidInt($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); + } - - /** - * 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 - * @param int|string $mode - * @param bool $recursive - * @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); } - if (!file_exists($path)) { - if (!function_exists('mkdir')) { + /** + * 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; } - if (!@mkdir($path, 0777, $recursive)) { + + $parentFolder = dirname($subFolderName); + if (!is_writable($parentFolder)) { return false; } - } - return self::chmod($path, $mode); - } + $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); + } - /** - * 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; - } + if ($success) { + $success = rename($cName, $destination); + } else { + break; + } + } - $parentFolder = dirname($subFolderName); - if (!is_writable($parentFolder)) { - return false; + if ($success && $deleteSubFolder) { + $success = self::rrmdir($subFolderName, true); + } + } + + if (!$success) { + $this->log("[ERROR] Problem om moveUpfromSubFolder subFolder:" . $subFolderName); + } + + return $success; } - $success = true; - if (($subList = glob(rtrim($subFolderName, '/').'/*', GLOB_NOSORT)) === false) { - self::log("[ERROR] Problem glob folder ".$subFolderName); - return false; - } else { - foreach ($subList as $cName) { - $destination = $parentFolder.'/'.basename($cName); - if (file_exists($destination)) { - $success = self::deletePath($destination); + /** + * 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 ($success) { - $success = rename($cName, $destination); + if ($stderr == '') { + $this->log("Shell exec unzip succeeded"); + $success = true; } else { - break; + $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 ($success && $deleteSubFolder) { - $success = self::deleteDirectory($subFolderName, true); + if (($realPath = realpath($archive_filepath)) !== false) { + return $realPath; + } else { + return $archive_filepath; } } - if (!$success) { - self::log("[ERROR] Problem om moveUpfromSubFolder subFolder:".$subFolderName); + /** + * 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; } - return $success; - } + /** + * 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; + } - /** - * Extracts only the 'dup-installer' files using Shell-Exec Unzip - * - * @param string $archive_filepath The path to the archive file. - * - * @return bool Returns true if the data was properly extracted - */ - private function extractInstallerShellexec($archive_filepath) - { - $success = false; - self::log("Attempting to use Shell Exec"); - $unzip_filepath = $this->getUnzipFilePath(); - - if ($unzip_filepath != null) { - $unzip_command = "$unzip_filepath -q $archive_filepath ".self::INSTALLER_DIR_NAME.'/* 2>&1'; - self::log("Executing unzip command"); - $stderr = shell_exec($unzip_command); - - $lib_directory = dirname(__FILE__).'/'.self::INSTALLER_DIR_NAME.'/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 = dirname(__FILE__).'/snaplib'; - $unzip_command = "$unzip_filepath -q $archive_filepath snaplib/* 2>&1"; - self::log("Executing unzip command"); - $stderr .= shell_exec($unzip_command); - self::mkdir($lib_directory,'u+rwx'); - rename($local_lib_directory, $snaplib_directory); - } - - if ($stderr == '') { - self::log("Shell exec unzip succeeded"); - $success = true; - } else { - self::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 (isset($_GET['archive'])) { - $archive_filepath = $_GET['archive']; - } else { - $archive_filename = self::ARCHIVE_FILENAME; - $archive_filepath = str_replace("\\", '/', dirname(__FILE__) . '/' . $archive_filename); - } - - return $archive_filepath; - } - - /** - * Gets the DUPX_Bootstrap_Zip_Mode enum type that should be used - * - * @return DUPX_Bootstrap_Zip_Mode Returns the current mode of the bootstrapper - */ - private function getZipMode() - { - $zip_mode = DUPX_Bootstrap_Zip_Mode::AutoUnzip; - - if (isset($_GET['zipmode'])) { - $zipmode_string = $_GET['zipmode']; - self::log("Unzip mode specified in querystring: $zipmode_string"); - - switch ($zipmode_string) { - case 'autounzip': - $zip_mode = DUPX_Bootstrap_Zip_Mode::AutoUnzip; - break; - - case 'ziparchive': - $zip_mode = DUPX_Bootstrap_Zip_Mode::ZipArchive; - break; - - case 'shellexec': - $zip_mode = DUPX_Bootstrap_Zip_Mode::ShellExec; - break; - } - } - - return $zip_mode; - } - - /** - * Checks to see if a string starts with specific characters - * - * @return bool Returns true if the string starts with a specific format - */ - 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; + } - /** - * 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'); + //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; + } + } - //Function disabled at server level - if (array_intersect($cmds, array_map('trim', explode(',', @ini_get('disable_functions'))))) - return false; + if (! function_exists('shell_exec')) { + 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)))) + // Can we issue a simple echo command? + if (!@shell_exec('echo duplicator')) { return false; - } + } - if (! function_exists('shell_exec')) { - return false; - } + return true; + } - // Can we issue a simple echo command? - if (!@shell_exec('echo duplicator')) - return false; + /** + * 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 true; - } + return $filepath; + } - /** - * 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 - * - * @return array of zip files - */ - public static function getFilesWithExtension($extension) - { - $files = array(); - foreach (glob("*.{$extension}") as $name) { - if (file_exists($name)) { - $files[] = $name; + /** + * 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"; } } - if (count($files) > 0) { + /** + * 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; } - //FALL BACK: Windows XP has bug with glob, - //add secondary check for PHP lameness - if ($dh = opendir('.')) { - while (false !== ($name = readdir($dh))) { - $ext = substr($name, strrpos($name, '.') + 1); - if (in_array($ext, array($extension))) { - $files[] = $name; + /** + * 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; } } - closedir($dh); } - return $files; + /** + * 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); + } } - - /** - * Safely remove a directory and recursively if needed - * - * @param string $directory The full path to the directory to remove - * @param string $recursive recursively remove all items - * - * @return bool Returns true if all content was removed - */ - public static function deleteDirectory($directory, $recursive) + + class LogHandler { - $success = true; - $filenames = array_diff(scandir($directory), array('.', '..')); + /** @var bool */ + private static $initialized = false; - foreach ($filenames as $filename) { - $fullPath = $directory.'/'.$filename; + /** + * 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; + } + } - if (is_dir($fullPath)) { - if ($recursive) { - $success = self::deleteDirectory($fullPath, true); - } - } else { - $success = @unlink($fullPath); - if ($success === false) { - self::log('[ERROR] '.__FUNCTION__.": Problem deleting file:".$fullPath); - } + /** + * 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('
        ' . htmlspecialchars($log_message) . '
        '); + break; + case E_NOTICE: + case E_WARNING: + default: + $log_message = self::getMessage($errno, $errstr, $errfile, $errline); + DUPX_Bootstrap::getInstance()->log($log_message); + break; } + } - if ($success === false) { - self::log("[ERROR] Problem deleting dir:".$directory); - 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; } - return $success && rmdir($directory); + /** + * Shutdown handler + * + * @return void + */ + public static function shutdown() + { + if (($error = error_get_last())) { + LogHandler::error($error['type'], $error['message'], $error['file'], $error['line']); + } + } } - /** - * Safely remove a file or directory and recursively if needed - * - * @param string $directory The full path to the directory to remove - * - * @return bool Returns true if all content was removed - */ - public static function deletePath($path) + class DUPX_CSRF { - $success = true; - if (is_dir($path)) { - $success = self::deleteDirectory($path, true); - } else { - $success = @unlink($path); + 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; + } - if ($success === false) { - self::log('[ERROR] '. __FUNCTION__.": Problem deleting file:".$path); + /** + * 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; } } - return $success; - } - - /** - * 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 The path to make safe - * - * @return string The original $path with a with all slashes facing '/'. - */ - public static function setSafePath($path) - { - return str_replace("\\", "/", $path); - } -} + /** + * 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(); + } -class DUPX_Handler -{ - /** - * - * @var bool - */ - private static $initialized = false; - - /** - * This function only initializes the error handler the first time it is called - */ - public static function init_error_handler() - { - if (!self::$initialized) { - @set_error_handler(array(__CLASS__, 'error')); - @register_shutdown_function(array(__CLASS__, 'shutdown')); - self::$initialized = true; + self::setKeyVal($keyName, $token); + return $token; } - } - - /** - * 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::log($log_message) === false) { - $log_message = "Can\'t write logfile\n\n".$log_message; - } - die('
        '.htmlspecialchars($log_message).'
        '); - break; - case E_NOTICE : - case E_WARNING : - default : - $log_message = self::getMessage($errno, $errstr, $errfile, $errline); - DUPX_Bootstrap::log($log_message); - break; + + /** + * 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; } - } - 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; + /** 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); } - $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())) { - DUPX_Handler::error($error['type'], $error['message'], $error['file'], $error['line']); + /** 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'])))); } - } -} -class DUPX_CSRF { - - /** - * 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; - - /** - * Set new CSRF - * - * @param $key string CSRF Key - * @param $key string CSRF Val - * - * @return Void - */ - public static function setKeyVal($key, $val) { - $CSRFVars = self::getCSRFVars(); - $CSRFVars[$key] = $val; - self::saveCSRFVars($CSRFVars); - self::$CSRFVars = false; - } - - /** - * Get CSRF value by passing CSRF key - * - * @param $key string 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) { - $keyName = self::getKeyName($form); - $CSRFVars = self::getCSRFVars(); - if (isset($CSRFVars[$keyName]) && $CSRFVars[$keyName] == $token) { // token OK - return true; - } - return FALSE; - } - - /** Generate token - * @param void - * @return string - */ - protected static function token() { - mt_srand((double) microtime() * 10000); - $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 - * @param void - * @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 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 (class_exists('DUPX_Bootstrap')) { - return DUPX_Bootstrap::PACKAGE_HASH; - } else { - return $GLOBALS['DUPX_AC']->package_hash; - } - } - - /** - * 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 (class_exists('DUPX_Bootstrap')) { - $dupInstallerfolderPath = dirname(__FILE__).'/dup-installer/'; - } else { - $dupInstallerfolderPath = $GLOBALS['DUPX_INIT'].'/'; - } - $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 (!isset(self::$CSRFVars) || false === self::$CSRFVars) { - $filePath = self::getFilePath(); - if (file_exists($filePath)) { - $contents = file_get_contents($filePath); - if (!($contents = file_get_contents($filePath))) { - throw new Exception('Fail to read the CSRF file.'); - } - 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 $CSRFVars array holds all CSRF key val - * @return void - */ - private static function saveCSRFVars($CSRFVars) { - $contents = json_encode($CSRFVars); - $filePath = self::getFilePath(); - if (!file_put_contents($filePath, $contents, LOCK_EX)) { - throw new Exception('Fail to write the CSRF file.'); - } - } -} + /** + * 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; + } -try { - $boot = new DUPX_Bootstrap(); - $boot_error = $boot->run(); + /** + * 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(); - if ($boot_error == null) { - $step1_csrf_token = DUPX_CSRF::generate('step1'); - DUPX_CSRF::setKeyVal('archive', $boot->archive); - DUPX_CSRF::setKeyVal('bootloader', $boot->bootloader); - DUPX_CSRF::setKeyVal('secondaryHash', DUPX_Bootstrap::SECONDARY_PACKAGE_HASH); - DUPX_CSRF::setKeyVal('installerOrigCall', DUPX_Bootstrap::getCurrentUrl()); - DUPX_CSRF::setKeyVal('installerOrigPath', __FILE__); - DUPX_CSRF::setKeyVal('booturl', '//'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); - DUPX_CSRF::setKeyVal('bootLogFile', DUPX_Bootstrap::getBootLogFilePath()); - DUPX_CSRF::setKeyVal('package_hash', DUPX_Bootstrap::PACKAGE_HASH); - } -} catch (Exception $e) { - $boot_error = $e->getMessage(); -} + 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); + } + ?> + + + + + + Duplicator Installer + + + +
        + Initializing Installer. Please wait... +
        + 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 .= "\n"; + } + $html .= "\n"; + $html .= ""; + echo $html; + ?> + + + + + - - -
        - - - - - - -
          Duplicator - Bootloader - version:
        -
        - -
        -
        -

        Setup Notice:

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

        - -

        Server Settings:

        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        ZipArchive:hasZipArchive ? 'Enabled' : 'Disabled'; ?>
        ShellExec Unzip:hasShellExecUnzip ? 'Enabled' : 'Disabled'; ?>
        Extraction Path:installerExtractPath; ?>
        Installer Path:installerContentsPath; ?>
        Archive Name: - [HASH]_archive.zip or [HASH]_archive.daf
        - This is based on the format used to build the archive -
        Archive Size: - Expected Size: readableByteSize($boot->archiveExpectedSize); ?>   - Actual Size: readableByteSize($boot->archiveActualSize); ?> -
        Boot Logdup-installer-bootlog__[HASH].txt
        -

        - -
        - Please Note: 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 - manually extract before running the installer. -
        -

        - -
        -
        - -
        - - - - - - - - -@@DUPARCHIVE_MINI_EXPANDER@@ - - + /* 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} + + + +
        + + + + + +
          Duplicator - Bootloader + + version:
        + » + + dup-installer-bootlog__[HASH].txt + +
        + +
        +
        +

        Setup Notice

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

        + +

        Server Settings

        + + + + + + + + + + + + + + + + + + + + + + + + + +
        ZipArchive:hasZipArchive ? 'Enabled' : 'Disabled'; ?>
        Shell Unzip:hasShellExecUnzip ? 'Enabled' : 'Disabled'; ?>
        Extraction Path:targetRoot; ?>
        Installer Path:targetDupInstFolder; ?>
        Archive Size: + Expected Size: readableByteSize($boot->archiveExpectedSize); ?>   + Actual Size: readableByteSize($boot->archiveActualSize); ?> +
        Boot Log + + dup-installer-bootlog__[HASH].txt + +
        +

        + +
        + 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 + manually extract before + running the installer. +
        +

        + +
        +
        + +
        + + + + + + + + - * @package Encoding - * @version 2.0 - * @link https://github.com/neitanod/forceutf8 - * @example https://github.com/neitanod/forceutf8 - * @license Revised BSD - */ - -//namespace ForceUTF8; -if (!class_exists('DUP_Encoding')) -{ - class DUP_Encoding { - - const ICONV_TRANSLIT = "TRANSLIT"; - const ICONV_IGNORE = "IGNORE"; - const WITHOUT_ICONV = ""; - - protected static $win1252ToUtf8 = array( - 128 => "\xe2\x82\xac", - - 130 => "\xe2\x80\x9a", - 131 => "\xc6\x92", - 132 => "\xe2\x80\x9e", - 133 => "\xe2\x80\xa6", - 134 => "\xe2\x80\xa0", - 135 => "\xe2\x80\xa1", - 136 => "\xcb\x86", - 137 => "\xe2\x80\xb0", - 138 => "\xc5\xa0", - 139 => "\xe2\x80\xb9", - 140 => "\xc5\x92", - 142 => "\xc5\xbd", - 145 => "\xe2\x80\x98", - 146 => "\xe2\x80\x99", - 147 => "\xe2\x80\x9c", - 148 => "\xe2\x80\x9d", - 149 => "\xe2\x80\xa2", - 150 => "\xe2\x80\x93", - 151 => "\xe2\x80\x94", - 152 => "\xcb\x9c", - 153 => "\xe2\x84\xa2", - 154 => "\xc5\xa1", - 155 => "\xe2\x80\xba", - 156 => "\xc5\x93", - - 158 => "\xc5\xbe", - 159 => "\xc5\xb8" - ); - - protected static $brokenUtf8ToUtf8 = array( - "\xc2\x80" => "\xe2\x82\xac", - - "\xc2\x82" => "\xe2\x80\x9a", - "\xc2\x83" => "\xc6\x92", - "\xc2\x84" => "\xe2\x80\x9e", - "\xc2\x85" => "\xe2\x80\xa6", - "\xc2\x86" => "\xe2\x80\xa0", - "\xc2\x87" => "\xe2\x80\xa1", - "\xc2\x88" => "\xcb\x86", - "\xc2\x89" => "\xe2\x80\xb0", - "\xc2\x8a" => "\xc5\xa0", - "\xc2\x8b" => "\xe2\x80\xb9", - "\xc2\x8c" => "\xc5\x92", - - "\xc2\x8e" => "\xc5\xbd", - - - "\xc2\x91" => "\xe2\x80\x98", - "\xc2\x92" => "\xe2\x80\x99", - "\xc2\x93" => "\xe2\x80\x9c", - "\xc2\x94" => "\xe2\x80\x9d", - "\xc2\x95" => "\xe2\x80\xa2", - "\xc2\x96" => "\xe2\x80\x93", - "\xc2\x97" => "\xe2\x80\x94", - "\xc2\x98" => "\xcb\x9c", - "\xc2\x99" => "\xe2\x84\xa2", - "\xc2\x9a" => "\xc5\xa1", - "\xc2\x9b" => "\xe2\x80\xba", - "\xc2\x9c" => "\xc5\x93", - - "\xc2\x9e" => "\xc5\xbe", - "\xc2\x9f" => "\xc5\xb8" - ); - - protected static $utf8ToWin1252 = array( - "\xe2\x82\xac" => "\x80", - - "\xe2\x80\x9a" => "\x82", - "\xc6\x92" => "\x83", - "\xe2\x80\x9e" => "\x84", - "\xe2\x80\xa6" => "\x85", - "\xe2\x80\xa0" => "\x86", - "\xe2\x80\xa1" => "\x87", - "\xcb\x86" => "\x88", - "\xe2\x80\xb0" => "\x89", - "\xc5\xa0" => "\x8a", - "\xe2\x80\xb9" => "\x8b", - "\xc5\x92" => "\x8c", - - "\xc5\xbd" => "\x8e", - - - "\xe2\x80\x98" => "\x91", - "\xe2\x80\x99" => "\x92", - "\xe2\x80\x9c" => "\x93", - "\xe2\x80\x9d" => "\x94", - "\xe2\x80\xa2" => "\x95", - "\xe2\x80\x93" => "\x96", - "\xe2\x80\x94" => "\x97", - "\xcb\x9c" => "\x98", - "\xe2\x84\xa2" => "\x99", - "\xc5\xa1" => "\x9a", - "\xe2\x80\xba" => "\x9b", - "\xc5\x93" => "\x9c", - - "\xc5\xbe" => "\x9e", - "\xc5\xb8" => "\x9f" - ); - - static function toUTF8($text){ - /** - * Function \ForceUTF8\Encoding::toUTF8 - * - * This function leaves UTF8 characters alone, while converting almost all non-UTF8 to UTF8. - * - * It assumes that the encoding of the original string is either Windows-1252 or ISO 8859-1. - * - * It may fail to convert characters to UTF-8 if they fall into one of these scenarios: - * - * 1) when any of these characters: ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞß - * are followed by any of these: ("group B") - * ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶•¸¹º»¼½¾¿ - * For example: %ABREPRESENT%C9%BB. «REPRESENTÉ» - * The "«" (%AB) character will be converted, but the "É" followed by "»" (%C9%BB) - * is also a valid unicode character, and will be left unchanged. - * - * 2) when any of these: àáâãäåæçèéêëìíîï are followed by TWO chars from group B, - * 3) when any of these: ðñòó are followed by THREE chars from group B. - * - * @name toUTF8 - * @param string $text Any string. - * @return string The same string, UTF8 encoded - * - */ - - if(is_array($text)) - { - foreach($text as $k => $v) - { - $text[$k] = self::toUTF8($v); - } - return $text; - } - - if(!is_string($text)) { - return $text; - } - - $max = self::strlen($text); - - $buf = ""; - for($i = 0; $i < $max; $i++){ - $c1 = $text[$i]; - if($c1>="\xc0"){ //Should be converted to UTF8, if it's not UTF8 already - $c2 = $i+1 >= $max? "\x00" : $text[$i+1]; - $c3 = $i+2 >= $max? "\x00" : $text[$i+2]; - $c4 = $i+3 >= $max? "\x00" : $text[$i+3]; - if($c1 >= "\xc0" & $c1 <= "\xdf"){ //looks like 2 bytes UTF8 - if($c2 >= "\x80" && $c2 <= "\xbf"){ //yeah, almost sure it's UTF8 already - $buf .= $c1 . $c2; - $i++; - } else { //not valid UTF8. Convert it. - $cc1 = (chr(ord($c1) / 64) | "\xc0"); - $cc2 = ($c1 & "\x3f") | "\x80"; - $buf .= $cc1 . $cc2; - } - } elseif($c1 >= "\xe0" & $c1 <= "\xef"){ //looks like 3 bytes UTF8 - if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf"){ //yeah, almost sure it's UTF8 already - $buf .= $c1 . $c2 . $c3; - $i = $i + 2; - } else { //not valid UTF8. Convert it. - $cc1 = (chr(ord($c1) / 64) | "\xc0"); - $cc2 = ($c1 & "\x3f") | "\x80"; - $buf .= $cc1 . $cc2; - } - } elseif($c1 >= "\xf0" & $c1 <= "\xf7"){ //looks like 4 bytes UTF8 - if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf" && $c4 >= "\x80" && $c4 <= "\xbf"){ //yeah, almost sure it's UTF8 already - $buf .= $c1 . $c2 . $c3 . $c4; - $i = $i + 3; - } else { //not valid UTF8. Convert it. - $cc1 = (chr(ord($c1) / 64) | "\xc0"); - $cc2 = ($c1 & "\x3f") | "\x80"; - $buf .= $cc1 . $cc2; - } - } else { //doesn't look like UTF8, but should be converted - $cc1 = (chr(ord($c1) / 64) | "\xc0"); - $cc2 = (($c1 & "\x3f") | "\x80"); - $buf .= $cc1 . $cc2; - } - } elseif(($c1 & "\xc0") == "\x80"){ // needs conversion - if(isset(self::$win1252ToUtf8[ord($c1)])) { //found in Windows-1252 special cases - $buf .= self::$win1252ToUtf8[ord($c1)]; - } else { - $cc1 = (chr(ord($c1) / 64) | "\xc0"); - $cc2 = (($c1 & "\x3f") | "\x80"); - $buf .= $cc1 . $cc2; - } - } else { // it doesn't need conversion - $buf .= $c1; - } - } - return $buf; - } - - static function toWin1252($text, $option = self::WITHOUT_ICONV) { - if(is_array($text)) { - foreach($text as $k => $v) { - $text[$k] = self::toWin1252($v, $option); - } - return $text; - } else if(is_string($text)) { - return self::utf8_decode($text, $option); - } else { - return $text; - } - } - - static function toISO8859($text) { - return self::toWin1252($text); - } - - static function toLatin1($text) { - return self::toWin1252($text); - } - - static function fixUTF8($text, $option = self::WITHOUT_ICONV){ - if(is_array($text)) { - foreach($text as $k => $v) { - $text[$k] = self::fixUTF8($v, $option); - } - return $text; - } - - $last = ""; - while($last <> $text){ - $last = $text; - $text = self::toUTF8(self::utf8_decode($text, $option)); - } - $text = self::toUTF8(self::utf8_decode($text, $option)); - return $text; - } - - static function UTF8FixWin1252Chars($text){ - // If you received an UTF-8 string that was converted from Windows-1252 as it was ISO8859-1 - // (ignoring Windows-1252 chars from 80 to 9F) use this function to fix it. - // See: http://en.wikipedia.org/wiki/Windows-1252 - - return str_replace(array_keys(self::$brokenUtf8ToUtf8), array_values(self::$brokenUtf8ToUtf8), $text); - } - - static function removeBOM($str=""){ - if(substr($str, 0,3) == pack("CCC",0xef,0xbb,0xbf)) { - $str=substr($str, 3); - } - return $str; - } - - protected static function strlen($text) - { - if((version_compare(PHP_VERSION, '7.2.0') >= 0)) { - return (function_exists('mb_strlen')) - ? mb_strlen($text,'8bit') - : strlen($text); - } else { - return (function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload')) & 2) - ? mb_strlen($text,'8bit') - : strlen($text); - } - } - - public static function normalizeEncoding($encodingLabel) - { - $encoding = strtoupper($encodingLabel); - $encoding = preg_replace('/[^a-zA-Z0-9\s]/', '', $encoding); - $equivalences = array( - 'ISO88591' => 'ISO-8859-1', - 'ISO8859' => 'ISO-8859-1', - 'ISO' => 'ISO-8859-1', - 'LATIN1' => 'ISO-8859-1', - 'LATIN' => 'ISO-8859-1', - 'UTF8' => 'UTF-8', - 'UTF' => 'UTF-8', - 'WIN1252' => 'ISO-8859-1', - 'WINDOWS1252' => 'ISO-8859-1' - ); - - if(empty($equivalences[$encoding])){ - return 'UTF-8'; - } - - return $equivalences[$encoding]; - } - - public static function encode($encodingLabel, $text) - { - $encodingLabel = self::normalizeEncoding($encodingLabel); - if($encodingLabel == 'ISO-8859-1') return self::toLatin1($text); - return self::toUTF8($text); - } - - protected static function utf8_decode($text, $option) - { - if ($option == self::WITHOUT_ICONV || !function_exists('iconv')) { - $o = utf8_decode( - str_replace(array_keys(self::$utf8ToWin1252), array_values(self::$utf8ToWin1252), self::toUTF8($text)) - ); - } else { - $o = iconv("UTF-8", "Windows-1252" . ($option == self::ICONV_TRANSLIT ? '//TRANSLIT' : ($option == self::ICONV_IGNORE ? '//IGNORE' : '')), $text); - } - return $o; - } - } -} \ No newline at end of file + + * @package Encoding + * @version 2.0 + * @link https://github.com/neitanod/forceutf8 + * @example https://github.com/neitanod/forceutf8 + * @license Revised BSD + */ + +//namespace ForceUTF8; +if (!class_exists('DUP_Encoding')) { + class DUP_Encoding + { + const ICONV_TRANSLIT = "TRANSLIT"; + const ICONV_IGNORE = "IGNORE"; + const WITHOUT_ICONV = ""; + protected static $win1252ToUtf8 = array( + 128 => "\xe2\x82\xac", + + 130 => "\xe2\x80\x9a", + 131 => "\xc6\x92", + 132 => "\xe2\x80\x9e", + 133 => "\xe2\x80\xa6", + 134 => "\xe2\x80\xa0", + 135 => "\xe2\x80\xa1", + 136 => "\xcb\x86", + 137 => "\xe2\x80\xb0", + 138 => "\xc5\xa0", + 139 => "\xe2\x80\xb9", + 140 => "\xc5\x92", + 142 => "\xc5\xbd", + 145 => "\xe2\x80\x98", + 146 => "\xe2\x80\x99", + 147 => "\xe2\x80\x9c", + 148 => "\xe2\x80\x9d", + 149 => "\xe2\x80\xa2", + 150 => "\xe2\x80\x93", + 151 => "\xe2\x80\x94", + 152 => "\xcb\x9c", + 153 => "\xe2\x84\xa2", + 154 => "\xc5\xa1", + 155 => "\xe2\x80\xba", + 156 => "\xc5\x93", + + 158 => "\xc5\xbe", + 159 => "\xc5\xb8" + ); + protected static $brokenUtf8ToUtf8 = array( + "\xc2\x80" => "\xe2\x82\xac", + + "\xc2\x82" => "\xe2\x80\x9a", + "\xc2\x83" => "\xc6\x92", + "\xc2\x84" => "\xe2\x80\x9e", + "\xc2\x85" => "\xe2\x80\xa6", + "\xc2\x86" => "\xe2\x80\xa0", + "\xc2\x87" => "\xe2\x80\xa1", + "\xc2\x88" => "\xcb\x86", + "\xc2\x89" => "\xe2\x80\xb0", + "\xc2\x8a" => "\xc5\xa0", + "\xc2\x8b" => "\xe2\x80\xb9", + "\xc2\x8c" => "\xc5\x92", + + "\xc2\x8e" => "\xc5\xbd", + + + "\xc2\x91" => "\xe2\x80\x98", + "\xc2\x92" => "\xe2\x80\x99", + "\xc2\x93" => "\xe2\x80\x9c", + "\xc2\x94" => "\xe2\x80\x9d", + "\xc2\x95" => "\xe2\x80\xa2", + "\xc2\x96" => "\xe2\x80\x93", + "\xc2\x97" => "\xe2\x80\x94", + "\xc2\x98" => "\xcb\x9c", + "\xc2\x99" => "\xe2\x84\xa2", + "\xc2\x9a" => "\xc5\xa1", + "\xc2\x9b" => "\xe2\x80\xba", + "\xc2\x9c" => "\xc5\x93", + + "\xc2\x9e" => "\xc5\xbe", + "\xc2\x9f" => "\xc5\xb8" + ); + protected static $utf8ToWin1252 = array( + "\xe2\x82\xac" => "\x80", + + "\xe2\x80\x9a" => "\x82", + "\xc6\x92" => "\x83", + "\xe2\x80\x9e" => "\x84", + "\xe2\x80\xa6" => "\x85", + "\xe2\x80\xa0" => "\x86", + "\xe2\x80\xa1" => "\x87", + "\xcb\x86" => "\x88", + "\xe2\x80\xb0" => "\x89", + "\xc5\xa0" => "\x8a", + "\xe2\x80\xb9" => "\x8b", + "\xc5\x92" => "\x8c", + + "\xc5\xbd" => "\x8e", + + + "\xe2\x80\x98" => "\x91", + "\xe2\x80\x99" => "\x92", + "\xe2\x80\x9c" => "\x93", + "\xe2\x80\x9d" => "\x94", + "\xe2\x80\xa2" => "\x95", + "\xe2\x80\x93" => "\x96", + "\xe2\x80\x94" => "\x97", + "\xcb\x9c" => "\x98", + "\xe2\x84\xa2" => "\x99", + "\xc5\xa1" => "\x9a", + "\xe2\x80\xba" => "\x9b", + "\xc5\x93" => "\x9c", + + "\xc5\xbe" => "\x9e", + "\xc5\xb8" => "\x9f" + ); + + public static function toUTF8($text) + { + /** + * Function \ForceUTF8\Encoding::toUTF8 + * + * This function leaves UTF8 characters alone, while converting almost all non-UTF8 to UTF8. + * + * It assumes that the encoding of the original string is either Windows-1252 or ISO 8859-1. + * + * It may fail to convert characters to UTF-8 if they fall into one of these scenarios: + * + * 1) when any of these characters: ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞß + * are followed by any of these: ("group B") + * ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶•¸¹º»¼½¾¿ + * For example: %ABREPRESENT%C9%BB. «REPRESENTÉ» + * The "«" (%AB) character will be converted, but the "É" followed by "»" (%C9%BB) + * is also a valid unicode character, and will be left unchanged. + * + * 2) when any of these: àáâãäåæçèéêëìíîï are followed by TWO chars from group B, + * 3) when any of these: ðñòó are followed by THREE chars from group B. + * + * @name toUTF8 + * @param string $text Any string. + * @return string The same string, UTF8 encoded + * + */ + + if (is_array($text)) { + foreach ($text as $k => $v) { + $text[$k] = self::toUTF8($v); + } + return $text; + } + + if (!is_string($text)) { + return $text; + } + + $max = self::strlen($text); + $buf = ""; + for ($i = 0; $i < $max; $i++) { + $c1 = $text[$i]; + if ($c1 >= "\xc0") { + //Should be converted to UTF8, if it's not UTF8 already + $c2 = $i + 1 >= $max ? "\x00" : $text[$i + 1]; + $c3 = $i + 2 >= $max ? "\x00" : $text[$i + 2]; + $c4 = $i + 3 >= $max ? "\x00" : $text[$i + 3]; + if ($c1 >= "\xc0" & $c1 <= "\xdf") { + //looks like 2 bytes UTF8 + if ($c2 >= "\x80" && $c2 <= "\xbf") { + //yeah, almost sure it's UTF8 already + $buf .= $c1 . $c2; + $i++; + } else { + //not valid UTF8. Convert it. + $cc1 = (chr(ord($c1) / 64) | "\xc0"); + $cc2 = ($c1 & "\x3f") | "\x80"; + $buf .= $cc1 . $cc2; + } + } elseif ($c1 >= "\xe0" & $c1 <= "\xef") { + //looks like 3 bytes UTF8 + if ($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf") { + //yeah, almost sure it's UTF8 already + $buf .= $c1 . $c2 . $c3; + $i = $i + 2; + } else { + //not valid UTF8. Convert it. + $cc1 = (chr(ord($c1) / 64) | "\xc0"); + $cc2 = ($c1 & "\x3f") | "\x80"; + $buf .= $cc1 . $cc2; + } + } elseif ($c1 >= "\xf0" & $c1 <= "\xf7") { + //looks like 4 bytes UTF8 + if ($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf" && $c4 >= "\x80" && $c4 <= "\xbf") { + //yeah, almost sure it's UTF8 already + $buf .= $c1 . $c2 . $c3 . $c4; + $i = $i + 3; + } else { + //not valid UTF8. Convert it. + $cc1 = (chr(ord($c1) / 64) | "\xc0"); + $cc2 = ($c1 & "\x3f") | "\x80"; + $buf .= $cc1 . $cc2; + } + } else { + //doesn't look like UTF8, but should be converted + $cc1 = (chr(ord($c1) / 64) | "\xc0"); + $cc2 = (($c1 & "\x3f") | "\x80"); + $buf .= $cc1 . $cc2; + } + } elseif (($c1 & "\xc0") == "\x80") { + // needs conversion + if (isset(self::$win1252ToUtf8[ord($c1)])) { +//found in Windows-1252 special cases + $buf .= self::$win1252ToUtf8[ord($c1)]; + } else { + $cc1 = (chr(ord($c1) / 64) | "\xc0"); + $cc2 = (($c1 & "\x3f") | "\x80"); + $buf .= $cc1 . $cc2; + } + } else { + // it doesn't need conversion + $buf .= $c1; + } + } + return $buf; + } + + public static function toWin1252($text, $option = self::WITHOUT_ICONV) + { + if (is_array($text)) { + foreach ($text as $k => $v) { + $text[$k] = self::toWin1252($v, $option); + } + return $text; + } elseif (is_string($text)) { + return self::utf8_decode($text, $option); + } else { + return $text; + } + } + + public static function toISO8859($text) + { + return self::toWin1252($text); + } + + public static function toLatin1($text) + { + return self::toWin1252($text); + } + + public static function fixUTF8($text, $option = self::WITHOUT_ICONV) + { + if (is_array($text)) { + foreach ($text as $k => $v) { + $text[$k] = self::fixUTF8($v, $option); + } + return $text; + } + + $last = ""; + while ($last <> $text) { + $last = $text; + $text = self::toUTF8(self::utf8_decode($text, $option)); + } + $text = self::toUTF8(self::utf8_decode($text, $option)); + return $text; + } + + public static function UTF8FixWin1252Chars($text) + { + // If you received an UTF-8 string that was converted from Windows-1252 as it was ISO8859-1 + // (ignoring Windows-1252 chars from 80 to 9F) use this function to fix it. + // See: http://en.wikipedia.org/wiki/Windows-1252 + + return str_replace(array_keys(self::$brokenUtf8ToUtf8), array_values(self::$brokenUtf8ToUtf8), $text); + } + + public static function removeBOM($str = "") + { + if (substr($str, 0, 3) == pack("CCC", 0xef, 0xbb, 0xbf)) { + $str = substr($str, 3); + } + return $str; + } + + protected static function strlen($text) + { + if ((version_compare(PHP_VERSION, '7.2.0') >= 0)) { + return (function_exists('mb_strlen')) + ? mb_strlen($text, '8bit') + : strlen($text); + } else { + return (function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload')) & 2) + ? mb_strlen($text, '8bit') + : strlen($text); + } + } + + public static function normalizeEncoding($encodingLabel) + { + $encoding = strtoupper($encodingLabel); + $encoding = preg_replace('/[^a-zA-Z0-9\s]/', '', $encoding); + $equivalences = array( + 'ISO88591' => 'ISO-8859-1', + 'ISO8859' => 'ISO-8859-1', + 'ISO' => 'ISO-8859-1', + 'LATIN1' => 'ISO-8859-1', + 'LATIN' => 'ISO-8859-1', + 'UTF8' => 'UTF-8', + 'UTF' => 'UTF-8', + 'WIN1252' => 'ISO-8859-1', + 'WINDOWS1252' => 'ISO-8859-1' + ); + if (empty($equivalences[$encoding])) { + return 'UTF-8'; + } + + return $equivalences[$encoding]; + } + + public static function encode($encodingLabel, $text) + { + $encodingLabel = self::normalizeEncoding($encodingLabel); + if ($encodingLabel == 'ISO-8859-1') { + return self::toLatin1($text); + } + return self::toUTF8($text); + } + + protected static function utf8_decode($text, $option) + { + if ($option == self::WITHOUT_ICONV || !function_exists('iconv')) { + $o = utf8_decode(str_replace(array_keys(self::$utf8ToWin1252), array_values(self::$utf8ToWin1252), self::toUTF8($text))); + } else { + $o = iconv("UTF-8", "Windows-1252" . ($option == self::ICONV_TRANSLIT ? '//TRANSLIT' : ($option == self::ICONV_IGNORE ? '//IGNORE' : '')), $text); + } + return $o; + } + } + +} diff --git a/lib/forceutf8/index.php b/lib/forceutf8/index.php index b4962229..c9199655 100644 --- a/lib/forceutf8/index.php +++ b/lib/forceutf8/index.php @@ -1,2 +1,3 @@ With over **25 million downloads** Duplicator successfully gives WordPress users the ability to migrate, copy, move or clone a site from one location to another and also serves as a simple backup utility. Duplicator handles serialized and base64 serialized replacements. Standard WordPress migration and WordPress backups are easily handled by this plugin as are **zero downtime migrations**. +> With over **30 million downloads** Duplicator successfully gives WordPress users the ability to migrate, copy, move or clone a site from one location to another and also serves as a simple backup utility. Duplicator handles serialized and base64 serialized replacements. Standard WordPress migration and WordPress backups are easily handled by this plugin as are **zero downtime migrations**. For complete details visit [snapcreek.com](https://snapcreek.com/duplicator/?utm_source=duplicator_free&utm_medium=wp_org&utm_content=desc_details&utm_campaign=duplicator_free). diff --git a/src/Core/Controllers/ControllersManager.php b/src/Core/Controllers/ControllersManager.php new file mode 100644 index 00000000..78599e0c --- /dev/null +++ b/src/Core/Controllers/ControllersManager.php @@ -0,0 +1,149 @@ + array(), + 'stored' => array(), + 'instFile' => array() + ); + + public static function init() + { + add_action('admin_init', array(__CLASS__, 'adminInit')); + add_action(self::HOOK_FIRST_LOGIN_AFTER_INSTALL, array(__CLASS__, 'removeFirstLoginOption')); + add_action(self::HOOK_FIRST_LOGIN_AFTER_INSTALL, array(__CLASS__, 'renameInstallersPhpFiles')); + add_action(self::HOOK_FIRST_LOGIN_AFTER_INSTALL, array(__CLASS__, 'storeMigrationFiles')); + add_action(self::HOOK_FIRST_LOGIN_AFTER_INSTALL, array(__CLASS__, 'setDupSettingsAfterInstall')); + // save cleanup report after actions + add_action(self::HOOK_FIRST_LOGIN_AFTER_INSTALL, array(__CLASS__, 'saveCleanupReport'), 100); + + // LAST BEACAUSE MAKE A WP_REDIRECT + add_action(self::HOOK_FIRST_LOGIN_AFTER_INSTALL, array(__CLASS__, 'autoCleanFileAfterInstall'), 99999); + } + + public static function adminInit() + { + if (self::isFirstLoginAfterInstall()) { + add_action('current_screen', array(__CLASS__, 'wpAdminHook'), 99999); + update_option(DUP_UI_Notice::OPTION_KEY_MIGRATION_SUCCESS_NOTICE, true); + do_action(self::HOOK_FIRST_LOGIN_AFTER_INSTALL, self::getMigrationData()); + } + } + + /** + * + */ + public static function wpAdminHook() + { + if (!DUP_CTRL_Tools::isToolPage()) { + wp_redirect( + ControllersManager::getMenuLink( + 'duplicator-tools', + 'diagnostics', + null, + array(), + false + ) + ); + exit; + } + } + + /** + * + * @return boolean + */ + public static function isFirstLoginAfterInstall() + { + if (is_user_logged_in() && get_option(self::FIRST_LOGIN_OPTION, false)) { + if (is_multisite()) { + if (is_super_admin()) { + return true; + } + } else { + if (current_user_can('manage_options')) { + return true; + } + } + } + + return false; + } + + /** + * Purge all caches + * + * @return string[] // messages + */ + public static function purgeCaches() + { + if ( + self::getMigrationData('restoreBackupMode') || + in_array(self::getMigrationData('installType'), array(4,5,6,7)) //update with define when installerstat will be in namespace + ) { + return array(); + } + + return CachesPurge::purgeAll(); + } + + /** + * + * @param array $migrationData + * @return void + */ + public static function autoCleanFileAfterInstall($migrationData) + { + if ($migrationData == false || $migrationData['cleanInstallerFiles'] == false) { + return; + } + + wp_redirect(DUP_CTRL_Tools::getCleanFilesAcrtionUrl(false)); + exit; + } + + /** + * + * @param array $migrationData + * @return void + */ + public static function setDupSettingsAfterInstall($migrationData) + { + flush_rewrite_rules(true); + } + + /** + * return cleanup report + * + * @return array + */ + public static function getCleanupReport() + { + $option = get_option(self::CLEAN_INSTALL_REPORT_OPTION); + if (is_array($option)) { + self::$migrationCleanupReport = array_merge(self::$migrationCleanupReport, $option); + } + + return self::$migrationCleanupReport; + } + + /** + * save clean up report in wordpress options + * + * @return boolean + */ + public static function saveCleanupReport() + { + return add_option(self::CLEAN_INSTALL_REPORT_OPTION, self::$migrationCleanupReport, '', 'no'); + } + + /** + * + * @param array $migrationData + * @return void + */ + public static function removeFirstLoginOption($migrationData) + { + delete_option(self::FIRST_LOGIN_OPTION); + } + + /** + * + * @staticvar array $migrationData + * + * @param string|null $key + * @return mixed + */ + public static function getMigrationData($key = null) + { + static $migrationData = null; + if (is_null($migrationData)) { + $migrationData = get_option(self::MIGRATION_DATA_OPTION, false); + if (is_string($migrationData)) { + $migrationData = (array) json_decode($migrationData); + } + } + + if (is_null($key)) { + return $migrationData; + } elseif (isset($migrationData[$key])) { + return $migrationData[$key]; + } else { + return false; + } + } + + /** + * + * @return string + */ + public static function getSaveModeWarning() + { + switch (self::getMigrationData('safeMode')) { + case 1: + //safe_mode basic + return __('NOTICE: Safe mode (Basic) was enabled during install, be sure to re-enable all your plugins.', 'duplicator'); + case 2: + //safe_mode advance + return __('NOTICE: Safe mode (Advanced) was enabled during install, be sure to re-enable all your plugins.', 'duplicator'); + case 0: + default: + return ''; + } + } + + /** + * Check the root path and in case there are installer files without hashes rename them. + * + * @param integer $fileTimeDelay If the file is younger than $fileTimeDelay seconds then it is not renamed. + * + * @return void + */ + public static function renameInstallersPhpFiles($fileTimeDelay = 0) + { + $fileTimeDelay = is_numeric($fileTimeDelay) ? (int) $fileTimeDelay : 0; + + $pathsTocheck = array( + SnapIO::safePathTrailingslashit(ABSPATH), + SnapIO::safePathTrailingslashit(SnapWP::getHomePath()), + SnapIO::safePathTrailingslashit(WP_CONTENT_DIR) + ); + + $migrationData = self::getMigrationData(); + if (isset($migrationData['installerPath'])) { + $pathsTocheck[] = SnapIO::safePathTrailingslashit(dirname($migrationData['installerPath'])); + } + if (isset($migrationData['dupInstallerPath'])) { + $pathsTocheck[] = SnapIO::safePathTrailingslashit(dirname($migrationData['dupInstallerPath'])); + } + $pathsTocheck = array_unique($pathsTocheck); + + $filesToCheck = array(); + foreach ($pathsTocheck as $cFolder) { + if ( + !is_dir($cFolder) || + !is_writable($cFolder) // rename permissions + ) { + continue; + } + $cFile = $cFolder . 'installer.php'; + if ( + !is_file($cFile) || + !SnapIO::chmod($cFile, 'u+rw') || + !is_readable($cFile) + ) { + continue; + } + $filesToCheck[] = $cFile; + } + + $installerTplCheck = '/const\s+ARCHIVE_FILENAME\s*=\s*[\'"](.+?)[\'"]\s*;.*const\s+PACKAGE_HASH\s*=\s*[\'"](.+?)[\'"]\s*;/s'; + + foreach ($filesToCheck as $file) { + $fileName = basename($file); + + if ($fileTimeDelay > 0 && (time() - filemtime($file)) < $fileTimeDelay) { + continue; + } + + if (($content = @file_get_contents($file, false, null)) === false) { + continue; + } + $matches = null; + if (preg_match($installerTplCheck, $content, $matches) !== 1) { + continue; + } + + $archiveName = $matches[1]; + $hash = $matches[2]; + $matches = null; + + + if (preg_match(DUPLICATOR_ARCHIVE_REGEX_PATTERN, $archiveName, $matches) !== 1) { + if (SnapIO::unlink($file)) { + self::$migrationCleanupReport['instFile'][] = "
        " + . " " + . sprintf(__('Installer file %s removed for security reasons', 'duplicator'), esc_html($fileName)) + . "
        "; + } else { + self::$migrationCleanupReport['instFile'][] = "
        " + . ' ' + . sprintf(__('Can\'t remove installer file %s, please remove it for security reasons', 'duplicator'), esc_html($fileName)) + . '
        '; + } + continue; + } + + $archiveHash = $matches[1]; + if (strpos($file, $archiveHash) === false) { + if (SnapIO::rename($file, dirname($file) . '/' . $archiveHash . '_installer.php', true)) { + self::$migrationCleanupReport['instFile'][] = "
        " + . " " + . sprintf(__('Installer file %s renamed with HASH', 'duplicator'), esc_html($fileName)) + . "
        "; + } else { + self::$migrationCleanupReport['instFile'][] = "
        " + . ' ' + . sprintf(__('Can\'t rename installer file %s with HASH, please remove it for security reasons', 'duplicator'), esc_html($fileName)) + . '
        '; + } + } + } + } + + /** + * + * @param array $migrationData + */ + public static function storeMigrationFiles($migrationData) + { + $ssdInstallerPath = DUP_Settings::getSsdirInstallerPath(); + wp_mkdir_p($ssdInstallerPath); + SnapIO::emptyDir($ssdInstallerPath); + + $filesToMove = array( + $migrationData['installerLog'], + $migrationData['installerBootLog'], + $migrationData['origFileFolderPath'] + ); + + foreach ($filesToMove as $path) { + if (file_exists($path)) { + if (SnapIO::rcopy($path, $ssdInstallerPath . '/' . basename($path), true)) { + self::$migrationCleanupReport['stored'] = "
        " + . " " + . __('Original files folder moved in installer backup directory', 'duplicator') . " - " . esc_html($path) . + "
        "; + } else { + self::$migrationCleanupReport['stored'] = "
        " + . ' ' + . sprintf(__('Can\'t move %s to %s', 'duplicagtor'), esc_html($path), $ssdInstallerPath) + . '
        '; + } + } + } + } + + /** + * + * @return array + */ + public static function getStoredMigrationLists() + { + if (($migrationData = self::getMigrationData()) == false) { + $filesToCheck = array(); + } else { + $filesToCheck = array( + $migrationData['installerLog'] => __('Installer log', 'duplicator'), + $migrationData['installerBootLog'] => __('Installer boot log', 'duplicator'), + $migrationData['origFileFolderPath'] => __('Original files folder', 'duplicator') + ); + } + + $result = array(); + + foreach ($filesToCheck as $path => $label) { + $storedPath = DUP_Settings::getSsdirInstallerPath() . '/' . basename($path); + if (!file_exists($storedPath)) { + continue; + } + $result[$storedPath] = $label; + } + + return $result; + } + + /** + * + * @return bool + */ + public static function haveFileToClean() + { + return count(self::checkInstallerFilesList()) > 0; + } + + /** + * Gets a list of all the installer files and directory by name and full path + * + * @remarks + * FILES: installer.php, installer-backup.php, dup-installer-bootlog__[HASH].txt + * DIRS: dup-installer + * Last set is for lazy developer cleanup files that a developer may have + * accidentally left around lets be proactive for the user just in case. + * + * @return [string] // [file_name] + */ + public static function getGenericInstallerFiles() + { + return array( + 'installer.php', + '[HASH]installer-backup.php', + 'dup-installer', + 'dup-installer[HASH]', + 'dup-installer-bootlog__[HASH].txt', + '[HASH]_archive.zip|daf' + ); + } + + /** + * + * @return string[] + * @throws Exception + */ + public static function checkInstallerFilesList() + { + $migrationData = self::getMigrationData(); + + $foldersToChkeck = array( + SnapIO::safePathTrailingslashit(ABSPATH), + SnapWP::getHomePath(), + ); + + $result = array(); + + if (!empty($migrationData)) { + if ( + file_exists($migrationData['archivePath']) && + !DUP_Archive::isBackupPathChild($migrationData['archivePath']) + ) { + $result[] = $migrationData['archivePath']; + } + if ( + self::isInstallerFile($migrationData['installerPath']) && + !DUP_Archive::isBackupPathChild($migrationData['archivePath']) + ) { + $result[] = $migrationData['installerPath']; + } + if (file_exists($migrationData['installerBootLog'])) { + $result[] = $migrationData['installerBootLog']; + } + if (file_exists($migrationData['dupInstallerPath'])) { + $result[] = $migrationData['dupInstallerPath']; + } + } + + foreach ($foldersToChkeck as $folder) { + $result = array_merge($result, SnapIO::regexGlob($folder, array( + 'regexFile' => array( + DUPLICATOR_ARCHIVE_REGEX_PATTERN, + DUPLICATOR_INSTALLER_REGEX_PATTERN, + DUPLICATOR_DUP_INSTALLER_BOOTLOG_REGEX_PATTERN, + DUPLICATOR_DUP_INSTALLER_OWRPARAM_REGEX_PATTERN + ), + 'regexFolder' => array( + DUPLICATOR_DUP_INSTALLER_FOLDER_REGEX_PATTERN + ) + ))); + } + + $result = array_map(array('\\Duplicator\\Libs\\Snap\\SnapIO', 'safePathUntrailingslashit'), $result); + return array_unique($result); + } + + /** + * @param $path string Path to check + * @return bool true if the file at current path is the installer file + * @throws Exception + */ + public static function isInstallerFile($path) + { + if (!is_file($path) || !is_array($last5Lines = SnapIO::getLastLinesOfFile($path, 5)) || empty($last5Lines)) { + return false; + } + + return strpos(implode("", $last5Lines), "DUPLICATOR_INSTALLER_EOF") !== false; + } + + public static function cleanMigrationFiles() + { + $cleanList = self::checkInstallerFilesList(); + + $result = array(); + + foreach ($cleanList as $path) { + try { + $success = (SnapIO::rrmdir($path) !== false); + } catch (Exception $ex) { + $success = false; + } catch (Error $ex) { + $success = false; + } + + $result[$path] = $success; + } + + delete_option(self::CLEAN_INSTALL_REPORT_OPTION); + + return $result; + } +} diff --git a/src/Libs/Certificates/cacert.pem b/src/Libs/Certificates/cacert.pem new file mode 100644 index 00000000..0bf312fe --- /dev/null +++ b/src/Libs/Certificates/cacert.pem @@ -0,0 +1,3232 @@ +## +## Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Tue Oct 26 03:12:05 2021 GMT +## +## This is a bundle of X.509 certificates of public Certificate Authorities +## (CA). These were automatically extracted from Mozilla's root certificates +## file (certdata.txt). This file can be found in the mozilla source tree: +## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt +## +## It contains the certificates in PEM format and therefore +## can be directly used with curl / libcurl / php_curl, or with +## an Apache+mod_ssl webserver for SSL client authentication. +## Just configure this file as the SSLCACertificateFile. +## +## Conversion done with mk-ca-bundle.pl version 1.28. +## SHA256: bb36818a81feaa4cca61101e6d6276cd09e972efcb08112dfed846918ca41d7f +## + + +GlobalSign Root CA +================== +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx +GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds +b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD +VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa +DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc +THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb +Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP +c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX +gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF +AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj +Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG +j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH +hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC +X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +GlobalSign Root CA - R2 +======================= +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6 +ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp +s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN +S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL +TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C +ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i +YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN +BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp +9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu +01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7 +9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +Entrust.net Premium 2048 Secure Server CA +========================================= +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u +ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp +bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx +NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 +d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u +ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL +Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr +hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW +nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi +VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ +KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy +T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT +J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e +nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- + +Baltimore CyberTrust Root +========================= +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE +ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li +ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC +SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs +dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME +uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB +UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C +G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 +XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr +l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI +VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB +BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh +cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 +hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa +Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H +RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +Entrust Root Certification Authority +==================================== +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw +b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG +A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 +MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu +MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu +Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz +A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww +Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 +j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN +rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 +MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH +hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM +Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa +v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS +W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 +tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +Comodo AAA Services root +======================== +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw +MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl +c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV +BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG +C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs +i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW +Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH +Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK +Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f +BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl +cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz +LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm +7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z +8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C +12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +QuoVadis Root CA 2 +================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +QuoVadis Root CA 3 +================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Security Communication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw +8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM +DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX +5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd +DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 +JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g +0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a +mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ +s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ +6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi +FL39vmwLAw== +-----END CERTIFICATE----- + +XRamp Global CA Root +==================== +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE +BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj +dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx +HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg +U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu +IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx +foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE +zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs +AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry +xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap +oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC +AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc +/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n +nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz +8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +Go Daddy Class 2 CA +=================== +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY +VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG +A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g +RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD +ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv +2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 +qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j +YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY +vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O +BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o +atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu +MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim +PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt +I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI +Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b +vZ8= +-----END CERTIFICATE----- + +Starfield Class 2 CA +==================== +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc +U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo +MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG +A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG +SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY +bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ +JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm +epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN +F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF +MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f +hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo +bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs +afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM +PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD +KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 +QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +DigiCert Assured ID Root CA +=========================== +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx +MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO +9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy +UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW +/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy +oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf +GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF +66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq +hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc +EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn +SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i +8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +DigiCert Global Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw +MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn +TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 +BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H +4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y +7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB +o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm +8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF +BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr +EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt +tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 +UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +DigiCert High Assurance EV Root CA +================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw +KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw +MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ +MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu +Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t +Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS +OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 +MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ +NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe +h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB +Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY +JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ +V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp +myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK +mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K +-----END CERTIFICATE----- + +SwissSign Gold CA - G2 +====================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +SwissSign Silver CA - G2 +======================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +SecureTrust CA +============== +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy +dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe +BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX +OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t +DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH +GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b +01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH +ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj +aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ +KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu +SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf +mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ +nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +Secure Global CA +================ +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH +bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg +MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg +Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx +YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ +bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g +8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV +HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi +0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn +oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA +MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ +OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn +CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 +3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +COMODO Certification Authority +============================== +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb +MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD +T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH ++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww +xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV +4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA +1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI +rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k +b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC +AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP +OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc +IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN ++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== +-----END CERTIFICATE----- + +Network Solutions Certificate Authority +======================================= +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG +EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr +IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx +MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx +jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT +aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT +crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc +/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB +AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv +bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA +A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q +4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ +GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD +ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- + +COMODO ECC Certification Authority +================================== +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix +GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X +4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni +wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG +FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA +U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +Certigna +======== +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw +EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 +MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI +Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q +XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH +GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p +ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg +DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf +Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ +tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ +BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J +SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA +hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ +ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu +PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY +1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +Cybertrust Global Root +====================== +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li +ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4 +MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD +ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA ++Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW +0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL +AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin +89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT +8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2 +MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G +A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO +lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi +5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2 +hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T +X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----END CERTIFICATE----- + +ePKI Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG +EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx +MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq +MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs +IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi +lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv +qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX +12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O +WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ +ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao +lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ +vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi +Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi +MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 +1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq +KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV +xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP +NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r +GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE +xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx +gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy +sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD +BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +certSIGN ROOT CA +================ +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD +VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa +Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE +CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I +JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH +rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 +ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD +0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 +AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B +Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB +AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 +SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 +x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt +vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz +TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +NetLock Arany (Class Gold) Főtanúsítvány +======================================== +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G +A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 +dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB +cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx +MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO +ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 +c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu +0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw +/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk +H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw +fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 +neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW +qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta +YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna +NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu +dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +Hongkong Post Root CA 1 +======================= +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT +DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx +NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n +IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 +ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr +auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh +qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY +V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV +HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i +h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio +l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei +IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps +T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT +c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== +-----END CERTIFICATE----- + +SecureSign RootCA11 +=================== +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi +SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS +b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw +KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 +cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL +TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO +wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq +g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP +O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA +bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX +t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh +OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r +bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ +Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 +y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 +lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER +MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv +c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE +BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt +U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA +fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG +0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA +pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm +1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC +AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf +QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE +FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o +lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX +I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 +yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi +LXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +GlobalSign Root CA - R3 +======================= +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt +iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ +0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 +rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl +OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 +xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 +lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 +EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E +bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 +YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r +kpeDMdmztcpHWD9f +-----END CERTIFICATE----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +========================================================= +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw +QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB +NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD +Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P +B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY +7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH +ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI +plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX +MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX +LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK +bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU +vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud +EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH +DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA +bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx +ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx +51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk +R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP +T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f +Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl +osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR +crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR +saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD +KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi +6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +Izenpe.com +========== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Go Daddy Root Certificate Authority - G2 +======================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu +MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G +A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq +9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD ++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd +fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl +NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 +BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac +vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r +5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV +N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 +-----END CERTIFICATE----- + +Starfield Root Certificate Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 +eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw +DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg +VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB +dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv +W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs +bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk +N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf +ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU +JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol +TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx +4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw +F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ +c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +Starfield Services Root Certificate Authority - G2 +================================================== +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl +IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT +dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 +h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa +hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP +LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB +rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG +SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP +E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy +xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza +YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 +-----END CERTIFICATE----- + +AffirmTrust Commercial +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw +MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb +DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV +C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 +BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww +MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV +HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG +hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi +qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv +0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh +sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +AffirmTrust Networking +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw +MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE +Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI +dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 +/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb +h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV +HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu +UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 +12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 +WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 +/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +AffirmTrust Premium +=================== +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy +OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy +dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn +BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV +5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs ++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd +GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R +p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI +S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 +6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 +/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo ++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv +MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC +6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S +L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK ++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV +BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg +IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 +g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb +zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== +-----END CERTIFICATE----- + +AffirmTrust Premium ECC +======================= +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV +BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx +MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U +cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ +N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW +BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK +BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X +57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM +eQ== +-----END CERTIFICATE----- + +Certum Trusted Network CA +========================= +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK +ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy +MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU +ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC +l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J +J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 +fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 +cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB +Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw +DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj +jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 +mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj +Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +TWCA Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ +VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG +EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB +IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx +QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC +oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP +4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r +y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG +9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC +mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW +QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY +T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny +Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +Security Communication RootCA2 +============================== +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh +dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC +SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy +aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ ++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R +3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV +spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K +EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 +QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB +CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj +u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk +3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q +tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 +mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +EC-ACC +====== +-----BEGIN CERTIFICATE----- +MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE +BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w +ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD +VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE +CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT +BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7 +MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt +SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl +Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh +cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK +w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT +ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4 +HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a +E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw +0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD +VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0 +Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l +dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ +lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa +Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe +l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2 +E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D +5EI= +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2011 +======================================================= +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT +O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y +aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z +IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT +AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z +IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo +IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI +1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa +71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u +8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH +3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/ +MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8 +MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu +b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt +XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD +/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N +7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----END CERTIFICATE----- + +Actalis Authentication Root CA +============================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Buypass Class 2 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X +DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 +g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn +9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b +/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU +CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff +awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI +zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn +Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX +Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs +M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI +osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S +aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd +DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD +LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 +oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC +wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS +CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN +rJgWVqA= +-----END CERTIFICATE----- + +Buypass Class 3 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X +DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH +sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR +5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh +7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ +ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH +2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV +/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ +RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA +Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq +j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G +uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG +Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 +ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 +KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz +6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug +UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe +eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi +Cp/HuZc= +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 3 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx +MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK +9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU +NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF +iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W +0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr +AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb +fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT +ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h +P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== +-----END CERTIFICATE----- + +D-TRUST Root Class 3 CA 2 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe +Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE +LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD +ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA +BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv +KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z +p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC +AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ +4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y +eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw +MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G +PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw +OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm +2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV +dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph +X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- + +D-TRUST Root Class 3 CA 2 EV 2009 +================================= +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw +OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw +OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS +egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh +zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T +7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60 +sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35 +11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv +cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v +ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El +MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp +b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh +c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+ +PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX +ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA +NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv +w9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- + +CA Disig Root R2 +================ +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw +EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp +ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx +EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp +c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC +w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia +xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7 +A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S +GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV +g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa +5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE +koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A +Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i +Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u +Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV +sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je +dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8 +1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx +mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01 +utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0 +sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg +UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV +7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- + +ACCVRAIZ1 +========= +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB +SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1 +MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH +UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM +jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0 +RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD +aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ +0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG +WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7 +8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR +5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J +9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK +Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw +Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu +Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM +Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA +QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh +AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA +YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj +AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA +IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk +aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0 +dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2 +MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI +hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E +R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN +YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49 +nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ +TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3 +sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg +Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd +3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p +EfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- + +TWCA Global Root CA +=================== +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT +CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD +QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK +EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg +Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C +nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV +r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR +Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV +tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W +KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99 +sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p +yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn +kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI +zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g +cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M +8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg +/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg +lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP +A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m +i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8 +EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3 +zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0= +-----END CERTIFICATE----- + +TeliaSonera Root CA v1 +====================== +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE +CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4 +MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW +VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+ +6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA +3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k +B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn +Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH +oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3 +F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ +oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7 +gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc +TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB +AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW +DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm +zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW +pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV +G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc +c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT +JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2 +qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6 +Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems +WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE----- + +E-Tugra Certification Authority +=============================== +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w +DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls +ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN +ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw +NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx +QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl +cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD +DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd +hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K +CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g +ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ +BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0 +E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz +rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq +jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn +rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5 +dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB +/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG +MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK +kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO +XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807 +VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo +a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc +dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV +KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT +Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0 +8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G +C7TbO6Orb1wdtn7os4I07QZcJA== +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 2 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx +MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ +SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F +vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970 +2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV +WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy +YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4 +r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf +vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR +3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg== +-----END CERTIFICATE----- + +Atos TrustedRoot 2011 +===================== +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU +cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4 +MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG +A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV +hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr +54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+ +DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320 +HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR +z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R +l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ +bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h +k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh +TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9 +61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G +3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- + +QuoVadis Root CA 1 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE +PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm +PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6 +Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN +ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l +g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV +7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX +9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f +iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg +t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI +hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3 +GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct +Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP ++V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh +3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa +wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6 +O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0 +FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV +hMJKzRwuJIczYOXD +-----END CERTIFICATE----- + +QuoVadis Root CA 2 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh +ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY +NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t +oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o +MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l +V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo +L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ +sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD +6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh +lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI +hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K +pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9 +x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz +dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X +U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw +mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD +zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN +JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr +O3jtZsSOeWmD3n+M +-----END CERTIFICATE----- + +QuoVadis Root CA 3 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286 +IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL +Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe +6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3 +I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U +VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7 +5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi +Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM +dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt +rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI +hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS +t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ +TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du +DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib +Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD +hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX +0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW +dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2 +PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE----- + +DigiCert Assured ID Root G2 +=========================== +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw +MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH +35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq +bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw +VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP +YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn +lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO +w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv +0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz +d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW +hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M +jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE----- + +DigiCert Assured ID Root G3 +=========================== +-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD +VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 +MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb +RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs +KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF +UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy +YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy +1vUhZscv6pZjamVFkpUBtA== +-----END CERTIFICATE----- + +DigiCert Global Root G2 +======================= +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx +MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ +kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO +3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV +BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM +UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB +o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu +5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr +F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U +WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH +QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/ +iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- + +DigiCert Global Root G3 +======================= +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD +VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw +MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k +aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C +AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O +YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp +Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y +3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34 +VOKa5Vt8sycX +-----END CERTIFICATE----- + +DigiCert Trusted Root G4 +======================== +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw +HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 +MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp +pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o +k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa +vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY +QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6 +MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm +mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7 +f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH +dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8 +oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY +ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr +yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy +7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah +ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN +5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb +/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa +5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK +G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP +82Z+ +-----END CERTIFICATE----- + +COMODO RSA Certification Authority +================================== +-----BEGIN CERTIFICATE----- +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 +LaZRfyHBNVOFBkpdn627G190 +-----END CERTIFICATE----- + +USERTrust RSA Certification Authority +===================================== +-----BEGIN CERTIFICATE----- +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 +Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE----- + +USERTrust ECC Certification Authority +===================================== +-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2 +0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez +nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV +HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB +HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu +9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R4 +=========================== +-----BEGIN CERTIFICATE----- +MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl +OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P +AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV +MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF +JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q= +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R5 +=========================== +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6 +SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS +h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx +uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7 +yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE----- + +Staat der Nederlanden EV Root CA +================================ +-----BEGIN CERTIFICATE----- +MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE +CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g +RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M +MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl +cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk +SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW +O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r +0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8 +Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV +XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr +08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV +0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd +74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx +fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa +ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI +eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu +c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq +5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN +b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN +f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi +5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4 +WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK +DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy +eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg== +-----END CERTIFICATE----- + +IdenTrust Commercial Root CA 1 +============================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG +EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS +b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES +MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB +IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld +hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/ +mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi +1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C +XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl +3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy +NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV +WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg +xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix +uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI +hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg +ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt +ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV +YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX +feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro +kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe +2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz +Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R +cGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- + +IdenTrust Public Sector Root CA 1 +================================= +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG +EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv +ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV +UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS +b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy +P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6 +Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI +rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf +qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS +mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn +ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh +LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v +iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL +4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B +Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw +DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A +mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt +GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt +m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx +NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4 +Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI +ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC +ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ +3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE----- + +Entrust Root Certification Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy +bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug +b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw +HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT +DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx +OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP +/vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz +HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU +s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y +TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx +AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6 +0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z +iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi +nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+ +vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO +e4pIb4tF9g== +-----END CERTIFICATE----- + +Entrust Root Certification Authority - EC1 +========================================== +-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx +FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn +YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl +ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw +FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs +LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg +dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt +IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy +AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef +9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h +vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8 +kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE----- + +CFCA EV ROOT +============ +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE +CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB +IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw +MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD +DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV +BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD +7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN +uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW +ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7 +xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f +py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K +gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol +hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ +tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf +BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q +ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua +4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG +E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX +BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn +aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy +PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX +kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C +ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GB CA +=============================== +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG +EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw +MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds +b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX +scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP +rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk +9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o +Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg +GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI +hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD +dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0 +VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui +HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- + +SZAFIR ROOT CA2 +=============== +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG +A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV +BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ +BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD +VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q +qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK +DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE +2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ +ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi +ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC +AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5 +O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67 +oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul +4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6 ++/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +Certum Trusted Network CA 2 +=========================== +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE +BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1 +bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y +ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ +TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB +IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9 +7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o +CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b +Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p +uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130 +GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ +9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB +Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye +hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM +BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI +hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW +Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA +L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo +clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM +pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb +w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo +J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm +ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX +is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7 +zAYspsbiDrW5viSP +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2015 +======================================================= +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT +BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0 +aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl +YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx +MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg +QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV +BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw +MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv +bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh +iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+ +6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd +FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr +i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F +GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2 +fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu +iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI +hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+ +D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM +d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y +d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn +82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb +davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F +Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt +J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa +JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q +p/UsQu0yrbYhnr68 +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions ECC RootCA 2015 +=========================================================== +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0 +aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u +cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj +aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw +MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj +IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD +VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290 +Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP +dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK +Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA +GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn +dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- + +ISRG Root X1 +============ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE +BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD +EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG +EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT +DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r +Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1 +3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K +b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN +Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ +4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf +1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu +hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH +usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r +OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G +A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY +9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV +0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt +hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw +TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx +e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA +JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD +YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n +JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ +m+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- + +AC RAIZ FNMT-RCM +================ +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT +AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw +MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD +TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf +qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr +btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL +j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou +08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw +WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT +tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ +47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC +ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa +i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o +dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s +D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ +j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT +Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW ++YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7 +Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d +8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm +5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG +rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- + +Amazon Root CA 1 +================ +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1 +MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH +FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ +gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t +dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce +VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3 +DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM +CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy +8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa +2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2 +xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + +Amazon Root CA 2 +================ +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1 +MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4 +kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp +N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9 +AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd +fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx +kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS +btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0 +Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN +c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+ +3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw +DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA +A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE +YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW +xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ +gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW +aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV +Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3 +KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi +JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw= +-----END CERTIFICATE----- + +Amazon Root CA 3 +================ +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB +f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr +Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43 +rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc +eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw== +-----END CERTIFICATE----- + +Amazon Root CA 4 +================ +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN +/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri +83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA +MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1 +AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- + +TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 +============================================= +-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT +D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr +IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g +TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp +ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD +VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt +c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth +bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11 +IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8 +6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc +wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0 +3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9 +WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU +ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh +AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc +lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R +e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j +q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= +-----END CERTIFICATE----- + +GDCA TrustAUTH R5 ROOT +====================== +-----BEGIN CERTIFICATE----- +MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw +BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD +DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow +YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ +IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs +AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p +OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr +pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ +9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ +xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM +R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ +D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4 +oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx +9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg +p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9 +H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35 +6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd ++PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ +HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD +F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ +8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv +/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT +aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== +-----END CERTIFICATE----- + +TrustCor RootCert CA-1 +====================== +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYDVQQGEwJQQTEP +MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig +U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkx +MjMxMTcyMzE2WjCBpDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFu +YW1hIENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUGA1UECwwe +VHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZUcnVzdENvciBSb290Q2Vy +dCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv463leLCJhJrMxnHQFgKq1mq +jQCj/IDHUHuO1CAmujIS2CNUSSUQIpidRtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4 +pQa81QBeCQryJ3pS/C3Vseq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0 +JEsq1pme9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CVEY4h +gLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorWhnAbJN7+KIor0Gqw +/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/DeOxCbeKyKsZn3MzUOcwHwYDVR0j +BBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwDQYJKoZIhvcNAQELBQADggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5 +mDo4Nvu7Zp5I/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf +ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZyonnMlo2HD6C +qFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djtsL1Ac59v2Z3kf9YKVmgenFK+P +3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdNzl/HHk484IkzlQsPpTLWPFp5LBk= +-----END CERTIFICATE----- + +TrustCor RootCert CA-2 +====================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +TrustCor ECA-1 +============== +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYDVQQGEwJQQTEP +MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig +U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3Mjgw +N1owgZwxCzAJBgNVBAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5 +MSQwIgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29y +IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3IgRUNBLTEwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb3w9U73NjKYKtR8aja+3+XzP4Q1HpGjOR +MRegdMTUpwHmspI+ap3tDvl0mEDTPwOABoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23 +xFUfJ3zSCNV2HykVh0A53ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmc +p0yJF4OuowReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/wZ0+ +fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZFZtS6mFjBAgMBAAGj +YzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAfBgNVHSMEGDAWgBREnkj1zG1I1KBL +f/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF +AAOCAQEABT41XBVwm8nHc2FvcivUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u +/ukZMjgDfxT2AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F +hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50soIipX1TH0Xs +J5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BIWJZpTdwHjFGTot+fDz2LYLSC +jaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1WitJ/X5g== +-----END CERTIFICATE----- + +SSL.com Root Certification Authority RSA +======================================== +-----BEGIN CERTIFICATE----- +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 +WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k= +-----END CERTIFICATE----- + +SSL.com Root Certification Authority ECC +======================================== +-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV +BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv +BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy +MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO +BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv +bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA +BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+ +8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR +hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT +jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW +e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z +5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE----- + +SSL.com EV Root Certification Authority RSA R2 +============================================== +-----BEGIN CERTIFICATE----- +MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w +DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u +MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy +MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI +DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD +VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh +hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w +cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO +Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+ +B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh +CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim +9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto +RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm +JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48 ++qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV +HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp +qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1 +++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx +Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G +guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz +OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7 +CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq +lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR +rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1 +hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX +9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== +-----END CERTIFICATE----- + +SSL.com EV Root Certification Authority ECC +=========================================== +-----BEGIN CERTIFICATE----- +MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV +BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy +BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw +MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx +EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM +LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy +3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O +BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe +5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ +N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm +m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== +-----END CERTIFICATE----- + +GlobalSign Root CA - R6 +======================= +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX +R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds +b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i +YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs +U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss +grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE +3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF +vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM +PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+ +azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O +WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy +CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP +0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN +b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV +HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0 +lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY +BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym +Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr +3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1 +0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T +uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK +oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t +JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GC CA +=============================== +-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD +SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo +MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa +Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL +ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh +bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr +VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab +NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E +AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk +AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE----- + +GTS Root R1 +=========== +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG +EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv +b3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG +A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx +9vaMf/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7r +aKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnW +r4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqM +LnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly +4cpk9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr +06zqkUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 +wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om +3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNu +JLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEM +BQADggIBADiWCu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1 +d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6ZXPYfcX3v73sv +fuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZRgyFmxhE+885H7pwoHyXa/6xm +ld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9b +gsiG1eGZbYwE8na6SfZu6W0eX6DvJ4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq +4BjFbkerQUIpm/ZgDdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWEr +tXvM+SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyyF62ARPBo +pY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9SQ98POyDGCBDTtWTurQ0 +sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdwsE3PYJ/HQcu51OyLemGhmW/HGY0dVHLql +CFF1pkgl +-----END CERTIFICATE----- + +GTS Root R2 +=========== +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG +EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv +b3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG +A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTuk +k3LvCvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo +7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWI +m8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5Gm +dFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbu +ak7MkogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscsz +cTJGr61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW +Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73Vululycsl +aVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy +5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEM +BQADggIBALZp8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT +vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiTz9D2PGcDFWEJ ++YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiApJiS4wGWAqoC7o87xdFtCjMw +c3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvbpxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3Da +WsYDQvTtN6LwG1BUSw7YhN4ZKJmBR64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5r +n/WkhLx3+WuXrD5RRaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56Gtmwfu +Nmsk0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC5AwiWVIQ +7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiFizoHCBy69Y9Vmhh1fuXs +gWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLnyOd/xCxgXS/Dr55FBcOEArf9LAhST4Ld +o/DUhgkC +-----END CERTIFICATE----- + +GTS Root R3 +=========== +-----BEGIN CERTIFICATE----- +MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV +UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg +UjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE +ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUU +Rout736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24Cej +QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP +0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFukfCPAlaUs3L6JbyO5o91lAFJekazInXJ0 +glMLfalAvWhgxeG4VDvBNhcl2MG9AjEAnjWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOa +KaqW04MjyaR7YbPMAuhd +-----END CERTIFICATE----- + +GTS Root R4 +=========== +-----BEGIN CERTIFICATE----- +MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV +UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg +UjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE +ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa +6zzuhXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqj +QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV +2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0CMRw3J5QdCHojXohw0+WbhXRIjVhLfoI +N+4Zba3bssx9BzT1YBkstTTZbyACMANxsbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11x +zPKwTdb+mciUqXWi4w== +-----END CERTIFICATE----- + +UCA Global G2 Root +================== +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG +EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x +NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU +cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT +oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV +8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS +h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o +LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/ +R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe +KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa +4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc +OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97 +8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo +5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 +1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A +Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9 +yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX +c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo +jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk +bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x +ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn +RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A== +-----END CERTIFICATE----- + +UCA Extended Validation Root +============================ +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG +EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u +IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G +A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs +iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF +Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu +eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR +59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH +0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR +el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv +B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth +WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS +NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS +3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL +BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR +ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM +aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4 +dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb ++7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW +F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi +GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc +GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi +djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr +dhh2n1ax +-----END CERTIFICATE----- + +Certigna Root CA +================ +-----BEGIN CERTIFICATE----- +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE +BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ +MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda +MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz +MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX +stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz +KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8 +JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16 +XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq +4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej +wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ +lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI +jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/ +/TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy +dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h +LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl +cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt +OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP +TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq +7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3 +4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd +8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS +6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY +tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS +aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde +E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE----- + +emSign Root CA - G1 +=================== +-----BEGIN CERTIFICATE----- +MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET +MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl +ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx +ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk +aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN +LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1 +cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW +DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ +6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH +hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG +MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2 +vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q +NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q ++Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih +U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx +iN66zB+Afko= +-----END CERTIFICATE----- + +emSign ECC Root CA - G3 +======================= +-----BEGIN CERTIFICATE----- +MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG +A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg +MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4 +MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11 +ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g +RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc +58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr +MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D +CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7 +jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj +-----END CERTIFICATE----- + +emSign Root CA - C1 +=================== +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx +EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp +Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE +BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD +ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up +ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/ +Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX +OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V +I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms +lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+ +XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD +ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp +/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1 +NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9 +wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ +BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI= +-----END CERTIFICATE----- + +emSign ECC Root CA - C3 +======================= +-----BEGIN CERTIFICATE----- +MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG +A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF +Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE +BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD +ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd +6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9 +SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA +B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA +MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU +ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== +-----END CERTIFICATE----- + +Hongkong Post Root CA 3 +======================= +-----BEGIN CERTIFICATE----- +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 +dBb9HxEGmpv0 +-----END CERTIFICATE----- + +Entrust Root Certification Authority - G4 +========================================= +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJBgNV +BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu +bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1 +dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYT +AlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 +L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3D +umSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV +3imz/f3ET+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds +8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQ +e9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7 +ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5X +xNMhIWNlUpEbsZmOeX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV +7rtNOzK+mndmnqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 +dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mW +Hv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9n +MA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4Q +jbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht +7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/B7NTeLUK +YvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uIAeV8KEsD+UmDfLJ/fOPt +jqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS02FREAutp9lfx1/cH6NcjKF+ +m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKW +RGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjA +JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G ++TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT +kcpG2om3PVODLAgfi49T3f+sHw== +-----END CERTIFICATE----- + +Microsoft ECC Root Certificate Authority 2017 +============================================= +-----BEGIN CERTIFICATE----- +MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV +UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQgRUND +IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4 +MjMxNjA0WjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw +NAYDVQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZRogPZnZH6 +thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYbhGBKia/teQ87zvH2RPUB +eMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIy5lycFIM ++Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlf +Xu5gKcs68tvWMoQZP3zVL8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaR +eNtUjGUBiudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= +-----END CERTIFICATE----- + +Microsoft RSA Root Certificate Authority 2017 +============================================= +-----BEGIN CERTIFICATE----- +MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQG +EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQg +UlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIw +NzE4MjMwMDIzWjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u +MTYwNAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZNt9GkMml +7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0ZdDMbRnMlfl7rEqUrQ7e +S0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw7 +1VdyvD/IybLeS2v4I2wDwAW9lcfNcztmgGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+ +dkC0zVJhUXAoP8XFWvLJjEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49F +yGcohJUcaDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaGYaRS +MLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6W6IYZVcSn2i51BVr +lMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4KUGsTuqwPN1q3ErWQgR5WrlcihtnJ +0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJ +ClTUFLkqqNfs+avNJVgyeY+QW5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZCLgLNFgVZJ8og +6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OCgMNPOsduET/m4xaRhPtthH80 +dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk ++ONVFT24bcMKpBLBaYVu32TxU5nhSnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex +/2kskZGT4d9Mozd2TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDy +AmH3pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGRxpl/j8nW +ZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiAppGWSZI1b7rCoucL5mxAyE +7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKT +c0QWbej09+CVgI+WXTik9KveCjCHk9hNAHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D +5KbvtwEwXlGjefVwaaZBRA+GsCyRxj3qrg+E +-----END CERTIFICATE----- + +e-Szigno Root CA 2017 +===================== +-----BEGIN CERTIFICATE----- +MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNVBAYTAkhVMREw +DwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUt +MjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJvb3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZa +Fw00MjA4MjIxMjA3MDZaMHExCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UE +CgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3pp +Z25vIFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtvxie+RJCx +s1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+HWyx7xf58etqjYzBhMA8G +A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSHERUI0arBeAyxr87GyZDv +vzAEwDAfBgNVHSMEGDAWgBSHERUI0arBeAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEA +tVfd14pVCzbhhkT61NlojbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxO +svxyqltZ+efcMQ== +-----END CERTIFICATE----- + +certSIGN Root CA G2 +=================== +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlJPMRQw +EgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjAeFw0xNzAy +MDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJBgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lH +TiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAMDFdRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05 +N0IwvlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZuIt4Imfk +abBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhpn+Sc8CnTXPnGFiWeI8Mg +wT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKscpc/I1mbySKEwQdPzH/iV8oScLumZfNp +dWO9lfsbl83kqK/20U6o2YpxJM02PbyWxPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91Qqh +ngLjYl/rNUssuHLoPj1PrCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732 +jcZZroiFDsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fxDTvf +95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgyLcsUDFDYg2WD7rlc +z8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6CeWRgKRM+o/1Pcmqr4tTluCRVLERL +iohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud +DgQWBBSCIS1mxteg4BXrzkwJd8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOB +ywaK8SJJ6ejqkX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC +b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQlqiCA2ClV9+BB +/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0OJD7uNGzcgbJceaBxXntC6Z5 +8hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+cNywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5 +BiKDUyUM/FHE5r7iOZULJK2v0ZXkltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklW +atKcsWMy5WHgUyIOpwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tU +Sxfj03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZkPuXaTH4M +NMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE1LlSVHJ7liXMvGnjSG4N +0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MXQRBdJ3NghVdJIgc= +-----END CERTIFICATE----- + +Trustwave Global Certification Authority +======================================== +-----BEGIN CERTIFICATE----- +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 +29FpHOTKyeC2nOnOcXHebD8WpHk= +-----END CERTIFICATE----- + +Trustwave Global ECC P256 Certification Authority +================================================= +-----BEGIN CERTIFICATE----- +MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYDVQQGEwJVUzER +MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy +dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1 +NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH77bOYj +43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoNFWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqm +P62jQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt +0UrrdaVKEJmzsaGLSvcwCgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjz +RM4q3wghDDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 +-----END CERTIFICATE----- + +Trustwave Global ECC P384 Certification Authority +================================================= +-----BEGIN CERTIFICATE----- +MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYDVQQGEwJVUzER +MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy +dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4 +NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGvaDXU1CDFH +Ba5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJj9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr +/TklZvFe/oyujUF5nQlgziip04pt89ZF1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV +HQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNn +ADBkAjA3AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsCMGcl +CrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVuSw== +-----END CERTIFICATE----- + +NAVER Global Root Certification Authority +========================================= +-----BEGIN CERTIFICATE----- +MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEMBQAwaTELMAkG +A1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRGT1JNIENvcnAuMTIwMAYDVQQD +DClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4 +NDJaFw0zNzA4MTgyMzU5NTlaMGkxCzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVT +UyBQTEFURk9STSBDb3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVAiQqrDZBb +UGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH38dq6SZeWYp34+hInDEW ++j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lEHoSTGEq0n+USZGnQJoViAbbJAh2+g1G7 +XNr4rRVqmfeSVPc0W+m/6imBEtRTkZazkVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2 +aacp+yPOiNgSnABIqKYPszuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4 +Yb8ObtoqvC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHfnZ3z +VHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaGYQ5fG8Ir4ozVu53B +A0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo0es+nPxdGoMuK8u180SdOqcXYZai +cdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3aCJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejy +YhbLgGvtPe31HzClrkvJE+2KAQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNV +HQ4EFgQU0p+I36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoNqo0hV4/GPnrK +21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatjcu3cvuzHV+YwIHHW1xDBE1UB +jCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bx +hYTeodoS76TiEJd6eN4MUZeoIUCLhr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTg +E34h5prCy8VCZLQelHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTH +D8z7p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8piKCk5XQ +A76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLRLBT/DShycpWbXgnbiUSY +qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG +I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg +kpzNNIaRkPpkUZ3+/uul9XXeifdy +-----END CERTIFICATE----- + +AC RAIZ FNMT-RCM SERVIDORES SEGUROS +=================================== +-----BEGIN CERTIFICATE----- +MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQswCQYDVQQGEwJF +UzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgwFgYDVQRhDA9WQVRFUy1RMjgy +NjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1SQ00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4 +MTIyMDA5MzczM1oXDTQzMTIyMDA5MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQt +UkNNMQ4wDAYDVQQLDAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNB +QyBSQUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuBBAAiA2IA +BPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LHsbI6GA60XYyzZl2hNPk2 +LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oKUm8BA06Oi6NCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqG +SM49BAMDA2kAMGYCMQCuSuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoD +zBOQn5ICMQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJyv+c= +-----END CERTIFICATE----- + +GlobalSign Root R46 +=================== +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUAMEYxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJv +b3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAX +BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08Es +CVeJOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQGvGIFAha/ +r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud316HCkD7rRlr+/fKYIje +2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo0q3v84RLHIf8E6M6cqJaESvWJ3En7YEt +bWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSEy132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvj +K8Cd+RTyG/FWaha/LIWFzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD4 +12lPFzYE+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCNI/on +ccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzsx2sZy/N78CsHpdls +eVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqaByFrgY/bxFn63iLABJzjqls2k+g9 +vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEM +BQADggIBAHx47PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg +JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti2kM3S+LGteWy +gxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIkpnnpHs6i58FZFZ8d4kuaPp92 +CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRFFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZm +OUdkLG5NrmJ7v2B0GbhWrJKsFjLtrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qq +JZ4d16GLuc1CLgSkZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwye +qiv5u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP4vkYxboz +nxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6N3ec592kD3ZDZopD8p/7 +DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3vouXsXgxT7PntgMTzlSdriVZzH81Xwj3 +QEUxeCp6 +-----END CERTIFICATE----- + +GlobalSign Root E46 +=================== +-----BEGIN CERTIFICATE----- +MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYxCzAJBgNVBAYT +AkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJvb3Qg +RTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNV +BAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkB +jtjqR+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGddyXqBPCCj +QjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQxCpCPtsad0kRL +gLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZk +vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+ +CAezNIm8BZ/3Hobui3A= +-----END CERTIFICATE----- + +GLOBALTRUST 2020 +================ +-----BEGIN CERTIFICATE----- +MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCQVQx +IzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVT +VCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYxMDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAh +BgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAy +MDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWi +D59bRatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9ZYybNpyrO +VPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3QWPKzv9pj2gOlTblzLmM +CcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPwyJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCm +fecqQjuCgGOlYx8ZzHyyZqjC0203b+J+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKA +A1GqtH6qRNdDYfOiaxaJSaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9OR +JitHHmkHr96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj04KlG +DfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9MedKZssCz3AwyIDMvU +clOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIwq7ejMZdnrY8XD2zHc+0klGvIg5rQ +mjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1Ud +IwQYMBaAFNwuH9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA +VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJCXtzoRlgHNQIw +4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd6IwPS3BD0IL/qMy/pJTAvoe9 +iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS +8cE54+X1+NZK3TTN+2/BT+MAi1bikvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2 +HcqtbepBEX4tdJP7wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxS +vTOBTI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6CMUO+1918 +oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn4rnvyOL2NSl6dPrFf4IF +YqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+IaFvowdlxfv1k7/9nR4hYJS8+hge9+6jl +gqispdNpQ80xiEmEU5LAsTkbOYMBMMTyqfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== +-----END CERTIFICATE----- + +ANF Secure Server Root CA +========================= +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Certum EC-384 CA +================ +-----BEGIN CERTIFICATE----- +MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQswCQYDVQQGEwJQ +TDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2 +MDcyNDU0WhcNNDMwMzI2MDcyNDU0WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERh +dGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx +GTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATEKI6rGFtq +vm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7TmFy8as10CW4kjPMIRBSqn +iBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68KjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFI0GZnQkdjrzife81r1HfS+8EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNo +ADBlAjADVS2m5hjEfO/JUG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0 +QoSZ/6vnnvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= +-----END CERTIFICATE----- + +Certum Trusted Root CA +====================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +TunTrust Root CA +================ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +HARICA TLS RSA Root CA 2021 +=========================== +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG +EwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u +cyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0EgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUz +OFoXDTQ1MDIxMzEwNTUzN1owbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRl +bWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNB +IFJvb3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569lmwVnlskN +JLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE4VGC/6zStGndLuwRo0Xu +a2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uva9of08WRiFukiZLRgeaMOVig1mlDqa2Y +Ulhu2wr7a89o+uOkXjpFc5gH6l8Cct4MpbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K +5FrZx40d/JiZ+yykgmvwKh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEv +dmn8kN3bLW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcYAuUR +0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqBAGMUuTNe3QvboEUH +GjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYqE613TBoYm5EPWNgGVMWX+Ko/IIqm +haZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHrW2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQ +CPxrvrNQKlr9qEgYRtaQQJKQCoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8G +A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAUX15QvWiWkKQU +EapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3f5Z2EMVGpdAgS1D0NTsY9FVq +QRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxajaH6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxD +QpSbIPDRzbLrLFPCU3hKTwSUQZqPJzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcR +j88YxeMn/ibvBZ3PzzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5 +vZStjBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0/L5H9MG0 +qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pTBGIBnfHAT+7hOtSLIBD6 +Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79aPib8qXPMThcFarmlwDB31qlpzmq6YR/ +PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YWxw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnn +kf3/W9b3raYvAwtt41dU63ZTGI0RmLo= +-----END CERTIFICATE----- + +HARICA TLS ECC Root CA 2021 +=========================== +-----BEGIN CERTIFICATE----- +MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQswCQYDVQQGEwJH +UjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBD +QTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoX +DTQ1MDIxMzExMDEwOVowbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWlj +IGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJv +b3QgQ0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7KKrxcm1l +AEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9YSTHMmE5gEYd103KUkE+b +ECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW +0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAi +rcJRQO9gcS3ujwLEXQNwSaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/Qw +CZ61IygNnxS2PFOiTAZpffpskcYqSUXm7LcT4Tps +-----END CERTIFICATE----- diff --git a/src/Libs/DupArchive/DupArchive.php b/src/Libs/DupArchive/DupArchive.php new file mode 100644 index 00000000..69bc8b2a --- /dev/null +++ b/src/Libs/DupArchive/DupArchive.php @@ -0,0 +1,286 @@ +': + $retVal = self::HEADER_TYPE_DIR; + break; + case '': + $retVal = self::HEADER_TYPE_FILE; + break; + case '': + $retVal = self::HEADER_TYPE_GLOB; + break; + default: + throw new Exception("Invalid header marker {$marker}. Location:" . ftell($archiveHandle)); + } + } + + return $retVal; + } + + /** + * Get archive index data + * + * @param string $archivePath archive path + * + * @return bool|array return index data, false if don't exists + */ + public static function getIndexData($archivePath) + { + try { + $indexContent = self::getSrcFile($archivePath, self::INDEX_FILE_NAME, 0, 3000, false); + if ($indexContent === false) { + return false; + } + $indexData = json_decode(rtrim($indexContent, "\0"), true); + + if (!is_array($indexData)) { + return false; + } + } catch (Exception $e) { + return false; + } catch (Error $e) { + return false; + } + + return $indexData; + } + + /** + * Get extra files offset if set or 0 + * + * @param string $archivePath archive path + * + * @return int + */ + public static function getExtraOffset($archivePath) + { + if (($indexData = self::getIndexData($archivePath)) === false) { + return 0; + } + return (isset($indexData[self::EXTRA_FILES_POS_KEY]) ? $indexData[self::EXTRA_FILES_POS_KEY] : 0); + } + + /** + * Add file in archive from src + * + * @param string $archivePath archive path + * @param string $relativePath relative path + * @param int $offset start search location + * @param int $sizeToSearch max size where search + * + * @return bool|int false if file not found of path position + */ + public static function seachPathInArchive($archivePath, $relativePath, $offset = 0, $sizeToSearch = 0) + { + if (($archiveHandle = fopen($archivePath, 'rb')) === false) { + throw new Exception("Can’t open archive at $archivePath!"); + } + $result = self::searchPath($archivePath, $relativePath, $offset, $sizeToSearch); + @fclose($archiveHandle); + return $result; + } + + /** + * Search path, if found set and return position + * + * @param resource $archiveHandle dup archive resource + * @param string $relativePath relative path to extract + * @param int $offset start search location + * @param int $sizeToSearch max size where search + * + * @return bool|int false if file not found of path position + */ + public static function searchPath($archiveHandle, $relativePath, $offset = 0, $sizeToSearch = 0) + { + if (!is_resource($archiveHandle)) { + throw new Exception('Archive handle must be a resource'); + } + + if (fseek($archiveHandle, $offset, SEEK_SET) < 0) { + return false; + } + + if ($offset == 0) { + DupArchiveReaderHeader::readFromArchive($archiveHandle); + } + + $result = false; + $position = ftell($archiveHandle); + $continue = true; + + do { + switch (($type = self::getNextHeaderType($archiveHandle))) { + case self::HEADER_TYPE_FILE: + $currentFileHeader = DupArchiveReaderFileHeader::readFromArchive($archiveHandle, true, true); + if ($currentFileHeader->relativePath == $relativePath) { + $continue = false; + $result = $position; + } + break; + case self::HEADER_TYPE_DIR: + $directoryHeader = DupArchiveReaderDirectoryHeader::readFromArchive($archiveHandle, true); + if ($directoryHeader->relativePath == $relativePath) { + $continue = false; + $result = $position; + } + break; + case self::HEADER_TYPE_NONE: + $continue = false; + break; + default: + throw new Exception('Invali header type "' . $type . '"'); + } + $position = ftell($archiveHandle); + if ($sizeToSearch > 0 && ($position - $offset) >= $sizeToSearch) { + break; + } + } while ($continue); + + if ($result !== false) { + if (fseek($archiveHandle, $result, SEEK_SET) < 0) { + return false; + } + } + return $result; + } + + /** + * Get file content + * + * @param string $archivePath archvie path + * @param string $relativePath relative path to extract + * @param int $offset start search location + * @param int $sizeToSearch max size where search + * @param bool $isCompressed true if is compressed + * + * @return bool|string false if file not found + */ + public static function getSrcFile($archivePath, $relativePath, $offset = 0, $sizeToSearch = 0, $isCompressed = null) + { + if (($archiveHandle = fopen($archivePath, 'rb')) === false) { + throw new Exception("Can’t open archive at $archivePath!"); + } + $archiveHeader = DupArchiveReaderHeader::readFromArchive($archiveHandle); + if (is_null($isCompressed)) { + $isCompressed = $archiveHeader->isCompressed; + } + + if (self::searchPath($archiveHandle, $relativePath, $offset, $sizeToSearch) === false) { + return false; + } + + if (self::getNextHeaderType($archiveHandle) != self::HEADER_TYPE_FILE) { + return false; + } + + $header = DupArchiveReaderFileHeader::readFromArchive($archiveHandle, false, true); + $result = self::getSrcFromHeader($archiveHandle, $header, $isCompressed); + @fclose($archiveHandle); + return $result; + } + + /** + * Get src file form header + * + * @param resource $archiveHandle archive handle + * @param DupArchiveReaderFileHeader $fileHeader file header + * @param bool $isCompressed true if is compressed + * + * @return string + */ + protected static function getSrcFromHeader($archiveHandle, DupArchiveReaderFileHeader $fileHeader, $isCompressed) + { + if ($fileHeader->fileSize == 0) { + return ''; + } + $dataSize = 0; + $result = ''; + + do { + $globHeader = DupArchiveReaderGlobHeader::readFromArchive($archiveHandle); + $result .= DupArchiveReaderGlobHeader::readContent($archiveHandle, $globHeader, $isCompressed); + $dataSize += $globHeader->originalSize; + } while ($dataSize < $fileHeader->fileSize); + + return $result; + } + + /** + * Skip file in archive + * + * @param resource $archiveHandle dup archive resource + * @param DupArchiveFileHeader $fileHeader file header + * + * @return void + */ + protected static function skipFileInArchive($archiveHandle, DupArchiveReaderFileHeader $fileHeader) + { + if ($fileHeader->fileSize == 0) { + return; + } + $dataSize = 0; + + do { + $globHeader = DupArchiveReaderGlobHeader::readFromArchive($archiveHandle, true); + $dataSize += $globHeader->originalSize; + } while ($dataSize < $fileHeader->fileSize); + } + + /** + * Assumes we are on one header and just need to get to the next + * + * @param resource $archiveHandle dup archive resource + * + * @return void + */ + protected static function skipToNextHeader($archiveHandle) + { + $headerType = self::getNextHeaderType($archiveHandle); + switch ($headerType) { + case self::HEADER_TYPE_FILE: + $fileHeader = DupArchiveReaderFileHeader::readFromArchive($archiveHandle, false, true); + self::skipFileInArchive($archiveHandle, $fileHeader); + break; + case self::HEADER_TYPE_DIR: + DupArchiveReaderDirectoryHeader::readFromArchive($archiveHandle, true); + break; + case self::HEADER_TYPE_NONE: + false; + } + } +} diff --git a/src/Libs/DupArchive/DupArchiveEngine.php b/src/Libs/DupArchive/DupArchiveEngine.php new file mode 100644 index 00000000..e288c422 --- /dev/null +++ b/src/Libs/DupArchive/DupArchiveEngine.php @@ -0,0 +1,828 @@ +basepathLength); + $result = ltrim($result, '/'); + if ($createState->newBasePath !== null) { + $result = $createState->newBasePath . $result; + } + } else { + $safePath = SnapIO::safePathUntrailingslashit($path); + $result = ltrim( + $createState->newBasePath . preg_replace('/^' . preg_quote(self::$targetRootPath, '/') . '(.*)/m', '$1', $safePath), + '/' + ); + } + return $result; + } + + /** + * Get archvie info from path + * + * @param string $filepath archvie path + * + * @return DupArchiveInfo + */ + public static function getArchiveInfo($filepath) + { + $archiveInfo = new DupArchiveInfo(); + + DupArchiveUtil::log("archive size=" . filesize($filepath)); + $archiveHandle = SnapIO::fopen($filepath, 'rb'); + $archiveInfo->archiveHeader = DupArchiveHeader::readFromArchive($archiveHandle); + $moreToRead = true; + + while ($moreToRead) { + $headerType = self::getNextHeaderType($archiveHandle); + + // DupArchiveUtil::log("next header type=$headerType: " . ftell($archiveHandle)); + + switch ($headerType) { + case self::HEADER_TYPE_FILE: + $fileHeader = DupArchiveFileHeader::readFromArchive($archiveHandle, true, true); + $archiveInfo->fileHeaders[] = $fileHeader; + DupArchiveUtil::log("file" . $fileHeader->relativePath); + break; + + case self::HEADER_TYPE_DIR: + $directoryHeader = DupArchiveDirectoryHeader::readFromArchive($archiveHandle, true); + + $archiveInfo->directoryHeaders[] = $directoryHeader; + break; + + case self::HEADER_TYPE_NONE: + $moreToRead = false; + } + } + return $archiveInfo; + } + + /** + * Add folder to archive + * + * can't span requests since create state can't store list of files + * + * @param string $archiveFilepath archive file + * @param string $directory folder to add + * @param string $basepath base path to consider (?) + * @param boolean $includeFiles if true include files + * @param string $newBasepath new base path + * @param int $globSize global size + * + * @return stdClass + */ + public static function addDirectoryToArchiveST( + $archiveFilepath, + $directory, + $basepath, + $includeFiles = false, + $newBasepath = null, + $globSize = DupArchiveCreateState::DEFAULT_GLOB_SIZE + ) { + if ($includeFiles) { + $scan = DupArchiveScanUtil::createScanObject($directory); + } else { + $scan = new stdClass(); + $scan->Files = array(); + $scan->Dirs = array(); + } + + $createState = new DupArchiveSimpleCreateState(); + + $createState->archiveOffset = filesize($archiveFilepath); + $createState->archivePath = $archiveFilepath; + $createState->basePath = $basepath; + $createState->basepathLength = strlen($basepath); + $createState->timerEnabled = false; + $createState->globSize = $globSize; + $createState->newBasePath = $newBasepath; + + self::addItemsToArchive($createState, $scan); + + $retVal = new stdClass(); + $retVal->numDirsAdded = $createState->currentDirectoryIndex; + $retVal->numFilesAdded = $createState->currentFileIndex; + + if ($createState->skippedFileCount > 0) { + throw new Exception("One or more files were were not able to be added when adding {$directory} to {$archiveFilepath}"); + } elseif ($createState->skippedDirectoryCount > 0) { + throw new Exception("One or more directories were not able to be added when adding {$directory} to {$archiveFilepath}"); + } + + return $retVal; + } + + /** + * Add relative file to archive + * + * @param string $archiveFilepath archive file + * @param string $filepath file to add + * @param string $relativePath relative path in archive + * @param int $globSize global size + * + * @return void + */ + public static function addRelativeFileToArchiveST( + $archiveFilepath, + $filepath, + $relativePath, + $globSize = DupArchiveCreateState::DEFAULT_GLOB_SIZE + ) { + $createState = new DupArchiveSimpleCreateState(); + + $createState->archiveOffset = filesize($archiveFilepath); + $createState->archivePath = $archiveFilepath; + $createState->basePath = null; + $createState->basepathLength = 0; + $createState->timerEnabled = false; + $createState->globSize = $globSize; + + $scan = new stdClass(); + + $scan->Files = array(); + $scan->Dirs = array(); + + $scan->Files[] = $filepath; + + if ($relativePath != null) { + $scan->FileAliases = array(); + $scan->FileAliases[$filepath] = $relativePath; + } + + self::addItemsToArchive($createState, $scan); + } + + /** + * Add file in archive from src + * + * @param string|resource $archive Archive path or archive handle + * @param string $src source string + * @param string $relativeFilePath relative path + * @param int $forceSize if 0 size is auto of content is filled of \0 char to size + * + * @return bool + */ + public static function addFileFromSrc( + $archive, + $src, + $relativeFilePath, + $forceSize = 0 + ) { + if (is_resource($archive)) { + $archiveHandle = $archive; + SnapIO::fseek($archiveHandle, 0, SEEK_SET); + } else { + if (($archiveHandle = SnapIO::fopen($archive, 'r+b')) == false) { + throw new Exception('Can\'t open archive'); + } + } + + $createState = new DupArchiveSimpleCreateState(); + $createState->archiveOffset = SnapIO::ftell($archiveHandle); + $createState->basePath = dirname($relativeFilePath); + $createState->basepathLength = strlen($createState->basePath); + $createState->timerEnabled = false; + + if ($forceSize == 0) { + $archiveHeader = DupArchiveHeader::readFromArchive($archiveHandle); + $createState->isCompressed = $archiveHeader->isCompressed; + } else { + // ff force size is enables the src isn't compress + $createState->isCompressed = false; + } + + SnapIO::fseek($archiveHandle, 0, SEEK_END); + + $result = DupArchiveFileProcessor::writeFileSrcToArchive($createState, $archiveHandle, $src, $relativeFilePath, $forceSize); + + if (!is_resource($archive)) { + SnapIO::fclose($archiveHandle); + } + return $result; + } + + /** + * Add file in archive from src + * + * @param string $archiveFilepath archive path + * @param string $src source string + * @param string $relativeFilePath relative path + * @param int $offset start search location + * @param int $sizeToSearch max size where search + * + * @return bool + */ + public static function replaceFileContent( + $archiveFilepath, + $src, + $relativeFilePath, + $offset = 0, + $sizeToSearch = 0 + ) { + if (($archiveHandle = SnapIO::fopen($archiveFilepath, 'r+b')) == false) { + throw new Exception('Can\'t open archive'); + } + + if (($filePos = self::searchPath($archiveHandle, $relativeFilePath, $offset, $sizeToSearch)) == false) { + return false; + } + $fileHeader = DupArchiveReaderFileHeader::readFromArchive($archiveHandle); + $globHeader = DupArchiveReaderGlobHeader::readFromArchive($archiveHandle); + SnapIO::fseek($archiveHandle, $filePos); + + $createState = new DupArchiveSimpleCreateState(); + $createState->archivePath = $archiveFilepath; + $createState->archiveOffset = $filePos; + $createState->basePath = dirname($relativeFilePath); + $createState->basepathLength = strlen($createState->basePath); + $createState->timerEnabled = false; + $createState->isCompressed = false; // replaced content can't be compressed + + $forceSize = $globHeader->storedSize; + + $result = DupArchiveFileProcessor::writeFileSrcToArchive($createState, $archiveHandle, $src, $relativeFilePath, $forceSize); + SnapIO::fclose($archiveHandle); + + return $result; + } + + + /** + * Add file in archive using base dir + * + * @param string $archiveFilepath archive file + * @param string $basePath base path + * @param string $filepath file to add + * @param int $globSize global size + * + * @return void + */ + public static function addFileToArchiveUsingBaseDirST( + $archiveFilepath, + $basePath, + $filepath, + $globSize = DupArchiveCreateState::DEFAULT_GLOB_SIZE + ) { + $createState = new DupArchiveSimpleCreateState(); + + $createState->archiveOffset = filesize($archiveFilepath); + $createState->archivePath = $archiveFilepath; + $createState->basePath = $basePath; + $createState->basepathLength = strlen($basePath); + $createState->timerEnabled = false; + $createState->globSize = $globSize; + + $scan = new stdClass(); + + $scan->Files = array(); + $scan->Dirs = array(); + + $scan->Files[] = $filepath; + + self::addItemsToArchive($createState, $scan); + } + + /** + * Create archive + * + * @param string $archivePath archive file path + * @param bool $isCompressed is compressed + * + * @return void + */ + public static function createArchive($archivePath, $isCompressed) + { + if (($archiveHandle = SnapIO::fopen($archivePath, 'w+b')) === false) { + throw new Exception('Can\t create dup archvie file ' . $archivePath); + } + + $archiveHeader = DupArchiveHeader::create($isCompressed); + $archiveHeader->writeToArchive($archiveHandle); + + //reserver space for index + $src = json_encode(array('test')); + $src .= str_repeat("\0", self::INDEX_FILE_SIZE - strlen($src)); + self::addFileFromSrc($archiveHandle, $src, self::INDEX_FILE_NAME, self::INDEX_FILE_SIZE); + + // Intentionally do not write build state since if something goes wrong we went it to start over on the archive + SnapIO::fclose($archiveHandle); + } + + /** + * Add items to archive + * + * @param DupArchiveCreateState $createState create state info + * @param stdClass $scanFSInfo scan if + * + * @return void + */ + public static function addItemsToArchive(DupArchiveCreateState $createState, stdClass $scanFSInfo) + { + if ($createState->globSize == -1) { + $createState->globSize = DupArchiveCreateState::DEFAULT_GLOB_SIZE; + } + + DupArchiveUtil::tlogObject("addItemsToArchive start", $createState); + + $directoryCount = count($scanFSInfo->Dirs); + $fileCount = count($scanFSInfo->Files); + $createState->startTimer(); + $archiveHandle = SnapIO::fopen($createState->archivePath, 'r+b'); + + DupArchiveUtil::tlog("Archive size=", filesize($createState->archivePath)); + DupArchiveUtil::tlog("Archive location is now " . SnapIO::ftell($archiveHandle)); + + $archiveHeader = DupArchiveHeader::readFromArchive($archiveHandle); + + $createState->isCompressed = $archiveHeader->isCompressed; + + if ($createState->archiveOffset == filesize($createState->archivePath)) { + DupArchiveUtil::tlog( + "Seeking to end of archive location because of offset {$createState->archiveOffset} " . + "for file size " . filesize($createState->archivePath) + ); + SnapIO::fseek($archiveHandle, 0, SEEK_END); + } else { + DupArchiveUtil::tlog("Seeking archive offset {$createState->archiveOffset} for file size " . filesize($createState->archivePath)); + SnapIO::fseek($archiveHandle, $createState->archiveOffset); + } + + while (($createState->currentDirectoryIndex < $directoryCount) && (!$createState->timedOut())) { + if ($createState->throttleDelayInUs !== 0) { + usleep($createState->throttleDelayInUs); + } + + $directory = $scanFSInfo->Dirs[$createState->currentDirectoryIndex]; + + try { + $relativeDirectoryPath = ''; + + if (isset($scanFSInfo->DirectoryAliases) && array_key_exists($directory, $scanFSInfo->DirectoryAliases)) { + $relativeDirectoryPath = $scanFSInfo->DirectoryAliases[$directory]; + } else { + $relativeDirectoryPath = self::getLocalPath($directory, $createState); + } + + if ($relativeDirectoryPath !== '') { + DupArchiveDirectoryProcessor::writeDirectoryToArchive($createState, $archiveHandle, $directory, $relativeDirectoryPath); + } else { + $createState->skippedDirectoryCount++; + $createState->currentDirectoryIndex++; + } + } catch (Exception $ex) { + DupArchiveUtil::log("Failed to add {$directory} to archive. Error: " . $ex->getMessage(), true); + + $createState->addFailure(DupArchiveProcessingFailure::TYPE_DIRECTORY, $directory, $ex->getMessage(), false); + $createState->currentDirectoryIndex++; + $createState->skippedDirectoryCount++; + $createState->save(); + } + } + + $createState->archiveOffset = SnapIO::ftell($archiveHandle); + + $workTimestamp = time(); + while (($createState->currentFileIndex < $fileCount) && (!$createState->timedOut())) { + $filepath = $scanFSInfo->Files[$createState->currentFileIndex]; + + try { + $relativeFilePath = ''; + + if (isset($scanFSInfo->FileAliases) && array_key_exists($filepath, $scanFSInfo->FileAliases)) { + $relativeFilePath = $scanFSInfo->FileAliases[$filepath]; + } else { + $relativeFilePath = self::getLocalPath($filepath, $createState); + } + + // Uncomment when testing error handling +// if((strpos($relativeFilePath, 'dup-installer') !== false) || (strpos($relativeFilePath, 'lib') !== false)) { +// Dup_Log::Trace("Was going to do intentional error to {$relativeFilePath} but skipping"); +// } else { +// throw new Exception("#### intentional file error when writing " . $relativeFilePath); +// } +// } + + DupArchiveFileProcessor::writeFilePortionToArchive($createState, $archiveHandle, $filepath, $relativeFilePath); + + if (($createState->isRobust) && (time() - $workTimestamp >= 1)) { + DupArchiveUtil::log("Robust mode create state save"); + + // When in robustness mode save the state every second + $workTimestamp = time(); + $createState->working = ($createState->currentDirectoryIndex < $directoryCount) || ($createState->currentFileIndex < $fileCount); + $createState->save(); + } + } catch (Snap32BitSizeLimitException $ex) { + throw $ex; + } catch (Exception $ex) { + DupArchiveUtil::log("Failed to add {$filepath} to archive. Error: " . $ex->getMessage() . $ex->getTraceAsString(), true); + $createState->currentFileIndex++; + $createState->skippedFileCount++; + $createState->addFailure(DupArchiveProcessingFailure::TYPE_FILE, $filepath, $ex->getMessage(), ($ex->getCode() === self::EXCEPTION_FATAL)); + $createState->save(); + } + } + + $createState->working = ($createState->currentDirectoryIndex < $directoryCount) || ($createState->currentFileIndex < $fileCount); + $createState->save(); + + SnapIO::fclose($archiveHandle); + + if (!$createState->working) { + DupArchiveUtil::log("compress done"); + } else { + DupArchiveUtil::tlog("compress not done so continuing later"); + } + } + + /** + * Expand archive + * + * @param DupArchiveExpandState $expandState expand state + * + * @return void + */ + public static function expandArchive(DupArchiveExpandState $expandState) + { + $expandState->startTimer(); + $archiveHandle = SnapIO::fopen($expandState->archivePath, 'rb'); + + SnapIO::fseek($archiveHandle, $expandState->archiveOffset); + + if ($expandState->archiveOffset == 0) { + $expandState->archiveHeader = DupArchiveHeader::readFromArchive($archiveHandle); + $expandState->isCompressed = $expandState->archiveHeader->isCompressed; + $expandState->archiveOffset = SnapIO::ftell($archiveHandle); + + $expandState->save(); + } else { + DupArchiveUtil::log("#### seeking archive offset {$expandState->archiveOffset}"); + } + + DupArchiveUtil::log('DUP EXPAND OFFSET ' . $expandState->archiveOffset); + + if ((!$expandState->validateOnly) || ($expandState->validationType == DupArchiveExpandState::VALIDATION_FULL)) { + $moreItems = self::expandItems($expandState, $archiveHandle); + } else { + $moreItems = self::standardValidateItems($expandState, $archiveHandle); + } + + $expandState->working = $moreItems; + $expandState->save(); + + SnapIO::fclose($archiveHandle, false); + + if (!$expandState->working) { + DupArchiveUtil::log("DUP EXPAND DONE"); + + if (($expandState->expectedFileCount != -1) && ($expandState->expectedFileCount != $expandState->fileWriteCount)) { + $expandState->addFailure( + DupArchiveProcessingFailure::TYPE_FILE, + 'Archive', + "Number of files expected ({$expandState->expectedFileCount}) doesn't equal number written ({$expandState->fileWriteCount})." + ); + } + + if (($expandState->expectedDirectoryCount != -1) && ($expandState->expectedDirectoryCount != $expandState->directoryWriteCount)) { + $expandState->addFailure( + DupArchiveProcessingFailure::TYPE_DIRECTORY, + 'Archive', + "Number of directories expected ({$expandState->expectedDirectoryCount}) " . + "doesn't equal number written ({$expandState->directoryWriteCount})." + ); + } + } else { + DupArchiveUtil::tlogObject("expand not done so continuing later", $expandState); + } + } + + /** + * Single-threaded file expansion + * + * @param string $archiveFilePath archive path + * @param string $relativeFilePaths relative file path in archive + * @param string $destPath destination path + * + * @return void + */ + public static function expandFiles($archiveFilePath, $relativeFilePaths, $destPath) + { + // Not setting timeout timestamp so it will never timeout + DupArchiveUtil::tlog("opening archive {$archiveFilePath}"); + + $archiveHandle = SnapIO::fopen($archiveFilePath, 'r'); + + /* @var $expandState DupArchiveSimpleExpandState */ + $expandState = new DupArchiveSimpleExpandState(); + + $expandState->archiveHeader = DupArchiveHeader::readFromArchive($archiveHandle); + $expandState->isCompressed = $expandState->archiveHeader->isCompressed; + $expandState->archiveOffset = SnapIO::ftell($archiveHandle); + $expandState->includedFiles = $relativeFilePaths; + $expandState->filteredDirectories = array('*'); + $expandState->filteredFiles = array('*'); + // $expandState->basePath = $destPath . '/tempExtract'; // RSR remove once extract works + $expandState->basePath = $destPath; // RSR remove once extract works + // TODO: Filter out all directories/files except those in the list + self::expandItems($expandState, $archiveHandle); + } + + /** + * Expand dup archive items + * + * @param DupArchiveExpandState $expandState dup archive expand state + * @param resource $archiveHandle dup archvie resource + * + * @return bool true if more to read + */ + private static function expandItems(DupArchiveExpandState $expandState, $archiveHandle) + { + $moreToRead = true; + $workTimestamp = time(); + + while ($moreToRead && (!$expandState->timedOut())) { + if ($expandState->throttleDelayInUs !== 0) { + usleep($expandState->throttleDelayInUs); + } + + if ($expandState->currentFileHeader != null) { + DupArchiveUtil::tlog("Writing file {$expandState->currentFileHeader->relativePath}"); + + if (self::filePassesFilters($expandState)) { + try { + $fileCompleted = DupArchiveFileProcessor::writeToFile($expandState, $archiveHandle); + } catch (Exception $ex) { + DupArchiveUtil::log("Failed to write to {$expandState->currentFileHeader->relativePath}. Error: " . $ex->getMessage(), true); + + // Reset things - skip over this file within the archive. + SnapIO::fseek($archiveHandle, $expandState->lastHeaderOffset); + self::skipToNextHeader($archiveHandle, $expandState->currentFileHeader); + + $expandState->archiveOffset = ftell($archiveHandle); + $expandState->addFailure( + DupArchiveProcessingFailure::TYPE_FILE, + $expandState->currentFileHeader->relativePath, + $ex->getMessage(), + false + ); + $expandState->resetForFile(); + $expandState->lastHeaderOffset = -1; + $expandState->save(); + } + } else { + self::skipFileInArchive($archiveHandle, $expandState->currentFileHeader); + $expandState->resetForFile(); + } + } else { + // Header is null so read in the next one + $expandState->lastHeaderOffset = @ftell($archiveHandle); + $headerType = self::getNextHeaderType($archiveHandle); + + DupArchiveUtil::tlog('header type ' . $headerType); + switch ($headerType) { + case self::HEADER_TYPE_FILE: + DupArchiveUtil::tlog('File header'); + $expandState->currentFileHeader = DupArchiveFileHeader::readFromArchive($archiveHandle, false, true); + $expandState->archiveOffset = @ftell($archiveHandle); + DupArchiveUtil::tlog('Just read file header from archive'); + break; + case self::HEADER_TYPE_DIR: + DupArchiveUtil::tlog('Directory Header'); + $directoryHeader = DupArchiveDirectoryHeader::readFromArchive($archiveHandle, true); + + if (self::passesDirectoryExclusion($expandState, $directoryHeader->relativePath)) { + $createdDirectory = true; + + if (!$expandState->validateOnly) { + $createdDirectory = DupArchiveFileProcessor::createDirectory($expandState, $directoryHeader); + } + + if ($createdDirectory) { + $expandState->directoryWriteCount++; + } + } + $expandState->archiveOffset = ftell($archiveHandle); + DupArchiveUtil::tlog('Just read directory header ' . $directoryHeader->relativePath . ' from archive'); + break; + case self::HEADER_TYPE_NONE: + $moreToRead = false; + } + } + + if (($expandState->isRobust) && (time() - $workTimestamp >= 1)) { + DupArchiveUtil::log("Robust mode extract state save for standard validate"); + + // When in robustness mode save the state every second + $workTimestamp = time(); + $expandState->save(); + } + } + + $expandState->save(); + + return $moreToRead; + } + + /** + * check exclude dir + * + * @param DupArchiveExpandState $expandState dup archive expand state + * @param string $candidate check exclude dir + * + * @return bool + */ + private static function passesDirectoryExclusion(DupArchiveExpandState $expandState, $candidate) + { + foreach ($expandState->filteredDirectories as $directoryFilter) { + if ($directoryFilter === '*') { + return false; + } + + if (SnapIO::getRelativePath($candidate, $directoryFilter) !== false) { + return false; + } + } + + if (in_array($candidate, $expandState->excludedDirWithoutChilds)) { + return false; + } + + return true; + } + + /** + * Check flils filters + * + * @param DupArchiveExpandState $expandState dup archive expand state + * + * @return boolean + */ + private static function filePassesFilters(DupArchiveExpandState $expandState) + { + $candidate = $expandState->currentFileHeader->relativePath; + + // Included files trumps all exclusion filters + foreach ($expandState->includedFiles as $includedFile) { + if ($includedFile === $candidate) { + return true; + } + } + + if (self::passesDirectoryExclusion($expandState, $candidate)) { + foreach ($expandState->filteredFiles as $fileFilter) { + if ($fileFilter === '*' || $fileFilter === $candidate) { + return false; + } + } + } else { + return false; + } + + return true; + } + + /** + * Validate items + * + * @param DupArchiveExpandState $expandState dup archive expan state + * @param resource $archiveHandle dup archive resource + * + * @return bool true if more to read + */ + private static function standardValidateItems(DupArchiveExpandState $expandState, $archiveHandle) + { + $moreToRead = true; + + $to = $expandState->timedOut(); + $workTimestamp = time(); + + while ($moreToRead && (!$to)) { + if ($expandState->throttleDelayInUs !== 0) { + usleep($expandState->throttleDelayInUs); + } + + if ($expandState->currentFileHeader != null) { + try { + $fileCompleted = DupArchiveFileProcessor::standardValidateFileEntry($expandState, $archiveHandle); + + if ($fileCompleted) { + $expandState->resetForFile(); + } + + // Expand state taken care of within the write to file to ensure consistency + } catch (Exception $ex) { + DupArchiveUtil::log("Failed validate file in archive. Error: " . $ex->getMessage(), true); + DupArchiveUtil::logObject("expand state", $expandState, true); + // $expandState->currentFileIndex++; + // RSR TODO: Need way to skip past that file + + $expandState->addFailure(DupArchiveProcessingFailure::TYPE_FILE, $expandState->currentFileHeader->relativePath, $ex->getMessage()); + $expandState->save(); + + $moreToRead = false; + } + } else { + $headerType = self::getNextHeaderType($archiveHandle); + + switch ($headerType) { + case self::HEADER_TYPE_FILE: + $expandState->currentFileHeader = DupArchiveFileHeader::readFromArchive($archiveHandle, false, true); + $expandState->archiveOffset = ftell($archiveHandle); + break; + case self::HEADER_TYPE_DIR: + $directoryHeader = DupArchiveDirectoryHeader::readFromArchive($archiveHandle, true); + $expandState->directoryWriteCount++; + $expandState->archiveOffset = ftell($archiveHandle); + break; + case self::HEADER_TYPE_NONE: + $moreToRead = false; + } + } + + if (($expandState->isRobust) && (time() - $workTimestamp >= 1)) { + DupArchiveUtil::log("Robust mdoe extract state save for standard validate"); + + // When in robustness mode save the state every second + $workTimestamp = time(); + $expandState->save(); + } + $to = $expandState->timedOut(); + } + + $expandState->save(); + + return $moreToRead; + } +} diff --git a/src/Libs/DupArchive/DupArchiveExpandBasicEngine.php b/src/Libs/DupArchive/DupArchiveExpandBasicEngine.php new file mode 100644 index 00000000..012f1e21 --- /dev/null +++ b/src/Libs/DupArchive/DupArchiveExpandBasicEngine.php @@ -0,0 +1,272 @@ +destDirectory = $destDirectory; + $writeInfo->isCompressed = $archiveHeader->isCompressed; + + if ($offset > 0) { + fseek($archiveHandle, $offset); + } + + $moreToRead = true; + + while ($moreToRead) { + if ($writeInfo->currentFileHeader != null) { + try { + if (self::passesInclusionFilter($inclusionFilter, $writeInfo->currentFileHeader->relativePath)) { + self::writeToFile($archiveHandle, $writeInfo); + $writeInfo->fileWriteCount++; + } elseif ($writeInfo->currentFileHeader->fileSize > 0) { + self::skipFileInArchive($archiveHandle, $writeInfo->currentFileHeader); + } + $writeInfo->currentFileHeader = null; + // Expand state taken care of within the write to file to ensure consistency + } catch (Exception $ex) { + if (!$ignoreErrors) { + throw $ex; + } + } + } else { + $headerType = self::getNextHeaderType($archiveHandle); + + switch ($headerType) { + case self::HEADER_TYPE_FILE: + $writeInfo->currentFileHeader = DupArchiveReaderFileHeader::readFromArchive($archiveHandle, false, true); + break; + case self::HEADER_TYPE_DIR: + $directoryHeader = DupArchiveReaderDirectoryHeader::readFromArchive($archiveHandle, true); + // self::log("considering $inclusionFilter and {$directoryHeader->relativePath}"); + if (self::passesInclusionFilter($inclusionFilter, $directoryHeader->relativePath)) { + // self::log("passed"); + $directory = "{$writeInfo->destDirectory}/{$directoryHeader->relativePath}"; + + // $mode = $directoryHeader->permissions; + // rodo handle this more elegantly @mkdir($directory, $directoryHeader->permissions, true); + if (is_callable(self::$mkdirCallback)) { + call_user_func(self::$mkdirCallback, $directory, 'u+rwx', true); + } else { + mkdir($directory, 0755, true); + } + $writeInfo->directoryWriteCount++; + } else { + // self::log("didnt pass"); + } + break; + case self::HEADER_TYPE_NONE: + $moreToRead = false; + } + } + } + + fclose($archiveHandle); + } + + /** + * Write to file + * + * @param resource $archiveHandle archive file handle + * @param DupArchiveExpanderInfo $writeInfo write info + * + * @return void + */ + private static function writeToFile($archiveHandle, DupArchiveExpanderInfo $writeInfo) + { + $destFilePath = $writeInfo->getCurrentDestFilePath(); + + if ($writeInfo->currentFileHeader->fileSize > 0) { + $parentDir = dirname($destFilePath); + if (!file_exists($parentDir)) { + if (is_callable(self::$mkdirCallback)) { + $res = call_user_func(self::$mkdirCallback, $parentDir, 'u+rwx', true); + } else { + $res = mkdir($parentDir, 0755, true); + } + if (!$res) { + throw new Exception("Couldn't create {$parentDir}"); + } + } + + $destFileHandle = fopen($destFilePath, 'wb+'); + if ($destFileHandle === false) { + throw new Exception("Couldn't open {$destFilePath} for writing."); + } + + do { + self::appendGlobToFile($archiveHandle, $destFileHandle, $writeInfo); + + $currentFileOffset = ftell($destFileHandle); + + $moreGlobstoProcess = $currentFileOffset < $writeInfo->currentFileHeader->fileSize; + } while ($moreGlobstoProcess); + + fclose($destFileHandle); + + if (is_callable(self::$chmodCallback)) { + call_user_func(self::$chmodCallback, $destFilePath, 'u+rw'); + } else { + chmod($destFilePath, 0644); + } + + self::validateExpandedFile($writeInfo); + } else { + if (touch($destFilePath) === false) { + throw new Exception("Couldn't create $destFilePath"); + } + + if (is_callable(self::$chmodCallback)) { + call_user_func(self::$chmodCallback, $destFilePath, 'u+rw'); + } else { + chmod($destFilePath, 0644); + } + } + } + + /** + * Validate file + * + * @param DupArchiveExpanderInfo $writeInfo write info + * + * @return void + */ + private static function validateExpandedFile(DupArchiveExpanderInfo $writeInfo) + { + if ($writeInfo->currentFileHeader->hash !== '00000000000000000000000000000000') { + $hash = hash_file('crc32b', $writeInfo->getCurrentDestFilePath()); + + if ($hash !== $writeInfo->currentFileHeader->hash) { + throw new Exception("MD5 validation fails for {$writeInfo->getCurrentDestFilePath()}"); + } + } + } + + /** + * Undocumented function + * Assumption is that archive handle points to a glob header on this call + * + * @param resource $archiveHandle archive handle + * @param resource $destFileHandle dest file handle + * @param DupArchiveExpanderInfo $writeInfo write info + * + * @return void + */ + private static function appendGlobToFile($archiveHandle, $destFileHandle, DupArchiveExpanderInfo $writeInfo) + { + $globHeader = DupArchiveReaderGlobHeader::readFromArchive($archiveHandle, false); + $globContents = fread($archiveHandle, $globHeader->storedSize); + + if ($globContents === false) { + throw new Exception("Error reading glob from " . $writeInfo->getCurrentDestFilePath()); + } + + if ($writeInfo->isCompressed) { + $globContents = gzinflate($globContents); + } + + if (fwrite($destFileHandle, $globContents) !== strlen($globContents)) { + throw new Exception("Unable to write all bytes of data glob to storage."); + } + } + + /** + * Check filter + * + * @param string $filter filter + * @param string $candidate candidate + * + * @return bool + */ + private static function passesInclusionFilter($filter, $candidate) + { + return (substr($candidate, 0, strlen($filter)) == $filter); + } +} diff --git a/src/Libs/DupArchive/DupArchiveLoggerBase.php b/src/Libs/DupArchive/DupArchiveLoggerBase.php new file mode 100644 index 00000000..27d8e9b9 --- /dev/null +++ b/src/Libs/DupArchive/DupArchiveLoggerBase.php @@ -0,0 +1,24 @@ +relativePathLength == 0) { + // Don't allow a base path to be written to the archive + return; + } + + $headerString = '' . + $this->mtime . '

        ' . + $this->permissions . '

        ' . + $this->relativePathLength . '' . + $this->relativePath . '
        '; + + //SnapIO::fwrite($archiveHandle, $headerString); + $bytes_written = @fwrite($archiveHandle, $headerString); + + if ($bytes_written === false) { + throw new Exception('Error writing to file.'); + } else { + return $bytes_written; + } + } +} diff --git a/src/Libs/DupArchive/Headers/DupArchiveFileHeader.php b/src/Libs/DupArchive/Headers/DupArchiveFileHeader.php new file mode 100644 index 00000000..a95b01d9 --- /dev/null +++ b/src/Libs/DupArchive/Headers/DupArchiveFileHeader.php @@ -0,0 +1,120 @@ +fileSize = SnapIO::filesize($filepath); + $instance->permissions = substr(sprintf('%o', fileperms($filepath)), -4); + $instance->mtime = SnapIO::filemtime($filepath); + + if ($instance->fileSize > self::MAX_SIZE_FOR_HASHING) { + $instance->hash = "00000000000000000000000000000000"; + } else { + $instance->hash = hash_file('crc32b', $filepath); + } + + $instance->relativePath = $relativeFilePath; + $instance->relativePathLength = strlen($instance->relativePath); + + return $instance; + } + + /** + * create header from src + * + * @param string $src source string + * @param string $relativeFilePath relative path in archvie + * @param int $forceSize if 0 size is auto of content is filled of \0 char to size + * + * @return static + */ + public static function createFromSrc($src, $relativeFilePath, $forceSize = 0) + { + $instance = new static(); + + $instance->fileSize = strlen($src); + $instance->permissions = '0644'; + $instance->mtime = time(); + + $srcLen = strlen($src); + + if ($forceSize > 0 && $srcLen < $forceSize) { + $charsToAdd = $forceSize - $srcLen; + $src .= str_repeat("\0", $charsToAdd); + } + + if ($instance->fileSize > self::MAX_SIZE_FOR_HASHING) { + $instance->hash = "00000000000000000000000000000000"; + } else { + $instance->hash = hash('crc32b', $src); + } + + $instance->relativePath = $relativeFilePath; + $instance->relativePathLength = strlen($instance->relativePath); + + return $instance; + } + + /** + * Write header in archive + * + * @param resource $archiveHandle archive resource + * + * @return int bytes written + */ + public function writeToArchive($archiveHandle) + { + $headerString = '' . + $this->fileSize . '' . + $this->mtime . '

        ' . + $this->permissions . '

        ' . + $this->hash . '' . + $this->relativePathLength . '' . + $this->relativePath . '
        '; + + //SnapIO::fwrite($archiveHandle, $headerString); + $bytes_written = @fwrite($archiveHandle, $headerString); + + if ($bytes_written === false) { + throw new Exception('Error writing to file.'); + } else { + return $bytes_written; + } + } +} diff --git a/src/Libs/DupArchive/Headers/DupArchiveGlobHeader.php b/src/Libs/DupArchive/Headers/DupArchiveGlobHeader.php new file mode 100644 index 00000000..92fdf996 --- /dev/null +++ b/src/Libs/DupArchive/Headers/DupArchiveGlobHeader.php @@ -0,0 +1,49 @@ +xxxx
        + + $headerString = '' . $this->originalSize . '' . $this->storedSize . '' . $this->hash . ''; + + //SnapIO::fwrite($archiveHandle, $headerString); + $bytes_written = @fwrite($archiveHandle, $headerString); + + if ($bytes_written === false) { + throw new Exception('Error writing to file.'); + } else { + return $bytes_written; + } + } +} diff --git a/src/Libs/DupArchive/Headers/DupArchiveHeader.php b/src/Libs/DupArchive/Headers/DupArchiveHeader.php new file mode 100644 index 00000000..9067195e --- /dev/null +++ b/src/Libs/DupArchive/Headers/DupArchiveHeader.php @@ -0,0 +1,54 @@ +version = DupArchiveEngine::DUPARCHIVE_VERSION; + $instance->isCompressed = $isCompressed; + return $instance; + } + + /** + * Write header to archive + * + * @param resource $archiveHandle archive resource + * + * @return void + */ + public function writeToArchive($archiveHandle) + { + SnapIO::fwrite($archiveHandle, '' . $this->version . '' . ($this->isCompressed ? 'true' : 'false') . ''); + } +} diff --git a/src/Libs/DupArchive/Headers/DupArchiveHeaderU.php b/src/Libs/DupArchive/Headers/DupArchiveHeaderU.php new file mode 100644 index 00000000..b04f9b76 --- /dev/null +++ b/src/Libs/DupArchive/Headers/DupArchiveHeaderU.php @@ -0,0 +1,45 @@ +'; + $expectedEnd = ''; + + $startingElement = fread($archiveHandle, strlen($expectedStart)); + + if ($startingElement !== $expectedStart) { + throw new Exception("Invalid starting element. Was expecting {$expectedStart} but got {$startingElement}"); + } + + $headerString = stream_get_line($archiveHandle, self::MAX_FILED_LEN, $expectedEnd); + + if ($headerString === false) { + throw new Exception('Error reading line.'); + } + + return $headerString; + } +} diff --git a/src/Libs/DupArchive/Headers/DupArchiveReaderDirectoryHeader.php b/src/Libs/DupArchive/Headers/DupArchiveReaderDirectoryHeader.php new file mode 100644 index 00000000..97097f0d --- /dev/null +++ b/src/Libs/DupArchive/Headers/DupArchiveReaderDirectoryHeader.php @@ -0,0 +1,80 @@ + + $startElement = fread($archiveHandle, 3); + + if ($startElement === false) { + if (feof($archiveHandle)) { + return false; + } else { + throw new Exception('Error reading directory header'); + } + } + + if ($startElement != '') { + throw new Exception("Invalid directory header marker found [{$startElement}] : location " . ftell($archiveHandle)); + } + } + + $instance->mtime = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'MT'); + $instance->permissions = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'P'); + $instance->relativePathLength = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'RPL'); + + // Skip the + fread($archiveHandle, 4); + + $instance->relativePath = fread($archiveHandle, $instance->relativePathLength); + + // Skip the + // fread($archiveHandle, 5); + + // Skip the + // fread($archiveHandle, 4); + + // Skip the and the + fread($archiveHandle, 9); + + return $instance; + } +} diff --git a/src/Libs/DupArchive/Headers/DupArchiveReaderFileHeader.php b/src/Libs/DupArchive/Headers/DupArchiveReaderFileHeader.php new file mode 100644 index 00000000..ed5ae9d0 --- /dev/null +++ b/src/Libs/DupArchive/Headers/DupArchiveReaderFileHeader.php @@ -0,0 +1,101 @@ + 20000 files -> 1.2MB larger + * xxxxxx + * # F#x#x#x#x#x#x! + * + * @param resource $archiveHandle archive resource + * @param boolean $skipContents if true skip contents + * @param boolean $skipMarker if true skip marker + * + * @return static + */ + public static function readFromArchive($archiveHandle, $skipContents = false, $skipMarker = false) + { + // RSR TODO Read header from archive handle and populate members + // TODO: return null if end of archive or throw exception if can read something but its not a file header + + $instance = new static(); + + if (!$skipMarker) { + $marker = @fread($archiveHandle, 3); + + if ($marker === false) { + if (feof($archiveHandle)) { + return false; + } else { + throw new Exception('Error reading file header'); + } + } + + if ($marker != '') { + throw new Exception("Invalid file header marker found [{$marker}] : location " . ftell($archiveHandle)); + } + } + + $instance->fileSize = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'FS'); + $instance->mtime = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'MT'); + $instance->permissions = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'P'); + $instance->hash = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'HA'); + $instance->relativePathLength = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'RPL'); + + // Skip + fread($archiveHandle, 4); + $instance->relativePath = fread($archiveHandle, $instance->relativePathLength); + + // Skip + // fread($archiveHandle, 5); + + // Skip the + // fread($archiveHandle, 4); + + // Skip the and the
        + fread($archiveHandle, 9); + + if ($skipContents && ($instance->fileSize > 0)) { + $dataSize = 0; + $moreGlobs = true; + while ($moreGlobs) { + $globHeader = DupArchiveReaderGlobHeader::readFromArchive($archiveHandle, true); + $dataSize += $globHeader->originalSize; + $moreGlobs = ($dataSize < $instance->fileSize); + } + } + + return $instance; + } +} diff --git a/src/Libs/DupArchive/Headers/DupArchiveReaderGlobHeader.php b/src/Libs/DupArchive/Headers/DupArchiveReaderGlobHeader.php new file mode 100644 index 00000000..0bf35279 --- /dev/null +++ b/src/Libs/DupArchive/Headers/DupArchiveReaderGlobHeader.php @@ -0,0 +1,89 @@ +') { + throw new Exception("Invalid glob header marker found {$startElement}. location:" . ftell($archiveHandle)); + } + + $instance->originalSize = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'OS'); + $instance->storedSize = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'SS'); + $instance->hash = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'HA'); + + // Skip the + fread($archiveHandle, 4); + + if ($skipGlob) { + if (fseek($archiveHandle, $instance->storedSize, SEEK_CUR) === -1) { + throw new Exception("Can't fseek when skipping glob at location:" . ftell($archiveHandle)); + } + } + + return $instance; + } + + /** + * Get glob content from header + * + * @param resource $archiveHandle archive hadler + * @param self $header chunk glob header + * @param bool $isCompressed true if is compressed + * + * @return string + */ + public static function readContent($archiveHandle, self $header, $isCompressed) + { + if ($header->storedSize == 0) { + return 0; + } + + if (($globContents = fread($archiveHandle, $header->storedSize)) === false) { + throw new Exception("Error reading glob content"); + } + + return ($isCompressed ? gzinflate($globContents) : $globContents); + } +} diff --git a/src/Libs/DupArchive/Headers/DupArchiveReaderHeader.php b/src/Libs/DupArchive/Headers/DupArchiveReaderHeader.php new file mode 100644 index 00000000..89b7b6e6 --- /dev/null +++ b/src/Libs/DupArchive/Headers/DupArchiveReaderHeader.php @@ -0,0 +1,56 @@ +') { + throw new Exception("Invalid archive header marker found {$startElement}"); + } + + $instance->version = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'V'); + $instance->isCompressed = filter_var(DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'C'), FILTER_VALIDATE_BOOLEAN); + + // Skip the + fgets($archiveHandle, 5); + return $instance; + } +} diff --git a/src/Libs/DupArchive/Info/DupArchiveExpanderInfo.php b/src/Libs/DupArchive/Info/DupArchiveExpanderInfo.php new file mode 100644 index 00000000..23913bf0 --- /dev/null +++ b/src/Libs/DupArchive/Info/DupArchiveExpanderInfo.php @@ -0,0 +1,28 @@ +destDirectory != null) { + return "{$this->destDirectory}/{$this->currentFileHeader->relativePath}"; + } else { + return null; + } + } +} diff --git a/src/Libs/DupArchive/Info/DupArchiveInfo.php b/src/Libs/DupArchive/Info/DupArchiveInfo.php new file mode 100644 index 00000000..259a2dde --- /dev/null +++ b/src/Libs/DupArchive/Info/DupArchiveInfo.php @@ -0,0 +1,26 @@ +fileHeaders = array(); + $this->directoryHeaders = array(); + } +} diff --git a/src/Libs/DupArchive/Processors/DupArchiveDirectoryProcessor.php b/src/Libs/DupArchive/Processors/DupArchiveDirectoryProcessor.php new file mode 100644 index 00000000..47c9c19e --- /dev/null +++ b/src/Libs/DupArchive/Processors/DupArchiveDirectoryProcessor.php @@ -0,0 +1,46 @@ +permissions = substr(sprintf('%o', fileperms($sourceDirectoryPath)), -4); + $directoryHeader->mtime = SnapIO::filemtime($sourceDirectoryPath); + $directoryHeader->relativePath = $relativeDirectoryPath; + $directoryHeader->relativePathLength = strlen($directoryHeader->relativePath); + + $directoryHeader->writeToArchive($archiveHandle); + + // Just increment this here - the actual state save is on the outside after timeout or completion of all directories + $createState->currentDirectoryIndex++; + } +} diff --git a/src/Libs/DupArchive/Processors/DupArchiveFileProcessor.php b/src/Libs/DupArchive/Processors/DupArchiveFileProcessor.php new file mode 100644 index 00000000..b8ce3458 --- /dev/null +++ b/src/Libs/DupArchive/Processors/DupArchiveFileProcessor.php @@ -0,0 +1,529 @@ +archiveOffset = SnapIO::ftell($archiveHandle); + $createState->currentFileIndex++; + $createState->currentFileOffset = 0; + $createState->skippedFileCount++; + $createState->addFailure(DupArchiveProcessingFailure::TYPE_FILE, $sourceFilepath, "Couldn't open $sourceFilepath", false); + return; + } + + if ($createState->currentFileOffset > 0) { + SnapIO::fseek($sourceHandle, $createState->currentFileOffset); + } else { + $fileHeader = DupArchiveFileHeader::createFromFile($sourceFilepath, $relativeFilePath); + $fileHeader->writeToArchive($archiveHandle); + } + + $sourceFileSize = filesize($sourceFilepath); + + $moreFileDataToProcess = true; + + while ((!$createState->timedOut()) && $moreFileDataToProcess) { + if ($createState->throttleDelayInUs !== 0) { + usleep($createState->throttleDelayInUs); + } + + $moreFileDataToProcess = self::appendGlobToArchive($createState, $archiveHandle, $sourceHandle, $sourceFilepath, $sourceFileSize); + $createState->archiveOffset = SnapIO::ftell($archiveHandle); + + if ($moreFileDataToProcess) { + $createState->currentFileOffset += $createState->globSize; + } else { + $createState->currentFileIndex++; + $createState->currentFileOffset = 0; + } + + // Only writing state after full group of files have been written - less reliable but more efficient + // $createState->save(); + } + + SnapIO::fclose($sourceHandle); + } + + /** + * Write file to archive from source + * + * @param DupArchiveCreateState $createState dup archive create state + * @param resource $archiveHandle archive resource + * @param string $src source string + * @param string $relativeFilePath relative file path + * @param int $forceSize if 0 size is auto of content is filled of \0 char to size + * + * @return void + */ + public static function writeFileSrcToArchive( + DupArchiveCreateState $createState, + $archiveHandle, + $src, + $relativeFilePath, + $forceSize = 0 + ) { + DupArchiveUtil::tlog("writeFileSrcToArchive"); + + $fileHeader = DupArchiveFileHeader::createFromSrc($src, $relativeFilePath, $forceSize); + $fileHeader->writeToArchive($archiveHandle); + + self::appendFileSrcToArchive($createState, $archiveHandle, $src, $forceSize); + $createState->currentFileIndex++; + $createState->currentFileOffset = 0; + $createState->archiveOffset = SnapIO::ftell($archiveHandle); + } + + /** + * Expand du archive + * + * Assumption is that this is called at the beginning of a glob header since file header already writtern + * + * @param DupArchiveExpandState $expandState expand state + * @param resource $archiveHandle archive resource + * + * @return bool true on success + */ + public static function writeToFile(DupArchiveExpandState $expandState, $archiveHandle) + { + if (isset($expandState->fileRenames[$expandState->currentFileHeader->relativePath])) { + $destFilepath = $expandState->fileRenames[$expandState->currentFileHeader->relativePath]; + } else { + $destFilepath = self::getNewFilePath($expandState->basePath, $expandState->currentFileHeader->relativePath); + } + $parentDir = dirname($destFilepath); + + $moreGlobstoProcess = true; + + SnapIO::dirWriteCheckOrMkdir($parentDir, 'u+rwx', true); + + if ($expandState->currentFileHeader->fileSize > 0) { + if ($expandState->currentFileOffset > 0) { + $destFileHandle = SnapIO::fopen($destFilepath, 'r+b'); + SnapIO::fseek($destFileHandle, $expandState->currentFileOffset); + } else { + $destFileHandle = SnapIO::fopen($destFilepath, 'w+b'); + } + + while (!$expandState->timedOut()) { + $moreGlobstoProcess = $expandState->currentFileOffset < $expandState->currentFileHeader->fileSize; + + if ($moreGlobstoProcess) { + if ($expandState->throttleDelayInUs !== 0) { + usleep($expandState->throttleDelayInUs); + } + + self::appendGlobToFile($expandState, $archiveHandle, $destFileHandle, $destFilepath); + + $expandState->currentFileOffset = ftell($destFileHandle); + $expandState->archiveOffset = SnapIO::ftell($archiveHandle); + + $moreGlobstoProcess = $expandState->currentFileOffset < $expandState->currentFileHeader->fileSize; + + if (!$moreGlobstoProcess) { + break; + } + } else { + // rsr todo record fclose error + @fclose($destFileHandle); + $destFileHandle = null; + + if ($expandState->validationType == DupArchiveExpandState::VALIDATION_FULL) { + self::validateExpandedFile($expandState); + } + break; + } + } + + DupArchiveUtil::tlog('Out of glob loop'); + + if ($destFileHandle != null) { + // rsr todo record file close error + @fclose($destFileHandle); + $destFileHandle = null; + } + + if (!$moreGlobstoProcess && $expandState->validateOnly && ($expandState->validationType == DupArchiveExpandState::VALIDATION_FULL)) { + if (!is_writable($destFilepath)) { + SnapIO::chmod($destFilepath, 'u+rw'); + } + if (@unlink($destFilepath) === false) { + // $expandState->addFailure(DupArchiveFailureTypes::File, $destFilepath, "Couldn't delete {$destFilepath} during validation", false); + // TODO: Have to know how to handle this - want to report it but don’t want to mess up validation - + // some non critical errors could be important to validation + } + } + } else { + // 0 length file so just touch it + $moreGlobstoProcess = false; + + if (file_exists($destFilepath)) { + @unlink($destFilepath); + } + + if (touch($destFilepath) === false) { + throw new Exception("Couldn't create {$destFilepath}"); + } + } + + if (!$moreGlobstoProcess) { + self::setFileMode($expandState, $destFilepath); + DupArchiveUtil::tlog('No more globs to process'); + + $expandState->fileWriteCount++; + $expandState->resetForFile(); + } + + return !$moreGlobstoProcess; + } + + /** + * Create directory + * + * @param DupArchiveExpandState $expandState expand state + * @param DupArchiveDirectoryHeader $directoryHeader directory header + * + * @return boolean + */ + public static function createDirectory(DupArchiveExpandState $expandState, DupArchiveDirectoryHeader $directoryHeader) + { + /* @var $expandState DupArchiveExpandState */ + $destDirPath = self::getNewFilePath($expandState->basePath, $directoryHeader->relativePath); + + $mode = $directoryHeader->permissions; + + if ($expandState->directoryModeOverride != -1) { + $mode = $expandState->directoryModeOverride; + } + + if (!SnapIO::dirWriteCheckOrMkdir($destDirPath, $mode, true)) { + $error_message = "Unable to create directory $destDirPath"; + $expandState->addFailure(DupArchiveProcessingFailure::TYPE_DIRECTORY, $directoryHeader->relativePath, $error_message, false); + DupArchiveUtil::tlog($error_message); + return false; + } else { + return true; + } + } + + /** + * Set file mode if is enabled + * + * @param DupArchiveExpandState $expandState dup expand state + * @param string $filePath file path + * + * @return bool + */ + public static function setFileMode(DupArchiveExpandState $expandState, $filePath) + { + if ($expandState->fileModeOverride === -1) { + return; + } + return SnapIO::chmod($filePath, $expandState->fileModeOverride); + } + + /** + * Validate file entry + * + * @param DupArchiveExpandState $expandState dup expand state + * @param resource $archiveHandle dup archive resource + * + * @return bool + */ + public static function standardValidateFileEntry(DupArchiveExpandState $expandState, $archiveHandle) + { + $moreGlobstoProcess = $expandState->currentFileOffset < $expandState->currentFileHeader->fileSize; + + if (!$moreGlobstoProcess) { + // Not a 'real' write but indicates that we actually did fully process a file in the archive + $expandState->fileWriteCount++; + } else { + while ((!$expandState->timedOut()) && $moreGlobstoProcess) { + // Read in the glob header but leave the pointer at the payload + $globHeader = DupArchiveGlobHeader::readFromArchive($archiveHandle, false); + $globContents = fread($archiveHandle, $globHeader->storedSize); + + if ($globContents === false) { + throw new Exception("Error reading glob from archive"); + } + + $hash = hash('crc32b', $globContents); + + if ($hash != $globHeader->hash) { + $expandState->addFailure( + DupArchiveProcessingFailure::TYPE_FILE, + $expandState->currentFileHeader->relativePath, + 'Hash mismatch on DupArchive file entry', + true + ); + DupArchiveUtil::tlog("Glob hash mismatch during standard check of {$expandState->currentFileHeader->relativePath}"); + } else { + // DupArchiveUtil::tlog("Glob MD5 passes"); + } + + $expandState->currentFileOffset += $globHeader->originalSize; + $expandState->archiveOffset = SnapIO::ftell($archiveHandle); + $moreGlobstoProcess = $expandState->currentFileOffset < $expandState->currentFileHeader->fileSize; + + if (!$moreGlobstoProcess) { + $expandState->fileWriteCount++; + $expandState->resetForFile(); + } + } + } + + return !$moreGlobstoProcess; + } + + /** + * Validate file + * + * @param DupArchiveExpandState $expandState dup expand state + * + * @return void + */ + private static function validateExpandedFile(DupArchiveExpandState $expandState) + { + /* @var $expandState DupArchiveExpandState */ + $destFilepath = self::getNewFilePath($expandState->basePath, $expandState->currentFileHeader->relativePath); + + if ($expandState->currentFileHeader->hash !== '00000000000000000000000000000000') { + $hash = hash_file('crc32b', $destFilepath); + + if ($hash !== $expandState->currentFileHeader->hash) { + $expandState->addFailure(DupArchiveProcessingFailure::TYPE_FILE, $destFilepath, "MD5 mismatch for {$destFilepath}", false); + } else { + DupArchiveUtil::tlog('MD5 Match for ' . $destFilepath); + } + } else { + DupArchiveUtil::tlog('MD5 non match is 0\'s'); + } + } + + /** + * Append file to archive + * + * @param DupArchiveCreateState $createState create state + * @param resource $archiveHandle archive resource + * @param resource $sourceFilehandle file resource + * @param string $sourceFilepath file path + * @param int $fileSize file size + * + * @return bool true if more file remaning + */ + private static function appendGlobToArchive( + DupArchiveCreateState $createState, + $archiveHandle, + $sourceFilehandle, + $sourceFilepath, + $fileSize + ) { + DupArchiveUtil::tlog("Appending file glob to archive for file {$sourceFilepath} at file offset {$createState->currentFileOffset}"); + + if ($fileSize == 0) { + return false; + } + + $fileSize -= $createState->currentFileOffset; + $globContents = @fread($sourceFilehandle, $createState->globSize); + + if ($globContents === false) { + throw new Exception("Error reading $sourceFilepath"); + } + + $originalSize = strlen($globContents); + + if ($createState->isCompressed) { + $globContents = gzdeflate($globContents, 2); // 2 chosen as best compromise between speed and size + $storeSize = strlen($globContents); + } else { + $storeSize = $originalSize; + } + + $globHeader = new DupArchiveGlobHeader(); + $globHeader->originalSize = $originalSize; + $globHeader->storedSize = $storeSize; + $globHeader->hash = hash('crc32b', $globContents); + $globHeader->writeToArchive($archiveHandle); + + if (@fwrite($archiveHandle, $globContents) === false) { + // Considered fatal since we should always be able to write to the archive - + // plus the header has already been written (could back this out later though) + throw new Exception( + "Error writing $sourceFilepath to archive. Ensure site still hasn't run out of space.", + DupArchiveEngine::EXCEPTION_FATAL + ); + } + + $fileSizeRemaining = $fileSize - $createState->globSize; + $moreFileRemaining = $fileSizeRemaining > 0; + + return $moreFileRemaining; + } + + /** + * Append file in dup archvie from source string + * + * @param DupArchiveCreateState $createState create state + * @param resource $archiveHandle archive handle + * @param string $src source to add + * @param int $forceSize if 0 size is auto of content is filled of \0 char to size + * + * @return bool + */ + private static function appendFileSrcToArchive( + DupArchiveCreateState $createState, + $archiveHandle, + $src, + $forceSize = 0 + ) { + DupArchiveUtil::tlog("Appending file glob to archive from src"); + + if (($originalSize = strlen($src)) == 0 && $forceSize == 0) { + return false; + } + + if ($forceSize == 0 && $createState->isCompressed) { + $src = gzdeflate($src, 2); // 2 chosen as best compromise between speed and size + $storeSize = strlen($src); + } else { + $storeSize = $originalSize; + } + + if ($forceSize > 0 && $storeSize < $forceSize) { + $charsToAdd = $forceSize - $storeSize; + $src .= str_repeat("\0", $charsToAdd); + $storeSize = $forceSize; + } + + $globHeader = new DupArchiveGlobHeader(); + $globHeader->originalSize = $originalSize; + $globHeader->storedSize = $storeSize; + $globHeader->hash = hash('crc32b', $src); + $globHeader->writeToArchive($archiveHandle); + + + if (SnapIO::fwriteChunked($archiveHandle, $src) === false) { + // Considered fatal since we should always be able to write to the archive - + // plus the header has already been written (could back this out later though) + throw new Exception( + "Error writing SRC to archive. Ensure site still hasn't run out of space.", + DupArchiveEngine::EXCEPTION_FATAL + ); + } + + return true; + } + + /** + * Extract file from dup archive + * Assumption is that archive handle points to a glob header on this call + * + * @param DupArchiveExpandState $expandState dup archive expand state + * @param resource $archiveHandle archvie resource + * @param resource $destFileHandle file resource + * @param string $destFilePath file path + * + * @return void + */ + private static function appendGlobToFile( + DupArchiveExpandState $expandState, + $archiveHandle, + $destFileHandle, + $destFilePath + ) { + DupArchiveUtil::tlog('Appending file glob to file ' . $destFilePath . ' at file offset ' . $expandState->currentFileOffset); + + // Read in the glob header but leave the pointer at the payload + $globHeader = DupArchiveGlobHeader::readFromArchive($archiveHandle, false); + if (($globContents = DupArchiveGlobHeader::readContent($archiveHandle, $globHeader, $expandState->archiveHeader->isCompressed)) === false) { + throw new Exception("Error reading glob from $destFilePath"); + } + + if (@fwrite($destFileHandle, $globContents) === false) { + throw new Exception("Error writing glob to $destFilePath"); + } else { + DupArchiveUtil::tlog('Successfully wrote glob'); + } + } +} diff --git a/src/Libs/DupArchive/Processors/DupArchiveProcessingFailure.php b/src/Libs/DupArchive/Processors/DupArchiveProcessingFailure.php new file mode 100644 index 00000000..bbd40f84 --- /dev/null +++ b/src/Libs/DupArchive/Processors/DupArchiveProcessingFailure.php @@ -0,0 +1,25 @@ + fullNewPath */ + public $fileRenames = array(); + public $directoryModeOverride = -1; + public $fileModeOverride = -1; + public $lastHeaderOffset = -1; + + /** + * Reset state for file + * + * @return void + */ + public function resetForFile() + { + $this->currentFileHeader = null; + $this->currentFileOffset = 0; + } + + /** + * save expand state + * + * @return void + */ + abstract public function save(); +} diff --git a/src/Libs/DupArchive/States/DupArchiveSimpleCreateState.php b/src/Libs/DupArchive/States/DupArchiveSimpleCreateState.php new file mode 100644 index 00000000..b32b6e18 --- /dev/null +++ b/src/Libs/DupArchive/States/DupArchiveSimpleCreateState.php @@ -0,0 +1,35 @@ +currentDirectoryIndex = 0; + $this->currentFileIndex = 0; + $this->currentFileOffset = 0; + } + + /** + * Save state + * + * @return void + */ + public function save() + { + } +} diff --git a/src/Libs/DupArchive/States/DupArchiveSimpleExpandState.php b/src/Libs/DupArchive/States/DupArchiveSimpleExpandState.php new file mode 100644 index 00000000..76597b57 --- /dev/null +++ b/src/Libs/DupArchive/States/DupArchiveSimpleExpandState.php @@ -0,0 +1,32 @@ +failures) > 0) { + foreach ($this->failures as $failure) { + if ($failure->isCritical) { + return true; + } + } + } + + return false; + } + + /** + * Che failure summary + * + * @param boolean $includeCritical include critical failures + * @param boolean $includeWarnings include warnings failures + * + * @return string + */ + public function getFailureSummary($includeCritical = true, $includeWarnings = false) + { + if (count($this->failures) > 0) { + $message = ''; + + foreach ($this->failures as $failure) { + if ($includeCritical || !$failure->isCritical) { + $message .= "\n" . $this->getFailureString($failure); + } + } + + return $message; + } else { + if ($includeCritical) { + if ($includeWarnings) { + return 'No errors or warnings.'; + } else { + return 'No errors.'; + } + } else { + return 'No warnings.'; + } + } + } + + /** + * Return failure string from item + * + * @param DupArchiveProcessingFailure $failure failure item + * + * @return string + */ + public function getFailureString(DupArchiveProcessingFailure $failure) + { + $s = ''; + + if ($failure->isCritical) { + $s = 'CRITICAL: '; + } + + return "{$s}{$failure->subject} : {$failure->description}"; + } + + /** + * Add failure item + * + * @param int $type failure type enum + * @param string $subject failure subject + * @param string $description failure description + * @param boolean $isCritical true if is critical + * + * @return DupArchiveProcessingFailure + */ + public function addFailure($type, $subject, $description, $isCritical = true) + { + $this->failureCount++; + if ($this->failureCount > self::MAX_FAILURE) { + return false; + } + + $failure = new DupArchiveProcessingFailure(); + + $failure->type = $type; + $failure->subject = $subject; + $failure->description = $description; + $failure->isCritical = $isCritical; + + $this->failures[] = $failure; + + return $failure; + } + + /** + * Set start time + * + * @return void + */ + public function startTimer() + { + if ($this->timerEnabled) { + $this->timeoutTimestamp = time() + $this->timeSliceInSecs; + } + } + + /** + * Check if is timeout + * + * @return bool + */ + public function timedOut() + { + if ($this->timerEnabled) { + if ($this->timeoutTimestamp != -1) { + return time() >= $this->timeoutTimestamp; + } else { + return false; + } + } else { + return false; + } + } +} diff --git a/src/Libs/DupArchive/Utils/DupArchiveScanUtil.php b/src/Libs/DupArchive/Utils/DupArchiveScanUtil.php new file mode 100644 index 00000000..85e59d26 --- /dev/null +++ b/src/Libs/DupArchive/Utils/DupArchiveScanUtil.php @@ -0,0 +1,97 @@ +Dirs = DupArchiveUtil::expandDirectories($sourceDirectory, true); + $scan->Files = DupArchiveUtil::expandFiles($sourceDirectory, true); + + return $scan; + } + + /** + * Scan folder and add result to scan file + * + * @param string $scanFilepath scan file + * @param string $sourceDirectory folder to scan + * + * @return void + */ + public static function createScan($scanFilepath, $sourceDirectory) + { + DupArchiveUtil::tlog("Creating scan"); + + $scan = self::createScanObject($sourceDirectory); + $scan_handle = fopen($scanFilepath, 'w'); + + if ($scan_handle === false) { + echo "Couldn't create scan file"; + die(); + } + + $jsn = SnapJson::jsonEncode($scan); + + fwrite($scan_handle, $jsn); + return $scan; + } +} diff --git a/src/Libs/DupArchive/Utils/DupArchiveUtil.php b/src/Libs/DupArchive/Utils/DupArchiveUtil.php new file mode 100644 index 00000000..8c23d85a --- /dev/null +++ b/src/Libs/DupArchive/Utils/DupArchiveUtil.php @@ -0,0 +1,166 @@ +log($s, $flush, $callingFunctionName); + } else { + // throw new Exception('Logging object not initialized'); + } + } + + /** + * Write trace log + * + * @param string $s log string + * @param boolean $flush if true flosh name + * @param string $callingFunctionName function has called log + * + * @return void + */ + public static function tlog($s, $flush = false, $callingFunctionName = null) + { + if (self::$TRACE_ON) { + if ($callingFunctionName === null) { + $callingFunctionName = SnapUtil::getCallingFunctionName(); + } + + self::log("####{$s}", $flush, $callingFunctionName); + } + } + + /** + * Write object in trace log + * + * @param string $s log string + * @param mixed $o value to write in log + * @param boolean $flush if true flosh name + * @param string $callingFunctionName function has called log + * + * @return void + */ + public static function tlogObject($s, $o, $flush = false, $callingFunctionName = null) + { + if (is_object($o)) { + $o = get_object_vars($o); + } + + $ostring = print_r($o, true); + + if ($callingFunctionName === null) { + $callingFunctionName = SnapUtil::getCallingFunctionName(); + } + + self::tlog($s, $flush, $callingFunctionName); + self::tlog($ostring, $flush, $callingFunctionName); + } + + /** + * Write object in log + * + * @param string $s log string + * @param mixed $o value to write in log + * @param boolean $flush if true flosh name + * @param string $callingFunctionName function has called log + * + * @return void + */ + public static function logObject($s, $o, $flush = false, $callingFunctionName = null) + { + $ostring = print_r($o, true); + + if ($callingFunctionName === null) { + $callingFunctionName = SnapUtil::getCallingFunctionName(); + } + + self::log($s, $flush, $callingFunctionName); + self::log($ostring, $flush, $callingFunctionName); + } +} diff --git a/src/Libs/Snap/JsonSerializable.php b/src/Libs/Snap/JsonSerializable.php new file mode 100644 index 00000000..ff8003a9 --- /dev/null +++ b/src/Libs/Snap/JsonSerializable.php @@ -0,0 +1,32 @@ + $reflect->name); + } + + if (method_exists($obj, '__sleep')) { + $includeProps = $obj->__sleep(); + if (!is_array($includeProps)) { + throw new Exception('__sleep method must return an array'); + } + } else { + $includeProps = true; + } + + // Get all props of current class but not props private of parent class and static props + foreach ($reflect->getProperties() as $prop) { + if ($prop->isStatic()) { + continue; + } + $propName = $prop->getName(); + if ($includeProps !== true && !in_array($propName, $includeProps)) { + continue; + } + $prop->setAccessible(true); + $propValue = $prop->getValue($obj); + $result[$propName] = self::valueToJsonData($propValue, $flags, $objParents); + } + + return $result; + } + + /** + * Recursive parse values, all objects are transformed to array + * + * @param mixed $value valute to parse + * @param int $flags flags bitmask + * @param string[] $objParents objs parents unique hash ids + * + * @return mixed + */ + final public static function valueToJsonData($value, $flags = 0, $objParents = array()) + { + switch (gettype($value)) { + case "boolean": + case "integer": + case "double": + case "string": + case "NULL": + return $value; + case "array": + $result = array(); + foreach ($value as $key => $arrayVal) { + $result[$key] = self::valueToJsonData($arrayVal, $flags, $objParents); + } + return $result; + case "object": + $objHash = spl_object_hash($value); + if (in_array($objHash, $objParents)) { + // prevent infinite recursion loop + return null; + } + $objParents[] = $objHash; + return self::objectToJsonData($value, $flags, $objParents); + case "resource": + case "resource (closed)": + case "unknown type": + default: + return null; + } + } + + /** + * Return value from json decoded data + * + * @param mixed $value json decoded data + * + * @return mixed + */ + final protected static function jsonDataToValue($value) + { + switch (gettype($value)) { + case 'array': + if (($newClassName = self::getClassFromArray($value)) === false) { + $result = array(); + foreach ($value as $key => $arrayVal) { + $result[$key] = self::jsonDataToValue($arrayVal); + } + } else { + $result = self::fillObjFromValue($value, self::getObjFromClass($newClassName)); + } + return $result; + case 'boolean': + case 'integer': + case 'double': + case 'string': + case "NULL": + return $value; + default: + return null; + } + } + + /** + * Get object from class name, if class don't exists return StdClass. + * With PHP 5.4.0 the object is intialized without call the constructor. + * + * @param string $class class name + * + * @return object + */ + final protected static function getObjFromClass($class) + { + if (class_exists($class)) { + if (version_compare(PHP_VERSION, '5.4.0') >= 0) { + $classReflect = new ReflectionClass($class); + return $classReflect->newInstanceWithoutConstructor(); + } else { + return new $class(); + } + } else { + return new \StdClass(); + } + } + + /** + * Fill passed object from array values + * + * @param array $value value from json data + * @param object $obj object to fill with json data + * + * @return object + */ + final protected static function fillObjFromValue($value, $obj) + { + if ($obj instanceof \stdClass) { + foreach ($value as $arrayProp => $arrayValue) { + if ($arrayProp == self::CLASS_KEY_FOR_JSON_SERIALIZE) { + continue; + } + $obj->{$arrayProp} = self::jsonDataToValue($arrayValue); + } + } else { + $reflect = new ReflectionObject($obj); + foreach ($reflect->getProperties() as $prop) { + $prop->setAccessible(true); + $propName = $prop->getName(); + if (!isset($value[$propName]) || $prop->isStatic()) { + continue; + } + $prop->setValue($obj, self::jsonDataToValue($value[$propName])); + } + + if (method_exists($obj, '__wakeup')) { + $obj->__wakeup(); + } + } + return $obj; + } + + /** + * Return class name from array values + * + * @param array $array array data + * + * @return bool|string false if prop not found + */ + final protected static function getClassFromArray($array) + { + return (isset($array[self::CLASS_KEY_FOR_JSON_SERIALIZE]) ? $array[self::CLASS_KEY_FOR_JSON_SERIALIZE] : false); + } +} diff --git a/src/Libs/Snap/JsonSerialize/JsonSerialize.php b/src/Libs/Snap/JsonSerialize/JsonSerialize.php new file mode 100644 index 00000000..385699e2 --- /dev/null +++ b/src/Libs/Snap/JsonSerialize/JsonSerialize.php @@ -0,0 +1,86 @@ +=') ? + json_decode($json, true, $depth, $flags) : + json_decode($json, true, $depth) + ); + return self::jsonDataToValue($publicArray); + } + + /** + * Unserialize json on passed object + * + * @param string $json json string + * @param object|string $obj object to fill or class name + * @param integer $depth json_decode depth + * @param integer $flags json_decode flags + * + * @link https://www.php.net/manual/en/function.json-decode.php + * + * @return object + */ + public static function unserializeToObj($json, $obj, $depth = 512, $flags = 0) + { + if (is_object($obj)) { + } elseif (is_string($obj) && class_exists($obj)) { + $obj = self::getObjFromClass($obj); + } else { + throw new Exception('invalid obj param'); + } + $value = (version_compare(PHP_VERSION, '5.4', '>=') ? + json_decode($json, true, $depth, $flags) : + json_decode($json, true, $depth) + ); + if (!is_array($value)) { + throw new Exception('json value isn\'t an array VALUE: ' . SnapLog::v2str($value)); + } + return self::fillObjFromValue($value, $obj); + } +} diff --git a/src/Libs/Snap/Snap32BitSizeLimitException.php b/src/Libs/Snap/Snap32BitSizeLimitException.php new file mode 100644 index 00000000..ad7a586f --- /dev/null +++ b/src/Libs/Snap/Snap32BitSizeLimitException.php @@ -0,0 +1,14 @@ + 0) { + return isset($row[$indexColumns]) ? $row[$indexColumns] : 0; + } else { + return $lastOffset + 1; + } + } + + /** + * This function performs a select by structuring the primary key as offset if the table has a primary key. + * For optimization issues, no checks are performed on the input query and it is assumed that the select has at least a where value. + * If there are no conditions, you still have to perform an always true condition, for example + * SELECT * FROM `copy1_postmeta` WHERE 1 + * + * @param \mysqli|resource $dbh database connection + * @param string $query query string + * @param string $table table name + * @param int $offset row offset + * @param int $limit limit of query, 0 no limit + * @param mixed $lastRowOffset last offset to use on next function call + * @param null|callable $logCallback log callback + * + * @return \mysqli_result + */ + public static function selectUsingPrimaryKeyAsOffset($dbh, $query, $table, $offset, $limit, &$lastRowOffset = null, $logCallback = null) + { + $where = ''; + $orderby = ''; + $offsetStr = ''; + $limitStr = $limit > 0 ? ' LIMIT ' . $limit : ''; + + if (($primaryColumn = self::getUniqueIndexColumn($dbh, $table, $logCallback)) == false) { + $offsetStr = ' OFFSET ' . (is_scalar($offset) ? $offset : 0); + } else { + if (is_array($primaryColumn)) { + // COMPOSITE KEY + $orderByCols = array(); + foreach ($primaryColumn as $colIndex => $col) { + $orderByCols[] = '`' . $col . '` ASC'; + } + $orderby = ' ORDER BY ' . implode(',', $orderByCols); + } else { + $orderby = ' ORDER BY `' . $primaryColumn . '` ASC'; + } + $where = self::getOffsetKeyCondition($dbh, $primaryColumn, $offset); + } + $query .= $where . $orderby . $limitStr . $offsetStr; + + if (($result = self::query($dbh, $query)) === false) { + if (is_callable($logCallback)) { + call_user_func($logCallback, $dbh, $result, $query); + } + throw new \Exception('SELECT ERROR: ' . self::error($dbh) . ' QUERY: ' . $query); + } + + if (is_callable($logCallback)) { + call_user_func($logCallback, $dbh, $result, $query); + } + + if (self::dbConnTypeByResult($result) === self::CONN_MYSQLI) { + if ($primaryColumn == false) { + $lastRowOffset = $offset + $result->num_rows; + } else { + if ($result->num_rows == 0) { + $lastRowOffset = $offset; + } else { + $result->data_seek(($result->num_rows - 1)); + $row = $result->fetch_assoc(); + if (is_array($primaryColumn)) { + $lastRowOffset = array(); + foreach ($primaryColumn as $col) { + $lastRowOffset[$col] = $row[$col]; + } + } else { + $lastRowOffset = $row[$primaryColumn]; + } + $result->data_seek(0); + } + } + } else { + if ($primaryColumn == false) { + $lastRowOffset = $offset + mysql_num_rows($result); + } else { + if (mysql_num_rows($result) == 0) { + $lastRowOffset = $offset; + } else { + mysql_data_seek($result, (mysql_num_rows($result) - 1)); + $row = mysql_fetch_assoc($result); + if (is_array($primaryColumn)) { + $lastRowOffset = array(); + foreach ($primaryColumn as $col) { + $lastRowOffset[$col] = $row[$col]; + } + } else { + $lastRowOffset = $row[$primaryColumn]; + } + mysql_data_seek($result, 0); + } + } + } + + return $result; + } + + /** + * Depending on the structure type of the primary key returns the condition to position at the right offset + * + * @param mysqli|resource $dbh database connection + * @param string|string[] $primaryColumn primaricolumng index + * @param mixed $offset offset + * + * @return string + */ + protected static function getOffsetKeyCondition($dbh, $primaryColumn, $offset) + { + $condition = ''; + + if ($offset === 0) { + return ''; + } + + // COUPOUND KEY + if (is_array($primaryColumn)) { + $isFirstCond = true; + + foreach ($primaryColumn as $colIndex => $col) { + if (is_array($offset) && isset($offset[$col])) { + if ($isFirstCond) { + $isFirstCond = false; + } else { + $condition .= ' OR '; + } + $condition .= ' ('; + for ($prevColIndex = 0; $prevColIndex < $colIndex; $prevColIndex++) { + $condition .= + ' `' . $primaryColumn[$prevColIndex] . '` = "' . + self::realEscapeString($dbh, $offset[$primaryColumn[$prevColIndex]]) . '" AND '; + } + $condition .= ' `' . $col . '` > "' . self::realEscapeString($dbh, $offset[$col]) . '")'; + } + } + } else { + $condition = '`' . $primaryColumn . '` > "' . self::realEscapeString($dbh, (is_scalar($offset) ? $offset : 0)) . '"'; + } + + return (strlen($condition) ? ' AND (' . $condition . ')' : ''); + } + + /** + * get current database engine (mysql, maria, percona) + * + * @param \mysqli|resource $dbh database connection + * + * @return string + */ + public static function getDBEngine($dbh) + { + if (($result = self::query($dbh, "SHOW VARIABLES LIKE 'version%'")) === false) { + // on query error assume is mysql. + return self::DB_ENGINE_MYSQL; + } + + $rows = array(); + while ($row = self::fetchRow($result)) { + $rows[] = $row; + } + self::freeResult($result); + + $version = isset($rows[0][1]) ? $rows[0][1] : false; + $versionComment = isset($rows[1][1]) ? $rows[1][1] : false; + + //Default is mysql + if ($version === false && $versionComment === false) { + return self::DB_ENGINE_MYSQL; + } + + if (stripos($version, 'maria') !== false || stripos($versionComment, 'maria') !== false) { + return self::DB_ENGINE_MARIA; + } + + if (stripos($version, 'percona') !== false || stripos($versionComment, 'percona') !== false) { + return self::DB_ENGINE_PERCONA; + } + + return self::DB_ENGINE_MYSQL; + } + + /** + * Escape string + * + * @param resoruce|\mysqli $dbh database connection + * @param string $string string to escape + * + * @return string

        Returns an escaped string.

        + */ + public static function realEscapeString($dbh, $string) + { + if (self::dbConnType($dbh) === self::CONN_MYSQLI) { + return mysqli_real_escape_string($dbh, $string); + } else { + return mysql_real_escape_string($string, $dbh); + } + } + + /** + * + * @param resoruce|\mysqli $dbh database connection + * @param string $query query string + * + * @return mixed

        Returns FALSE on failure. For successful SELECT, SHOW, DESCRIBE or + * EXPLAIN queries mysqli_query() will return a mysqli_result object. + * For other successful queries mysqli_query() will return TRUE.

        + */ + public static function query($dbh, $query) + { + try { + if (self::dbConnType($dbh) === self::CONN_MYSQLI) { + return mysqli_query($dbh, $query); + } else { + return mysql_query($query, $dbh); + } + } catch (Exception $e) { + return false; + } + } + + /** + * + * @param resoruce|\mysqli_result $result query result + * + * @return int + */ + public static function numRows($result) + { + if (self::dbConnTypeByResult($result) === self::CONN_MYSQLI) { + return $result->num_rows; + } else { + return mysql_num_rows($result); + } + } + + /** + * + * @param resoruce|\mysqli_result $result query result + * + * @return array|null|false Returns an array of strings that corresponds to the fetched row. NULL if there are no more rows in result set + * + */ + public static function fetchRow($result) + { + if (self::dbConnTypeByResult($result) === self::CONN_MYSQLI) { + return mysqli_fetch_row($result); + } elseif (is_resource($result)) { + return mysql_fetch_row($result); + } + } + + /** + * + * @param resoruce|\mysqli_result $result query result + * + * @return array Returns an associative array of values representing the fetched row in the result set, + * where each key in the array represents the name of one of the result set's + * columns or null if there are no more rows in result set. + */ + public static function fetchAssoc($result) + { + if (self::dbConnTypeByResult($result) === self::CONN_MYSQLI) { + return mysqli_fetch_assoc($result); + } elseif (is_resource($result)) { + return mysql_fetch_assoc($result); + } + } + + /** + * + * @param resoruce|mysqli_result $result query result + * + * @return boolean + */ + public static function freeResult($result) + { + if (self::dbConnTypeByResult($result) === self::CONN_MYSQLI) { + return $result->free(); + } elseif (is_resource($result)) { + return mysql_free_result($result); + } else { + $result = null; + return true; + } + } + + /** + * + * @param resoruce|\mysqli $dbh database connection + * + * @return string + */ + public static function error($dbh) + { + if (self::dbConnType($dbh) === self::CONN_MYSQLI) { + if ($dbh instanceof \mysqli) { + return mysqli_error($dbh); + } else { + return 'Unable to retrieve the error message from MySQL'; + } + } else { + if (is_resource($dbh)) { + return mysql_error($dbh); + } else { + return 'Unable to retrieve the error message from MySQL'; + } + } + } + + /** + * + * @param resoruce|\mysqli $dbh database connection + * + * @return string // self::CONN_MYSQLI|self::CONN_MYSQL + */ + public static function dbConnType($dbh) + { + return (is_object($dbh) && get_class($dbh) == 'mysqli') ? self::CONN_MYSQLI : self::CONN_MYSQL; + } + + /** + * + * @param resoruce|\mysqli_result $result query resyult + * + * @return type // self::CONN_MYSQLI|self::CONN_MYSQL + */ + public static function dbConnTypeByResult($result) + { + return (is_object($result) && get_class($result) == 'mysqli_result') ? self::CONN_MYSQLI : self::CONN_MYSQL; + } + + /** + * This function takes in input the values of a multiple inster with this format + * (v1, v2, v3 ...),(v1, v2, v3, ...),... + * and returns a two dimensional array where each item is a row containing the list of values + * [ + * [v1, v2, v3 ...], + * [v1, v2, v3 ...], + * ... + * ] + * The return values are not processed but are taken exactly as they are in the dump file. + * So if they are escaped it remains unchanged + * + * @param string $query query values + * + * @return array + */ + public static function getValuesFromQueryInsert($query) + { + $result = array(); + $isItemOpen = false; + $isStringOpen = false; + $char = ''; + $pChar = ''; + + $currentItem = array(); + $currentValue = ''; + + for ($i = 0; $i < strlen($query); $i++) { + $pChar = $char; + $char = $query[$i]; + + switch ($char) { + case '(': + if ($isItemOpen == false && !$isStringOpen) { + $isItemOpen = true; + continue 2; + } + break; + case ')': + if ($isItemOpen && !$isStringOpen) { + $isItemOpen = false; + $currentItem[] = trim($currentValue); + $currentValue = ''; + $result[] = $currentItem; + $currentItem = array(); + continue 2; + } + break; + case '\'': + case '"': + if ($isStringOpen === false && $pChar !== '\\') { + $isStringOpen = $char; + } elseif ($isStringOpen === $char && $pChar !== '\\') { + $isStringOpen = false; + } + break; + case ',': + if ($isItemOpen == false) { + continue 2; + } elseif ($isStringOpen === false) { + $currentItem[] = trim($currentValue); + $currentValue = ''; + continue 2; + } + break; + default: + break; + } + + if ($isItemOpen == false) { + continue; + } + + $currentValue .= $char; + } + return $result; + } + + /** + * This is the inverse of getValuesFromQueryInsert, from an array of values it returns the valody of an insert query + * + * @param array $values rows values + * + * @return string + */ + public static function getQueryInsertValuesFromArray($values) + { + + return implode( + ',', + array_map( + function ($rowVals) { + return '(' . implode(',', $rowVals) . ')'; + }, + $values + ) + ); + } + + /** + * Returns the content of a value resulting from getValuesFromQueryInsert in string + * Then remove the outer quotes and escape + * "value\"test" become value"test + * + * @param string $value value + * + * @return string + */ + public static function parsedQueryValueToString($value) + { + $result = preg_replace('/^[\'"]?(.*?)[\'"]?$/s', '$1', $value); + return stripslashes($result); + } + + /** + * Returns the content of a value resulting from getValuesFromQueryInsert in int + * Then remove the outer quotes and escape + * "100" become (int)100 + * + * @param string $value value + * + * @return int + */ + public static function parsedQueryValueToInt($value) + { + return (int) preg_replace('/^[\'"]?(.*?)[\'"]?$/s', '$1', $value); + } + + /** + * Return the list of mysqlrealconnect existing flags values from mask + * @see https://www.php.net/manual/en/mysqli.real-connect.php + * + * @param bool $returnStr if true return define string else values + * @param null|int[] $filter if not null only the values that exist and are contained in the array are returned + * + * @return string[] + */ + public static function getMysqlConnectFlagsList($returnStr = true, $filter = null) + { + static $flagsList = null; + + if (is_null($flagsList)) { + $flagsList = array(); + + if (defined('MYSQLI_CLIENT_COMPRESS')) { + $flagsList[MYSQLI_CLIENT_COMPRESS] = 'MYSQLI_CLIENT_COMPRESS'; + } + if (defined('MYSQLI_CLIENT_FOUND_ROWS')) { + $flagsList[MYSQLI_CLIENT_FOUND_ROWS] = 'MYSQLI_CLIENT_FOUND_ROWS'; + } + if (defined('MYSQLI_CLIENT_IGNORE_SPACE')) { + $flagsList[MYSQLI_CLIENT_IGNORE_SPACE] = 'MYSQLI_CLIENT_IGNORE_SPACE'; + } + if (defined('MYSQLI_CLIENT_INTERACTIVE')) { + $flagsList[MYSQLI_CLIENT_INTERACTIVE] = 'MYSQLI_CLIENT_INTERACTIVE'; + } + if (defined('MYSQLI_CLIENT_SSL')) { + $flagsList[MYSQLI_CLIENT_SSL] = 'MYSQLI_CLIENT_SSL'; + } + if (defined('MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT')) { + $flagsList[MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT] = 'MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT'; + } + } + + if (is_null($filter)) { + $result = $flagsList; + } else { + $result = array(); + foreach ($flagsList as $flagVal => $flag) { + if (!in_array($flagVal, $filter)) { + continue; + } + $result[$flagVal] = $flag; + } + } + + if ($returnStr) { + return array_values($result); + } else { + return array_keys($result); + } + } + + /** + * Return the list of mysqlrealconnect flags values from mask + * @see https://www.php.net/manual/en/mysqli.real-connect.php + * + * @param int $value mask value + * + * @return int[] + */ + public static function getMysqlConnectFlagsFromMaskVal($value) + { + /* + MYSQLI_CLIENT_COMPRESS 32 + MYSQLI_CLIENT_FOUND_ROWS 2 + MYSQLI_CLIENT_IGNORE_SPACE 256 + MYSQLI_CLIENT_INTERACTIVE 1024 + MYSQLI_CLIENT_SSL 2048 + MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT 64 + */ + + $result = array(); + + foreach (self::getMysqlConnectFlagsList(false) as $flagVal) { + if (($value & $flagVal) > 0) { + $result[] = $flagVal; + } + } + + return $result; + } +} diff --git a/src/Libs/Snap/SnapIO.php b/src/Libs/Snap/SnapIO.php new file mode 100644 index 00000000..5694a16d --- /dev/null +++ b/src/Libs/Snap/SnapIO.php @@ -0,0 +1,1592 @@ + $value) { + ${$var} = $value; + } + + ob_start(); + if ($required) { + require($path); + } else { + include($path); + } + return ob_get_clean(); + } + + /** + * Copy file + * + * @param string $source source path + * @param string $dest detination path + * @param boolean $overwriteIfExists if true and file exists the file is overwritten + * + * @return boolean Returns true on success or false on failure. + */ + public static function copy($source, $dest, $overwriteIfExists = true) + { + if (file_exists($dest)) { + if ($overwriteIfExists) { + self::rm($dest); + } else { + return false; + } + } + return copy($source, $dest); + } + + /** + * Copy recursive folder content + * + * @param string $source source path + * @param string $dest detination path + * + * @return boolean Returns true on success or false on failure. + */ + public static function rcopy($source, $dest) + { + if (!is_readable($source)) { + return false; + } + + if (is_dir($source)) { + if (!file_exists($dest)) { + if (!self::mkdir($dest)) { + return false; + } + } + + if (($handle = opendir($source)) == false) { + return false; + } + + while ($file = readdir($handle)) { + if ($file == "." || $file == "..") { + continue; + } + + if (!self::rcopy($source . '/' . $file, $dest . '/' . $file)) { + closedir($handle); + return false; + } + } + closedir($handle); + return true; + } else { + return copy($source, $dest); + } + } + + /** + * Untrailingslashit path + * + * @param string $path file path + * + * @return string + */ + public static function untrailingslashit($path) + { + return rtrim($path, '/\\'); + } + + /** + * Trailingslashit path + * + * @param string $path file path + * + * @return string + */ + public static function trailingslashit($path) + { + return self::untrailingslashit($path) . '/'; + } + + /** + * Normalize path + * + * @param string $path file path + * @param boolean $real if true apply realpath function + * + * @return string + */ + public static function safePath($path, $real = false) + { + if ($real) { + if (($res = realpath($path)) === false) { + $res = $path; + } + } else { + $res = $path; + } + return self::normalizePath($res); + } + + /** + * Untrailingslashit and normalize path + * + * @param string $path file path + * @param boolean $real if true apply realpath function + * + * @return string + */ + public static function safePathUntrailingslashit($path, $real = false) + { + if ($real) { + if (($res = realpath($path)) === false) { + $res = $path; + } + } else { + $res = $path; + } + return rtrim(self::normalizePath($res), '/'); + } + + /** + * Trailingslashit and normalize path + * + * @param string $path file path + * @param boolean $real if true apply realpath function + * + * @return string + */ + public static function safePathTrailingslashit($path, $real = false) + { + return self::safePathUntrailingslashit($path, $real) . '/'; + } + + /** + * Remove file path + * + * @param string $file path + * + * @return bool

        Returns TRUE on success or FALSE on failure.

        + */ + public static function unlink($file) + { + try { + if (!file_exists($file)) { + return true; + } + if (!function_exists('unlink') || is_dir($file)) { + return false; + } + self::chmod($file, 'u+rw'); + return @unlink($file); + } catch (Exception $e) { + return false; + } catch (Error $e) { + return false; + } + } + + /** + * Rename file from old name to new name + * + * @param string $oldname path + * @param string $newname path + * @param bool $removeIfExists if true remove exists file + * + * @return bool

        Returns TRUE on success or FALSE on failure.

        + */ + public static function rename($oldname, $newname, $removeIfExists = false) + { + try { + if (!file_exists($oldname) || !function_exists('rename')) { + return false; + } + + if ($removeIfExists && file_exists($newname)) { + if (!self::rrmdir($newname)) { + return false; + } + } + return @rename($oldname, $newname); + } catch (Exception $e) { + return false; + } catch (Error $e) { + return false; + } + } + + /** + * Open file + * + * @param string $filepath File path + * @param string $mode The mode parameter specifies the type of access you require to the stream. + * @param boolean $throwOnError thorw exception on error + * + * @return boolean|resource Returns a file pointer resource on success, or false on failure + */ + public static function fopen($filepath, $mode, $throwOnError = true) + { + if (strlen($filepath) > SnapOS::maxPathLen()) { + throw new Exception('Skipping a file that exceeds allowed max path length [' . SnapOS::maxPathLen() . ']. File: ' . $filepath); + } + + if (SnapString::startsWith($mode, 'w') || SnapString::startsWith($mode, 'c') || file_exists($filepath)) { + $file_handle = @fopen($filepath, $mode); + } else { + if ($throwOnError) { + throw new Exception("$filepath doesn't exist"); + } else { + return false; + } + } + + if (!is_resource($file_handle)) { + if ($throwOnError) { + throw new Exception("Error opening $filepath"); + } else { + return false; + } + } else { + return $file_handle; + } + } + + /** + * Touch file + * + * @param string $filepath File path + * @param int $time The touch time. If time is not supplied, the current system time is used. + * + * @return bool Returns true on success or false on failure. + */ + public static function touch($filepath, $time = null) + { + if (!function_exists('touch')) { + return false; + } + + if ($time === null) { + $time = time(); + } + return @touch($filepath, $time); + } + + /** + * Remove folder + * + * @param string $dirname dir path + * @param boolean $mustExist if true and folder don't esist thorw error + * + * @return void + */ + public static function rmdir($dirname, $mustExist = false) + { + if (file_exists($dirname)) { + self::chmod($dirname, 'u+rwx'); + if (self::rrmdir($dirname) === false) { + throw new Exception("Couldn't remove {$dirname}"); + } + } elseif ($mustExist) { + throw new Exception("{$dirname} doesn't exist"); + } + } + + /** + * Remove file + * + * @param string $filepath file path + * @param boolean $mustExist if true and folder don't esist thorw error + * + * @return void + */ + public static function rm($filepath, $mustExist = false) + { + if (file_exists($filepath)) { + self::chmod($filepath, 'u+rw'); + if (@unlink($filepath) === false) { + throw new Exception("Couldn't remove {$filepath}"); + } + } elseif ($mustExist) { + throw new Exception("{$filepath} doesn't exist"); + } + } + + /** + * string string in file + * + * @param resource $handle file handle + * @param string $string fwrite string + * + * @return int bytes written + * + */ + public static function fwrite($handle, $string) + { + $bytes_written = @fwrite($handle, $string); + + if ($bytes_written != strlen($string)) { + throw new Exception('Error writing all bytes to file.'); + } else { + return $bytes_written; + } + } + + /** + * wrinte file in chunk mode. For big data. + * + * @param resource $handle file handle + * @param string $content fwrite string + * + * @return int bytes written + * + * @throws Exception + */ + public static function fwriteChunked($handle, $content) + { + if (strlen($content) == 0) { + return 0; + } + + $pieces = str_split($content, self::FWRITE_CHUNK_SIZE); + $written = 0; + + foreach ($pieces as $piece) { + if (($fwResult = @fwrite($handle, $piece, self::FWRITE_CHUNK_SIZE)) === false) { + throw new Exception('Error writing to file.'); + } + $written += $fwResult; + } + + if ($written != strlen($content)) { + throw new Exception('Error writing all bytes to file.'); + } + + return $written; + } + + /** + * Append file $from to file $to, if $to file don't exits create it. + * In case of error throw exceptions. + * + * @param string $from file path + * @param string $to file path + * + * @return int writte bytes + */ + public static function appendFileToFile($from, $to) + { + try { + $written = 0; + $fromHd = false; + $toHd = false; + + if (!file_exists($from) || !is_readable($from)) { + throw new Exception('File: ' . $from . ' don\'t exists os isn\'t readable'); + } + + if (file_exists($to) && !is_writable($to)) { + throw new Exception('File: ' . $to . ' isn\'t writeable'); + } + + if (($fromHd = @fopen($from, "rb")) === false) { + throw new Exception('Could not open file: ' . $from); + } + + if (($toHd = @fopen($to, "ab")) === false) { + throw new Exception('Could not open file: ' . $to); + } + + if (($fromStat = fstat($fromHd)) == false) { + throw new Exception('Can\t stat file: ' . $from); + } + + while ($buffer = fread($fromHd, self::FWRITE_CHUNK_SIZE)) { + if (($fwResult = @fwrite($toHd, $buffer)) === false) { + throw new Exception('Error writing to file ' . $to); + } + $written += $fwResult; + } + + if ($written != $fromStat['size']) { + throw new Exception('Error on file append, written bytes ' . $written . ' expected ' . $fromStat['size']); + } + } catch (Exception $e) { + if ($fromHd !== false) { + fclose($fromHd); + } + if ($toHd !== false) { + fclose($toHd); + } + throw $e; + } + + fclose($fromHd); + fclose($toHd); + + return $written; + } + + /** + * File get + * + * @param resource $handle file handle + * @param int $length max num bytes + * + * @return string + */ + public static function fgets($handle, $length) + { + $line = fgets($handle, $length); + + if ($line === false) { + throw new Exception('Error reading line.'); + } + + return $line; + } + + /** + * File close + * + * @param resource $handle file handle + * @param boolean $exception_on_fail if true thorw exception on fail + * + * @return void + */ + public static function fclose($handle, $exception_on_fail = true) + { + if ((@fclose($handle) === false) && $exception_on_fail) { + throw new Exception("Error closing file"); + } + } + + /** + * Exec a flock, thow exception on failure + * + * @param resource $handle file handle + * @param int $operation flock openration + * + * @return void + */ + public static function flock($handle, $operation) + { + if (@flock($handle, $operation) === false) { + throw new Exception("Error locking file"); + } + } + + /** + * Returns the current position of the file read/write pointer + * throw exception on failure + * + * @param resource $file_handle file handle + * + * @return int + */ + public static function ftell($file_handle) + { + $position = @ftell($file_handle); + + if ($position === false) { + throw new Exception("Couldn't retrieve file offset."); + } else { + return $position; + } + } + + /** + * 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; + } + } + } + + /** + * Return files size, throw eception on failure + * + * @param string $filename file path + * + * @return int + */ + public static function filesize($filename) + { + $file_size = @filesize($filename); + + if ($file_size === false) { + throw new Exception("Error retrieving file size of $filename"); + } + + return $file_size; + } + + /** + * Fseek on file, throw exception on failure + * + * @param resource $handle file handle + * @param int $offset The offset. + * @param int $whence whence values are: SEEK_SET + * - Set position equal to offset bytes. SEEK_CUR + * - Set position to current location plus offset. SEEK_END + * - Set position to end-of-file plus offset. + * + * @return void + */ + public static function fseek($handle, $offset, $whence = SEEK_SET) + { + $ret_val = @fseek($handle, $offset, $whence); + + if ($ret_val !== 0) { + $filepath = stream_get_meta_data($handle); + $filepath = $filepath["uri"]; + $filesize = self::filesize($filepath); + // For future debug + /* + error_log('$offset: '.$offset); + error_log('$filesize: '.$filesize); + error_log($whence. ' == '. SEEK_SET); + */ + if ($ret_val === false) { + throw new Exception("Trying to fseek($offset, $whence) and came back false"); + } elseif ( + abs($offset) > self::FILE_SIZE_LIMIT_32BIT || + $filesize > self::FILE_SIZE_LIMIT_32BIT || + ($offset <= 0 && ($whence == SEEK_SET || $whence == SEEK_END)) + ) { + //This check is not strict, but in most cases 32 Bit PHP will be the issue + throw new Snap32BitSizeLimitException("Trying to seek on a file beyond the capability of 32 bit PHP. offset=$offset filesize=$filesize"); + } else { + throw new Exception("Error seeking to file offset $offset. Retval = $ret_val"); + } + } + } + + /** + * Gets file modification time + * + * @param string $filename file path + * + * @return int|false the time the file was last modified, or false on failure. + * The time is returned as a Unix timestamp, which is suitable for the date function + */ + public static function filemtime($filename) + { + $mtime = filemtime($filename); + + if ($mtime === false) { + throw new Exception("Cannot retrieve last modified time of $filename"); + } + + return $mtime; + } + + /** + * File put content, thorw exception on failure + * + * @param string $filename file path + * @param mixed $data The data to write. Can be either a string, an array or a stream resource. + * @return bool + */ + public static function filePutContents($filename, $data) + { + if (($dirFile = realpath(dirname($filename))) === false) { + throw new Exception('FILE ERROR: put_content for file ' . $filename . ' failed [realpath fail]'); + } + if (!is_dir($dirFile)) { + throw new Exception('FILE ERROR: put_content for file ' . $filename . ' failed [dir ' . $dirFile . ' doesn\'t exist]'); + } + if (!is_writable($dirFile)) { + throw new Exception('FILE ERROR: put_content for file ' . $filename . ' failed [dir ' . $dirFile . ' exists but isn\'t writable]'); + } + $realFileName = $dirFile . basename($filename); + if (file_exists($realFileName) && !is_writable($realFileName)) { + throw new Exception('FILE ERROR: put_content for file ' . $filename . ' failed [file exist ' . $realFileName . ' but isn\'t writable'); + } + if (file_put_contents($filename, $data) === false) { + throw new Exception('FILE ERROR: put_content for file ' . $filename . ' failed [Couldn\'t write data to ' . $realFileName . ']'); + } + return true; + } + + /** + * 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 permission 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_numeric($mode)) { + $octalMode = intval((($mode[0] === '0' ? '' : '0') . $mode), 8); + } elseif (is_string($mode) && 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; + } + } + } + } else { + return true; + } + + // 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); + } + + /** + * Return file perms in string + * + * @param int|string $perms permssions + * + * @return string|bool // false if fail + */ + public static function permsToString($perms) + { + if (is_int($perms)) { + return decoct($perms); + } elseif (is_numeric($perms)) { + return ($perms[0] === '0' ? '' : '0') . $perms; + } elseif (is_string($perms)) { + return $perms; + } else { + false; + } + } + + /** + * 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) > SnapOS::maxPathLen()) { + throw new Exception('Skipping a file that exceeds allowed max path length [' . SnapOS::maxPathLen() . ']. File: ' . $path); + } + + if (!file_exists($path)) { + if (!function_exists('mkdir')) { + return false; + } + if (!@mkdir($path, 0777, $recursive)) { + return false; + } + } + + return self::chmod($path, $mode); + } + + /** + * this function call snap mkdir if te folder don't exists od don't have write or exec permissions + * + * this function handles the variable MODE in a way similar to the chmod of lunux + * The mode variable can be set to have more flexibility but not giving the user write and read and exec permissions doesn't make much sense + * + * @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. + */ + public static function dirWriteCheckOrMkdir($path, $mode = 'u+rwx', $recursive = false, $context = null) + { + if (!file_exists($path)) { + return self::mkdir($path, $mode, $recursive, $context); + } elseif (!is_writable($path) || (function_exists('is_executable') && !is_executable($path))) { + return self::chmod($path, $mode); + } else { + return true; + } + } + + /** + * from wordpress function wp_is_stream + * + * @param string $path The resource path or URL. + * @return bool True if the path is a stream URL. + */ + public static function isStream($path) + { + $scheme_separator = strpos($path, '://'); + + if (false === $scheme_separator) { + // $path isn't a stream + return false; + } + + $stream = substr($path, 0, $scheme_separator); + + return in_array($stream, stream_get_wrappers(), true); + } + + /** + * From Wordpress function: wp_mkdir_p + * + * Recursive directory creation based on full path. + * + * Will attempt to set permissions on folders. + * + * @param string $target Full path to attempt to create. + * @return bool Whether the path was created. True if path already exists. + */ + public static function mkdirP($target) + { + $wrapper = null; + + // Strip the protocol. + if (self::isStream($target)) { + list( $wrapper, $target ) = explode('://', $target, 2); + } + + // From php.net/mkdir user contributed notes. + $target = str_replace('//', '/', $target); + + // Put the wrapper back on the target. + if ($wrapper !== null) { + $target = $wrapper . '://' . $target; + } + + /* + * Safe mode fails with a trailing slash under certain PHP versions. + * Use rtrim() instead of untrailingslashit to avoid formatting.php dependency. + */ + $target = rtrim($target, '/'); + if (empty($target)) { + $target = '/'; + } + + if (file_exists($target)) { + return @is_dir($target); + } + + // We need to find the permissions of the parent folder that exists and inherit that. + $target_parent = dirname($target); + while ('.' != $target_parent && !is_dir($target_parent) && dirname($target_parent) !== $target_parent) { + $target_parent = dirname($target_parent); + } + + // Get the permission bits. + if ($stat = @stat($target_parent)) { + $dir_perms = $stat['mode'] & 0007777; + } else { + $dir_perms = 0777; + } + + if (@mkdir($target, $dir_perms, true)) { + /* + * If a umask is set that modifies $dir_perms, we'll have to re-set + * the $dir_perms correctly with chmod() + */ + if ($dir_perms != ( $dir_perms & ~umask() )) { + $folder_parts = explode('/', substr($target, strlen($target_parent) + 1)); + for ($i = 1, $c = count($folder_parts); $i <= $c; $i++) { + @chmod($target_parent . '/' . implode('/', array_slice($folder_parts, 0, $i)), $dir_perms); + } + } + + return true; + } + + return false; + } + + /** + * This function returns the relative path to mainPath + * + * @param string $path file path + * @param string $mainPath main path + * @param bool $real if true check real path + * + * @return bool|string false if path isn't a sub path of main path or return the relative path + */ + public static function getRelativePath($path, $mainPath, $real = false) + { + if (strlen($mainPath) == 0) { + return ltrim(self::safePathUntrailingslashit($path, $real), '/'); + } + + $safePath = self::safePathUntrailingslashit($path, $real); + $safeMainPath = self::safePathUntrailingslashit($mainPath, $real); + + if ($safePath === $safeMainPath) { + return ''; + } elseif (strpos($safePath, self::trailingslashit($safeMainPath)) === 0) { + return ltrim(substr($safePath, strlen($safeMainPath)), '/'); + } else { + return false; + } + } + + /** + * Check if path is child of mainPath + * + * @param string $path file path + * @param string $mainPath main path + * @param boolean $reverseCheck if true check if path is child of mainpath and if mainPash is child of path + * @param boolean $trueIfEquals if paths are equals and is true return true else false + * + * @return boolean + */ + public static function isChildPath($path, $mainPath, $reverseCheck = false, $trueIfEquals = true) + { + if (strlen($mainPath) == 0) { + return true; + } + + if ($reverseCheck && strlen($path) == 0) { + return true; + } + + $safePath = self::safePathUntrailingslashit($path); + $safeMainPath = self::safePathUntrailingslashit($mainPath); + + if ($safePath === $safeMainPath) { + return $trueIfEquals; + } elseif (strpos($safePath, self::trailingslashit($safeMainPath)) === 0) { + return true; + } elseif ($reverseCheck && strpos($safeMainPath, self::trailingslashit($safePath)) === 0) { + return true; + } else { + return false; + } + } + + /** + * Return sorted array by subfolders count + * + * @param string[] $paths paths lists + * @param boolean $childsFirst if true put childs before parents + * @param boolean $maintainIndex if true maintain array indexes + * @param boolean $sortKeys if true sort by keys + * + * @return string[] + */ + public static function sortBySubfoldersCount($paths, $childsFirst = false, $maintainIndex = false, $sortKeys = false) + { + if ($sortKeys) { + $function = 'uksort'; + } elseif ($maintainIndex) { + $function = 'uasort'; + } else { + $function = 'usort'; + } + + $function($paths, function ($a, $b) use ($childsFirst) { + $lenA = count(preg_split('/[\\\\\/]+/', $a)); + $lenB = count(preg_split('/[\\\\\/]+/', $b)); + if ($lenA === $lenB) { + return strcmp($a, $b) * ($childsFirst ? -1 : 1); + } elseif ($lenA > $lenB) { + return ($childsFirst ? -1 : 1); + } else { + return ($childsFirst ? 1 : -1); + } + }); + return $paths; + } + + /** + * from wp_normalize_path + * + * @param string $path Path to normalize. + * + * @return string Normalized path. + */ + public static function normalizePath($path) + { + $wrapper = ''; + if (self::isStream($path)) { + list( $wrapper, $path ) = explode('://', $path, 2); + $wrapper .= '://'; + } + + // Standardise all paths to use / + $path = str_replace('\\', '/', $path); + + // Replace multiple slashes down to a singular, allowing for network shares having two slashes. + $path = preg_replace('|(?<=.)/+|', '/', $path); + if (strpos($path, '//') === 0) { + $path = substr($path, 1); + } + + // Windows paths should uppercase the drive letter + if (':' === substr($path, 1, 1)) { + $path = ucfirst($path); + } + + return $wrapper . $path; + } + + /** + * Get common parent path from given paths + * + * @param array $paths - array of paths + * @return common parent path + */ + public static function getCommonPath($paths = array()) + { + if (empty($paths)) { + return ''; + } if (!is_array($paths)) { + $paths = array($paths); + } else { + $paths = array_values($paths); + } + + $pathAssoc = array(); + $numPaths = count($paths); + $minPathCouts = PHP_INT_MAX; + + for ($i = 0; $i < $numPaths; $i++) { + $pathAssoc[$i] = explode('/', self::safePathUntrailingslashit($paths[$i])); + $pathCount = count($pathAssoc[$i]); + if ($minPathCouts > $pathCount) { + $minPathCouts = $pathCount; + } + } + + for ($partIndex = 0; $partIndex < $minPathCouts; $partIndex++) { + $currentPart = $pathAssoc[0][$partIndex]; + for ($currentPath = 1; $currentPath < $numPaths; $currentPath++) { + if ($pathAssoc[$currentPath][$partIndex] != $currentPart) { + break 2; + } + } + } + + $resultParts = array_slice($pathAssoc[0], 0, $partIndex); + + return implode('/', $resultParts); + } + + /** + * remove root path transforming the current path into a relative path + * + * ex. /aaa/bbb become aaa/bbb + * ex. C:\aaa\bbb become aaa\bbb + * + * @param string $path file path + * + * @return string + */ + public static function removeRootPath($path) + { + return preg_replace('/^(?:[A-Za-z]:)?[\/](.*)/', '$1', $path); + } + + /** + * Returns the last N lines of a file. Simular to tail command + * + * @param string $filepath The full path to the file to be tailed + * @param int $lines The number of lines to return with each tail call + * + * @return string The last N parts of the file + */ + public static function tailFile($filepath, $lines = 2) + { + // Open file + $f = @fopen($filepath, "rb"); + if ($f === false) { + return false; + } + + // Sets buffer size + $buffer = 256; + + // Jump to last character + fseek($f, -1, SEEK_END); + + // Read it and adjust line number if necessary + // (Otherwise the result would be wrong if file doesn't end with a blank line) + if (fread($f, 1) != "\n") { + $lines -= 1; + } + + // Start reading + $output = ''; + $chunk = ''; + + // While we would like more + while (ftell($f) > 0 && $lines >= 0) { + // Figure out how far back we should jump + $seek = min(ftell($f), $buffer); + // Do the jump (backwards, relative to where we are) + fseek($f, -$seek, SEEK_CUR); + // Read a chunk and prepend it to our output + $output = ($chunk = fread($f, $seek)) . $output; + // Jump back to where we started reading + fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR); + // Decrease our line counter + $lines -= substr_count($chunk, "\n"); + } + + // While we have too many lines + // (Because of buffer size we might have read too many) + while ($lines++ < 0) { + // Find first newline and remove all text before that + $output = substr($output, strpos($output, "\n") + 1); + } + fclose($f); + return trim($output); + } + + /** + * Return lasts fine of file + * + * @param string $path Path to the file + * @param int $n Number of lines to get + * @param int $charLimit Number of chars to include in each line + * + * @return bool|array Last $n lines of file + * + * @throws Exception + */ + public static function getLastLinesOfFile($path, $n, $charLimit = null) + { + if (!is_readable($path)) { + return false; + } + + if (($handle = self::fopen($path, 'r', false)) === false) { + return false; + } + + $result = array(); + $pos = -1; + $currentLine = ''; + $counter = 0; + + while ($counter < $n && -1 !== fseek($handle, $pos, SEEK_END)) { + $char = fgetc($handle); + if (PHP_EOL == $char) { + $trimmedValue = trim($currentLine); + if (is_null($charLimit)) { + $currentLine = substr($currentLine, 0); + } else { + $currentLine = substr($currentLine, 0, (int) $charLimit); + if (strlen($currentLine) == $charLimit) { + $currentLine .= '...'; + } + } + + if (!empty($trimmedValue)) { + $result[] = $currentLine; + $counter++; + } + $currentLine = ''; + } else { + $currentLine = $char . $currentLine; + } + $pos--; + } + self::fclose($handle, false); + + return array_reverse($result); + } + + /** + * Thif function scan a folder filter by regex + * + * @param string $dir dir to scan + * @param array $options array( + * 'regexFile' => [bool|string|array], if is bool alrays or never match, + * if is string o array of string check if rexeses match file name + * 'regexFolder' => [bool|string|array], if is bool alrays or never match, + * if is string o array of string check if rexeses match file name + * 'checkFullPath' => bool, if false only current file/folder name is passed at regex if true is passed the full path + * 'recursive' => bool, if false check only passed folder or all sub folder recursively + * 'invert' => bool, if false pass invert the result + * 'childFirst' => bool if false is parsed parent folters first or child folders first + * ) + * + * @return string[] paths lists + */ + public static function regexGlob($dir, $options) + { + $result = array(); + + self::regexGlobCallback($dir, function ($path) use (&$result) { + $result[] = $path; + }, $options); + + return $result; + } + + /** + * Execute the callback function foreach right element, private function for optimization + * + * @param string $dir dir to scan + * @param callable $callback callback function + * @param array $options array( + * 'regexFile' => [bool|string|array], if is bool alrays or never match, + * if is string o array of string check if rexeses match file name + * 'regexFolder' => [bool|string|array], if is bool alrays or never match, + * if is string o array of string check if rexeses match file name + * 'checkFullPath' => bool, if false only current file/folder name is passed at regex + * if true is passed the full path + * 'recursive' => bool, if false check only passed folder or all sub folder recursively + * 'invert' => bool, if false pass invert the result + * 'childFirst' => bool if false is parsed parent folters first or child folders first + * ) + * + * @return boolean Returns true on success or false on failure. + */ + protected static function regexGlobCallbackPrivate($dir, $callback, &$options) + { + if (($dh = opendir($dir)) == false) { + return false; + } + + while (($elem = readdir($dh)) !== false) { + if ($elem === '.' || $elem === '..') { + continue; + } + + $fullPath = $dir . $elem; + $isDir = is_dir($fullPath); + if (($regex = $isDir ? $options['regexFolder'] : $options['regexFile']) === false) { + continue; + } + + if ($isDir && is_link($fullPath)) { + $realPath = self::safePathUntrailingslashit($fullPath, true); + if (in_array($realPath, $options['symlinks'])) { + continue; + } + $options['symlinks'][] = $realPath; + } + + if (is_bool($regex)) { + $match = $regex; + } else { + $match = false; + $pathCheck = $options['checkFullPath'] ? $fullPath : $elem; + + foreach ($regex as $currentRegex) { + if (preg_match($currentRegex, $pathCheck) === 1) { + $match = true; + break; + } + } + + if ($options['invert']) { + $match = !$match; + } + } + + if ($match) { + if ($isDir && $options['execChildFirst']) { + self::regexGlobCallbackPrivate($fullPath . '/', $callback, $options); + } + + call_user_func($callback, $fullPath); + + if ($isDir && $options['execChildAfter']) { + self::regexGlobCallbackPrivate($fullPath . '/', $callback, $options); + } + } + } + closedir($dh); + + return true; + } + + /** + * Execute the callback function foreach right element (folder or files) + * + * @param string $dir dir to scan + * @param callable $callback callback function + * @param array $options array( + * 'regexFile' => [bool|string|array], if is bool alrays or never match, + * if is string o array of string check if rexeses match file name + * 'regexFolder' => [bool|string|array], if is bool alrays or never match, + * if is string o array of string check if rexeses match file name + * 'checkFullPath' => bool, if false only current file/folder name is passed at regex + * if true is passed the full path + * 'recursive' => bool, if false check only passed folder or all sub folder recursively + * 'invert' => bool, if false pass invert the result + * 'childFirst' => bool if false is parsed parent folters first or child folders first + * ) + * + * @return boolean Returns true on success or false on failure. + */ + public static function regexGlobCallback($dir, $callback, $options = array()) + { + $dir = self::safePathTrailingslashit($dir); + + if (!is_dir($dir) || !is_readable($dir)) { + return false; + } + + if (!is_callable($callback)) { + return false; + } + + $options = array_merge(array( + 'regexFile' => true, + 'regexFolder' => true, + 'checkFullPath' => false, + 'recursive' => false, + 'invert' => false, + 'childFirst' => false, + 'symlinks' => array() + ), (array) $options); + + if (is_bool($options['regexFile'])) { + $options['regexFile'] = ($options['regexFile'] xor $options['invert']); + } elseif (is_scalar($options['regexFile'])) { + $options['regexFile'] = array($options['regexFile']); + } + + if (is_bool($options['regexFolder'])) { + $options['regexFolder'] = ($options['regexFolder'] xor $options['invert']); + } elseif (is_scalar($options['regexFolder'])) { + $options['regexFolder'] = array($options['regexFolder']); + } + + // optimizization + $options['execChildFirst'] = ($options['recursive'] && $options['childFirst'] === true); + $options['execChildAfter'] = ($options['recursive'] && $options['childFirst'] === false); + + return self::regexGlobCallbackPrivate($dir, $callback, $options); + } + + /** + * Empty passed dir + * + * @param string $dir folder to empty + * @param string[] $filter childs name to skip + * + * @return boolean Returns true on success or false on failure. + */ + public static function emptyDir($dir, $filter = array()) + { + $dir = self::safePathTrailingslashit($dir); + if (!is_dir($dir) || !is_readable($dir)) { + return false; + } + + if (($dh = opendir($dir)) == false) { + return false; + } + + $listToDelete = array(); + + while (($elem = readdir($dh)) !== false) { + if ($elem === '.' || $elem === '..') { + continue; + } + + if (in_array($elem, $filter)) { + continue; + } + + $fullPath = $dir . $elem; + if (self::chmod($fullPath, 'ugo+rwx')) { + $listToDelete[] = $fullPath; + } + } + closedir($dh); + + foreach ($listToDelete as $path) { + self::rrmdir($path); + } + return true; + } + + /** + * Returns a path to the base root folder of path taking into account the + * open_basedir setting. + * + * @param string $path file path + * + * @return bool|string Base root path of $path if it's accessible, otherwise false; + */ + public static function getMaxAllowedRootOfPath($path) + { + $path = self::safePathUntrailingslashit($path, true); + + if (!self::isOpenBaseDirEnabled()) { + $parts = explode("/", $path); + return $parts[0] . "/"; + } else { + return self::getOpenBaseDirRootOfPath($path); + } + } + + /** + * Check if php.ini open_basedir is enabled + * + * @return bool true if open_basedir is set + */ + public static function isOpenBaseDirEnabled() + { + $iniVar = ini_get("open_basedir"); + return !empty($iniVar); + } + + /** + * Get open_basedir list paths + * + * @return string[] Paths contained in the open_basedir setting. Empty array if the setting is not enabled. + */ + public static function getOpenBaseDirPaths() + { + if (!($openBase = ini_get("open_basedir"))) { + return array(); + } + return explode(PATH_SEPARATOR, $openBase); + } + + /** + * Get open base dir root path of path + * + * @param $path file path + * + * @return bool|string Path to the base dir of $path if it exists, otherwise false + */ + public static function getOpenBaseDirRootOfPath($path) + { + foreach (self::getOpenBaseDirPaths() as $allowedPath) { + $allowedPath = $allowedPath !== "/" ? self::safePathUntrailingslashit($allowedPath) : "/"; + if (strpos($path, $allowedPath) === 0) { + return $allowedPath; + } + } + + return false; + } + + /** + * this function is similar at dirname but if empty path return empty value not . + * and is SO indipendent so work on not normalized path + * + * @param string $path file path + * + * @return string + */ + public static function getRelativeDirname($path) + { + if (preg_match('/^(.*)[\/]+/', $path, $matches) !== 1) { + return ''; + } + + return $matches[1]; + } + + /** + * Set full user permissions on folder (rwx) + * + * @param string $path dir path + * + * @return boolean // return false if folder don't have read write permission on folder + */ + public static function dirAddFullPermsAndCheckResult($path) + { + if (!SnapIO::chmod($path, 'u+rwx')) { + return false; + } + + if (!is_readable($path) || !is_writable($path)) { + return false; + } + + if (function_exists('is_executable') && !is_executable($path) && !SnapOS::isWindows()) { + return false; + } + + return true; + } + + /** + * set full user permissions on file (rwx) + * + * @param string $path file path + * + * @return boolean // return false if folder don't have read write permission on folder + */ + public static function fileAddFullPermsAndCheckResult($path) + { + if (!SnapIO::chmod($path, 'u+rw')) { + return false; + } + + if (!is_readable($path) || !is_writable($path)) { + return false; + } + + return true; + } +} diff --git a/src/Libs/Snap/SnapJson.php b/src/Libs/Snap/SnapJson.php new file mode 100644 index 00000000..e242eac9 --- /dev/null +++ b/src/Libs/Snap/SnapJson.php @@ -0,0 +1,304 @@ +=')) { + $args = array($data, $options, $depth); + } elseif (version_compare(PHP_VERSION, '5.3', '>=')) { + $args = array($data, $options); + } else { + $args = array($data); + } + + $preparedData = self::jsonPrepareData($data); + // Prepare the data for JSON serialization. + $args[0] = $preparedData; + + $json = call_user_func_array('json_encode', $args); + + // If json_encode() was successful, no need to do more sanity checking. + // ... unless we're in an old version of PHP, and json_encode() returned + // a string containing 'null'. Then we need to do more sanity checking. + if (false !== $json && ( version_compare(PHP_VERSION, '5.5', '>=') || false === strpos($json, 'null') )) { + return $json; + } + + try { + $args[0] = self::jsonSanityCheck($preparedData, $depth); + } catch (\Exception $e) { + return false; + } + + $json = null; + $preparedData = null; + return call_user_func_array('json_encode', $args); + } + + /** + * wp_json_encode with pretty print if define exists + * + * @param mixed $data Variable (usually an array or object) to encode as JSON. + * @param int $options Optional. Options to be passed to json_encode(). Default 0. + * @param int $depth Optional. Maximum depth to walk through $data. Must be + * greater than 0. Default 512. + * @return string|false The JSON encoded string, or false if it cannot be encoded. + */ + public static function jsonEncodePPrint($data, $options = 0, $depth = 512) + { + if (defined('JSON_PRETTY_PRINT')) { + return self::jsonEncode($data, JSON_PRETTY_PRINT | $options, $depth); + } else { + return self::jsonEncode($data, $options, $depth); + } + } + + /** + * Prepares response data to be serialized to JSON. + * + * This supports the JsonSerializable interface for PHP 5.2-5.3 as well. + * + * @ignore + * @since 4.4.0 + * @access private + * + * @param mixed $data Native representation. + * @return bool|int|float|null|string|array Data ready for `json_encode()`. + */ + private static function jsonPrepareData($data) + { + if ( + !defined('WP_JSON_SERIALIZE_COMPATIBLE') || + WP_JSON_SERIALIZE_COMPATIBLE === false + ) { + return $data; + } + + switch (gettype($data)) { + case 'boolean': + case 'integer': + case 'double': + case 'string': + case 'NULL': + // These values can be passed through. + return $data; + + case 'array': + // Arrays must be mapped in case they also return objects. + return array_map(array(__CLASS__, 'jsonPrepareData'), $data); + + case 'object': + // If this is an incomplete object (__PHP_Incomplete_Class), bail. + if (!is_object($data)) { + return null; + } + + if ($data instanceof \JsonSerializable) { + $data = $data->jsonSerialize(); + } else { + $data = get_object_vars($data); + } + + // Now, pass the array (or whatever was returned from jsonSerialize through). + return self::jsonPrepareData($data); + + default: + return null; + } + } + + /** + * Perform sanity checks on data that shall be encoded to JSON. + * + * @ignore + * @since 4.1.0 + * @access private + * + * @see wp_json_encode() + * + * @param mixed $data Variable (usually an array or object) to encode as JSON. + * @param int $depth Maximum depth to walk through $data. Must be greater than 0. + * @return mixed The sanitized data that shall be encoded to JSON. + */ + private static function jsonSanityCheck($data, $depth) + { + if ($depth < 0) { + throw new \Exception('Reached depth limit'); + } + + if ($data instanceof \JsonSerializable) { + $data = $data->jsonSerialize(); + } + + if (is_array($data)) { + $output = array(); + foreach ($data as $id => $el) { + // Don't forget to sanitize the ID! + if (is_string($id)) { + $clean_id = self::jsonConvertString($id); + } else { + $clean_id = $id; + } + + // Check the element type, so that we're only recursing if we really have to. + if (is_array($el) || is_object($el)) { + $output[$clean_id] = self::jsonSanityCheck($el, $depth - 1); + } elseif (is_string($el)) { + $output[$clean_id] = self::jsonConvertString($el); + } else { + $output[$clean_id] = $el; + } + } + } elseif (is_object($data)) { + $output = new \stdClass(); + foreach ($data as $id => $el) { + if (is_string($id)) { + $clean_id = self::jsonConvertString($id); + } else { + $clean_id = $id; + } + + if (is_array($el) || is_object($el)) { + $output->$clean_id = self::jsonSanityCheck($el, $depth - 1); + } elseif (is_string($el)) { + $output->$clean_id = self::jsonConvertString($el); + } else { + $output->$clean_id = $el; + } + } + } elseif (is_string($data)) { + return self::jsonConvertString($data); + } else { + return $data; + } + + return $output; + } + + /** + * Return json string + * + * @param string $string data + * + * @return string + */ + private static function jsonConvertString($string) + { + static $use_mb = null; + if (is_null($use_mb)) { + $use_mb = function_exists('mb_convert_encoding'); + } + + if ($use_mb) { + $encoding = mb_detect_encoding($string, mb_detect_order(), true); + if ($encoding) { + return mb_convert_encoding($string, 'UTF-8', $encoding); + } else { + return mb_convert_encoding($string, 'UTF-8', 'UTF-8'); + } + } else { + return self::checkInvalidUTF8($string, true); + } + } + + /** + * Checks for invalid UTF8 in a string. + * + * @param string $string The text which is to be checked. + * @param bool $strip Optional. Whether to attempt to strip out invalid UTF8. Default is false. + * + * @return string The checked text. + */ + public static function checkInvalidUTF8($string, $strip = false) + { + $string = (string) $string; + + if (0 === strlen($string)) { + return ''; + } + + // Check for support for utf8 in the installed PCRE library once and store the result in a static + static $utf8_pcre = null; + if (!isset($utf8_pcre)) { + $utf8_pcre = @preg_match('/^./u', 'a'); + } + // We can't demand utf8 in the PCRE installation, so just return the string in those cases + if (!$utf8_pcre) { + return $string; + } + + // preg_match fails when it encounters invalid UTF8 in $string + if (1 === @preg_match('/^./us', $string)) { + return $string; + } + + // Attempt to strip the bad chars if requested (not recommended) + if ($strip && function_exists('iconv')) { + return iconv('utf-8', 'utf-8', $string); + } + + return ''; + } + + /** + * + * todo remove esc_attr wp function + * + * @param mixed $val object to be encoded + * @return string escaped json string + */ + public static function jsonEncodeEscAttr($val) + { + return esc_attr(json_encode($val)); + } + + /** + * this function return a json encoded string without quotes at the beginning and the end + * + * @param string $string json string + * @return string + * @throws \Exception + */ + public static function getJsonWithoutQuotes($string) + { + if (!is_string($string)) { + throw new \Exception('the function getJsonStringWithoutQuotes take only strings'); + } + + return substr(self::jsonEncode($string), 1, -1); + } +} diff --git a/src/Libs/Snap/SnapLog.php b/src/Libs/Snap/SnapLog.php new file mode 100644 index 00000000..f92f81fe --- /dev/null +++ b/src/Libs/Snap/SnapLog.php @@ -0,0 +1,198 @@ +"; + $lfp = self::$logFilepath; + // echo "logging $s to {$lfp}
        "; + if (self::$logFilepath === null) { + throw new Exception('Logging not initialized'); + } + + if (isset($_SERVER['REQUEST_TIME_FLOAT'])) { + $timepart = $_SERVER['REQUEST_TIME_FLOAT']; + } else { + $timepart = $_SERVER['REQUEST_TIME']; + } + + $thread_id = sprintf("%08x", abs(crc32($_SERVER['REMOTE_ADDR'] . $timepart . $_SERVER['REMOTE_PORT']))); + + $s = $thread_id . ' ' . date('h:i:s') . ":$s"; + + if (self::$logHandle === null) { + self::$logHandle = fopen(self::$logFilepath, 'a'); + } + + fwrite(self::$logHandle, "$s\n"); + + if ($flush) { + fflush(self::$logHandle); + + fclose(self::$logHandle); + + self::$logHandle = fopen(self::$logFilepath, 'a'); + } + } + + /** + * Init profiling + * + * @return void + */ + public static function initProfiling() + { + self::$profileLogArray = array(); + } + + /** + * Write profile to log + * + * @param string $s profile key + * + * @return void + */ + public static function writeToPLog($s) + { + throw new Exception('not implemented'); + $currentTime = microtime(true); + + if (array_key_exists($s, self::$profileLogArray)) { + $dSame = $currentTime - self::$profileLogArray[$s]; + $dSame = number_format($dSame, 7); + } else { + $dSame = 'N/A'; + } + + if (self::$prevTS != -1) { + $dPrev = $currentTime - self::$prevTS; + $dPrev = number_format($dPrev, 7); + } else { + $dPrev = 'N/A'; + } + + self::$profileLogArray[$s] = $currentTime; + self::$prevTS = $currentTime; + + self::log(" {$dPrev} : {$dSame} : {$currentTime} : {$s}"); + } + + /** + * Get formatted string fo value + * + * @param mixed $var value to convert to string + * @param bool $checkCallable if true check if var is callable and display it + * + * @return string + */ + public static function v2str($var, $checkCallable = false) + { + if ($checkCallable && is_callable($var)) { + return '(callable) ' . print_r($var, true); + } + switch (gettype($var)) { + case "boolean": + return $var ? 'true' : 'false'; + case "integer": + case "double": + return (string) $var; + case "string": + return '"' . $var . '"'; + case "array": + case "object": + return print_r($var, true); + case "resource": + case "resource (closed)": + case "NULL": + case "unknown type": + default: + return gettype($var); + } + } + + /** + * Get exception message file line trace + * + * @param Exception|Error $e exception object + * @param bool $displayMessage if true diplay exception message + * + * @return string + */ + public static function getTextException($e, $displayMessage = true) + { + $result = ($displayMessage ? $e->getMessage() . "\n" : ''); + return $result . "FILE:" . $e->getFile() . '[' . $e->getLIne() . "]\n" . + "TRACE:\n" . $e->getTraceAsString(); + } +} diff --git a/src/Libs/Snap/SnapNet.php b/src/Libs/Snap/SnapNet.php new file mode 100644 index 00000000..4a8dc9ea --- /dev/null +++ b/src/Libs/Snap/SnapNet.php @@ -0,0 +1,51 @@ + &$val) { + if (is_array($val)) { + $val = implode(',', $val); + } + $post_params[] = $key . '=' . urlencode($val); + } + + $post_string = implode('&', $post_params); + + $parts = parse_url($url); + + $fp = fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80, $errno, $errstr, 60); + + $out = "POST " . $parts['path'] . " HTTP/1.1\r\n"; + $out .= "Host: " . $parts['host'] . "\r\n"; + $out .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $out .= "Content-Length: " . strlen($post_string) . "\r\n"; + $out .= "Connection: Close\r\n\r\n"; + + if (isset($post_string)) { + $out .= $post_string; + } + + fwrite($fp, $out); + + fclose($fp); + } +} diff --git a/src/Libs/Snap/SnapOS.php b/src/Libs/Snap/SnapOS.php new file mode 100644 index 00000000..3e6d80c0 --- /dev/null +++ b/src/Libs/Snap/SnapOS.php @@ -0,0 +1,63 @@ +rootPath = SnapIO::safePathUntrailingslashit($root, true); + $this->origFilesFolder = SnapIO::safePathTrailingslashit($origFolderParentPath, true) . self::ORIG_FOLDER_PREFIX . $hash; + $this->persistanceFile = $this->origFilesFolder . '/' . self::PERSISTANCE_FILE_NAME; + } + + /** + * Create a main folder if don't exist and load the entries + * + * @param boolean $reset if strue reset orig file folder + * + * @return void + */ + public function init($reset = false) + { + $this->createMainFolder($reset); + $this->load(); + } + + /** + * Create orig file folder + * + * @param boolean $reset if true delete current folder + * + * @return boolean return true if succeded + * + * @throws \Exception + */ + protected function createMainFolder($reset = false) + { + if ($reset) { + $this->deleteMainFolder(); + } + + if (!file_exists($this->origFilesFolder)) { + if (!SnapIO::mkdir($this->origFilesFolder, 'u+rwx')) { + throw new \Exception('Can\'t create the original files folder ' . SnapLog::v2str($this->origFilesFolder)); + } + } + + $htaccessFile = $this->origFilesFolder . '/.htaccess'; + if (!file_exists($htaccessFile)) { + $content = <<persistanceFile)) { + $this->save(); + } + + return true; + } + + /** + * @return string Main folder path + * @throws \Exception + */ + public function getMainFolder() + { + if (!file_exists($this->origFilesFolder)) { + throw new \Exception('Can\'t get the original files folder ' . SnapLog::v2str($this->origFilesFolder)); + } + + return $this->origFilesFolder; + } + + /** + * delete origianl files folder + * + * @return boolean + * @throws \Exception + */ + public function deleteMainFolder() + { + if (file_exists($this->origFilesFolder) && !SnapIO::rrmdir($this->origFilesFolder)) { + throw new \Exception('Can\'t delete the original files folder ' . SnapLog::v2str($this->origFilesFolder)); + } + $this->origFolderEntries = array(); + + return true; + } + + /** + * add a entry on original folder. + * + * @param string $identifier entry identifier + * @param string $path entry path. can be a file or a folder + * @param string $mode MODE_MOVE move the item in original folder + * MODE_COPY copy the item in original folder + * @param bool|string $rename if rename is a string the item is renamed in original folder. + * + * @return boolean true if succeded + * + * @throws Exception + */ + public function addEntry($identifier, $path, $mode = self::MODE_MOVE, $rename = false) + { + if (!file_exists($path)) { + return false; + } + + $baseName = empty($rename) ? basename($path) : $rename; + + if (($relativePath = SnapIO::getRelativePath($path, $this->rootPath)) === false) { + $isRelative = false; + } else { + $isRelative = true; + } + $parentFolder = $isRelative ? dirname($relativePath) : SnapIO::removeRootPath(dirname($path)); + if (empty($parentFolder) || $parentFolder === '.') { + $parentFolder = ''; + } else { + $parentFolder .= '/'; + } + $targetFolder = $this->origFilesFolder . '/' . $parentFolder; + if (!file_exists($targetFolder)) { + SnapIO::mkdirP($targetFolder); + } + $dest = $targetFolder . $baseName; + + switch ($mode) { + case self::MODE_MOVE: + // Don't use rename beacause new files must have the current script owner + if (!SnapIO::rcopy($path, $dest)) { + throw new \Exception('Can\'t copy the original file ' . SnapLog::v2str($path)); + } + if (!SnapIO::rrmdir($path, $dest)) { + throw new \Exception('Can\'t remove the original file ' . SnapLog::v2str($path)); + } + break; + case self::MODE_COPY: + if (!SnapIO::rcopy($path, $dest)) { + throw new \Exception('Can\'t copy the original file ' . SnapLog::v2str($path)); + } + break; + default: + throw new \Exception('invalid mode addEntry'); + } + + $this->origFolderEntries[$identifier] = array( + 'baseName' => $baseName, + 'source' => $isRelative ? $relativePath : $path, + 'stored' => $parentFolder . $baseName, + 'mode' => $mode, + 'isRelative' => $isRelative + ); + + $this->save(); + return true; + } + + /** + * Get entry info from identifier + * + * @param string $identifier orig file identifier + * + * @return boolean|string false if entry don't exists + */ + public function getEntry($identifier) + { + if (isset($this->origFolderEntries[$identifier])) { + return $this->origFolderEntries[$identifier]; + } else { + return false; + } + } + + /** + * Get entry stored path in original folder + * + * @param string $identifier orig file identifier + * + * @return boolean|string false if entry don't exists + */ + public function getEntryStoredPath($identifier) + { + if (isset($this->origFolderEntries[$identifier])) { + return $this->origFilesFolder . '/' . $this->origFolderEntries[$identifier]['stored']; + } else { + return false; + } + } + + /** + * Return true if identifier org file is relative path + * + * @param string $identifier orig file identifier + * + * @return boolean + */ + public function isRelative($identifier) + { + if (isset($this->origFolderEntries[$identifier])) { + $this->origFolderEntries[$identifier]['isRelative']; + } else { + return false; + } + } + + /** + * Get entry target restore path + * + * @param string $identifier orig file identifier + * @param null|string $defaultIfIsAbsolute if isn't null return the value if path is absolute + * + * @return boolean false if entry don't exists + */ + public function getEntryTargetPath($identifier, $defaultIfIsAbsolute = null) + { + if (isset($this->origFolderEntries[$identifier])) { + if ($this->origFolderEntries[$identifier]['isRelative']) { + return $this->rootPath . '/' . $this->origFolderEntries[$identifier]['source']; + } else { + if (is_null($defaultIfIsAbsolute)) { + return $this->origFolderEntries[$identifier]['source']; + } else { + return $defaultIfIsAbsolute; + } + } + } else { + return false; + } + } + + /** + * this function restore current entry in original position. + * If mode is copy it simply delete the entry else move the entry in original position + * + * @param string $identifier identified of current entrye + * @param boolean $save update saved entries + * @param null|string $defaultIfIsAbsolute if isn't null return the value if path is absolute + * + * @return boolean true if succeded + * + * @throws Exception + */ + public function restoreEntry($identifier, $save = true, $defaultIfIsAbsolute = null) + { + if (!isset($this->origFolderEntries[$identifier])) { + return false; + } + + $stored = $this->getEntryStoredPath($identifier); + if (($original = $this->getEntryTargetPath($identifier, $defaultIfIsAbsolute)) === false) { + return false; + } + + switch ($this->origFolderEntries[$identifier]['mode']) { + case self::MODE_MOVE: + if (!SnapIO::rename($stored, $original)) { + throw new \Exception('Can\'t move the original file ' . SnapLog::v2str($stored)); + } + break; + case self::MODE_COPY: + if (!SnapIO::rrmdir($stored)) { + throw new \Exception('Can\'t delete entry ' . SnapLog::v2str($stored)); + } + break; + default: + throw new \Exception('invalid mode addEntry'); + } + + unset($this->origFolderEntries[$identifier]); + if ($save) { + $this->save(); + } + return true; + } + + /** + * Put all entries on original position and empty original folder + * + * @param string[] $exclude identifiers list t exclude + * + * @return boolean + */ + public function restoreAll($exclude = array()) + { + foreach (array_keys($this->origFolderEntries) as $ident) { + if (in_array($ident, $exclude)) { + continue; + } + $this->restoreEntry($ident, false); + } + $this->save(); + return true; + } + + /** + * Save notices from json file + * + * @return void + */ + public function save() + { + if (!file_put_contents($this->persistanceFile, SnapJson::jsonEncodePPrint($this->origFolderEntries))) { + throw new \Exception('Can\'t write persistence file'); + } + return true; + } + + /** + * Load notice from json file + * + * @return boolean + */ + private function load() + { + if (file_exists($this->persistanceFile)) { + $json = file_get_contents($this->persistanceFile); + $this->origFolderEntries = json_decode($json, true); + } else { + $this->origFolderEntries = array(); + } + return true; + } +} diff --git a/src/Libs/Snap/SnapString.php b/src/Libs/Snap/SnapString.php new file mode 100644 index 00000000..6e744a5b --- /dev/null +++ b/src/Libs/Snap/SnapString.php @@ -0,0 +1,139 @@ + $maxWidth) { + $s = substr($s, 0, $maxWidth - 3) . '...'; + } + + return $s; + } + + /** + * Returns true if the $haystack string starts with the $needle + * + * @param string $haystack The full string to search in + * @param string $needle The string to for + * + * @return bool Returns true if the $haystack string starts with the $needle + */ + public static function startsWith($haystack, $needle) + { + return (strpos($haystack, $needle) === 0); + } + + /** + * Returns true if the $haystack string end with the $needle + * + * @param string $haystack The full string to search in + * @param string $needle The string to for + * + * @return bool Returns true if the $haystack string starts with the $needle + */ + public static function endsWith($haystack, $needle) + { + $length = strlen($needle); + if ($length == 0) { + return true; + } + return (substr($haystack, -$length) === $needle); + } + + /** + * Returns true if the $needle is found in the $haystack + * + * @param string $haystack The full string to search in + * @param string $needle The string to for + * + * @return bool + */ + public static function contains($haystack, $needle) + { + $pos = strpos($haystack, $needle); + return ($pos !== false); + } + + /** + * Implode array key values to a string + * + * @param string $glue separator + * @param array $pieces array fo implode + * @param string $format format + * + * @return string + */ + public static function implodeKeyVals($glue, $pieces, $format = '%s="%s"') + { + $strList = array(); + foreach ($pieces as $key => $value) { + if (is_scalar($value)) { + $strList[] = sprintf($format, $key, $value); + } else { + $strList[] = sprintf($format, $key, print_r($value, true)); + } + } + return implode($glue, $strList); + } + + /** + * Replace last occurrence + * + * @param string $search The value being searched for + * @param string $replace The replacement value that replaces found search values + * @param string $str The string or array being searched and replaced on, otherwise known as the haystack + * @param boolean $caseSensitive Whether the replacement should be case sensitive or not + * + * @return string + */ + public static function strLastReplace($search, $replace, $str, $caseSensitive = true) + { + $pos = $caseSensitive ? strrpos($str, $search) : strripos($str, $search); + if (false !== $pos) { + $str = substr_replace($str, $replace, $pos, strlen($search)); + } + return $str; + } + + /** + * Check if passed string have html tags + * + * @param string $string input string + * + * @return boolean + */ + public static function isHTML($string) + { + return ($string != strip_tags($string)); + } +} diff --git a/src/Libs/Snap/SnapURL.php b/src/Libs/Snap/SnapURL.php new file mode 100644 index 00000000..7f7a72ea --- /dev/null +++ b/src/Libs/Snap/SnapURL.php @@ -0,0 +1,221 @@ + false, + 'host' => false, + 'port' => false, + 'user' => false, + 'pass' => false, + 'path' => '', + 'scheme' => false, + 'query' => false, + 'fragment' => false + ); + + /** + * Append a new query value to the end of a URL + * + * @param string $url The URL to append the new value to + * @param string $key The new key name + * @param string $value The new key name value + * + * @return string Returns the new URL with with the query string name and value + */ + public static function appendQueryValue($url, $key, $value) + { + $separator = (parse_url($url, PHP_URL_QUERY) == null) ? '?' : '&'; + $modified_url = $url . "$separator$key=$value"; + + return $modified_url; + } + + /** + * Add www. in url if don't have + * + * @param string $url input URL + * + * @return string + */ + public static function wwwAdd($url) + { + return preg_replace('/^((?:\w+\:)?\/\/)?(?!www\.)(.+)/', '$1www.$2', $url); + } + + /** + * Remove www. in url if don't have + * + * @param string $url input URL + * + * @return string + */ + public static function wwwRemove($url) + { + return preg_replace('/^((?:\w+\:)?\/\/)?www\.(.+)/', '$1$2', $url); + } + + /** + * Fetches current URL via PHP + * + * @param bool $queryString If true the query string will also be returned. + * @param boolean $requestUri If true check REQUEST_URI else SCRIPT_NAME + * @param int $getParentDirLevel If 0 get current script name or parent folder, if 1 parent folder if 2 parent of parent folder ... + * + * @return string The current page url + */ + 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; + } + + /** + * this function is a native PHP parse_url wrapper + * this function returns an associative array with all the keys present and the values = false if they do not exist. + * + * @param string $url

        The URL to parse. Invalid characters are replaced by _.

        + * @param int $component if != 1 return specific URL component + * + * @return mixed

        On seriously malformed URLs, parse_url() may return FALSE.

        + *

        If the component parameter is omitted, an associative array is returned. + * At least one element will be present within the array. Potential keys within this array are:

        + *
          + *
        • scheme - e.g. http
        • + *
        • host
        • + *
        • port
        • + *
        • user
        • + *
        • pass
        • + *
        • path
        • + *
        • query - after the question mark ?
        • + *
        • fragment - after the hashmark #
        • + *
        + *

        If the component parameter is specified, + * parse_url() returns a string (or an integer, + * in the case of PHP_URL_PORT) instead of an array. + * If the requested component doesn't exist within the given URL, NULL will be returned.

        + */ + public static function parseUrl($url, $component = -1) + { + if (preg_match('/^([a-zA-Z0-9]+\:)?\/\//', $url) !== 1) { + // fix invalid URL for only host string ex. 'myhost.com' + $url = '//' . $url; + } + + $result = parse_url($url, $component); + if (is_array($result)) { + $result = array_merge(self::$DEF_ARRAY_PARSE_URL, $result); + } + + return $result; + } + + /** + * Remove scheme from URL + * + * @param string $url source url + * @param bool $removeWww if true remove www + * + * @return string + */ + public static function removeScheme($url, $removeWww = false) + { + $parts = self::parseUrl($url); + unset($parts['scheme']); + $result = self::buildUrl($parts); + if ($removeWww) { + $result = self::wwwRemove($result); + } + return ltrim($result, '/'); + } + + /** + * this function build a url from array result of parse url. + * if work with both parse_url native function result and snap parseUrl result + * + * @param array $parts url parts from parseUrl + * + * @return bool|string return false if param isn't array + */ + public static function buildUrl($parts) + { + if (!is_array($parts)) { + return false; + } + + $result = ''; + $result .= (isset($parts['scheme']) && $parts['scheme'] !== false) ? $parts['scheme'] . ':' : ''; + $result .= ( + (isset($parts['user']) && $parts['user'] !== false) || + (isset($parts['host']) && $parts['host'] !== false)) ? '//' : ''; + + $result .= (isset($parts['user']) && $parts['user'] !== false) ? $parts['user'] : ''; + $result .= (isset($parts['pass']) && $parts['pass'] !== false) ? ':' . $parts['pass'] : ''; + $result .= (isset($parts['user']) && $parts['user'] !== false) ? '@' : ''; + + $result .= (isset($parts['host']) && $parts['host'] !== false) ? $parts['host'] : ''; + $result .= (isset($parts['port']) && $parts['port'] !== false) ? ':' . $parts['port'] : ''; + + $result .= (isset($parts['path']) && $parts['path'] !== false) ? $parts['path'] : ''; + $result .= (isset($parts['query']) && $parts['query'] !== false) ? '?' . $parts['query'] : ''; + $result .= (isset($parts['fragment']) && $parts['fragment'] !== false) ? '#' . $parts['fragment'] : ''; + + return $result; + } + + /** + * Encode alla chars + * + * @param string $url input URL + * + * @return string + */ + public static function urlEncodeAll($url) + { + $hex = unpack('H*', urldecode($url)); + return preg_replace('~..~', '%$0', strtoupper($hex[1])); + } +} diff --git a/src/Libs/Snap/SnapUtil.php b/src/Libs/Snap/SnapUtil.php new file mode 100644 index 00000000..41691a3b --- /dev/null +++ b/src/Libs/Snap/SnapUtil.php @@ -0,0 +1,775 @@ + 0) { + $percent = $startingPercent + (($endingPercent - $startingPercent) * ($currentTaskCount / (float) $totalTaskCount)); + } else { + $percent = $startingPercent; + } + + return min(max($startingPercent, $percent), $endingPercent); + } + + /** + * Compare two versions like version_compare but the ability to enter the number of levels to compare. + * For example, if the level is 2 between 4.1.1 and 4.1.2.1, 4.1 is compared with 4.1 and so they are equal. + * + * @param string $version1 version one + * @param string $version2 version two + * @param string $operator operetor type + * @param int $vLevel version level 0 is all levels + * + * @return int|bool + */ + public static function versionCompare($version1, $version2, $operator = null, $vLevel = 0) + { + if ($vLevel > 0) { + $tV1 = array_slice(explode('.', $version1), 0, $vLevel); + $version1 = implode('.', $tV1); + $tV2 = array_slice(explode('.', $version2), 0, $vLevel); + $version2 = implode('.', $tV2); + } + return version_compare($version1, $version2, $operator); + } + + /** + * Return true if is PHP7+ + * + * @return bool + */ + public static function isPHP7Plus() + { + static $isPHP7Plus = null; + if (is_null($isPHP7Plus)) { + $isPHP7Plus = version_compare(PHP_VERSION, '7.0.0', '>='); + } + return $isPHP7Plus; + } + + /** + * Groups an array into arrays by a given key, or set of keys, shared between all array members. + * + * Based on {@author Jake Zatecky}'s {@link https://github.com/jakezatecky/array_group_by array_group_by()} function. + * This variant allows $key to be closures. + * + * @param array $array The array to have grouping performed on. + * @param mixed $key The key to group or split by. Can be a _string_, an _integer_, a _float_, or a _callable_. + * - If the key is a callback, it must return a valid key from the array. + * - If the key is _NULL_, the iterated element is skipped. + * - string|int callback ( mixed $item ) + * + * @return array|null Returns a multidimensional array or `null` if `$key` is invalid. + */ + public static function arrayGroupBy(array $array, $key) + { + if (!is_string($key) && !is_int($key) && !is_float($key) && !is_callable($key)) { + trigger_error('array_group_by(): The key should be a string, an integer, or a callback', E_USER_ERROR); + return null; + } + $func = (!is_string($key) && is_callable($key) ? $key : null); + $_key = $key; + // Load the new array, splitting by the target key + $grouped = array(); + foreach ($array as $value) { + $key = null; + if (is_callable($func)) { + $key = call_user_func($func, $value); + } elseif (is_object($value) && isset($value->{$_key})) { + $key = $value->{$_key}; + } elseif (isset($value[$_key])) { + $key = $value[$_key]; + } + if ($key === null) { + continue; + } + $grouped[$key][] = $value; + } + // Recursively build a nested grouping if more parameters are supplied + // Each grouped array value is grouped according to the next sequential key + if (func_num_args() > 2) { + $args = func_get_args(); + foreach ($grouped as $key => $value) { + $params = array_merge(array($value), array_slice($args, 2, func_num_args())); + $grouped[$key] = call_user_func_array(array(__CLASS__, 'arrayGroupBy'), $params); + } + } + return $grouped; + } + + /** + * Converts human readable types (10GB) to bytes + * + * @param string $from A human readable byte size such as 100MB + * + * @return int Returns and integer of the byte size + */ + public static function convertToBytes($from) + { + if (is_numeric($from)) { + return $from; + } + + $number = substr($from, 0, -2); + switch (strtoupper(substr($from, -2))) { + case "KB": + return $number * 1024; + case "MB": + return $number * pow(1024, 2); + case "GB": + return $number * pow(1024, 3); + case "TB": + return $number * pow(1024, 4); + case "PB": + return $number * pow(1024, 5); + } + + $number = substr($from, 0, -1); + switch (strtoupper(substr($from, -1))) { + case "K": + return $number * 1024; + case "M": + return $number * pow(1024, 2); + case "G": + return $number * pow(1024, 3); + case "T": + return $number * pow(1024, 4); + case "P": + return $number * pow(1024, 5); + } + return $from; + } + + /** + * Sanitize input for XSS code + * + * @param string $input The value to sanitize + * + * @return string Returns the input value cleaned up. + */ + public static function sanitize($input) + { + return htmlspecialchars(self::sanitizeNSChars($input)); + } + + /** + * Remove all non stamp chars from string + * + * @param string $string input string + * + * @return string + */ + public static function sanitizeNSChars($string) + { + return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/u', '', (string) $string); + } + + /** + * remove all non stamp chars from string and newline + * trim string + * + * @param string $string input string + * + * @return string + */ + public static function sanitizeNSCharsNewline($string) + { + return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F\r\n]/u', '', (string) $string); + } + + /** + * Remove all non stamp chars, newline, spaces and tabulation from string + * + * @param string $string input string + * + * @return string + */ + public static function sanitizeNSCharsNewlineTabs($string) + { + return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F\r\n\s]/u', '', (string) $string); + } + + /** + * remove all non stamp chars from string and newline + * trim string + * + * @param string $string input string + * + * @return string + */ + public static function sanitizeNSCharsNewlineTrim($string) + { + return trim(self::sanitizeNSCharsNewline($string)); + } + + /** + * Determines whether a PHP ini value is changeable at runtime. + * + * @since 4.6.0 + * + * @staticvar array $ini_all + * + * @link https://secure.php.net/manual/en/function.ini-get-all.php + * + * @param string $setting The name of the ini setting to check. + * @return bool True if the value is changeable at runtime. False otherwise. + */ + public static function isIniValChangeable($setting) + { + // if ini_set is disabled can change the values + if (!function_exists('ini_set')) { + return false; + } + + if (function_exists('isIniValChangeable')) { + return 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(); + } + } + + // Bit operator to workaround https://bugs.php.net/bug.php?id=44936 which changes access level to 63 in PHP 5.2.6 - 5.2.17. + if (isset($ini_all[$setting]['access']) && ( INI_ALL === ( $ini_all[$setting]['access'] & 7 ) || INI_USER === ( $ini_all[$setting]['access'] & 7 ) )) { + return true; + } + + // If we were unable to retrieve the details, fail gracefully to assume it's changeable. + if (!is_array($ini_all)) { + return true; + } + + return false; + } + + /** + * The val value returns if it is between min and max otherwise it returns min or max + * + * @param int $val input value + * @param int $min min value + * @param int $max max value + * + * @return int + */ + public static function getIntBetween($val, $min, $max) + { + return min((int) $max, max((int) $min, (int) $val)); + } + + /** + * Gets a specific external variable by name and optionally filters it by request + * + * @param string $variable_name

        Name of a variable to get.

        + * @param int $filter

        The ID of the filter to apply. The Types of filters manual page lists the available filters.

        + *

        If omitted, FILTER_DEFAULT will be used, + * which is equivalent to FILTER_UNSAFE_RAW. + * This will result in no filtering taking place by default.

        + * @param array|int $options

        Associative array of options or bitwise disjunction of flags. + * If filter accepts options, flags can be provided in "flags" field of array.

        + * + * @return mixed

        Value of the requested variable on success, FALSE + * if the filter fails, or NULL + * if the variable_name variable is not set. + * If the flag FILTER_NULL_ON_FAILURE is used, + * it returns FALSE if the variable is not set and NULL if the filter fails.

        + * + * @link http://php.net/manual/en/function.filter-input.php + * @see filter_var(), filter_input_array(), filter_var_array() + */ + public static function filterInputRequest($variable_name, $filter = FILTER_DEFAULT, $options = 0) + { + if (isset($_GET[$variable_name]) && !isset($_POST[$variable_name])) { + return filter_input(INPUT_GET, $variable_name, $filter, $options); + } + + return filter_input(INPUT_POST, $variable_name, $filter, $options); + } + + /** + * Default filter sanitize string, apply sanitizeNSChars function. + * + * @param int $type One of INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, or INPUT_ENV. + * @param string $var_name Name of a variable to get. + * @param mixed $default default value if dont exists + * + * @return string + */ + public static function filterInputDefaultSanitizeString($type, $var_name, $default = '') + { + $filter = FILTER_UNSAFE_RAW; + $options = array( + 'options' => array( 'default' => null) + ); + if ($type == self::INPUT_REQUEST) { + $result = self::filterInputRequest($var_name, $filter, $options); + } else { + $result = filter_input($type, $var_name, $filter, $options); + } + if (is_null($result)) { + return $default; + } + return self::sanitizeNSChars($result); + } + + /** + * All characters that are not explicitly accepted are removed. + * By default, only alphanumeric characters are accepted. + * + * @param mixed $input input value + * @param string $extraAcceptChars extra accepted chars + * + * @return string|string[] + */ + public static function sanitizeStrict($input, $extraAcceptChars = '') + { + $regex = '/[^a-zA-Z0-9 ' . preg_quote($extraAcceptChars, '/') . ' ]/m'; + if (is_scalar($input) || is_null($input)) { + $input = (string) $input; + } elseif (is_array($input)) { + } elseif (is_object($input)) { + $input = (array) $input; + } else { + $input = ''; + } + + if (is_array($input)) { + foreach ($input as $key => $val) { + $input[$key] = self::sanitizeStrict($val, $extraAcceptChars); + } + return $input; + } + + $result = preg_replace($regex, '', $input); + return (is_null($result) ? '' : $result); + } + + /** + * Sanitize value from input $_GET, $_POST, $_REQUEST ... + * + * @param int $type One of INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV or Sanitize::INPUT_REQUEST + * @param string $varName Name of a variable to get. + * @param mixed $default default value if var $varName don't exists + * @param string $extraAcceptChars extra accepted chars + * + * @return string|string[]|mixed return default value if varName isn't defined + */ + public static function sanitizeStrictInput($type, $varName, $default = false, $extraAcceptChars = '') + { + if (($value = self::getValueByType($type, $varName)) === null) { + return $default; + } + + return self::sanitizeStrict($value, $extraAcceptChars); + } + + + /** + * Return value input by type null if don't exists + * + * @param int $type One of INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV or Sanitize::INPUT_REQUEST + * @param string $varName Name of a variable to get. + * + * @return string|string[]|null + */ + protected static function getValueByType($type, $varName) + { + $doNothingCallback = function ($v) { + return $v; + }; + + if ($type === self::INPUT_REQUEST) { + $type = ((isset($_GET[$varName]) && !isset($_POST[$varName])) ? INPUT_GET : INPUT_POST); + } + $value = filter_input($type, $varName, FILTER_CALLBACK, array('options' => $doNothingCallback)); + + /** @var string|string[]|null $value */ + return $value; + } + + /** + * Gets external variables and optionally filters them + *

        This function is useful for retrieving many values without repetitively calling filter_input().

        + * + * @param array|int $definition

        An array defining the arguments. + * A valid key is a string containing a variable name and a valid value is either a filter type, + * or an array optionally specifying the filter, flags and options. + * If the value is an array, valid keys are filter which specifies the filter type, + * flags which specifies any flags that apply to the filter, and options + * which specifies any options that apply to the filter. See the example below for a better understanding.

        + *

        This parameter can be also an integer holding a filter constant. + * Then all values in the input array are filtered by this filter.

        + * @param bool $add_empty

        Add missing keys as NULL to the return value.

        + * + * @return mixed

        An array containing the values of the requested variables on success. + * If the input array designated by type is not populated, + * the function returns NULL if the FILTER_NULL_ON_FAILURE flag is not given, + * or FALSE otherwise. For other failures, FALSE is returned.

        + *

        An array value will be FALSE if the filter fails, or NULL + * if the variable is not set. Or if the flag FILTER_NULL_ON_FAILURE is used, + * it returns FALSE if the variable is not set and NULL if the filter fails. + * If the add_empty parameter is FALSE, no array element will be added for unset variables.

        + * + * @link http://php.net/manual/en/function.filter-input-array.php + * @see filter_input(), filter_var_array() + */ + public static function filterInputRequestArray($definition = FILTER_DEFAULT, $add_empty = true) + { + if (!is_array($definition) || count($definition) === 0) { + return array(); + } + $getKeys = is_array($_GET) ? array_keys($_GET) : array(); + $postKeys = is_array($_POST) ? array_keys($_POST) : array(); + $keys = array_keys($definition); + + if (count(array_intersect($keys, $getKeys)) && !count(array_intersect($keys, $postKeys))) { + $type = INPUT_GET; + } else { + $type = INPUT_POST; + } + + $result = filter_input_array($type, $definition, $add_empty); + + if (!is_array($result)) { + $result = array(); + foreach ($keys as $key) { + $result[$key] = null; + } + } + return $result; + } + + /** + * Close all buffers and return content + * + * @param bool $getContent If true it returns buffer content, otherwise it is discarded + * + * @return string + */ + public static function obCleanAll($getContent = true) + { + static $minLevel = null; + if ($minLevel === null) { + $isZipCompression = filter_var(@ini_get('zlib.output_compression'), FILTER_VALIDATE_BOOLEAN); + $minLevel = ($isZipCompression ? 1 : 0); + } + $result = ''; + $levels = ob_list_handlers(); + for ($i = (count($levels) - 1); $i > $minLevel; $i--) { + if (strcmp($levels[$i], 'ob_gzhandler') === 0) { + break; + } + if ($getContent) { + $result .= ob_get_clean(); + } + ob_clean(); + } + return $result; + } + + /** + * Array map recursively + * + * @param callable $callback + * @param array $array + * + * @return array + */ + public static function arrayMapRecursive($callback, $array) + { + if (!is_array($array)) { + throw new Exception('$array must be an array'); + } + if (!is_callable($callback)) { + throw new Exception('$callback must be callable'); + } + $func = function ($item) use (&$func, &$callback) { + return is_array($item) ? array_map($func, $item) : call_user_func($callback, $item); + }; + return array_map($func, $array); + } + + /** + * Implemented array_key_first + * + * @link https://www.php.net/manual/en/function.array-key-first.php + * + * @param array $arr array input + * + * @return int|string|null + */ + public static function arrayKeyFirst($arr) + { + if (!function_exists('array_key_first')) { + foreach ($arr as $key => $unused) { + return $key; + } + return null; + } else { + return array_key_first($arr); + } + } + + /** + * Get number of bit supported by PHP + * + * @return string + */ + public static function getArchitectureString() + { + return (PHP_INT_SIZE * 8) . '-bit'; + } + + /** + * In array check by callback + * + * @param array $haystack array input + * @param callable $callback callback function + * + * @return null|bool + */ + public static function inArrayExtended($haystack, $callback) + { + if (!is_callable($callback)) { + return null; + } + + foreach ($haystack as $value) { + if (call_user_func($callback, $value)) { + return true; + } + } + + return false; + } + + /** + * This is a binary recursion, so it only works on an ordered array of integers. + * (If it is not ordered, it does not work) + * + * The advantage of using this search instead of normal array search is that the complexity goes from O(n) to O(log n). + * + * @param int[] $array array values + * @param int $x element to search + * + * @return bool + */ + public static function binarySearch($array, $x) + { + if (count($array) === 0) { + return false; + } + $low = 0; + $high = count($array) - 1; + + while ($low <= $high) { + $mid = floor(($low + $high) / 2); + + if ($array[$mid] == $x) { + return true; + } + if ($x < $array[$mid]) { + $high = $mid - 1; + } else { + $low = $mid + 1; + } + } + return false; + } + + /** + * Generates a random password drawn from the defined set of characters. + * Copy of the wp_generate_password() function from wp-includes/pluggable.php with minor tweaks + * + * @param int $length Optional. The length of password to generate. Default 12. + * @param bool $special_chars Optional. Whether to include standard special characters. + * Default true. + * @param bool $extra_special_chars Optional. Whether to include other special characters. + * Used when generating secret keys and salts. Default false. + * + * @return string The random password. + */ + public static function generatePassword($length = 12, $special_chars = true, $extra_special_chars = false) + { + $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + if ($special_chars) { + $chars .= '!@#$%^&*()'; + } + if ($extra_special_chars) { + $chars .= '-_ []{}<>~`+=,.;:/?|'; + } + + $password = ''; + for ($i = 0; $i < $length; $i++) { + $password .= substr($chars, self::rand(0, strlen($chars) - 1), 1); + } + + return $password; + } + + /** + * Generates a random number + * Copy of the wp_rand() function from wp-includes/pluggable.php with minor tweaks + * + * @global string $rnd_value + * @staticvar string $seed + * @staticvar bool $external_rand_source_available + * + * @param int $min Lower limit for the generated number + * @param int $max Upper limit for the generated number + * @return int A random number between min and max + */ + public static function rand($min = 0, $max = 0) + { + global $rnd_value; + // Some misconfigured 32bit environments (Entropy PHP, for example) truncate integers + // larger than PHP_INT_MAX to PHP_INT_MAX rather than overflowing them to floats. + $max_random_number = 3000000000 === 2147483647 ? (float) "4294967295" : 4294967295; + // 4294967295 = 0xffffffff + // We only handle Ints, floats are truncated to their integer value. + $min = (int) $min; + $max = (int) $max; + // Use PHP's CSPRNG, or a compatible method + static $use_random_int_functionality = null; + if (is_null($use_random_int_functionality)) { + $use_random_int_functionality = function_exists('random_int'); + } + if ($use_random_int_functionality) { + try { + $_max = ( 0 != $max ) ? $max : $max_random_number; + // rand() can accept arguments in either order, PHP cannot. + $_max = max($min, $_max); + $_min = min($min, $_max); + $val = random_int($_min, $_max); + if (false !== $val) { + return abs(intval($val)); + } else { + $use_random_int_functionality = false; + } + } catch (Error $e) { + $use_random_int_functionality = false; + } catch (Exception $e) { + $use_random_int_functionality = false; + } + } + + // Reset $rnd_value after 14 uses + // 32(md5) + 40(sha1) + 40(sha1) / 8 = 14 random numbers from $rnd_value + if (strlen($rnd_value) < 8) { + static $seed = ''; + $rnd_value = md5(uniqid(microtime() . mt_rand(), true) . $seed); + $rnd_value .= sha1($rnd_value); + $rnd_value .= sha1($rnd_value . $seed); + $seed = md5($seed . $rnd_value); + } + + // Take the first 8 digits for our value + $value = substr($rnd_value, 0, 8); + // Strip the first eight, leaving the remainder for the next call to rand(). + $rnd_value = substr($rnd_value, 8); + $value = abs(hexdec($value)); + // Reduce the value to be within the min - max range + if ($max != 0) { + $value = $min + ( $max - $min + 1 ) * $value / ( $max_random_number + 1 ); + } + + return abs(intval($value)); + } + + /** + * Function phpinfo wrapper + * @see https://www.php.net/manual/en/function.phpinfo.php + * + * @param int $flags see phpinfo function flags + * + * @return bool Returns true on success or false on failure. + */ + public static function phpinfo($flags = INFO_ALL) + { + if (!function_exists('phpinfo')) { + return false; + } + return phpinfo($flags); + } + + +} diff --git a/src/Libs/Snap/SnapWP.php b/src/Libs/Snap/SnapWP.php new file mode 100644 index 00000000..36b1aea8 --- /dev/null +++ b/src/Libs/Snap/SnapWP.php @@ -0,0 +1,711 @@ + bool, + * 'havePrefix' => bool, + * 'subsiteId' => int, + * 'isMultisiteCore' => bool + * ] + */ + public static function getTableInfoByName($table, $prefix) + { + $result = array( + 'isCore' => false, + 'havePrefix' => false, + 'subsiteId' => -1, + 'isMultisiteCore' => false + ); + + if (preg_match('/^' . preg_quote($prefix, '/') . '(?:(\d+)_)?(.+)/', $table, $matches) !== 1) { + return $result; + } + + $result['havePrefix'] = true; + $nameWithoutPrefix = $matches[2]; + $result['isMultisiteCore'] = in_array($nameWithoutPrefix, self::getMultisiteTables()); + $result['isCore'] = $result['isMultisiteCore'] || in_array($nameWithoutPrefix, self::getSiteCoreTables()); + + if (is_numeric($matches[1])) { + $result['subsiteId'] = (int) $matches[1]; + } elseif (!$result['isMultisiteCore']) { + $result['subsiteId'] = 1; + } + return $result; + } + + /** + * Get the list of wp prefixes from given tables list + * + * @param string[] $tables List of table names to check for unique WP prefixes + * + * @return string[] + */ + public static function getUniqueWPTablePrefixes($tables) + { + $userPrefix = array(); + $userMetaPrefix = array(); + + foreach ($tables as $table) { + if (preg_match("/^(.*)users$/m", $table, $matches)) { + $userPrefix[] = $matches[1]; + } elseif (preg_match("/^(.*)usermeta$/m", $table, $matches)) { + $userMetaPrefix[] = $matches[1]; + } + } + + return array_intersect($userPrefix, $userMetaPrefix); + } + + /** + * Modifies the database based on specified SQL statements. + * + * Useful for creating new tables and updating existing tables to a new structure. + * + * From Wordpress dbDelta + * + * @global \wpdb $wpdb WordPress database abstraction object. + * + * @param string[]|string $queries Optional. The query to run. Can be multiple queries + * in an array, or a string of queries separated by + * semicolons. Default empty string. + * @param bool $execute Optional. Whether or not to execute the query right away. + * Default true. + * @return array Strings containing the results of the various update queries. + */ + public static function dbDelta($queries = '', $execute = true) + { + $mysqliDriver = new \mysqli_driver(); + + $defReporting = $mysqliDriver->report_mode; + mysqli_report(MYSQLI_REPORT_OFF); + + $result = dbDelta($queries, $execute); + mysqli_report($defReporting); + + return $result; + } + + /** + * Get Auto_increment value of wp_blogs table in multisite. + * That is id of the first next subsite that will be imported. + * + * @return int // returns Auto_increment value of wp_blogs table in multisite, + * // returns -1 if Auto_increment value can not be obtained for any reason + */ + public static function getNextSubsiteIdAI() + { + $nextSubsiteIdAI = -1; + if (!is_multisite()) { + return $nextSubsiteIdAI; + } + /** @var \wpdb $wpdb */ + global $wpdb; + + $sql = $wpdb->prepare("SHOW TABLE STATUS LIKE %s", $wpdb->prefix . "blogs"); + $result = $wpdb->get_results($sql, ARRAY_A); + if (count($result) < 1) { + return $nextSubsiteIdAI; + } + $row = $result[0]; + if (array_key_exists("Auto_increment", $row)) { + $nextSubsiteIdAI = intval($row["Auto_increment"]); + } + return $nextSubsiteIdAI; + } + + /** + * From a tables list filters all tables without WP prefix + * + * @param string[] $tables tables list + * + * @return string[] + */ + public static function getTablesWithPrefix($tables) + { + /** @var \wpdb $wpdb */ + global $wpdb; + + $tables = (array) $tables; + + $result = array(); + + foreach ($tables as $table) { + if (strpos($table, $wpdb->prefix) === 0) { + $result[] = $table; + } + } + return $result; + } + + /** + * Check if passed folder is home folder + * + * @param string $folder folder path + * + * @return boolean return true if folder is wordpress home folder + * + */ + public static function isWpHomeFolder($folder) + { + $indexPhp = SnapIO::trailingslashit($folder) . 'index.php'; + if (!file_exists($indexPhp)) { + return false; + } + + if (($indexContent = file_get_contents($indexPhp)) === false) { + return false; + } + + return (preg_match('/require\s*[\s\(].*[\'"].*wp-blog-header.php[\'"]\s*\)?/', $indexContent) === 1); + } + + /** + * This function is the equivalent of the get_home_path function but with various fixes + * + * @staticvar string $home_path + * @return string + */ + public static function getHomePath() + { + static $home_path = null; + + if (is_null($home_path)) { + // outside wordpress this function makes no sense + if (!defined('ABSPATH')) { + $home_path = false; + return $home_path; + } + + if (isset($_SERVER['SCRIPT_FILENAME']) && is_readable($_SERVER['SCRIPT_FILENAME'])) { + $scriptFilename = $_SERVER['SCRIPT_FILENAME']; + } else { + $files = get_included_files(); + $scriptFilename = array_shift($files); + } + + $realScriptDirname = SnapIO::safePathTrailingslashit(dirname($scriptFilename), true); + $realAbsPath = SnapIO::safePathTrailingslashit(ABSPATH, true); + + if (strpos($realScriptDirname, $realAbsPath) === 0) { + // normalize URLs without www + $home = SnapURL::wwwRemove(set_url_scheme(get_option('home'), 'http')); + $siteurl = SnapURL::wwwRemove(set_url_scheme(get_option('siteurl'), 'http')); + + if (!empty($home) && 0 !== strcasecmp($home, $siteurl)) { + if (stripos($siteurl, $home) === 0) { + $wp_path_rel_to_home = str_ireplace($home, '', $siteurl); /* $siteurl - $home */ + $pos = strripos( + str_replace('\\', '/', $scriptFilename), + SnapIO::trailingslashit($wp_path_rel_to_home) + ); + $home_path = substr($scriptFilename, 0, $pos); + $home_path = SnapIO::trailingslashit($home_path); + } else { + $home_path = ABSPATH; + } + } else { + $home_path = ABSPATH; + } + } else { + // On frontend the home path is the folder of index.php + $home_path = SnapIO::trailingslashit(dirname($scriptFilename)); + } + + // make sure the folder exists or consider ABSPATH + if (!file_exists($home_path)) { + $home_path = ABSPATH; + } + + $home_path = str_replace('\\', '/', $home_path); + } + return $home_path; + } + + /** + * Return admin url, if is multisite return network_admin_url + * + * @param string $path Optional. Path relative to the admin URL. Default 'admin'. + * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). + * 'http' or 'https' can be passed to force those schemes. + * @return string Admin URL link with optional path appended. + */ + public static function getAdminUrl($path, $scheme = 'admin') + { + if (is_multisite()) { + return network_admin_url($path, $scheme); + } else { + return admin_url($path, $scheme); + } + } + + + /** + * Ser relative abs path + * + * @param string $string abs path + * + * @return void + */ + public static function setWpCoreRelativeAbsPath($string = '') + { + self::$wpCoreRelativePath = (string) $string; + } + + /** + * check if path is in wordpress core list + * PATH_FULL and PATH_RELATIVE is better optimized and perform less operations + * + * @param string $path file path + * @param int $fullPath if PATH_AUTO check if is a full path or relative path + * if PATH_FULL remove ABSPATH len without check + * if PATH_RELATIVE consider path a relative path + * @param bool $isSafe if false call rtrim(SnapIO::safePath( PATH ), '/') + * if true consider path a safe path without check + * + * + * @return boolean + */ + public static function isWpCore($path, $fullPath = self::PATH_AUTO, $isSafe = false) + { + if ($isSafe == false) { + $path = rtrim(SnapIO::safePath($path), '/'); + } + + switch ($fullPath) { + case self::PATH_FULL: + $absPath = self::getSafeAbsPath(); + if (strlen($path) < strlen($absPath)) { + return false; + } + $relPath = ltrim(substr($path, strlen($absPath)), '/'); + break; + case self::PATH_RELATIVE: + if (($relPath = SnapIO::getRelativePath($path, self::$wpCoreRelativePath)) === false) { + return false; + } + break; + case self::PATH_AUTO: + default: + $absPath = self::getSafeAbsPath(); + if (strpos($path, $absPath) === 0) { + $relPath = ltrim(substr($path, strlen($absPath)), '/'); + } else { + $relPath = ltrim($path, '/'); + } + } + + // if rel path is empty is consider root path so is a core folder. + if (strlen($relPath) === 0) { + return true; + } + + $pExploded = explode('/', $relPath); + $corePaths = self::getCorePathsList(); + + foreach ($pExploded as $current) { + if (!isset($corePaths[$current])) { + return false; + } + + if (is_scalar($corePaths[$current])) { + // is file so don't have childs + $corePaths = array(); + } else { + $corePaths = $corePaths[$current]; + } + } + return true; + } + + /** + * + * @param string $relPath // if empty is consider abs root path + * @return array // [ 'dirs' => [] , 'files' => [] ] + */ + public static function getWpCoreFilesListInFolder($relPath = '') + { + $corePaths = self::getCorePathsList(); + if (strlen($relPath) > 0) { + $pExploded = explode('/', $relPath); + foreach ($pExploded as $current) { + if (!isset($corePaths[$current])) { + $corePaths = array(); + break; + } + + if (is_scalar($corePaths[$current])) { + // is file so don't have childs + $corePaths = array(); + } else { + $corePaths = $corePaths[$current]; + } + } + } + + $result = array( + 'dirs' => array(), + 'files' => array() + ); + + foreach ($corePaths as $name => $content) { + if (is_array($content)) { + $result['dirs'][] = $name; + } else { + $result['files'][] = $name; + } + } + + return $result; + } + + /** + * get core path list from relative abs path + * [ + * 'folder' => [ + * 's-folder1' => [ + * file1 => [], + * file2 => [], + * ], + * 's-folder2' => [], + * file1 => [] + * ] + * ] + * + * @return array + */ + public static function getCorePathsList() + { + if (is_null(self::$corePathList)) { + require_once(dirname(__FILE__) . '/wordpress_core_files.php'); + } + return self::$corePathList; + } + + /** + * Returns the main site ID for the network. + * + * Copied from the source of the get_main_site_id() except first line in https://developer.wordpress.org/reference/functions/get_main_site_id/ + * get_main_site_id() is introduced in WP 4.9.0. It is for backward compatibility + * + * @param int|null $network_id network id + * + * @return int The ID of the main site. + */ + public static function getMainSiteId($network_id = null) + { + // For > WP 4.9.0 + if (function_exists('get_main_site_id')) { + return get_main_site_id($network_id); + } + + if (!is_multisite()) { + return get_current_blog_id(); + } + + $network = function_exists('get_network') ? get_network($network_id) : wp_get_network($network_id); + if (!$network) { + return 0; + } + + return $network->site_id; + } + + /** + * Return object list of sites + * + * @param string|array $args list of filters, see wordpress get_sites function + * + * @return WP_Site[]|int[] site list or ids + */ + public static function getSites($args = array()) + { + if (!function_exists('is_multisite') || !is_multisite()) { + return false; + } + + if (!isset($args['number'])) { + $args['number'] = self::DEFAULT_MAX_GET_SITES_NUMBER; + } + + if (function_exists('get_sites')) { + return get_sites($args); + } else { + $result = array(); + $blogs = wp_get_sites($args); + $returnIds = (isset($args['fields']) && $args['fields'] === 'ids'); + foreach ($blogs as $blog) { + if (is_array($blog)) { + $blog = (object) $blog; + } + $result[] = ($returnIds ? $blog->blog_id : $blog); + } + return $result; + } + } + + /** + * Return list of subiste ids + * + * @return int[] + */ + public static function getSitesIds() + { + if (!is_multisite()) { + return array(1); + } + + return SnapWP::getSites(array('fields' => 'ids')); + } + + /** + * return the list of possible dropins plugins + * + * @return string[] + */ + public static function getDropinsPluginsNames() + { + return array( + 'advanced-cache.php', // WP_CACHE + 'db.php', // auto on load + 'db-error.php', // auto on error + 'install.php', // auto on installation + 'maintenance.php', // auto on maintenance + 'object-cache.php', // auto on load + 'php-error.php', // auto on error + 'fatal-error-handler.php', // auto on error + 'sunrise.php', + 'blog-deleted.php', + 'blog-inactive.php', + 'blog-suspended.php' + ); + } + + /** + * Return site and subsite tables names without prefix + * + * @return string[] + */ + public static function getSiteCoreTables() + { + return array( + 'commentmeta', + 'comments', + 'links', + 'options', + 'postmeta', + 'posts', + 'term_relationships', + 'term_taxonomy', + 'terms', + 'termmeta' + ); + } + + /** + * Return multisite general tables without prefix + * + * @return string[] + */ + public static function getMultisiteTables() + { + return array( + 'blogmeta', + 'blogs', + 'blog_versions', + 'registration_log', + 'signups', + 'site', + 'sitemeta' + ); + } + + /** + * Returns wp option "timezone_string" + * + * @return string // timezone_string, will be empty if manual offset is chosen + */ + public static function getTimeZoneString() + { + static $timezoneString = null; + if (is_null($timezoneString)) { + $timezoneString = get_option('timezone_string'); + } + return $timezoneString; + } + + /** + * Returns 1 if DST is active on given timestamp, 0 if it's not active. + * Currently active timezone is taken into account. + * + * @param integer $timestamp In seconds + * + * @return integer // 1 if DST is active, 0 otherwise + */ + public static function getDST($timestamp) + { + $timezoneString = self::getTimeZoneString(); + if (!$timezoneString) { + // There is no DST if manual offset is chosen in WP settings timezone + return 0; + } + $date = new \DateTime(); + $date->setTimestamp($timestamp); + $date->setTimezone(new \DateTimeZone($timezoneString)); + return $date->format('I'); + } + + /** + * Converts timestamp to date string with given format, according to + * currently selected timezone in Wordpress settings + * + * @param string $format Format for date + * @param integer $timestamp In seconds + * + * @return string // Date converted to string in currently selected timezone + */ + public static function getDateInWPTimezone($format, $timestamp) + { + $timezoneString = self::getTimeZoneString(); + if ($timezoneString) { + // Particular timezone is selected, not manual offset. This means that DST could be in place, + // and we can't use current gmt_offset. We have to use the timezone! + $date = new \DateTime(); + $date->setTimestamp($timestamp); + $date->setTimezone(new \DateTimeZone($timezoneString)); + return $date->format($format); + } + // Manual offset is selected. In this case there is no DST so we can + // create the date string using current gmt_offset. + $local_time = $timestamp + ((int) get_option('gmt_offset') * 3600); + return (string) date($format, $local_time); + } + + /** + * + * @param int $blogId // f multisite and blogId > 0 return the user of blog + * @return array + */ + public static function getAdminUserLists($blogId = 0) + { + $args = array( + 'fields' => array('id', 'user_login') + ); + + if (is_multisite()) { + $args['blog_id'] = $blogId; + if ($blogId == 0) { + $args['login__in'] = get_site_option('site_admins'); + } + } else { + $args['role'] = 'administrator'; + } + + return get_users($args); + } + + /** + * Return post types count + * + * @return array + */ + public static function getPostTypesCount() + { + $postTypes = get_post_types(); + $postTypeCount = array(); + + foreach ($postTypes as $postName) { + $postObj = get_post_type_object($postName); + if (!$postObj->public) { + continue; + } + $postCountForTypes = (array) wp_count_posts($postName); + $postCount = 0; + foreach ($postCountForTypes as $num) { + $postCount += $num; + } + $postTypeCount[$postObj->label] = $postCount; + } + + return $postTypeCount; + } +} diff --git a/src/Libs/Snap/index.php b/src/Libs/Snap/index.php new file mode 100644 index 00000000..c9199655 --- /dev/null +++ b/src/Libs/Snap/index.php @@ -0,0 +1,3 @@ +>>>>> THIS FILE IS AUTOGENERATED DON'T MODIFY THIS DIRECTLY <<<<< + * >>>>>> USE THE GENERATOR SCRIPT <<<<< + * + * >>>>>> THIS FILE IS AUTOGENERATED DON'T MODIFY THIS DIRECTLY <<<<< + * >>>>>> USE THE GENERATOR SCRIPT <<<<< + * + * >>>>>> THIS FILE IS AUTOGENERATED DON'T MODIFY THIS DIRECTLY <<<<< + * >>>>>> USE THE GENERATOR SCRIPT <<<<< + * + * Core wordpress file list + * + * Standard: PSR-2 + * @link http://www.php-fig.org/psr/psr-2 + * + * @package snaplib + * @subpackage classes/utilities + * @copyright (c) 2017, Snapcreek LLC + * @license https://opensource.org/licenses/GPL-3.0 GNU Public License + * + */ + +defined('ABSPATH') || defined('DUPXABSPATH') || exit; + +/* + * >>>>>> THIS FILE IS AUTOGENERATED DON'T MODIFY THIS DIRECTLY <<<<< + * >>>>>> USE THE GENERATOR SCRIPT <<<<< + * + * >>>>>> THIS FILE IS AUTOGENERATED DON'T MODIFY THIS DIRECTLY <<<<< + * >>>>>> USE THE GENERATOR SCRIPT <<<<< + * + * >>>>>> THIS FILE IS AUTOGENERATED DON'T MODIFY THIS DIRECTLY <<<<< + * >>>>>> USE THE GENERATOR SCRIPT <<<<< + * + */ +self::$corePathList = array( + 'wp-login.php' => "f", + 'wp-config-sample.php' => "f", + 'license.txt' => "f", + 'wp-activate.php' => "f", + 'wp-comments-post.php' => "f", + 'wp-signup.php' => "f", + 'wp-mail.php' => "f", + 'wp-links-opml.php' => "f", + 'wp-load.php' => "f", + 'wp-blog-header.php' => "f", + 'readme.html' => "f", + 'wp-includes' => array( + 'category-template.php' => "f", + 'class-wp-recovery-mode-email-service.php' => "f", + 'default-constants.php' => "f", + 'class-wp-http-requests-hooks.php' => "f", + 'class-wp-block-patterns-registry.php' => "f", + 'media.php' => "f", + 'block-patterns.php' => "f", + 'functions.php' => "f", + 'ms-network.php' => "f", + 'class-requests.php' => "f", + 'cache.php' => "f", + 'class-wp-dependency.php' => "f", + 'class-wp-http-proxy.php' => "f", + 'class-phpass.php' => "f", + 'ms-settings.php' => "f", + 'class-wp-customize-manager.php' => "f", + 'class-wp-block-styles-registry.php' => "f", + 'class-wp-recovery-mode-key-service.php' => "f", + 'class-walker-category.php' => "f", + 'class-wp-metadata-lazyloader.php' => "f", + 'block-template-utils.php' => "f", + 'blocks.php' => "f", + 'l10n.php' => "f", + 'cron.php' => "f", + 'template.php' => "f", + 'class-wp-widget-factory.php' => "f", + 'class-wp-network.php' => "f", + 'https-migration.php' => "f", + 'nav-menu-template.php' => "f", + 'class-wp-matchesmapregex.php' => "f", + 'feed-rdf.php' => "f", + 'https-detection.php' => "f", + 'widgets' => array( + 'class-wp-widget-pages.php' => "f", + 'class-wp-widget-text.php' => "f", + 'class-wp-widget-custom-html.php' => "f", + 'class-wp-widget-recent-comments.php' => "f", + 'class-wp-widget-tag-cloud.php' => "f", + 'class-wp-widget-links.php' => "f", + 'class-wp-widget-block.php' => "f", + 'class-wp-widget-media-video.php' => "f", + 'class-wp-widget-archives.php' => "f", + 'class-wp-widget-search.php' => "f", + 'class-wp-widget-calendar.php' => "f", + 'class-wp-widget-meta.php' => "f", + 'class-wp-widget-media.php' => "f", + 'class-wp-nav-menu-widget.php' => "f", + 'class-wp-widget-media-audio.php' => "f", + 'class-wp-widget-recent-posts.php' => "f", + 'class-wp-widget-categories.php' => "f", + 'class-wp-widget-rss.php' => "f", + 'class-wp-widget-media-image.php' => "f", + 'class-wp-widget-media-gallery.php' => "f" + ), + 'class-wp-paused-extensions-storage.php' => "f", + 'class-walker-page-dropdown.php' => "f", + 'class-wp-text-diff-renderer-inline.php' => "f", + 'theme-compat' => array( + 'sidebar.php' => "f", + 'embed-404.php' => "f", + 'embed-content.php' => "f", + 'footer-embed.php' => "f", + 'header-embed.php' => "f", + 'header.php' => "f", + 'footer.php' => "f", + 'embed.php' => "f", + 'comments.php' => "f", + 'comments-popup.php' => "f" + ), + 'class-phpmailer.php' => "f", + 'class-wp-post-type.php' => "f", + 'block-supports' => array( + 'elements.php' => "f", + 'layout.php' => "f", + 'dimensions.php' => "f", + 'border.php' => "f", + 'duotone.php' => "f", + 'generated-classname.php' => "f", + 'align.php' => "f", + 'colors.php' => "f", + 'typography.php' => "f", + 'utils.php' => "f", + 'custom-classname.php' => "f", + 'spacing.php' => "f" + ), + 'class-wp-locale-switcher.php' => "f", + 'load.php' => "f", + 'class-wp-recovery-mode-cookie-service.php' => "f", + 'class-wp-role.php' => "f", + 'pluggable-deprecated.php' => "f", + 'class-wp-oembed-controller.php' => "f", + 'class-wp-term.php' => "f", + 'class-smtp.php' => "f", + 'capabilities.php' => "f", + 'IXR' => array( + 'class-IXR-server.php' => "f", + 'class-IXR-date.php' => "f", + 'class-IXR-request.php' => "f", + 'class-IXR-error.php' => "f", + 'class-IXR-client.php' => "f", + 'class-IXR-base64.php' => "f", + 'class-IXR-clientmulticall.php' => "f", + 'class-IXR-value.php' => "f", + 'class-IXR-message.php' => "f", + 'class-IXR-introspectionserver.php' => "f" + ), + 'class-wp-text-diff-renderer-table.php' => "f", + 'class-wp-xmlrpc-server.php' => "f", + 'class-wp-site-query.php' => "f", + 'class-wp-admin-bar.php' => "f", + 'session.php' => "f", + 'class-wp-block-type-registry.php' => "f", + 'rewrite.php' => "f", + 'registration-functions.php' => "f", + 'option.php' => "f", + 'class-walker-comment.php' => "f", + 'post-formats.php' => "f", + 'class-wp-customize-setting.php' => "f", + 'pluggable.php' => "f", + 'class-wp-block-type.php' => "f", + 'class-wp-http-response.php' => "f", + 'class-wp-error.php' => "f", + 'deprecated.php' => "f", + 'blocks' => array( + 'loginout' => array( + 'block.json' => "f" + ), + 'pullquote' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'theme-rtl.css' => "f", + 'editor-rtl.css' => "f", + 'theme-rtl.min.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'theme.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'theme.min.css' => "f", + 'style.min.css' => "f" + ), + 'site-tagline.php' => "f", + 'gallery' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'theme-rtl.css' => "f", + 'editor-rtl.css' => "f", + 'theme-rtl.min.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'theme.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'theme.min.css' => "f", + 'style.min.css' => "f" + ), + 'code' => array( + 'style-rtl.min.css' => "f", + 'theme-rtl.css' => "f", + 'theme-rtl.min.css' => "f", + 'block.json' => "f", + 'theme.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'theme.min.css' => "f", + 'style.min.css' => "f" + ), + 'more' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'post-featured-image' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'comment-content' => array( + 'style-rtl.min.css' => "f", + 'block.json' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'social-link.php' => "f", + 'pattern' => array( + 'block.json' => "f" + ), + 'query-no-results' => array( + 'block.json' => "f" + ), + 'comments-pagination-previous' => array( + 'block.json' => "f" + ), + 'post-navigation-link.php' => "f", + 'home-link.php' => "f", + 'image' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'theme-rtl.css' => "f", + 'editor-rtl.css' => "f", + 'theme-rtl.min.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'theme.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'theme.min.css' => "f", + 'style.min.css' => "f" + ), + 'post-terms.php' => "f", + 'latest-posts' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'post-date' => array( + 'block.json' => "f" + ), + 'block' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'media-text' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'site-title' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'archives.php' => "f", + 'spacer' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'comments-pagination-numbers.php' => "f", + 'post-author.php' => "f", + 'comments-title' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'buttons' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'video' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'theme-rtl.css' => "f", + 'editor-rtl.css' => "f", + 'theme-rtl.min.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'theme.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'theme.min.css' => "f", + 'style.min.css' => "f" + ), + 'cover' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'post-template' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'image.php' => "f", + 'template-part.php' => "f", + 'subhead' => array( + 'block.json' => "f" + ), + 'site-logo' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'legacy-widget' => array( + 'block.json' => "f" + ), + 'audio' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'theme-rtl.css' => "f", + 'editor-rtl.css' => "f", + 'theme-rtl.min.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'theme.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'theme.min.css' => "f", + 'style.min.css' => "f" + ), + 'comment-reply-link' => array( + 'block.json' => "f" + ), + 'comment-date' => array( + 'block.json' => "f" + ), + 'widget-group' => array( + 'block.json' => "f" + ), + 'read-more' => array( + 'style-rtl.min.css' => "f", + 'block.json' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'table' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'theme-rtl.css' => "f", + 'editor-rtl.css' => "f", + 'theme-rtl.min.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'theme.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'theme.min.css' => "f", + 'style.min.css' => "f" + ), + 'latest-comments.php' => "f", + 'query.php' => "f", + 'query-pagination' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'social-links' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'comments-pagination-previous.php' => "f", + 'button' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'navigation-submenu.php' => "f", + 'term-description' => array( + 'block.json' => "f" + ), + 'rss' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'columns' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'calendar.php' => "f", + 'calendar' => array( + 'style-rtl.min.css' => "f", + 'block.json' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'page-list' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'quote' => array( + 'style-rtl.min.css' => "f", + 'theme-rtl.css' => "f", + 'theme-rtl.min.css' => "f", + 'block.json' => "f", + 'theme.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'theme.min.css' => "f", + 'style.min.css' => "f" + ), + 'post-excerpt.php' => "f", + 'post-comments' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'comments-pagination-next.php' => "f", + 'post-navigation-link' => array( + 'block.json' => "f" + ), + 'query-title.php' => "f", + 'text-columns' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'comment-author-name.php' => "f", + 'post-content.php' => "f", + 'post-title.php' => "f", + 'post-comments.php' => "f", + 'query-pagination-numbers.php' => "f", + 'query-pagination-previous' => array( + 'block.json' => "f" + ), + 'separator' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'theme-rtl.css' => "f", + 'editor-rtl.css' => "f", + 'theme-rtl.min.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'theme.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'theme.min.css' => "f", + 'style.min.css' => "f" + ), + 'archives' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'social-link' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'avatar' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'site-title.php' => "f", + 'post-template.php' => "f", + 'comment-author-name' => array( + 'block.json' => "f" + ), + 'missing' => array( + 'block.json' => "f" + ), + 'shortcode.php' => "f", + 'verse' => array( + 'style-rtl.min.css' => "f", + 'block.json' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'categories' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'term-description.php' => "f", + 'post-title' => array( + 'style-rtl.min.css' => "f", + 'block.json' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'classic' => array( + 'block.json' => "f" + ), + 'post-terms' => array( + 'style-rtl.min.css' => "f", + 'block.json' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'post-date.php' => "f", + 'tag-cloud' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'latest-posts.php' => "f", + 'comments-query-loop' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'rss.php' => "f", + 'query-title' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'comments-pagination-numbers' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'post-author-biography' => array( + 'block.json' => "f" + ), + 'embed' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'theme-rtl.css' => "f", + 'editor-rtl.css' => "f", + 'theme-rtl.min.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'theme.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'theme.min.css' => "f", + 'style.min.css' => "f" + ), + 'post-comments-form.php' => "f", + 'shortcode' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'query-pagination-previous.php' => "f", + 'comment-edit-link' => array( + 'block.json' => "f" + ), + 'query-no-results.php' => "f", + 'comments-pagination-next' => array( + 'block.json' => "f" + ), + 'file' => array( + 'style-rtl.min.css' => "f", + 'view.min.asset.php' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'view.js' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'view.min.js' => "f", + 'editor-rtl.min.css' => "f", + 'view.asset.php' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'freeform' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'legacy-widget.php' => "f", + 'categories.php' => "f", + 'site-tagline' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'home-link' => array( + 'block.json' => "f" + ), + 'read-more.php' => "f", + 'navigation-link.php' => "f", + 'index.php' => "f", + 'comment-template' => array( + 'style-rtl.min.css' => "f", + 'block.json' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'page-list.php' => "f", + 'template-part' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'theme-rtl.css' => "f", + 'editor-rtl.css' => "f", + 'theme-rtl.min.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'theme.css' => "f", + 'theme.min.css' => "f" + ), + 'comments-pagination.php' => "f", + 'site-logo.php' => "f", + 'comment-reply-link.php' => "f", + 'search' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'theme-rtl.css' => "f", + 'editor-rtl.css' => "f", + 'theme-rtl.min.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'theme.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'theme.min.css' => "f", + 'style.min.css' => "f" + ), + 'list' => array( + 'style-rtl.min.css' => "f", + 'block.json' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'post-excerpt' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'column' => array( + 'block.json' => "f" + ), + 'group' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'theme-rtl.css' => "f", + 'editor-rtl.css' => "f", + 'theme-rtl.min.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'theme.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'theme.min.css' => "f", + 'style.min.css' => "f" + ), + 'pattern.php' => "f", + 'preformatted' => array( + 'style-rtl.min.css' => "f", + 'block.json' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'comments-pagination' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'navigation-link' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'html' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'comment-content.php' => "f", + 'nextpage' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'post-featured-image.php' => "f", + 'latest-comments' => array( + 'style-rtl.min.css' => "f", + 'block.json' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'query-pagination-next.php' => "f", + 'comment-template.php' => "f", + 'query-pagination-numbers' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'navigation-submenu' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'comment-date.php' => "f", + 'comments-title.php' => "f", + 'block.php' => "f", + 'heading' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'post-comments-form' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'cover.php' => "f", + 'widget-group.php' => "f", + 'gallery.php' => "f", + 'search.php' => "f", + 'post-content' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'tag-cloud.php' => "f", + 'avatar.php' => "f", + 'comment-edit-link.php' => "f", + 'navigation.php' => "f", + 'post-author' => array( + 'style-rtl.min.css' => "f", + 'block.json' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'file.php' => "f", + 'query-pagination.php' => "f", + 'query-pagination-next' => array( + 'block.json' => "f" + ), + 'query' => array( + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f" + ), + 'navigation' => array( + 'style-rtl.min.css' => "f", + 'view.min.asset.php' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'view.js' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'view.min.js' => "f", + 'editor-rtl.min.css' => "f", + 'view.asset.php' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'loginout.php' => "f", + 'paragraph' => array( + 'style-rtl.min.css' => "f", + 'editor.min.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'block.json' => "f", + 'editor-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'post-author-biography.php' => "f" + ), + 'default-filters.php' => "f", + 'ms-load.php' => "f", + 'class-wp-feed-cache.php' => "f", + 'plugin.php' => "f", + 'fonts' => array( + 'dashicons.svg' => "f", + 'dashicons.woff2' => "f", + 'dashicons.ttf' => "f", + 'dashicons.woff' => "f", + 'dashicons.eot' => "f" + ), + 'query.php' => "f", + 'class-pop3.php' => "f", + 'class-wp-user-request.php' => "f", + 'class-wp-user-meta-session-tokens.php' => "f", + 'class-wp-oembed.php' => "f", + 'class-wp-editor.php' => "f", + 'class-wp-image-editor-gd.php' => "f", + 'class.wp-scripts.php' => "f", + 'class-walker-nav-menu.php' => "f", + 'author-template.php' => "f", + 'ms-blogs.php' => "f", + 'class-wp-simplepie-sanitize-kses.php' => "f", + 'class-wp-walker.php' => "f", + 'taxonomy.php' => "f", + 'compat.php' => "f", + 'class-wp-block.php' => "f", + 'category.php' => "f", + 'atomlib.php' => "f", + 'class.wp-dependencies.php' => "f", + 'class-wp-recovery-mode.php' => "f", + 'Requests' => array( + 'Utility' => array( + 'CaseInsensitiveDictionary.php' => "f", + 'FilteredIterator.php' => "f" + ), + 'IDNAEncoder.php' => "f", + 'Transport' => array( + 'cURL.php' => "f", + 'fsockopen.php' => "f" + ), + 'Proxy.php' => "f", + 'IPv6.php' => "f", + 'Exception.php' => "f", + 'Hooks.php' => "f", + 'Proxy' => array( + 'HTTP.php' => "f" + ), + 'Response.php' => "f", + 'IRI.php' => "f", + 'SSL.php' => "f", + 'Auth' => array( + 'Basic.php' => "f" + ), + 'Response' => array( + 'Headers.php' => "f" + ), + 'Session.php' => "f", + 'Exception' => array( + 'Transport' => array( + 'cURL.php' => "f" + ), + 'HTTP' => array( + '431.php' => "f", + '415.php' => "f", + '428.php' => "f", + '414.php' => "f", + '408.php' => "f", + '417.php' => "f", + '502.php' => "f", + '306.php' => "f", + '412.php' => "f", + '410.php' => "f", + '416.php' => "f", + '505.php' => "f", + '401.php' => "f", + '305.php' => "f", + '404.php' => "f", + '403.php' => "f", + '411.php' => "f", + '500.php' => "f", + '429.php' => "f", + '504.php' => "f", + '402.php' => "f", + '501.php' => "f", + '405.php' => "f", + '409.php' => "f", + '406.php' => "f", + '413.php' => "f", + '304.php' => "f", + '418.php' => "f", + '511.php' => "f", + '407.php' => "f", + '503.php' => "f", + '400.php' => "f", + 'Unknown.php' => "f" + ), + 'HTTP.php' => "f", + 'Transport.php' => "f" + ), + 'Auth.php' => "f", + 'Cookie' => array( + 'Jar.php' => "f" + ), + 'Transport.php' => "f", + 'Cookie.php' => "f", + 'Hooker.php' => "f" + ), + 'robots-template.php' => "f", + 'revision.php' => "f", + 'wp-diff.php' => "f", + 'class-wp-roles.php' => "f", + 'sitemaps' => array( + 'class-wp-sitemaps-index.php' => "f", + 'class-wp-sitemaps-renderer.php' => "f", + 'class-wp-sitemaps-stylesheet.php' => "f", + 'class-wp-sitemaps-registry.php' => "f", + 'class-wp-sitemaps.php' => "f", + 'class-wp-sitemaps-provider.php' => "f", + 'providers' => array( + 'class-wp-sitemaps-posts.php' => "f", + 'class-wp-sitemaps-taxonomies.php' => "f", + 'class-wp-sitemaps-users.php' => "f" + ) + ), + 'js' => array( + 'hoverIntent.js' => "f", + 'wp-a11y.min.js' => "f", + 'media-audiovideo.js' => "f", + 'zxcvbn-async.js' => "f", + 'media-models.js' => "f", + 'twemoji.js' => "f", + 'wp-pointer.js' => "f", + 'customize-preview-nav-menus.min.js' => "f", + 'wp-pointer.min.js' => "f", + 'json2.min.js' => "f", + 'backbone.js' => "f", + 'swfupload' => array( + 'handlers.js' => "f", + 'license.txt' => "f", + 'handlers.min.js' => "f", + 'swfupload.js' => "f", + 'plugins' => array( + 'swfupload.swfobject.js' => "f", + 'swfupload.cookies.js' => "f", + 'swfupload.queue.js' => "f", + 'swfupload.speed.js' => "f" + ), + 'swfupload.swf' => "f" + ), + 'twemoji.min.js' => "f", + 'mce-view.min.js' => "f", + 'swfobject.js' => "f", + 'colorpicker.min.js' => "f", + 'wp-emoji.js' => "f", + 'customize-preview-widgets.min.js' => "f", + 'zxcvbn.min.js' => "f", + 'wp-ajax-response.js' => "f", + 'wp-util.js' => "f", + 'underscore.js' => "f", + 'wp-emoji.min.js' => "f", + 'customize-preview-nav-menus.js' => "f", + 'underscore.min.js' => "f", + 'admin-bar.min.js' => "f", + 'wp-sanitize.js' => "f", + 'imagesloaded.min.js' => "f", + 'thickbox' => array( + 'loadingAnimation.gif' => "f", + 'thickbox.css' => "f", + 'thickbox.js' => "f", + 'macFFBgHack.png' => "f" + ), + 'wplink.min.js' => "f", + 'tinymce' => array( + 'wp-mce-help.php' => "f", + 'themes' => array( + 'modern' => array( + 'theme.js' => "f", + 'theme.min.js' => "f" + ), + 'inlite' => array( + 'theme.js' => "f", + 'theme.min.js' => "f" + ) + ), + 'wp-tinymce.js' => "f", + 'langs' => array( + 'wp-langs-en.js' => "f" + ), + 'wp-tinymce.js.gz' => "f", + 'license.txt' => "f", + 'utils' => array( + 'mctabs.js' => "f", + 'form_utils.js' => "f", + 'editable_selects.js' => "f", + 'validate.js' => "f" + ), + 'plugins' => array( + 'wordpress' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'directionality' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'image' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'wpview' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'wpeditimage' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'hr' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'lists' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'wpfullscreen' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'wptextpattern' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'link' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'fullscreen' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'wpembed' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'wplink' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'wpdialogs' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'textcolor' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'wpemoji' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'colorpicker' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'paste' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'compat3x' => array( + 'css' => array( + 'dialog.css' => "f" + ), + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'charmap' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'tabfocus' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'wpgallery' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ), + 'media' => array( + 'plugin.js' => "f", + 'moxieplayer.swf' => "f", + 'plugin.min.js' => "f" + ), + 'wpautoresize' => array( + 'plugin.js' => "f", + 'plugin.min.js' => "f" + ) + ), + 'wp-tinymce.php' => "f", + 'tiny_mce_popup.js' => "f", + 'skins' => array( + 'wordpress' => array( + 'wp-content.css' => "f", + 'images' => array( + 'gallery-2x.png' => "f", + 'playlist-video.png' => "f", + 'more-2x.png' => "f", + 'pagebreak.png' => "f", + 'audio.png' => "f", + 'playlist-audio.png' => "f", + 'dashicon-no-alt.png' => "f", + 'dashicon-no.png' => "f", + 'dashicon-edit.png' => "f", + 'embedded.png' => "f", + 'video.png' => "f", + 'pagebreak-2x.png' => "f", + 'gallery.png' => "f", + 'more.png' => "f" + ) + ), + 'lightgray' => array( + 'content.inline.min.css' => "f", + 'content.min.css' => "f", + 'skin.ie7.min.css' => "f", + 'fonts' => array( + 'tinymce-small.json' => "f", + 'tinymce.ttf' => "f", + 'tinymce-small.svg' => "f", + 'tinymce-small.woff' => "f", + 'tinymce.json' => "f", + 'readme.md' => "f", + 'tinymce.svg' => "f", + 'tinymce.woff' => "f", + 'tinymce-small.ttf' => "f", + 'tinymce-small.eot' => "f", + 'tinymce.eot' => "f" + ), + 'img' => array( + 'loader.gif' => "f", + 'object.gif' => "f", + 'trans.gif' => "f", + 'anchor.gif' => "f" + ), + 'skin.min.css' => "f" + ) + ), + 'tinymce.min.js' => "f" + ), + 'wp-emoji-release.min.js' => "f", + 'wp-emoji-loader.min.js' => "f", + 'wp-list-revisions.min.js' => "f", + 'wp-auth-check.js' => "f", + 'api-request.min.js' => "f", + 'customize-models.js' => "f", + 'clipboard.min.js' => "f", + 'customize-preview.min.js' => "f", + 'quicktags.js' => "f", + 'wp-list-revisions.js' => "f", + 'customize-models.min.js' => "f", + 'wp-util.min.js' => "f", + 'customize-preview-widgets.js' => "f", + 'admin-bar.js' => "f", + 'wpdialog.min.js' => "f", + 'wp-lists.min.js' => "f", + 'wp-emoji-loader.js' => "f", + 'clipboard.js' => "f", + 'autosave.min.js' => "f", + 'quicktags.min.js' => "f", + 'customize-selective-refresh.js' => "f", + 'jcrop' => array( + 'Jcrop.gif' => "f", + 'jquery.Jcrop.min.js' => "f", + 'jquery.Jcrop.min.css' => "f" + ), + 'wp-backbone.js' => "f", + 'media-editor.js' => "f", + 'media-editor.min.js' => "f", + 'plupload' => array( + 'handlers.js' => "f", + 'moxie.js' => "f", + 'moxie.min.js' => "f", + 'license.txt' => "f", + 'plupload.flash.swf' => "f", + 'wp-plupload.min.js' => "f", + 'handlers.min.js' => "f", + 'plupload.full.min.js' => "f", + 'wp-plupload.js' => "f", + 'plupload.silverlight.xap' => "f", + 'plupload.js' => "f", + 'plupload.min.js' => "f" + ), + 'media-grid.js' => "f", + 'hoverintent-js.min.js' => "f", + 'media-views.min.js' => "f", + 'wp-embed.js' => "f", + 'heartbeat.min.js' => "f", + 'wp-api.min.js' => "f", + 'customize-views.js' => "f", + 'customize-loader.js' => "f", + 'autosave.js' => "f", + 'crop' => array( + 'cropper.js' => "f", + 'cropper.css' => "f", + 'marqueeHoriz.gif' => "f", + 'marqueeVert.gif' => "f" + ), + 'wp-auth-check.min.js' => "f", + 'jquery' => array( + 'jquery.js' => "f", + 'jquery.form.min.js' => "f", + 'jquery.ui.touch-punch.js' => "f", + 'jquery.table-hotkeys.js' => "f", + 'jquery.query.js' => "f", + 'jquery.hotkeys.min.js' => "f", + 'jquery-migrate.min.js' => "f", + 'jquery.schedule.js' => "f", + 'jquery.hotkeys.js' => "f", + 'suggest.js' => "f", + 'jquery-migrate.js' => "f", + 'jquery.form.js' => "f", + 'jquery.min.js' => "f", + 'ui' => array( + 'effect-bounce.js' => "f", + 'jquery.ui.dialog.min.js' => "f", + 'jquery.ui.menu.min.js' => "f", + 'autocomplete.js' => "f", + 'spinner.js' => "f", + 'progressbar.min.js' => "f", + 'jquery.ui.core.min.js' => "f", + 'datepicker.js' => "f", + 'spinner.min.js' => "f", + 'dialog.min.js' => "f", + 'effect-pulsate.js' => "f", + 'jquery.ui.position.min.js' => "f", + 'jquery.ui.effect-drop.min.js' => "f", + 'checkboxradio.js' => "f", + 'slider.js' => "f", + 'accordion.min.js' => "f", + 'effect-clip.min.js' => "f", + 'controlgroup.min.js' => "f", + 'jquery.ui.sortable.min.js' => "f", + 'jquery.ui.effect.min.js' => "f", + 'effect-explode.min.js' => "f", + 'jquery.ui.effect-transfer.min.js' => "f", + 'dialog.js' => "f", + 'jquery.ui.draggable.min.js' => "f", + 'draggable.min.js' => "f", + 'effect-fold.min.js' => "f", + 'jquery.ui.spinner.min.js' => "f", + 'accordion.js' => "f", + 'effect-fade.min.js' => "f", + 'effect-size.js' => "f", + 'droppable.min.js' => "f", + 'resizable.js' => "f", + 'effect-explode.js' => "f", + 'effect.js' => "f", + 'effect-fade.js' => "f", + 'effect.min.js' => "f", + 'effect-drop.min.js' => "f", + 'jquery.ui.effect-slide.min.js' => "f", + 'selectable.min.js' => "f", + 'effect-transfer.js' => "f", + 'tooltip.min.js' => "f", + 'effect-shake.js' => "f", + 'selectmenu.js' => "f", + 'effect-shake.min.js' => "f", + 'droppable.js' => "f", + 'effect-highlight.min.js' => "f", + 'jquery.ui.datepicker.min.js' => "f", + 'effect-drop.js' => "f", + 'effect-blind.min.js' => "f", + 'button.js' => "f", + 'effect-slide.js' => "f", + 'core.js' => "f", + 'effect-highlight.js' => "f", + 'sortable.min.js' => "f", + 'position.min.js' => "f", + 'effect-fold.js' => "f", + 'jquery.ui.effect-pulsate.min.js' => "f", + 'jquery.ui.mouse.min.js' => "f", + 'jquery.ui.effect-explode.min.js' => "f", + 'jquery.ui.autocomplete.min.js' => "f", + 'effect-size.min.js' => "f", + 'jquery.ui.effect-bounce.min.js' => "f", + 'tabs.js' => "f", + 'core.min.js' => "f", + 'jquery.ui.progressbar.min.js' => "f", + 'effect-clip.js' => "f", + 'effect-puff.min.js' => "f", + 'jquery.ui.selectable.min.js' => "f", + 'checkboxradio.min.js' => "f", + 'effect-transfer.min.js' => "f", + 'menu.min.js' => "f", + 'jquery.ui.tabs.min.js' => "f", + 'resizable.min.js' => "f", + 'effect-scale.js' => "f", + 'jquery.ui.effect-highlight.min.js' => "f", + 'jquery.ui.tooltip.min.js' => "f", + 'jquery.ui.droppable.min.js' => "f", + 'mouse.min.js' => "f", + 'jquery.ui.effect-fade.min.js' => "f", + 'controlgroup.js' => "f", + 'menu.js' => "f", + 'jquery.ui.effect-clip.min.js' => "f", + 'jquery.ui.accordion.min.js' => "f", + 'jquery.ui.resizable.min.js' => "f", + 'effect-pulsate.min.js' => "f", + 'effect-bounce.min.js' => "f", + 'widget.min.js' => "f", + 'jquery.ui.effect-blind.min.js' => "f", + 'tabs.min.js' => "f", + 'datepicker.min.js' => "f", + 'button.min.js' => "f", + 'selectmenu.min.js' => "f", + 'effect-blind.js' => "f", + 'jquery.ui.effect-shake.min.js' => "f", + 'slider.min.js' => "f", + 'effect-scale.min.js' => "f", + 'draggable.js' => "f", + 'jquery.ui.slider.min.js' => "f", + 'mouse.js' => "f", + 'progressbar.js' => "f", + 'jquery.ui.effect-scale.min.js' => "f", + 'sortable.js' => "f", + 'jquery.ui.button.min.js' => "f", + 'tooltip.js' => "f", + 'effect-slide.min.js' => "f", + 'jquery.ui.widget.min.js' => "f", + 'effect-puff.js' => "f", + 'autocomplete.min.js' => "f", + 'selectable.js' => "f", + 'jquery.ui.effect-fold.min.js' => "f" + ), + 'jquery.table-hotkeys.min.js' => "f", + 'suggest.min.js' => "f", + 'jquery.serialize-object.js' => "f", + 'jquery.masonry.min.js' => "f", + 'jquery.color.min.js' => "f" + ), + 'wpdialog.js' => "f", + 'shortcode.js' => "f", + 'colorpicker.js' => "f", + 'tw-sack.min.js' => "f", + 'heartbeat.js' => "f", + 'wp-api.js' => "f", + 'customize-base.js' => "f", + 'media-models.min.js' => "f", + 'wp-custom-header.js' => "f", + 'media-audiovideo.min.js' => "f", + 'mce-view.js' => "f", + 'media-views.js' => "f", + 'wp-embed-template.js' => "f", + 'hoverIntent.min.js' => "f", + 'wp-embed.min.js' => "f", + 'utils.min.js' => "f", + 'customize-views.min.js' => "f", + 'customize-base.min.js' => "f", + 'customize-selective-refresh.min.js' => "f", + 'wp-ajax-response.min.js' => "f", + 'zxcvbn-async.min.js' => "f", + 'wp-lists.js' => "f", + 'comment-reply.min.js' => "f", + 'wp-embed-template.min.js' => "f", + 'wp-backbone.min.js' => "f", + 'wp-a11y.js' => "f", + 'backbone.min.js' => "f", + 'dist' => array( + 'api-fetch.js' => "f", + 'notices.min.js' => "f", + 'edit-site.js' => "f", + 'data-controls.min.js' => "f", + 'wordcount.min.js' => "f", + 'edit-widgets.min.js' => "f", + 'editor.min.js' => "f", + 'rich-text.js' => "f", + 'dom.js' => "f", + 'element.js' => "f", + 'widgets.js' => "f", + 'widgets.min.js' => "f", + 'blocks.min.js' => "f", + 'components.min.js' => "f", + 'edit-widgets.js' => "f", + 'editor.js' => "f", + 'blob.min.js' => "f", + 'components.js' => "f", + 'url.js' => "f", + 'i18n.min.js' => "f", + 'data-controls.js' => "f", + 'deprecated.js' => "f", + 'priority-queue.js' => "f", + 'token-list.min.js' => "f", + 'reusable-blocks.js' => "f", + 'dom-ready.js' => "f", + 'a11y.min.js' => "f", + 'element.min.js' => "f", + 'keycodes.js' => "f", + 'list-reusable-blocks.js' => "f", + 'autop.js' => "f", + 'warning.js' => "f", + 'escape-html.js' => "f", + 'blob.js' => "f", + 'block-directory.min.js' => "f", + 'dom-ready.min.js' => "f", + 'annotations.js' => "f", + 'viewport.js' => "f", + 'edit-site.min.js' => "f", + 'viewport.min.js' => "f", + 'server-side-render.js' => "f", + 'autop.min.js' => "f", + 'compose.js' => "f", + 'plugins.js' => "f", + 'block-directory.js' => "f", + 'primitives.js' => "f", + 'block-editor.min.js' => "f", + 'primitives.min.js' => "f", + 'keyboard-shortcuts.js' => "f", + 'html-entities.min.js' => "f", + 'notices.js' => "f", + 'wordcount.js' => "f", + 'core-data.js' => "f", + 'customize-widgets.min.js' => "f", + 'compose.min.js' => "f", + 'warning.min.js' => "f", + 'url.min.js' => "f", + 'block-serialization-default-parser.js' => "f", + 'data.min.js' => "f", + 'edit-post.js' => "f", + 'server-side-render.min.js' => "f", + 'redux-routine.min.js' => "f", + 'i18n.js' => "f", + 'redux-routine.js' => "f", + 'escape-html.min.js' => "f", + 'edit-post.min.js' => "f", + 'shortcode.js' => "f", + 'token-list.js' => "f", + 'preferences.js' => "f", + 'date.min.js' => "f", + 'hooks.min.js' => "f", + 'html-entities.js' => "f", + 'core-data.min.js' => "f", + 'keycodes.min.js' => "f", + 'priority-queue.min.js' => "f", + 'blocks.js' => "f", + 'format-library.min.js' => "f", + 'development' => array( + 'react-refresh-runtime.js' => "f", + 'react-refresh-entry.min.js' => "f", + 'react-refresh-runtime.min.js' => "f", + 'react-refresh-entry.js' => "f" + ), + 'is-shallow-equal.min.js' => "f", + 'date.js' => "f", + 'list-reusable-blocks.min.js' => "f", + 'block-library.js' => "f", + 'plugins.min.js' => "f", + 'nux.min.js' => "f", + 'media-utils.js' => "f", + 'is-shallow-equal.js' => "f", + 'media-utils.min.js' => "f", + 'dom.min.js' => "f", + 'customize-widgets.js' => "f", + 'vendor' => array( + 'moment.min.js' => "f", + 'wp-polyfill-element-closest.min.js' => "f", + 'wp-polyfill-fetch.js' => "f", + 'wp-polyfill-node-contains.js' => "f", + 'moment.js' => "f", + 'regenerator-runtime.min.js' => "f", + 'wp-polyfill-object-fit.min.js' => "f", + 'wp-polyfill-url.js' => "f", + 'react.js' => "f", + 'wp-polyfill.min.js' => "f", + 'wp-polyfill-formdata.js' => "f", + 'wp-polyfill-element-closest.js' => "f", + 'wp-polyfill-dom-rect.min.js' => "f", + 'react.min.js' => "f", + 'wp-polyfill-dom-rect.js' => "f", + 'lodash.min.js' => "f", + 'wp-polyfill-fetch.min.js' => "f", + 'wp-polyfill-object-fit.js' => "f", + 'react-dom.min.js' => "f", + 'wp-polyfill-formdata.min.js' => "f", + 'wp-polyfill-node-contains.min.js' => "f", + 'react-dom.js' => "f", + 'regenerator-runtime.js' => "f", + 'wp-polyfill-url.min.js' => "f", + 'wp-polyfill.js' => "f", + 'lodash.js' => "f" + ), + 'annotations.min.js' => "f", + 'block-editor.js' => "f", + 'data.js' => "f", + 'rich-text.min.js' => "f", + 'hooks.js' => "f", + 'api-fetch.min.js' => "f", + 'a11y.js' => "f", + 'block-serialization-default-parser.min.js' => "f", + 'shortcode.min.js' => "f", + 'format-library.js' => "f", + 'block-library.min.js' => "f", + 'deprecated.min.js' => "f", + 'nux.js' => "f", + 'keyboard-shortcuts.min.js' => "f", + 'preferences.min.js' => "f", + 'reusable-blocks.min.js' => "f" + ), + 'api-request.js' => "f", + 'customize-loader.min.js' => "f", + 'imgareaselect' => array( + 'jquery.imgareaselect.js' => "f", + 'jquery.imgareaselect.min.js' => "f", + 'border-anim-v.gif' => "f", + 'border-anim-h.gif' => "f", + 'imgareaselect.css' => "f" + ), + 'customize-preview.js' => "f", + 'utils.js' => "f", + 'wplink.js' => "f", + 'comment-reply.js' => "f", + 'mediaelement' => array( + 'controls.png' => "f", + 'mediaelement-migrate.js' => "f", + 'renderers' => array( + 'vimeo.js' => "f", + 'vimeo.min.js' => "f" + ), + 'mediaelement-migrate.min.js' => "f", + 'mediaelementplayer-legacy.min.css' => "f", + 'jumpforward.png' => "f", + 'skipback.png' => "f", + 'wp-mediaelement.css' => "f", + 'background.png' => "f", + 'mediaelement-and-player.min.js' => "f", + 'mediaelement.min.js' => "f", + 'mejs-controls.svg' => "f", + 'mediaelementplayer.min.css' => "f", + 'bigplay.png' => "f", + 'controls.svg' => "f", + 'wp-mediaelement.js' => "f", + 'mediaelement.js' => "f", + 'mediaelementplayer-legacy.css' => "f", + 'mejs-controls.png' => "f", + 'mediaelement-and-player.js' => "f", + 'wp-mediaelement.min.js' => "f", + 'wp-playlist.js' => "f", + 'bigplay.svg' => "f", + 'wp-mediaelement.min.css' => "f", + 'mediaelementplayer.css' => "f", + 'wp-playlist.min.js' => "f", + 'loading.gif' => "f", + 'froogaloop.min.js' => "f" + ), + 'media-grid.min.js' => "f", + 'wp-custom-header.min.js' => "f", + 'masonry.min.js' => "f", + 'shortcode.min.js' => "f", + 'wp-sanitize.min.js' => "f", + 'tw-sack.js' => "f", + 'json2.js' => "f", + 'codemirror' => array( + 'esprima.js' => "f", + 'htmlhint-kses.js' => "f", + 'csslint.js' => "f", + 'jsonlint.js' => "f", + 'codemirror.min.css' => "f", + 'codemirror.min.js' => "f", + 'fakejshint.js' => "f", + 'htmlhint.js' => "f", + 'jshint.js' => "f" + ) + ), + 'css' => array( + 'wp-embed-template.min.css' => "f", + 'admin-bar-rtl.css' => "f", + 'wp-auth-check.min.css' => "f", + 'buttons.min.css' => "f", + 'wp-embed-template-ie.min.css' => "f", + 'dashicons.css' => "f", + 'buttons.css' => "f", + 'editor.min.css' => "f", + 'buttons-rtl.css' => "f", + 'jquery-ui-dialog.css' => "f", + 'dashicons.min.css' => "f", + 'jquery-ui-dialog-rtl.min.css' => "f", + 'wp-embed-template-ie.css' => "f", + 'customize-preview.css' => "f", + 'editor.css' => "f", + 'editor-rtl.css' => "f", + 'admin-bar.min.css' => "f", + 'wp-auth-check-rtl.min.css' => "f", + 'admin-bar-rtl.min.css' => "f", + 'wp-pointer.min.css' => "f", + 'wp-pointer-rtl.css' => "f", + 'admin-bar.css' => "f", + 'customize-preview-rtl.min.css' => "f", + 'jquery-ui-dialog.min.css' => "f", + 'wp-pointer-rtl.min.css' => "f", + 'wp-pointer.css' => "f", + 'editor-rtl.min.css' => "f", + 'media-views.min.css' => "f", + 'customize-preview-rtl.css' => "f", + 'media-views-rtl.min.css' => "f", + 'buttons-rtl.min.css' => "f", + 'jquery-ui-dialog-rtl.css' => "f", + 'wp-embed-template.css' => "f", + 'dist' => array( + 'widgets' => array( + 'style-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'customize-widgets' => array( + 'style-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'list-reusable-blocks' => array( + 'style-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'reusable-blocks' => array( + 'style-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'format-library' => array( + 'style-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'nux' => array( + 'style-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'edit-post' => array( + 'style-rtl.min.css' => "f", + 'classic-rtl.min.css' => "f", + 'classic.min.css' => "f", + 'style.css' => "f", + 'classic-rtl.css' => "f", + 'style-rtl.css' => "f", + 'classic.css' => "f", + 'style.min.css' => "f" + ), + 'block-directory' => array( + 'style-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'editor' => array( + 'style-rtl.min.css' => "f", + 'editor-styles-rtl.css' => "f", + 'editor-styles-rtl.min.css' => "f", + 'editor-styles.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'editor-styles.css' => "f", + 'style.min.css' => "f" + ), + 'edit-site' => array( + 'style-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'block-library' => array( + 'style-rtl.min.css' => "f", + 'reset.min.css' => "f", + 'editor.min.css' => "f", + 'common.min.css' => "f", + 'editor.css' => "f", + 'theme-rtl.css' => "f", + 'editor-rtl.css' => "f", + 'common-rtl.min.css' => "f", + 'theme-rtl.min.css' => "f", + 'reset-rtl.min.css' => "f", + 'reset-rtl.css' => "f", + 'editor-rtl.min.css' => "f", + 'theme.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'common.css' => "f", + 'common-rtl.css' => "f", + 'theme.min.css' => "f", + 'reset.css' => "f", + 'style.min.css' => "f" + ), + 'edit-widgets' => array( + 'style-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ), + 'block-editor' => array( + 'style-rtl.min.css' => "f", + 'default-editor-styles-rtl.css' => "f", + 'default-editor-styles.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'default-editor-styles.min.css' => "f", + 'style.min.css' => "f", + 'default-editor-styles-rtl.min.css' => "f" + ), + 'components' => array( + 'style-rtl.min.css' => "f", + 'style.css' => "f", + 'style-rtl.css' => "f", + 'style.min.css' => "f" + ) + ), + 'media-views-rtl.css' => "f", + 'customize-preview.min.css' => "f", + 'wp-auth-check.css' => "f", + 'media-views.css' => "f", + 'wp-auth-check-rtl.css' => "f" + ), + 'bookmark-template.php' => "f", + 'rest-api.php' => "f", + 'theme-templates.php' => "f", + 'class-http.php' => "f", + 'php-compat' => array( + 'readonly.php' => "f" + ), + 'post-template.php' => "f", + 'user.php' => "f", + 'class-wp-comment.php' => "f", + 'class-wp-customize-section.php' => "f", + 'registration.php' => "f", + 'Text' => array( + 'Diff.php' => "f", + 'Diff' => array( + 'Engine' => array( + 'string.php' => "f", + 'xdiff.php' => "f", + 'native.php' => "f", + 'shell.php' => "f" + ), + 'Renderer.php' => "f", + 'Renderer' => array( + 'inline.php' => "f" + ) + ) + ), + 'class-json.php' => "f", + 'shortcodes.php' => "f", + 'class-wp-theme-json-schema.php' => "f", + 'vars.php' => "f", + 'spl-autoload-compat.php' => "f", + 'template-canvas.php' => "f", + 'class-wp-taxonomy.php' => "f", + 'class-wp-site.php' => "f", + 'post.php' => "f", + 'version.php' => "f", + 'ms-files.php' => "f", + 'block-i18n.json' => "f", + 'certificates' => array( + 'ca-bundle.crt' => "f" + ), + 'admin-bar.php' => "f", + 'class-wp-meta-query.php' => "f", + 'link-template.php' => "f", + 'class-snoopy.php' => "f", + 'class-wp-image-editor.php' => "f", + 'class-wp-widget.php' => "f", + 'feed-atom-comments.php' => "f", + 'class-wp-http-streams.php' => "f", + 'functions.wp-scripts.php' => "f", + 'rss.php' => "f", + 'PHPMailer' => array( + 'PHPMailer.php' => "f", + 'Exception.php' => "f", + 'SMTP.php' => "f" + ), + 'class-wp-feed-cache-transient.php' => "f", + 'class-wp-user.php' => "f", + 'post-thumbnail-template.php' => "f", + 'class-wp-recovery-mode-link-service.php' => "f", + 'class-IXR.php' => "f", + 'general-template.php' => "f", + 'ms-site.php' => "f", + 'wlwmanifest.xml' => "f", + 'class-wp-session-tokens.php' => "f", + 'rest-api' => array( + 'class-wp-rest-response.php' => "f", + 'fields' => array( + 'class-wp-rest-term-meta-fields.php' => "f", + 'class-wp-rest-post-meta-fields.php' => "f", + 'class-wp-rest-meta-fields.php' => "f", + 'class-wp-rest-user-meta-fields.php' => "f", + 'class-wp-rest-comment-meta-fields.php' => "f" + ), + 'endpoints' => array( + 'class-wp-rest-edit-site-export-controller.php' => "f", + 'class-wp-rest-block-patterns-controller.php' => "f", + 'class-wp-rest-menu-locations-controller.php' => "f", + 'class-wp-rest-block-renderer-controller.php' => "f", + 'class-wp-rest-block-types-controller.php' => "f", + 'class-wp-rest-taxonomies-controller.php' => "f", + 'class-wp-rest-search-controller.php' => "f", + 'class-wp-rest-terms-controller.php' => "f", + 'class-wp-rest-url-details-controller.php' => "f", + 'class-wp-rest-widget-types-controller.php' => "f", + 'class-wp-rest-autosaves-controller.php' => "f", + 'class-wp-rest-posts-controller.php' => "f", + 'class-wp-rest-blocks-controller.php' => "f", + 'class-wp-rest-block-directory-controller.php' => "f", + 'class-wp-rest-settings-controller.php' => "f", + 'class-wp-rest-pattern-directory-controller.php' => "f", + 'class-wp-rest-block-pattern-categories-controller.php' => "f", + 'class-wp-rest-widgets-controller.php' => "f", + 'class-wp-rest-menu-items-controller.php' => "f", + 'class-wp-rest-post-statuses-controller.php' => "f", + 'class-wp-rest-templates-controller.php' => "f", + 'class-wp-rest-post-types-controller.php' => "f", + 'class-wp-rest-comments-controller.php' => "f", + 'class-wp-rest-themes-controller.php' => "f", + 'class-wp-rest-global-styles-controller.php' => "f", + 'class-wp-rest-application-passwords-controller.php' => "f", + 'class-wp-rest-plugins-controller.php' => "f", + 'class-wp-rest-attachments-controller.php' => "f", + 'class-wp-rest-revisions-controller.php' => "f", + 'class-wp-rest-sidebars-controller.php' => "f", + 'class-wp-rest-menus-controller.php' => "f", + 'class-wp-rest-site-health-controller.php' => "f", + 'class-wp-rest-users-controller.php' => "f", + 'class-wp-rest-controller.php' => "f" + ), + 'search' => array( + 'class-wp-rest-search-handler.php' => "f", + 'class-wp-rest-post-search-handler.php' => "f", + 'class-wp-rest-post-format-search-handler.php' => "f", + 'class-wp-rest-term-search-handler.php' => "f" + ), + 'class-wp-rest-server.php' => "f", + 'class-wp-rest-request.php' => "f" + ), + 'media-template.php' => "f", + 'class-wp.php' => "f", + 'images' => array( + 'blank.gif' => "f", + 'wpicons-2x.png' => "f", + 'toggle-arrow.png' => "f", + 'rss.png' => "f", + 'w-logo-blue-white-bg.png' => "f", + 'xit-2x.gif' => "f", + 'uploader-icons-2x.png' => "f", + 'wlw' => array( + 'wp-comments.png' => "f", + 'wp-watermark.png' => "f", + 'wp-icon.png' => "f" + ), + 'arrow-pointer-blue.png' => "f", + 'down_arrow.gif' => "f", + 'admin-bar-sprite-2x.png' => "f", + 'crystal' => array( + 'document.png' => "f", + 'audio.png' => "f", + 'license.txt' => "f", + 'default.png' => "f", + 'text.png' => "f", + 'interactive.png' => "f", + 'spreadsheet.png' => "f", + 'archive.png' => "f", + 'video.png' => "f", + 'code.png' => "f" + ), + 'uploader-icons.png' => "f", + 'w-logo-blue.png' => "f", + 'down_arrow-2x.gif' => "f", + 'xit.gif' => "f", + 'wpspin-2x.gif' => "f", + 'wpicons.png' => "f", + 'arrow-pointer-blue-2x.png' => "f", + 'toggle-arrow-2x.png' => "f", + 'rss-2x.png' => "f", + 'media' => array( + 'document.png' => "f", + 'audio.png' => "f", + 'default.png' => "f", + 'text.png' => "f", + 'interactive.png' => "f", + 'spreadsheet.png' => "f", + 'archive.png' => "f", + 'video.png' => "f", + 'code.png' => "f" + ), + 'spinner-2x.gif' => "f", + 'smilies' => array( + 'icon_sad.gif' => "f", + 'icon_question.gif' => "f", + 'mrgreen.png' => "f", + 'icon_mrgreen.gif' => "f", + 'icon_surprised.gif' => "f", + 'frownie.png' => "f", + 'icon_razz.gif' => "f", + 'simple-smile.png' => "f", + 'icon_neutral.gif' => "f", + 'icon_eek.gif' => "f", + 'icon_confused.gif' => "f", + 'icon_biggrin.gif' => "f", + 'icon_exclaim.gif' => "f", + 'icon_idea.gif' => "f", + 'icon_mad.gif' => "f", + 'icon_cool.gif' => "f", + 'icon_rolleyes.gif' => "f", + 'rolleyes.png' => "f", + 'icon_redface.gif' => "f", + 'icon_wink.gif' => "f", + 'icon_lol.gif' => "f", + 'icon_arrow.gif' => "f", + 'icon_evil.gif' => "f", + 'icon_cry.gif' => "f", + 'icon_smile.gif' => "f", + 'icon_twisted.gif' => "f" + ), + 'spinner.gif' => "f", + 'admin-bar-sprite.png' => "f", + 'icon-pointer-flag.png' => "f", + 'icon-pointer-flag-2x.png' => "f", + 'wpspin.gif' => "f" + ), + 'template-loader.php' => "f", + 'class-wp-embed.php' => "f", + 'rss-functions.php' => "f", + 'class-wp-http-requests-response.php' => "f", + 'class-wp-ajax-response.php' => "f", + 'date.php' => "f", + 'class-wp-simplepie-file.php' => "f", + 'class-wp-theme-json-resolver.php' => "f", + 'meta.php' => "f", + 'kses.php' => "f", + 'class-wp-tax-query.php' => "f", + 'class-wp-network-query.php' => "f", + 'class-wp-hook.php' => "f", + 'ms-deprecated.php' => "f", + 'class-walker-category-dropdown.php' => "f", + 'class-wp-rewrite.php' => "f", + 'class-simplepie.php' => "f", + 'class.wp-styles.php' => "f", + 'class-wp-block-supports.php' => "f", + 'comment.php' => "f", + 'sitemaps.php' => "f", + 'block-editor.php' => "f", + 'pomo' => array( + 'entry.php' => "f", + 'mo.php' => "f", + 'translations.php' => "f", + 'streams.php' => "f", + 'po.php' => "f", + 'plural-forms.php' => "f" + ), + 'class-wp-customize-panel.php' => "f", + 'class-wp-http-cookie.php' => "f", + 'ms-default-filters.php' => "f", + 'class-walker-page.php' => "f", + 'bookmark.php' => "f", + 'customize' => array( + 'class-wp-customize-background-image-setting.php' => "f", + 'class-wp-customize-nav-menu-setting.php' => "f", + 'class-wp-customize-filter-setting.php' => "f", + 'class-wp-customize-date-time-control.php' => "f", + 'class-wp-customize-header-image-control.php' => "f", + 'class-wp-customize-nav-menus-panel.php' => "f", + 'class-wp-customize-nav-menu-item-control.php' => "f", + 'class-wp-customize-nav-menu-control.php' => "f", + 'class-wp-customize-custom-css-setting.php' => "f", + 'class-wp-widget-form-customize-control.php' => "f", + 'class-wp-customize-code-editor-control.php' => "f", + 'class-wp-widget-area-customize-control.php' => "f", + 'class-wp-customize-new-menu-control.php' => "f", + 'class-wp-customize-theme-control.php' => "f", + 'class-wp-customize-new-menu-section.php' => "f", + 'class-wp-customize-site-icon-control.php' => "f", + 'class-wp-customize-cropped-image-control.php' => "f", + 'class-wp-customize-upload-control.php' => "f", + 'class-wp-customize-image-control.php' => "f", + 'class-wp-customize-nav-menu-section.php' => "f", + 'class-wp-sidebar-block-editor-control.php' => "f", + 'class-wp-customize-background-image-control.php' => "f", + 'class-wp-customize-header-image-setting.php' => "f", + 'class-wp-customize-nav-menu-location-control.php' => "f", + 'class-wp-customize-partial.php' => "f", + 'class-wp-customize-nav-menu-auto-add-control.php' => "f", + 'class-wp-customize-sidebar-section.php' => "f", + 'class-wp-customize-themes-section.php' => "f", + 'class-wp-customize-themes-panel.php' => "f", + 'class-wp-customize-nav-menu-item-setting.php' => "f", + 'class-wp-customize-nav-menu-name-control.php' => "f", + 'class-wp-customize-nav-menu-locations-control.php' => "f", + 'class-wp-customize-background-position-control.php' => "f", + 'class-wp-customize-color-control.php' => "f", + 'class-wp-customize-media-control.php' => "f", + 'class-wp-customize-selective-refresh.php' => "f" + ), + 'class-wp-customize-control.php' => "f", + 'class-wp-locale.php' => "f", + 'theme.php' => "f", + 'class-wp-user-query.php' => "f", + 'class-wp-http-ixr-client.php' => "f", + 'ms-functions.php' => "f", + 'SimplePie' => array( + 'Locator.php' => "f", + 'Author.php' => "f", + 'Sanitize.php' => "f", + 'Registry.php' => "f", + 'Caption.php' => "f", + 'HTTP' => array( + 'Parser.php' => "f" + ), + 'Item.php' => "f", + 'Exception.php' => "f", + 'File.php' => "f", + 'Rating.php' => "f", + 'Restriction.php' => "f", + 'IRI.php' => "f", + 'Parser.php' => "f", + 'Enclosure.php' => "f", + 'Cache.php' => "f", + 'XML' => array( + 'Declaration' => array( + 'Parser.php' => "f" + ) + ), + 'Decode' => array( + 'HTML' => array( + 'Entities.php' => "f" + ) + ), + 'Misc.php' => "f", + 'Copyright.php' => "f", + 'Parse' => array( + 'Date.php' => "f" + ), + 'Content' => array( + 'Type' => array( + 'Sniffer.php' => "f" + ) + ), + 'Source.php' => "f", + 'Net' => array( + 'IPv6.php' => "f" + ), + 'Credit.php' => "f", + 'Cache' => array( + 'DB.php' => "f", + 'Memcache.php' => "f", + 'MySQL.php' => "f", + 'Redis.php' => "f", + 'File.php' => "f", + 'Base.php' => "f", + 'Memcached.php' => "f" + ), + 'Core.php' => "f", + 'gzdecode.php' => "f", + 'Category.php' => "f" + ), + 'class-oembed.php' => "f", + 'class-wp-object-cache.php' => "f", + 'assets' => array( + 'script-loader-react-refresh-runtime.php' => "f", + 'script-loader-packages.php' => "f", + 'script-loader-react-refresh-entry.php' => "f" + ), + 'class-feed.php' => "f", + 'class-wp-term-query.php' => "f", + 'class-wp-application-passwords.php' => "f", + 'class-wp-fatal-error-handler.php' => "f", + 'ms-default-constants.php' => "f", + 'feed-rss2.php' => "f", + 'locale.php' => "f", + 'class-wp-list-util.php' => "f", + 'embed.php' => "f", + 'class-wp-customize-widgets.php' => "f", + 'class-wp-block-template.php' => "f", + 'feed-rss2-comments.php' => "f", + 'default-widgets.php' => "f", + 'class-wp-http.php' => "f", + 'class-wp-block-parser.php' => "f", + 'error-protection.php' => "f", + 'ID3' => array( + 'getid3.lib.php' => "f", + 'module.tag.lyrics3.php' => "f", + 'license.commercial.txt' => "f", + 'module.audio.dts.php' => "f", + 'license.txt' => "f", + 'getid3.php' => "f", + 'module.audio.ac3.php' => "f", + 'module.audio.flac.php' => "f", + 'module.tag.apetag.php' => "f", + 'module.audio-video.matroska.php' => "f", + 'module.audio-video.quicktime.php' => "f", + 'module.audio.ogg.php' => "f", + 'module.audio.mp3.php' => "f", + 'module.audio-video.flv.php' => "f", + 'readme.txt' => "f", + 'module.tag.id3v2.php' => "f", + 'module.audio-video.riff.php' => "f", + 'module.audio-video.asf.php' => "f", + 'module.tag.id3v1.php' => "f" + ), + 'global-styles-and-settings.php' => "f", + 'embed-template.php' => "f", + 'update.php' => "f", + 'class-wp-block-editor-context.php' => "f", + 'theme.json' => "f", + 'comment-template.php' => "f", + 'nav-menu.php' => "f", + 'class-wp-query.php' => "f", + 'widgets.php' => "f", + 'formatting.php' => "f", + 'http.php' => "f", + 'class-wp-http-curl.php' => "f", + 'class-wp-block-pattern-categories-registry.php' => "f", + 'cache-compat.php' => "f", + 'feed-atom.php' => "f", + 'block-template.php' => "f", + 'feed.php' => "f", + 'class-wp-block-list.php' => "f", + 'class-wp-customize-nav-menus.php' => "f", + 'class-wp-http-encoding.php' => "f", + 'class-wp-theme.php' => "f", + 'canonical.php' => "f", + 'sodium_compat' => array( + 'lib' => array( + 'namespaced.php' => "f", + 'constants.php' => "f", + 'php72compat_const.php' => "f", + 'sodium_compat.php' => "f", + 'php72compat.php' => "f", + 'stream-xchacha20.php' => "f", + 'ristretto255.php' => "f" + ), + 'autoload-php7.php' => "f", + 'src' => array( + 'Core32' => array( + 'Salsa20.php' => "f", + 'Util.php' => "f", + 'BLAKE2b.php' => "f", + 'HSalsa20.php' => "f", + 'SipHash.php' => "f", + 'Poly1305' => array( + 'State.php' => "f" + ), + 'XSalsa20.php' => "f", + 'Poly1305.php' => "f", + 'X25519.php' => "f", + 'Int64.php' => "f", + 'Curve25519.php' => "f", + 'Int32.php' => "f", + 'HChaCha20.php' => "f", + 'Curve25519' => array( + 'Fe.php' => "f", + 'H.php' => "f", + 'Ge' => array( + 'Precomp.php' => "f", + 'P2.php' => "f", + 'P1p1.php' => "f", + 'Cached.php' => "f", + 'P3.php' => "f" + ), + 'README.md' => "f" + ), + 'ChaCha20.php' => "f", + 'XChaCha20.php' => "f", + 'Ed25519.php' => "f", + 'ChaCha20' => array( + 'Ctx.php' => "f", + 'IetfCtx.php' => "f" + ), + 'SecretStream' => array( + 'State.php' => "f" + ) + ), + 'Compat.php' => "f", + 'Crypto32.php' => "f", + 'File.php' => "f", + 'Core' => array( + 'Salsa20.php' => "f", + 'Util.php' => "f", + 'BLAKE2b.php' => "f", + 'HSalsa20.php' => "f", + 'SipHash.php' => "f", + 'Base64' => array( + 'UrlSafe.php' => "f", + 'Original.php' => "f", + 'Common.php' => "f" + ), + 'Poly1305' => array( + 'State.php' => "f" + ), + 'XSalsa20.php' => "f", + 'Poly1305.php' => "f", + 'X25519.php' => "f", + 'Curve25519.php' => "f", + 'HChaCha20.php' => "f", + 'Curve25519' => array( + 'Fe.php' => "f", + 'H.php' => "f", + 'Ge' => array( + 'Precomp.php' => "f", + 'P2.php' => "f", + 'P1p1.php' => "f", + 'Cached.php' => "f", + 'P3.php' => "f" + ), + 'README.md' => "f" + ), + 'Ristretto255.php' => "f", + 'ChaCha20.php' => "f", + 'XChaCha20.php' => "f", + 'Ed25519.php' => "f", + 'ChaCha20' => array( + 'Ctx.php' => "f", + 'IetfCtx.php' => "f" + ), + 'SecretStream' => array( + 'State.php' => "f" + ) + ), + 'Crypto.php' => "f", + 'SodiumException.php' => "f", + 'PHP52' => array( + 'SplFixedArray.php' => "f" + ) + ), + 'composer.json' => "f", + 'namespaced' => array( + 'Compat.php' => "f", + 'File.php' => "f", + 'Core' => array( + 'Salsa20.php' => "f", + 'Util.php' => "f", + 'BLAKE2b.php' => "f", + 'HSalsa20.php' => "f", + 'SipHash.php' => "f", + 'Poly1305' => array( + 'State.php' => "f" + ), + 'Poly1305.php' => "f", + 'X25519.php' => "f", + 'Curve25519.php' => "f", + 'Xsalsa20.php' => "f", + 'HChaCha20.php' => "f", + 'Curve25519' => array( + 'Fe.php' => "f", + 'H.php' => "f", + 'Ge' => array( + 'Precomp.php' => "f", + 'P2.php' => "f", + 'P1p1.php' => "f", + 'Cached.php' => "f", + 'P3.php' => "f" + ) + ), + 'ChaCha20.php' => "f", + 'XChaCha20.php' => "f", + 'Ed25519.php' => "f", + 'ChaCha20' => array( + 'Ctx.php' => "f", + 'IetfCtx.php' => "f" + ) + ), + 'Crypto.php' => "f" + ), + 'autoload.php' => "f", + 'LICENSE' => "f" + ), + 'class-wp-post.php' => "f", + 'random_compat' => array( + 'random_bytes_dev_urandom.php' => "f", + 'random_bytes_libsodium.php' => "f", + 'random_bytes_libsodium_legacy.php' => "f", + 'error_polyfill.php' => "f", + 'random_bytes_openssl.php' => "f", + 'random.php' => "f", + 'random_bytes_mcrypt.php' => "f", + 'cast_to_int.php' => "f", + 'random_int.php' => "f", + 'random_bytes_com_dotnet.php' => "f", + 'byte_safe_strings.php' => "f" + ), + 'feed-rss.php' => "f", + 'class-wp-date-query.php' => "f", + 'functions.wp-styles.php' => "f", + 'script-loader.php' => "f", + 'class-wp-image-editor-imagick.php' => "f", + 'block-patterns' => array( + 'quote.php' => "f", + 'heading-paragraph.php' => "f", + 'query-grid-posts.php' => "f", + 'text-two-columns.php' => "f", + 'social-links-shared-background-color.php' => "f", + 'query-medium-posts.php' => "f", + 'query-offset-posts.php' => "f", + 'text-two-columns-with-images.php' => "f", + 'text-three-columns-buttons.php' => "f", + 'query-small-posts.php' => "f", + 'three-buttons.php' => "f", + 'large-header-button.php' => "f", + 'two-buttons.php' => "f", + 'large-header.php' => "f", + 'query-standard-posts.php' => "f", + 'two-images.php' => "f", + 'query-large-title-posts.php' => "f" + ), + 'theme-i18n.json' => "f", + 'class-wp-theme-json.php' => "f", + 'class-wp-comment-query.php' => "f", + 'wp-db.php' => "f" + ), + 'wp-cron.php' => "f", + 'index.php' => "f", + 'xmlrpc.php' => "f", + 'wp-settings.php' => "f", + 'wp-trackback.php' => "f", + 'wp-admin' => array( + 'export.php' => "f", + 'media.php' => "f", + 'media-new.php' => "f", + 'freedoms.php' => "f", + 'my-sites.php' => "f", + 'edit-tags.php' => "f", + 'erase-personal-data.php' => "f", + 'edit-link-form.php' => "f", + 'ms-users.php' => "f", + 'customize.php' => "f", + 'user-new.php' => "f", + 'about.php' => "f", + 'export-personal-data.php' => "f", + 'edit-form-blocks.php' => "f", + 'load-scripts.php' => "f", + 'theme-editor.php' => "f", + 'load-styles.php' => "f", + 'setup-config.php' => "f", + 'upload.php' => "f", + 'tools.php' => "f", + 'upgrade.php' => "f", + 'edit-form-comment.php' => "f", + 'options-privacy.php' => "f", + 'themes.php' => "f", + 'users.php' => "f", + 'edit.php' => "f", + 'options-writing.php' => "f", + 'credits.php' => "f", + 'includes' => array( + 'class-custom-image-header.php' => "f", + 'image-edit.php' => "f", + 'export.php' => "f", + 'ms.php' => "f", + 'media.php' => "f", + 'class-wp-theme-install-list-table.php' => "f", + 'class-bulk-upgrader-skin.php' => "f", + 'class-wp-ms-themes-list-table.php' => "f", + 'class-wp-plugins-list-table.php' => "f", + 'class-wp-upgrader-skins.php' => "f", + 'class-wp-links-list-table.php' => "f", + 'class-walker-nav-menu-checklist.php' => "f", + 'class-wp-ms-users-list-table.php' => "f", + 'class-wp-privacy-data-export-requests-list-table.php' => "f", + 'class-bulk-theme-upgrader-skin.php' => "f", + 'template.php' => "f", + 'class-wp-press-this.php' => "f", + 'class-wp-filesystem-ftpsockets.php' => "f", + 'class-wp-site-health-auto-updates.php' => "f", + 'class-wp-internal-pointers.php' => "f", + 'class-wp-site-health.php' => "f", + 'image.php' => "f", + 'class-plugin-upgrader.php' => "f", + 'edit-tag-messages.php' => "f", + 'class-wp-upgrader.php' => "f", + 'class-theme-upgrader.php' => "f", + 'class-core-upgrader.php' => "f", + 'deprecated.php' => "f", + 'class-wp-comments-list-table.php' => "f", + 'class-wp-privacy-requests-table.php' => "f", + 'dashboard.php' => "f", + 'class-wp-themes-list-table.php' => "f", + 'plugin.php' => "f", + 'class-wp-posts-list-table.php' => "f", + 'upgrade.php' => "f", + 'class-file-upload-upgrader.php' => "f", + 'class-wp-filesystem-base.php' => "f", + 'class-wp-ajax-upgrader-skin.php' => "f", + 'class-wp-privacy-policy-content.php' => "f", + 'class-wp-media-list-table.php' => "f", + 'class-wp-filesystem-ftpext.php' => "f", + 'class-wp-ms-sites-list-table.php' => "f", + 'class-wp-users-list-table.php' => "f", + 'taxonomy.php' => "f", + 'credits.php' => "f", + 'class-wp-list-table.php' => "f", + 'noop.php' => "f", + 'revision.php' => "f", + 'class-language-pack-upgrader-skin.php' => "f", + 'class-wp-post-comments-list-table.php' => "f", + 'class-wp-privacy-data-removal-requests-list-table.php' => "f", + 'import.php' => "f", + 'menu.php' => "f", + 'class-wp-community-events.php' => "f", + 'class-pclzip.php' => "f", + 'user.php' => "f", + 'class-theme-installer-skin.php' => "f", + 'class-wp-filesystem-ssh2.php' => "f", + 'class-wp-upgrader-skin.php' => "f", + 'plugin-install.php' => "f", + 'class-wp-screen.php' => "f", + 'post.php' => "f", + 'class-wp-importer.php' => "f", + 'list-table.php' => "f", + 'class-ftp-pure.php' => "f", + 'class-bulk-plugin-upgrader-skin.php' => "f", + 'continents-cities.php' => "f", + 'class-wp-site-icon.php' => "f", + 'theme-install.php' => "f", + 'class-wp-plugin-install-list-table.php' => "f", + 'class-wp-application-passwords-list-table.php' => "f", + 'admin.php' => "f", + 'options.php' => "f", + 'class-plugin-upgrader-skin.php' => "f", + 'class-language-pack-upgrader.php' => "f", + 'class-plugin-installer-skin.php' => "f", + 'translation-install.php' => "f", + 'misc.php' => "f", + 'class-wp-terms-list-table.php' => "f", + 'class-wp-debug-data.php' => "f", + 'class-walker-category-checklist.php' => "f", + 'ms-deprecated.php' => "f", + 'class-wp-automatic-updater.php' => "f", + 'comment.php' => "f", + 'screen.php' => "f", + 'bookmark.php' => "f", + 'admin-filters.php' => "f", + 'theme.php' => "f", + 'class-wp-list-table-compat.php' => "f", + 'class-automatic-upgrader-skin.php' => "f", + 'privacy-tools.php' => "f", + 'class-walker-nav-menu-edit.php' => "f", + 'class-custom-background.php' => "f", + 'network.php' => "f", + 'class-ftp.php' => "f", + 'update.php' => "f", + 'nav-menu.php' => "f", + 'widgets.php' => "f", + 'class-wp-filesystem-direct.php' => "f", + 'schema.php' => "f", + 'update-core.php' => "f", + 'ms-admin-filters.php' => "f", + 'class-theme-upgrader-skin.php' => "f", + 'ajax-actions.php' => "f", + 'file.php' => "f", + 'class-ftp-sockets.php' => "f", + 'meta-boxes.php' => "f" + ), + 'ms-options.php' => "f", + 'link.php' => "f", + 'revision.php' => "f", + 'privacy.php' => "f", + 'js' => array( + 'xfn.min.js' => "f", + 'theme-plugin-editor.min.js' => "f", + 'comment.min.js' => "f", + 'tags.min.js' => "f", + 'auth-app.min.js' => "f", + 'theme.js' => "f", + 'press-this.js' => "f", + 'privacy-tools.min.js' => "f", + 'user-profile.min.js' => "f", + 'media.js' => "f", + 'word-count.min.js' => "f", + 'password-strength-meter.min.js' => "f", + 'editor.min.js' => "f", + 'site-health.js' => "f", + 'media-gallery.js' => "f", + 'language-chooser.js' => "f", + 'custom-background.js' => "f", + 'widgets' => array( + 'media-image-widget.min.js' => "f", + 'media-image-widget.js' => "f", + 'text-widgets.min.js' => "f", + 'media-gallery-widget.js' => "f", + 'media-audio-widget.js' => "f", + 'text-widgets.js' => "f", + 'custom-html-widgets.min.js' => "f", + 'media-gallery-widget.min.js' => "f", + 'media-widgets.min.js' => "f", + 'media-video-widget.min.js' => "f", + 'media-audio-widget.min.js' => "f", + 'media-video-widget.js' => "f", + 'custom-html-widgets.js' => "f", + 'media-widgets.js' => "f" + ), + 'widgets.js' => "f", + 'widgets.min.js' => "f", + 'accordion.min.js' => "f", + 'wp-fullscreen-stub.min.js' => "f", + 'editor.js' => "f", + 'inline-edit-tax.min.js' => "f", + 'theme-plugin-editor.js' => "f", + 'password-strength-meter.js' => "f", + 'image-edit.min.js' => "f", + 'editor-expand.min.js' => "f", + 'inline-edit-post.js' => "f", + 'color-picker.js' => "f", + 'user-suggest.min.js' => "f", + 'edit-comments.min.js' => "f", + 'link.js' => "f", + 'plugin-install.min.js' => "f", + 'xfn.js' => "f", + 'media.min.js' => "f", + 'revisions.min.js' => "f", + 'accordion.js' => "f", + 'color-picker.min.js' => "f", + 'common.js' => "f", + 'svg-painter.js' => "f", + 'wp-fullscreen.min.js' => "f", + 'set-post-thumbnail.min.js' => "f", + 'post.js' => "f", + 'application-passwords.min.js' => "f", + 'farbtastic.js' => "f", + 'gallery.js' => "f", + 'image-edit.js' => "f", + 'site-health.min.js' => "f", + 'link.min.js' => "f", + 'tags-box.js' => "f", + 'customize-nav-menus.js' => "f", + 'nav-menu.js' => "f", + 'media-gallery.min.js' => "f", + 'nav-menu.min.js' => "f", + 'editor-expand.js' => "f", + 'word-count.js' => "f", + 'privacy-tools.js' => "f", + 'code-editor.js' => "f", + 'post.min.js' => "f", + 'press-this.min.js' => "f", + 'customize-widgets.min.js' => "f", + 'theme.min.js' => "f", + 'wp-fullscreen.js' => "f", + 'edit-comments.js' => "f", + 'inline-edit-tax.js' => "f", + 'customize-controls.js' => "f", + 'user-profile.js' => "f", + 'media-upload.js' => "f", + 'revisions.js' => "f", + 'dashboard.min.js' => "f", + 'dashboard.js' => "f", + 'comment.js' => "f", + 'customize-controls.min.js' => "f", + 'custom-header.js' => "f", + 'inline-edit-post.min.js' => "f", + 'set-post-thumbnail.js' => "f", + 'wp-fullscreen-stub.js' => "f", + 'updates.js' => "f", + 'code-editor.min.js' => "f", + 'updates.min.js' => "f", + 'iris.min.js' => "f", + 'svg-painter.min.js' => "f", + 'common.min.js' => "f", + 'customize-nav-menus.min.js' => "f", + 'application-passwords.js' => "f", + 'bookmarklet.min.js' => "f", + 'tags.js' => "f", + 'customize-widgets.js' => "f", + 'gallery.min.js' => "f", + 'bookmarklet.js' => "f", + 'postbox.js' => "f", + 'tags-suggest.min.js' => "f", + 'auth-app.js' => "f", + 'postbox.min.js' => "f", + 'tags-box.min.js' => "f", + 'tags-suggest.js' => "f", + 'language-chooser.min.js' => "f", + 'plugin-install.js' => "f", + 'user-suggest.js' => "f", + 'custom-background.min.js' => "f", + 'media-upload.min.js' => "f" + ), + 'css' => array( + 'forms-rtl.min.css' => "f", + 'customize-controls-rtl.css' => "f", + 'site-icon.min.css' => "f", + 'themes-rtl.min.css' => "f", + 'press-this-editor-rtl.css' => "f", + 'revisions-rtl.min.css' => "f", + 'press-this-rtl.css' => "f", + 'wp-admin.css' => "f", + 'install-rtl.css' => "f", + 'code-editor-rtl.min.css' => "f", + 'widgets.min.css' => "f", + 'themes-rtl.css' => "f", + 'list-tables-rtl.css' => "f", + 'press-this-editor.min.css' => "f", + 'forms.min.css' => "f", + 'customize-nav-menus-rtl.css' => "f", + 'l10n.css' => "f", + 'list-tables.min.css' => "f", + 'press-this.css' => "f", + 'media-rtl.css' => "f", + 'customize-nav-menus.css' => "f", + 'admin-menu.css' => "f", + 'color-picker-rtl.min.css' => "f", + 'login-rtl.min.css' => "f", + 'press-this-editor.css' => "f", + 'color-picker-rtl.css' => "f", + 'nav-menus.css' => "f", + 'site-icon-rtl.css' => "f", + 'ie.css' => "f", + 'edit.css' => "f", + 'edit.min.css' => "f", + 'media.min.css' => "f", + 'about-rtl.min.css' => "f", + 'widgets-rtl.min.css' => "f", + 'common.min.css' => "f", + 'customize-nav-menus.min.css' => "f", + 'press-this-rtl.min.css' => "f", + 'revisions-rtl.css' => "f", + 'farbtastic.min.css' => "f", + 'install-rtl.min.css' => "f", + 'themes.css' => "f", + 'l10n-rtl.min.css' => "f", + 'edit-rtl.min.css' => "f", + 'nav-menus-rtl.min.css' => "f", + 'site-icon-rtl.min.css' => "f", + 'media-rtl.min.css' => "f", + 'colors' => array( + 'sunrise' => array( + 'colors.min.css' => "f", + 'colors.scss' => "f", + 'colors-rtl.min.css' => "f", + 'colors.css' => "f", + 'colors-rtl.css' => "f" + ), + 'blue' => array( + 'colors.min.css' => "f", + 'colors.scss' => "f", + 'colors-rtl.min.css' => "f", + 'colors.css' => "f", + 'colors-rtl.css' => "f" + ), + 'ectoplasm' => array( + 'colors.min.css' => "f", + 'colors.scss' => "f", + 'colors-rtl.min.css' => "f", + 'colors.css' => "f", + 'colors-rtl.css' => "f" + ), + 'modern' => array( + 'colors.min.css' => "f", + 'colors.scss' => "f", + 'colors-rtl.min.css' => "f", + 'colors.css' => "f", + 'colors-rtl.css' => "f" + ), + '_mixins.scss' => "f", + '_admin.scss' => "f", + 'coffee' => array( + 'colors.min.css' => "f", + 'colors.scss' => "f", + 'colors-rtl.min.css' => "f", + 'colors.css' => "f", + 'colors-rtl.css' => "f" + ), + 'ocean' => array( + 'colors.min.css' => "f", + 'colors.scss' => "f", + 'colors-rtl.min.css' => "f", + 'colors.css' => "f", + 'colors-rtl.css' => "f" + ), + 'light' => array( + 'colors.min.css' => "f", + 'colors.scss' => "f", + 'colors-rtl.min.css' => "f", + 'colors.css' => "f", + 'colors-rtl.css' => "f" + ), + 'midnight' => array( + 'colors.min.css' => "f", + 'colors.scss' => "f", + 'colors-rtl.min.css' => "f", + 'colors.css' => "f", + 'colors-rtl.css' => "f" + ), + '_variables.scss' => "f" + ), + 'revisions.min.css' => "f", + 'about.min.css' => "f", + 'common-rtl.min.css' => "f", + 'customize-nav-menus-rtl.min.css' => "f", + 'customize-controls-rtl.min.css' => "f", + 'site-health.css' => "f", + 'code-editor-rtl.css' => "f", + 'edit-rtl.css' => "f", + 'forms.css' => "f", + 'wp-admin-rtl.min.css' => "f", + 'code-editor.css' => "f", + 'customize-widgets-rtl.min.css' => "f", + 'color-picker.min.css' => "f", + 'l10n-rtl.css' => "f", + 'site-icon.css' => "f", + 'customize-widgets.css' => "f", + 'color-picker.css' => "f", + 'dashboard.css' => "f", + 'deprecated-media-rtl.css' => "f", + 'press-this-editor-rtl.min.css' => "f", + 'deprecated-media.min.css' => "f", + 'customize-widgets.min.css' => "f", + 'admin-menu-rtl.min.css' => "f", + 'widgets.css' => "f", + 'revisions.css' => "f", + 'dashboard-rtl.css' => "f", + 'admin-menu-rtl.css' => "f", + 'widgets-rtl.css' => "f", + 'login.min.css' => "f", + 'nav-menus-rtl.css' => "f", + 'ie-rtl.min.css' => "f", + 'ie.min.css' => "f", + 'install.css' => "f", + 'press-this.min.css' => "f", + 'about.css' => "f", + 'admin-menu.min.css' => "f", + 'login-rtl.css' => "f", + 'farbtastic.css' => "f", + 'dashboard.min.css' => "f", + 'forms-rtl.css' => "f", + 'l10n.min.css' => "f", + 'ie-rtl.css' => "f", + 'themes.min.css' => "f", + 'install.min.css' => "f", + 'site-health.min.css' => "f", + 'customize-widgets-rtl.css' => "f", + 'farbtastic-rtl.css' => "f", + 'wp-admin-rtl.css' => "f", + 'common.css' => "f", + 'list-tables.css' => "f", + 'customize-controls.css' => "f", + 'common-rtl.css' => "f", + 'login.css' => "f", + 'dashboard-rtl.min.css' => "f", + 'list-tables-rtl.min.css' => "f", + 'nav-menus.min.css' => "f", + 'deprecated-media.css' => "f", + 'about-rtl.css' => "f", + 'customize-controls.min.css' => "f", + 'site-health-rtl.css' => "f", + 'site-health-rtl.min.css' => "f", + 'media.css' => "f", + 'code-editor.min.css' => "f", + 'deprecated-media-rtl.min.css' => "f", + 'farbtastic-rtl.min.css' => "f", + 'wp-admin.min.css' => "f" + ), + 'site-health-info.php' => "f", + 'user' => array( + 'freedoms.php' => "f", + 'about.php' => "f", + 'credits.php' => "f", + 'privacy.php' => "f", + 'menu.php' => "f", + 'user-edit.php' => "f", + 'admin.php' => "f", + 'profile.php' => "f", + 'index.php' => "f" + ), + 'options-permalink.php' => "f", + 'import.php' => "f", + 'edit-form-advanced.php' => "f", + 'menu.php' => "f", + 'term.php' => "f", + 'custom-background.php' => "f", + 'link-manager.php' => "f", + 'network' => array( + 'freedoms.php' => "f", + 'site-info.php' => "f", + 'setup.php' => "f", + 'user-new.php' => "f", + 'about.php' => "f", + 'theme-editor.php' => "f", + 'upgrade.php' => "f", + 'themes.php' => "f", + 'users.php' => "f", + 'edit.php' => "f", + 'credits.php' => "f", + 'privacy.php' => "f", + 'site-themes.php' => "f", + 'menu.php' => "f", + 'site-settings.php' => "f", + 'user-edit.php' => "f", + 'plugin-install.php' => "f", + 'theme-install.php' => "f", + 'settings.php' => "f", + 'admin.php' => "f", + 'profile.php' => "f", + 'plugins.php' => "f", + 'site-new.php' => "f", + 'index.php' => "f", + 'site-users.php' => "f", + 'plugin-editor.php' => "f", + 'sites.php' => "f", + 'update.php' => "f", + 'update-core.php' => "f" + ), + 'install-helper.php' => "f", + 'user-edit.php' => "f", + 'async-upload.php' => "f", + 'plugin-install.php' => "f", + 'post.php' => "f", + 'options-discussion.php' => "f", + 'widgets-form.php' => "f", + 'theme-install.php' => "f", + 'admin.php' => "f", + 'options-reading.php' => "f", + 'options.php' => "f", + 'images' => array( + 'freedom-2.svg' => "f", + 'about-color-palette.svg' => "f", + 'list.png' => "f", + 'icons32-vs-2x.png' => "f", + 'resize-rtl.gif' => "f", + 'about-texture.png' => "f", + 'privacy.png' => "f", + 'about-header-privacy.svg' => "f", + 'media-button.png' => "f", + 'comment-grey-bubble-2x.png' => "f", + 'freedom-4.svg' => "f", + 'menu-2x.png' => "f", + 'xit-2x.gif' => "f", + 'sort-2x.gif' => "f", + 'media-button-video.gif' => "f", + 'about-color-palette-vert.svg' => "f", + 'icons32.png' => "f", + 'bubble_bg.gif' => "f", + 'media-button-other.gif' => "f", + 'menu.png' => "f", + 'browser-rtl.png' => "f", + 'align-left-2x.png' => "f", + 'browser.png' => "f", + 'sort.gif' => "f", + 'media-button-2x.png' => "f", + 'post-formats.png' => "f", + 'align-center.png' => "f", + 'icons32-2x.png' => "f", + 'resize-2x.gif' => "f", + 'imgedit-icons.png' => "f", + 'align-right-2x.png' => "f", + 'wpspin_light.gif' => "f", + 'freedom-3.svg' => "f", + 'wordpress-logo.svg' => "f", + 'wheel.png' => "f", + 'about-header-brushes.svg' => "f", + 'list-2x.png' => "f", + 'resize.gif' => "f", + 'w-logo-blue.png' => "f", + 'xit.gif' => "f", + 'imgedit-icons-2x.png' => "f", + 'stars.png' => "f", + 'arrows-2x.png' => "f", + 'about-badge.svg' => "f", + 'menu-vs.png' => "f", + 'about-header-credits.svg' => "f", + 'align-right.png' => "f", + 'align-left.png' => "f", + 'post-formats32.png' => "f", + 'freedoms.png' => "f", + 'align-none-2x.png' => "f", + 'wpspin_light-2x.gif' => "f", + 'freedom-1.svg' => "f", + 'wordpress-logo-white.svg' => "f", + 'resize-rtl-2x.gif' => "f", + 'w-logo-white.png' => "f", + 'se.png' => "f", + 'media-button-image.gif' => "f", + 'yes.png' => "f", + 'wordpress-logo.png' => "f", + 'generic.png' => "f", + 'icons32-vs.png' => "f", + 'menu-vs-2x.png' => "f", + 'align-center-2x.png' => "f", + 'media-button-music.gif' => "f", + 'spinner-2x.gif' => "f", + 'align-none.png' => "f", + 'spinner.gif' => "f", + 'about-header-about.svg' => "f", + 'comment-grey-bubble.png' => "f", + 'arrows.png' => "f", + 'privacy.svg' => "f", + 'date-button-2x.gif' => "f", + 'stars-2x.png' => "f", + 'no.png' => "f", + 'date-button.gif' => "f", + 'bubble_bg-2x.gif' => "f", + 'post-formats-vs.png' => "f", + 'post-formats32-vs.png' => "f", + 'about-header-freedoms.svg' => "f", + 'loading.gif' => "f", + 'mask.png' => "f", + 'marker.png' => "f" + ), + 'profile.php' => "f", + 'plugins.php' => "f", + 'install.php' => "f", + 'options-head.php' => "f", + 'link-parse-opml.php' => "f", + 'admin-functions.php' => "f", + 'moderation.php' => "f", + 'comment.php' => "f", + 'index.php' => "f", + 'ms-sites.php' => "f", + 'site-health.php' => "f", + 'link-add.php' => "f", + 'edit-comments.php' => "f", + 'plugin-editor.php' => "f", + 'maint' => array( + 'repair.php' => "f" + ), + 'nav-menus.php' => "f", + 'privacy-policy-guide.php' => "f", + 'network.php' => "f", + 'custom-header.php' => "f", + 'options-general.php' => "f", + 'options-media.php' => "f", + 'post-new.php' => "f", + 'update.php' => "f", + 'widgets.php' => "f", + 'ms-upgrade-network.php' => "f", + 'media-upload.php' => "f", + 'widgets-form-blocks.php' => "f", + 'admin-header.php' => "f", + 'update-core.php' => "f", + 'ms-themes.php' => "f", + 'ms-delete-site.php' => "f", + 'upgrade-functions.php' => "f", + 'menu-header.php' => "f", + 'ms-admin.php' => "f", + 'site-editor.php' => "f", + 'authorize-application.php' => "f", + 'admin-footer.php' => "f", + 'ms-edit.php' => "f", + 'press-this.php' => "f", + 'admin-ajax.php' => "f", + 'admin-post.php' => "f", + 'edit-tag-form.php' => "f" + ) + ); diff --git a/src/Libs/WpConfig/WPConfigTransformer.php b/src/Libs/WpConfig/WPConfigTransformer.php new file mode 100644 index 00000000..d7de6679 --- /dev/null +++ b/src/Libs/WpConfig/WPConfigTransformer.php @@ -0,0 +1,497 @@ +wp_config_path = $wp_config_path; + } + + /** + * Checks if a config exists in the wp-config.php file. + * + * @throws Exception If the wp-config.php file is empty. + * @throws Exception If the requested config type is invalid. + * + * @param string $type Config type (constant or variable). + * @param string $name Config name. + * + * @return bool + */ + public function exists($type, $name) + { + $wp_config_src = file_get_contents($this->wp_config_path); + + if (! trim($wp_config_src)) { + throw new Exception('wp-config.php file is empty.'); + } + + // SnapCreek custom change + // Normalize the newline to prevent an issue coming from OSX + $wp_config_src = str_replace(array("\r\n", "\r"), "\n", $wp_config_src); + + $this->wp_config_src = $wp_config_src; + $this->wp_configs = $this->parseWpConfig($this->wp_config_src); + + if (! isset($this->wp_configs[ $type ])) { + throw new Exception("Config type '{$type}' does not exist."); + } + + return isset($this->wp_configs[ $type ][ $name ]); + } + + /** + * Get the value of a config in the wp-config.php file. + * + * @throws Exception If the wp-config.php file is empty. + * @throws Exception If the requested config type is invalid. + * + * @param string $type Config type (constant or variable). + * @param string $name Config name. + * @param bool $get_real_value if true return real value + * + * @return array + */ + public function getValue($type, $name, $get_real_value = true) + { + $wp_config_src = file_get_contents($this->wp_config_path); + if (! trim($wp_config_src)) { + throw new Exception('wp-config.php file is empty.'); + } + + // SnapCreek custom change + // Normalize the newline to prevent an issue coming from OSX + $wp_config_src = str_replace(array("\r\n", "\r"), "\n", $wp_config_src); + + $this->wp_config_src = $wp_config_src; + $this->wp_configs = $this->parseWpConfig($this->wp_config_src); + + if (! isset($this->wp_configs[ $type ])) { + throw new Exception("Config type '{$type}' does not exist."); + } + + // Duplicator Extra + $val = $this->wp_configs[ $type ][ $name ]['value']; + if ($get_real_value) { + return self::getRealValFromVal($val); + } else { + return $val; + } + + return $val; + } + + /** + * Get typed val from string val + * + * @param string $val string value + * + * @return mixed + */ + public static function getRealValFromVal($val) + { + if ($val[0] === '\'') { + // string with ' + $result = substr($val, 1, strlen($val) - 2); + return str_replace(array('\\\'', '\\\\'), array('\'', '\\'), $result); + } elseif ($val[0] === '"') { + // string with " + return json_decode(str_replace('\\$', '$', $val)); + } elseif (strcasecmp($val, 'true') === 0) { + return true; + } elseif (strcasecmp($val, 'false') === 0) { + return false; + } elseif (strcasecmp($val, 'null') === 0) { + return null; + } elseif (preg_match('/^[-+]?[0-9]+$/', $val)) { + return (int) $val; + } elseif (preg_match('/^[-+]?[0-9]+\.[0-9]+$/', $val)) { + return (float) $val; + } else { + return $val; + } + } + + /** + * Adds a config to the wp-config.php file. + * + * @throws Exception If the config value provided is not a string. + * @throws Exception If the config placement anchor could not be located. + * + * @param string $type Config type (constant or variable). + * @param string $name Config name. + * @param string $value Config value. + * @param array $options (optional) Array of special behavior options. + * + * @return bool + */ + public function add($type, $name, $value, array $options = array()) + { + if (! is_string($value)) { + throw new Exception('Config value must be a string.'); + } + + if ($this->exists($type, $name)) { + return false; + } + + $defaults = array( + 'raw' => false, // Display value in raw format without quotes. + 'anchor' => "/* That's all, stop editing!", // Config placement anchor string. + 'separator' => PHP_EOL, // Separator between config definition and anchor string. + 'placement' => 'before', // Config placement direction (insert before or after). + ); + + list( $raw, $anchor, $separator, $placement ) = array_values(array_merge($defaults, $options)); + + $raw = (bool) $raw; + $anchor = (string) $anchor; + $separator = (string) $separator; + $placement = (string) $placement; + + // Custom code by the SnapCreek Team + if (false === strpos($this->wp_config_src, $anchor)) { + $other_anchor_points = array( + '/** Absolute path to the WordPress directory', + // ABSPATH defined check with single quote + "if ( !defined('ABSPATH') )", + "if ( ! defined( 'ABSPATH' ) )", + "if (!defined('ABSPATH') )", + "if(!defined('ABSPATH') )", + "if(!defined('ABSPATH'))", + "if ( ! defined( 'ABSPATH' ))", + "if ( ! defined( 'ABSPATH') )", + "if ( ! defined('ABSPATH' ) )", + "if (! defined( 'ABSPATH' ))", + "if (! defined( 'ABSPATH') )", + "if (! defined('ABSPATH' ) )", + "if ( !defined( 'ABSPATH' ))", + "if ( !defined( 'ABSPATH') )", + "if ( !defined('ABSPATH' ) )", + "if( !defined( 'ABSPATH' ))", + "if( !defined( 'ABSPATH') )", + "if( !defined('ABSPATH' ) )", + // ABSPATH defined check with double quote + 'if ( !defined("ABSPATH") )', + 'if ( ! defined( "ABSPATH" ) )', + 'if (!defined("ABSPATH") )', + 'if(!defined("ABSPATH") )', + 'if(!defined("ABSPATH"))', + 'if ( ! defined( "ABSPATH" ))', + 'if ( ! defined( "ABSPATH") )', + 'if ( ! defined("ABSPATH" ) )', + 'if (! defined( "ABSPATH" ))', + 'if (! defined( "ABSPATH") )', + 'if (! defined("ABSPATH" ) )', + 'if ( !defined( "ABSPATH" ))', + 'if ( !defined( "ABSPATH") )', + 'if ( !defined("ABSPATH" ) )', + 'if( !defined( "ABSPATH" ))', + 'if( !defined( "ABSPATH") )', + 'if( !defined("ABSPATH" ) )', + + '/** Sets up WordPress vars and included files', + 'require_once(ABSPATH', + 'require_once ABSPATH', + 'require_once( ABSPATH', + 'require_once', + "define( 'DB_NAME'", + 'define( "DB_NAME"', + "define('DB_NAME'", + 'define("DB_NAME"', + 'require', + 'include_once', + ); + foreach ($other_anchor_points as $anchor_point) { + $anchor_point = (string) $anchor_point; + if (false !== strpos($this->wp_config_src, $anchor_point)) { + $anchor = $anchor_point; + break; + } + } + } + + if (false === strpos($this->wp_config_src, $anchor)) { + throw new Exception('Unable to locate placement anchor.'); + } + + $new_src = $this->normalize($type, $name, $this->formatValue($value, $raw)); + $new_src = ( 'after' === $placement ) ? $anchor . $separator . $new_src : $new_src . $separator . $anchor; + $contents = str_replace($anchor, $new_src, $this->wp_config_src); + + return $this->save($contents); + } + + /** + * Updates an existing config in the wp-config.php file. + * + * @throws Exception If the config value provided is not a string. + * + * @param string $type Config type (constant or variable). + * @param string $name Config name. + * @param string $value Config value. + * @param array $options (optional) Array of special behavior options. + * + * @return bool + */ + public function update($type, $name, $value, array $options = array()) + { + if (! is_string($value)) { + throw new Exception('Config value must be a string.'); + } + + $defaults = array( + 'add' => true, // Add the config if missing. + 'raw' => false, // Display value in raw format without quotes. + 'normalize' => false, // Normalize config output using WP Coding Standards. + ); + + list( $add, $raw, $normalize ) = array_values(array_merge($defaults, $options)); + + $add = (bool) $add; + $raw = (bool) $raw; + $normalize = (bool) $normalize; + + if (! $this->exists($type, $name)) { + return ( $add ) ? $this->add($type, $name, $value, $options) : false; + } + + $old_src = $this->wp_configs[ $type ][ $name ]['src']; + $old_value = $this->wp_configs[ $type ][ $name ]['value']; + $new_value = $this->formatValue($value, $raw); + + if ($normalize) { + $new_src = $this->normalize($type, $name, $new_value); + } else { + $new_parts = $this->wp_configs[ $type ][ $name ]['parts']; + $new_parts[1] = str_replace($old_value, $new_value, $new_parts[1]); // Only edit the value part. + $new_src = implode('', $new_parts); + } + + $contents = preg_replace( + sprintf('/(?<=^|;|<\?php\s|<\?\s)(\s*?)%s/m', preg_quote(trim($old_src), '/')), + '$1' . self::REPLACE_TEMP_STIRNG, + $this->wp_config_src + ); + $contents = str_replace(self::REPLACE_TEMP_STIRNG, trim($new_src), $contents); + return $this->save($contents); + } + + /** + * Removes a config from the wp-config.php file. + * + * @param string $type Config type (constant or variable). + * @param string $name Config name. + * + * @return bool + */ + public function remove($type, $name) + { + if (! $this->exists($type, $name)) { + return false; + } + + $pattern = sprintf('/(?<=^|;|<\?php\s|<\?\s)%s\s*(\S|$)/m', preg_quote($this->wp_configs[ $type ][ $name ]['src'], '/')); + $contents = preg_replace($pattern, '$1', $this->wp_config_src); + + return $this->save($contents); + } + + /** + * Applies formatting to a config value. + * + * @throws Exception When a raw value is requested for an empty string. + * + * @param string $value Config value. + * @param bool $raw Display value in raw format without quotes. + * + * @return mixed + */ + protected function formatValue($value, $raw) + { + if ($raw && '' === trim($value)) { + throw new Exception('Raw value for empty string not supported.'); + } + + return ( $raw ) ? $value : var_export($value, true); + } + + /** + * Normalizes the source output for a name/value pair. + * + * @throws Exception If the requested config type does not support normalization. + * + * @param string $type Config type (constant or variable). + * @param string $name Config name. + * @param mixed $value Config value. + * + * @return string + */ + protected function normalize($type, $name, $value) + { + if ('constant' === $type) { + $placeholder = "define( '%s', %s );"; + } elseif ('variable' === $type) { + $placeholder = '$%s = %s;'; + } else { + throw new Exception("Unable to normalize config type '{$type}'."); + } + + return sprintf($placeholder, $name, $value); + } + + /** + * Parses the source of a wp-config.php file. + * + * @param string $src Config file source. + * + * @return array + */ + protected function parseWpConfig($src) + { + $configs = array(); + $configs['constant'] = array(); + $configs['variable'] = array(); + + if (function_exists('token_get_all')) { + // Strip comments. + foreach (token_get_all($src) as $token) { + if (in_array($token[0], array( T_COMMENT, T_DOC_COMMENT ), true)) { + $src = str_replace($token[1], '', $src); + } + } + } + + preg_match_all( + '/(?<=^|;|<\?php\s|<\?\s)' . + '(\h*define\s*\(\s*[\'"](\w*?)[\'"]\s*)(,\s*(\'\'|""|\'.*?[^\\\\]\'|".*?[^\\\\]"|.*?)\s*)' . + '((?:,\s*(?:true|false)\s*)?\)\s*;)/ims', + $src, + $constants + ); + preg_match_all('/(?<=^|;|<\?php\s|<\?\s)(\h*\$(\w+)\s*=)(\s*(\'\'|""|\'.*?[^\\\\]\'|".*?[^\\\\]"|.*?)\s*;)/ims', $src, $variables); + + if ( + !empty($constants[0]) && + !empty($constants[1]) && + !empty($constants[2]) && + !empty($constants[3]) && + !empty($constants[4]) && + !empty($constants[5]) + ) { + foreach ($constants[2] as $index => $name) { + $configs['constant'][ $name ] = array( + 'src' => $constants[0][ $index ], + 'value' => $constants[4][ $index ], + 'parts' => array( + $constants[1][ $index ], + $constants[3][ $index ], + $constants[5][ $index ], + ), + ); + } + } + + if (! empty($variables[0]) && ! empty($variables[1]) && ! empty($variables[2]) && ! empty($variables[3]) && ! empty($variables[4])) { + // Remove duplicate(s), last definition wins. + $variables[2] = array_reverse(array_unique(array_reverse($variables[2], true)), true); + foreach ($variables[2] as $index => $name) { + $configs['variable'][ $name ] = array( + 'src' => $variables[0][ $index ], + 'value' => $variables[4][ $index ], + 'parts' => array( + $variables[1][ $index ], + $variables[3][ $index ], + ), + ); + } + } + + return $configs; + } + + /** + * Saves new contents to the wp-config.php file. + * + * @throws Exception If the config file content provided is empty. + * @throws Exception If there is a failure when saving the wp-config.php file. + * + * @param string $contents New config contents. + * + * @return bool + */ + protected function save($contents) + { + if (!trim($contents)) { + throw new Exception('Cannot save the wp-config.php file with empty contents.'); + } + + if ($contents === $this->wp_config_src) { + return false; + } + + $result = file_put_contents($this->wp_config_path, $contents, LOCK_EX); + + if (false === $result) { + throw new Exception('Failed to update the wp-config.php file.'); + } + + return true; + } +} diff --git a/src/Libs/WpConfig/WPConfigTransformerSrc.php b/src/Libs/WpConfig/WPConfigTransformerSrc.php new file mode 100644 index 00000000..2711e2aa --- /dev/null +++ b/src/Libs/WpConfig/WPConfigTransformerSrc.php @@ -0,0 +1,100 @@ +wp_config_src = str_replace(array("\n\r", "\r"), array("\n", "\n"), $wp_config_src); + } + + /** + * Get content string + * + * @return string + */ + public function getSrc() + { + return $this->wp_config_src; + } + + /** + * Checks if a config exists in the wp-config.php src + * + * @throws Exception If the wp-config.php file is empty. + * @throws Exception If the requested config type is invalid. + * + * @param string $type Config type (constant or variable). + * @param string $name Config name. + * + * @return bool + */ + public function exists($type, $name) + { + $this->wp_configs = $this->parseWpConfig($this->wp_config_src); + + if (!isset($this->wp_configs[$type])) { + throw new Exception("Config type '{$type}' does not exist."); + } + + return isset($this->wp_configs[$type][$name]); + } + + /** + * Get the value of a config in the wp-config.php src + * + * @param string $type Config type (constant or variable). + * @param string $name Config name. + * @param bool $get_real_value if true return typed value + * + * @return array + */ + public function getValue($type, $name, $get_real_value = true) + { + $this->wp_configs = $this->parseWpConfig($this->wp_config_src); + + if (!isset($this->wp_configs[$type])) { + throw new Exception("Config type '{$type}' does not exist."); + } + + // Duplicator Extra + $val = $this->wp_configs[$type][$name]['value']; + if ($get_real_value) { + return self::getRealValFromVal($val); + } else { + return $val; + } + } + + /** + * Update wp_config_src + * + * @param string $contents config content + * + * @return boolean + */ + protected function save($contents) + { + $this->wp_config_src = $contents; + return true; + } +} diff --git a/src/Utils/Autoloader.php b/src/Utils/Autoloader.php new file mode 100644 index 00000000..d001d9e8 --- /dev/null +++ b/src/Utils/Autoloader.php @@ -0,0 +1,129 @@ + $mappedPath) { + if (strpos($className, $namespace) !== 0) { + continue; + } + + $filepath = $mappedPath . str_replace('\\', '/', substr($className, strlen($namespace))) . '.php'; + if (file_exists($filepath)) { + include_once($filepath); + return true; + } + } + } + + return false; + } + + /** + * Load external libs + * + * @param string $className class name + * + * @return bool return true if class is loaded + */ + protected static function externalLibs($className) + { + switch (strtolower(ltrim($className, '\\'))) { + default: + return false; + } + } + + /** + * mappgin of some legacy classes + * + * @return array + */ + protected static function customLegacyMapping() + { + return array(); + } + + /** + * Return namespace mapping + * + * @return string[] + */ + protected static function getNamespacesMapping() + { + // the order is important, it is necessary to insert the longest namespaces first + return array( + self::ROOT_INSTALLER_NAMESPACE => DUPLICATOR_LITE_PATH . '/installer/dup-installer/src/', + self::ROOT_NAMESPACE => DUPLICATOR_LITE_PATH . '/src/' + ); + } + + /** + * Returns true if the $haystack string end with the $needle, only for internal use + * + * @param string $haystack The full string to search in + * @param string $needle The string to for + * + * @return bool Returns true if the $haystack string starts with the $needle + */ + protected static function endsWith($haystack, $needle) + { + $length = strlen($needle); + if ($length == 0) { + return true; + } + + return (substr($haystack, -$length) === $needle); + } +} diff --git a/src/Utils/CachesPurge/CacheItem.php b/src/Utils/CachesPurge/CacheItem.php new file mode 100644 index 00000000..6ed4f3cb --- /dev/null +++ b/src/Utils/CachesPurge/CacheItem.php @@ -0,0 +1,106 @@ +name = $name; + if (!is_bool($checkCallback) && !is_callable($checkCallback)) { + throw new Exception('checkCallback must be boolean or callable'); + } + $this->checkCallback = $checkCallback; + + /* purge callback may not exist if the referenced plugin is not initialized. + * That's why the check is performed only if you actually purge the plugin + */ + $this->purgeCallback = $purgeCallback; + $this->purgedMessage = sprintf(__('All caches on %s have been purged.', 'duplicator'), $this->name); + } + + /** + * overwrite default purged message + * + * @param string $message message if item have benn purged + * @return void + */ + public function setPurgedMessage($message) + { + $this->purgedMessage = $message; + } + + /** + * purge caches item + * + * @param string $message message if item have benn purged + * @return bool + */ + public function purge(&$message) + { + try { + if ( + (is_bool($this->checkCallback) && $this->checkCallback) || + call_user_func($this->checkCallback) == true + ) { + DUP_Log::trace('Purge ' . $this->name); + if (!is_callable($this->purgeCallback)) { + throw new Exception('purgeCallback must be callable'); + } + call_user_func($this->purgeCallback); + $message = $this->purgedMessage; + } + return true; + } catch (Exception $e) { + DUP_Log::trace('Error purge ' . $this->name . ' message:' . $e->getMessage()); + $message = sprintf(__('Error on caches purge of %s.', 'duplicator'), $this->name); + return false; + } catch (Error $e) { + DUP_Log::trace('Error purge ' . $this->name . ' message:' . $e->getMessage()); + $message = sprintf(__('Error on caches purge of %s.', 'duplicator'), $this->name); + return false; + } + } +} diff --git a/src/Utils/CachesPurge/CachesPurge.php b/src/Utils/CachesPurge/CachesPurge.php new file mode 100644 index 00000000..75c3cb92 --- /dev/null +++ b/src/Utils/CachesPurge/CachesPurge.php @@ -0,0 +1,291 @@ +purge($message); + if (strlen($message) > 0 && $result) { + $globalMessages[] = $message; + } + } + + return $globalMessages; + } + + /** + * get list to cache items to purge + * + * @return CacheItem[] + */ + protected static function getPurgePlugins() + { + $items = array(); + $items[] = new CacheItem( + 'Elementor', + function () { + return class_exists("\\Elementor\\Plugin"); + }, + function () { + \Elementor\Plugin::$instance->files_manager->clear_cache(); + } + ); + $items[] = new CacheItem( + 'W3 Total Cache', + function () { + return function_exists('w3tc_pgcache_flush'); + }, + 'w3tc_pgcache_flush' + ); + $items[] = new CacheItem( + 'WP Super Cache', + function () { + return function_exists('wp_cache_clear_cache'); + }, + 'wp_cache_clear_cache' + ); + $items[] = new CacheItem( + 'WP Rocket', + function () { + return function_exists('rocket_clean_domain'); + }, + 'rocket_clean_domain' + ); + $items[] = new CacheItem( + 'Fast velocity minify', + function () { + return function_exists('fvm_purge_static_files'); + }, + 'fvm_purge_static_files' + ); + $items[] = new CacheItem( + 'Cachify', + function () { + return function_exists('cachify_flush_cache'); + }, + 'cachify_flush_cache' + ); + $items[] = new CacheItem( + 'Comet Cache', + function () { + return class_exists('\\comet_cache'); + }, + array('\\comet_cache', 'clear') + ); + $items[] = new CacheItem( + 'Zen Cache', + function () { + return class_exists('\\zencache'); + }, + array('\\zencache', 'clear') + ); + $items[] = new CacheItem( + 'LiteSpeed Cache', + function () { + return has_action('litespeed_purge_all'); + }, + function () { + return do_action('litespeed_purge_all'); + } + ); + $items[] = new CacheItem( + 'WP Cloudflare Super Page Cache', + function () { + return class_exists('\\SW_CLOUDFLARE_PAGECACHE'); + }, + function () { + return do_action("swcfpc_purge_everything"); + } + ); + $items[] = new CacheItem( + 'Hyper Cache', + function () { + return class_exists('\\HyperCache'); + }, + function () { + return do_action('autoptimize_action_cachepurged'); + } + ); + $items[] = new CacheItem( + 'Cache Enabler', + function () { + return has_action('ce_clear_cache'); + }, + function () { + return do_action('ce_clear_cache'); + } + ); + $items[] = new CacheItem( + 'WP Fastest Cache', + function () { + return function_exists('wpfc_clear_all_cache'); + }, + function () { + wpfc_clear_all_cache(true); + } + ); + $items[] = new CacheItem( + 'Breeze', + function () { + return class_exists("\\Breeze_PurgeCache"); + }, + array('\\Breeze_PurgeCache', 'breeze_cache_flush') + ); + $items[] = new CacheItem( + 'Swift Performance', + function () { + return class_exists("\\Swift_Performance_Cache"); + }, + array('\\Swift_Performance_Cache', 'clear_all_cache') + ); + $items[] = new CacheItem( + 'Hummingbird', + function () { + return has_action('wphb_clear_page_cache'); + }, + function () { + return do_action('wphb_clear_page_cache'); + } + ); + $items[] = new CacheItem( + 'WP-Optimize', + function () { + return has_action('wpo_cache_flush'); + }, + function () { + return do_action('wpo_cache_flush'); + } + ); + $items[] = new CacheItem( + 'Wordpress default', + function () { + return function_exists('wp_cache_flush'); + }, + 'wp_cache_flush' + ); + $items[] = new CacheItem( + 'Wordpress permalinks', + function () { + return function_exists('flush_rewrite_rules'); + }, + 'flush_rewrite_rules' + ); + return $items; + } + + /** + * get list to cache items to purge + * + * @return CacheItem[] + */ + protected static function getPurgeHosts() + { + $items = array(); + $items[] = new CacheItem( + 'Godaddy Managed WordPress Hosting', + function () { + return class_exists('\\WPaaS\\Plugin') && method_exists('\\WPass\\Plugin', 'vip'); + }, + function () { + $method = 'BAN'; + $url = home_url(); + $host = wpraiser_get_domain(); + $url = set_url_scheme(str_replace($host, \WPaas\Plugin::vip(), $url), 'http'); + update_option('gd_system_last_cache_flush', time(), 'no'); # purge apc + wp_remote_request( + esc_url_raw($url), + array( + 'method' => $method, + 'blocking' => false, + 'headers' => + array( + 'Host' => $host + ) + ) + ); + } + ); + $items[] = new CacheItem( + 'SG Optimizer (Siteground)', + function () { + return function_exists('sg_cachepress_purge_everything'); + }, + 'sg_cachepress_purge_everything' + ); + $items[] = new CacheItem( + 'WP Engine', + function () { + return (class_exists("\\WpeCommon") && + (method_exists('\\WpeCommon', 'purge_memcached') || + method_exists('\\WpeCommon', 'purge_varnish_cache'))); + }, + function () { + if (method_exists('\\WpeCommon', 'purge_memcached')) { + \WpeCommon::purge_memcached(); + } + if (method_exists('\\WpeCommon', 'purge_varnish_cache')) { + \WpeCommon::purge_varnish_cache(); + } + } + ); + $items[] = new CacheItem( + 'Kinsta', + function () { + global $kinsta_cache; + return ( + (isset($kinsta_cache) && + class_exists('\\Kinsta\\CDN_Enabler')) && + !empty($kinsta_cache->kinsta_cache_purge)); + }, + function () { + global $kinsta_cache; + $kinsta_cache->kinsta_cache_purge->purge_complete_caches(); + } + ); + $items[] = new CacheItem( + 'Pagely', + function () { + return class_exists('\\PagelyCachePurge'); + }, + function () { + $purge_pagely = new \PagelyCachePurge(); + $purge_pagely->purgeAll(); + } + ); + $items[] = new CacheItem( + 'Pressidum', + function () { + return defined('WP_NINUKIS_WP_NAME') && class_exists('\\Ninukis_Plugin'); + }, + function () { + $purge_pressidum = \Ninukis_Plugin::get_instance(); + $purge_pressidum->purgeAllCaches(); + } + ); + + $items[] = new CacheItem( + 'Pantheon Advanced Page Cache plugin', + function () { + return function_exists('pantheon_wp_clear_edge_all'); + }, + 'pantheon_wp_clear_edge_all' + ); + return $items; + } +} diff --git a/tools/DuplicatorPhpVersionCheck.php b/tools/DuplicatorPhpVersionCheck.php index 0345b798..4f8067e2 100644 --- a/tools/DuplicatorPhpVersionCheck.php +++ b/tools/DuplicatorPhpVersionCheck.php @@ -1,9 +1,11 @@

        '; + + $str = __('Please ask your host or server administrator to update to PHP %1s or greater.') . '
        '; $str .= __('If this is not possible, please visit the FAQ link titled ', 'duplicator'); $str .= ''; $str .= __('"What version of PHP Does Duplicator Support?"', 'duplicator'); diff --git a/tools/Lite/Requirements.php b/tools/Lite/Requirements.php index e4edc372..f483293b 100644 --- a/tools/Lite/Requirements.php +++ b/tools/Lite/Requirements.php @@ -1,4 +1,5 @@ ' . __('Please deactivate Duplicator PRO, then reactivate LITE version from the ', 'duplicator') . "" . __('plugins page', 'duplicator') . "."; - $result = false; + $result = false; } if ($result === false) { @@ -60,7 +61,7 @@ public static function canRun($pluginFile) } /** - * + * * @param string $plugin * @return boolean // return true if plugin key is active and plugin file exists */ @@ -92,7 +93,7 @@ public static function addProEnableNotice() } /** - * display admin notice + * display admin notice */ public static function addMultisiteNotice() { @@ -124,7 +125,7 @@ public static function proEnabledNotice()

        - + . diff --git a/uninstall.php b/uninstall.php index be01d723..111ad738 100644 --- a/uninstall.php +++ b/uninstall.php @@ -1,133 +1,57 @@ -prefix."duplicator_packages"; -$wpdb->query("DROP TABLE IF EXISTS `{$table_name}`"); -$wpdb->query("DELETE FROM ".$wpdb->usermeta." WHERE meta_key='".DUPLICATOR_ADMIN_NOTICES_USER_META_KEY."'"); - -delete_option(DUP_LITE_Plugin_Upgrade::DUP_VERSION_OPT_KEY); -delete_option('duplicator_usage_id'); - -//Remove entire storage directory -if (DUP_Settings::Get('uninstall_files')) { - $ssdir = DUP_Settings::getSsdirPath(); - $ssdir_tmp = DUP_Settings::getSsdirTmpPath(); - $ssdir_installer = DUP_Settings::getSsdirInstallerPath(); - $ssdir_dupInstaller = "{$ssdir}/dup-installer/"; - - //Sanity check for strange setup - $check = glob("{$ssdir}/wp-config.php"); - if (count($check) == 0) { - - //PHP sanity check - foreach (glob("{$ssdir}/*_database.sql") as $file) { - if (strstr($file, '_database.sql')) - @unlink("{$file}"); - } - foreach (glob("{$ssdir}/*_installer" . DUP_Installer::INSTALLER_SERVER_EXTENSION) as $file) { - if (strstr($file, '_installer' . DUP_Installer::INSTALLER_SERVER_EXTENSION)) - @unlink("{$file}"); - } - foreach (glob("{$ssdir}/*_archive.zip*") as $file) { - if (strstr($file, '_archive.zip')) - @unlink("{$file}"); - } - foreach (glob("{$ssdir}/*_archive.daf") as $file) { - if (strstr($file, '_archive.daf')) - @unlink("{$file}"); - } - foreach (glob("{$ssdir}/*_scan.json") as $file) { - if (strstr($file, '_scan.json')) - @unlink("{$file}"); - } - foreach (glob("{$ssdir_tmp}/*_scan.json") as $file) { - if (strstr($file, '_scan.json')) - @unlink("{$file}"); - } - // before 1.3.38 the [HASH]_wp-config.txt was present in main storage area - foreach (glob("{$ssdir}/*_wp-config.txt") as $file) { - if (strstr($file, '_wp-config.txt')) - @unlink("{$file}"); - } - foreach (glob("{$ssdir}/*.log") as $file) { - if (strstr($file, '.log')) - @unlink("{$file}"); - } - foreach (glob("{$ssdir}/*.log1") as $file) { - if (strstr($file, '.log1')) - @unlink("{$file}"); - } - foreach (glob("{$ssdir}/*.txt") as $file) { - if (strstr($file, '.txt')) - @unlink("{$file}"); - } - - //Check for core files and only continue removing data if the snapshots directory - //has not been edited by 3rd party sources, this helps to keep the system stable - $files = glob("{$ssdir}/*"); - if (is_array($files) && count($files) < 6) { - $defaults = array("{$ssdir}/index.php", "{$ssdir}/robots.txt", "{$ssdir}/dtoken.php"); - $compare = array_diff($defaults, $files); - - //There might be a .htaccess file or index.php/html etc. - if (count($compare) < 3) { - foreach ($defaults as $file) { - @unlink("{$file}"); - } - @unlink("{$ssdir}/.htaccess"); - - //installer log from previous install - foreach (glob("{$ssdir_installer}/*.txt") as $file) { - if (strstr($file, '.txt')) - @unlink("{$file}"); - } - - @rmdir($ssdir_installer); - @rmdir($ssdir_tmp); - - //Edge Case: dup-installer directory - if (file_exists($ssdir_dupInstaller)) { - error_log("Duplicator Removing: {$ssdir_dupInstaller}"); - DupLiteSnapLibIOU::emptyDir($ssdir_dupInstaller); - @rmdir($ssdir_dupInstaller); - } - - @rmdir($ssdir); - } - } - } -} - -//Remove all Settings -if (DUP_Settings::Get('uninstall_settings')) { - DUP_Settings::Delete(); - delete_option('duplicator_ui_view_state'); - delete_option('duplicator_package_active'); - delete_option("duplicator_exe_safe_mode"); - delete_option('duplicator_lite_inst_hash_notice'); -} \ No newline at end of file +query("DELETE FROM " . $wpdb->usermeta . " WHERE meta_key='" . DUPLICATOR_ADMIN_NOTICES_USER_META_KEY . "'"); +delete_option(DUP_LITE_Plugin_Upgrade::DUP_VERSION_OPT_KEY); +delete_option('duplicator_usage_id'); +//Remove entire storage directory + +if (DUP_Settings::Get('uninstall_files')) { + $table_name = $wpdb->prefix . "duplicator_packages"; + $wpdb->query("DROP TABLE IF EXISTS `{$table_name}`"); + + if (file_exists(DUP_Settings::getSsdirPathLegacy())) { + SnapIO::rrmdir(DUP_Settings::getSsdirPathLegacy()); + } + + if (file_exists(DUP_Settings::getSsdirPathWpCont())) { + SnapIO::rrmdir(DUP_Settings::getSsdirPathWpCont()); + } +} + +//Remove all Settings +if (DUP_Settings::Get('uninstall_settings')) { + DUP_Settings::Delete(); + delete_option('duplicator_ui_view_state'); + delete_option('duplicator_package_active'); + delete_option("duplicator_exe_safe_mode"); + delete_option('duplicator_lite_inst_hash_notice'); +} diff --git a/vendor/requests/LICENSE b/vendor/requests/LICENSE new file mode 100644 index 00000000..d61ae7b1 --- /dev/null +++ b/vendor/requests/LICENSE @@ -0,0 +1,49 @@ +Requests +======== + +Copyright (c) 2010-2012 Ryan McCue and contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +ComplexPie IRI Parser +===================== + +Copyright (c) 2007-2010, Geoffrey Sneddon and Steve Minutillo. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the SimplePie Team nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/requests/library/Requests.php b/vendor/requests/library/Requests.php new file mode 100644 index 00000000..bb266189 --- /dev/null +++ b/vendor/requests/library/Requests.php @@ -0,0 +1,980 @@ +dispatch('requests.before_request', array(&$url, &$headers, &$data, &$type, &$options)); + + if (!empty($options['transport'])) { + $transport = $options['transport']; + + if (is_string($options['transport'])) { + $transport = new $transport(); + } + } + else { + $need_ssl = (0 === stripos($url, 'https://')); + $capabilities = array('ssl' => $need_ssl); + $transport = self::get_transport($capabilities); + } + $response = $transport->request($url, $headers, $data, $options); + + $options['hooks']->dispatch('requests.before_parse', array(&$response, $url, $headers, $data, $type, $options)); + + return self::parse_response($response, $url, $headers, $data, $options); + } + + /** + * Send multiple HTTP requests simultaneously + * + * The `$requests` parameter takes an associative or indexed array of + * request fields. The key of each request can be used to match up the + * request with the returned data, or with the request passed into your + * `multiple.request.complete` callback. + * + * The request fields value is an associative array with the following keys: + * + * - `url`: Request URL Same as the `$url` parameter to + * {@see Requests::request} + * (string, required) + * - `headers`: Associative array of header fields. Same as the `$headers` + * parameter to {@see Requests::request} + * (array, default: `array()`) + * - `data`: Associative array of data fields or a string. Same as the + * `$data` parameter to {@see Requests::request} + * (array|string, default: `array()`) + * - `type`: HTTP request type (use Requests constants). Same as the `$type` + * parameter to {@see Requests::request} + * (string, default: `Requests::GET`) + * - `cookies`: Associative array of cookie name to value, or cookie jar. + * (array|Requests_Cookie_Jar) + * + * If the `$options` parameter is specified, individual requests will + * inherit options from it. This can be used to use a single hooking system, + * or set all the types to `Requests::POST`, for example. + * + * In addition, the `$options` parameter takes the following global options: + * + * - `complete`: A callback for when a request is complete. Takes two + * parameters, a Requests_Response/Requests_Exception reference, and the + * ID from the request array (Note: this can also be overridden on a + * per-request basis, although that's a little silly) + * (callback) + * + * @param array $requests Requests data (see description for more information) + * @param array $options Global and default options (see {@see Requests::request}) + * @return array Responses (either Requests_Response or a Requests_Exception object) + */ + public static function request_multiple($requests, $options = array()) { + $options = array_merge(self::get_default_options(true), $options); + + if (!empty($options['hooks'])) { + $options['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple')); + if (!empty($options['complete'])) { + $options['hooks']->register('multiple.request.complete', $options['complete']); + } + } + + foreach ($requests as $id => &$request) { + if (!isset($request['headers'])) { + $request['headers'] = array(); + } + if (!isset($request['data'])) { + $request['data'] = array(); + } + if (!isset($request['type'])) { + $request['type'] = self::GET; + } + if (!isset($request['options'])) { + $request['options'] = $options; + $request['options']['type'] = $request['type']; + } + else { + if (empty($request['options']['type'])) { + $request['options']['type'] = $request['type']; + } + $request['options'] = array_merge($options, $request['options']); + } + + self::set_defaults($request['url'], $request['headers'], $request['data'], $request['type'], $request['options']); + + // Ensure we only hook in once + if ($request['options']['hooks'] !== $options['hooks']) { + $request['options']['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple')); + if (!empty($request['options']['complete'])) { + $request['options']['hooks']->register('multiple.request.complete', $request['options']['complete']); + } + } + } + unset($request); + + if (!empty($options['transport'])) { + $transport = $options['transport']; + + if (is_string($options['transport'])) { + $transport = new $transport(); + } + } + else { + $transport = self::get_transport(); + } + $responses = $transport->request_multiple($requests, $options); + + foreach ($responses as $id => &$response) { + // If our hook got messed with somehow, ensure we end up with the + // correct response + if (is_string($response)) { + $request = $requests[$id]; + self::parse_multiple($response, $request); + $request['options']['hooks']->dispatch('multiple.request.complete', array(&$response, $id)); + } + } + + return $responses; + } + + /** + * Get the default options + * + * @see Requests::request() for values returned by this method + * @param boolean $multirequest Is this a multirequest? + * @return array Default option values + */ + protected static function get_default_options($multirequest = false) { + $defaults = array( + 'timeout' => 10, + 'connect_timeout' => 10, + 'useragent' => 'php-requests/' . self::VERSION, + 'protocol_version' => 1.1, + 'redirected' => 0, + 'redirects' => 10, + 'follow_redirects' => true, + 'blocking' => true, + 'type' => self::GET, + 'filename' => false, + 'auth' => false, + 'proxy' => false, + 'cookies' => false, + 'max_bytes' => false, + 'idn' => true, + 'hooks' => null, + 'transport' => null, + 'verify' => Requests::get_certificate_path(), + 'verifyname' => true, + ); + if ($multirequest !== false) { + $defaults['complete'] = null; + } + return $defaults; + } + + /** + * Get default certificate path. + * + * @return string Default certificate path. + */ + public static function get_certificate_path() { + if ( ! empty( Requests::$certificate_path ) ) { + return Requests::$certificate_path; + } + + return dirname(__FILE__) . '/Requests/Transport/cacert.pem'; + } + + /** + * Set default certificate path. + * + * @param string $path Certificate path, pointing to a PEM file. + */ + public static function set_certificate_path( $path ) { + Requests::$certificate_path = $path; + } + + /** + * Set the default values + * + * @param string $url URL to request + * @param array $headers Extra headers to send with the request + * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests + * @param string $type HTTP request type + * @param array $options Options for the request + * @return array $options + */ + protected static function set_defaults(&$url, &$headers, &$data, &$type, &$options) { + if (!preg_match('/^http(s)?:\/\//i', $url, $matches)) { + throw new Requests_Exception('Only HTTP(S) requests are handled.', 'nonhttp', $url); + } + + if (empty($options['hooks'])) { + $options['hooks'] = new Requests_Hooks(); + } + + if (is_array($options['auth'])) { + $options['auth'] = new Requests_Auth_Basic($options['auth']); + } + if ($options['auth'] !== false) { + $options['auth']->register($options['hooks']); + } + + if (is_string($options['proxy']) || is_array($options['proxy'])) { + $options['proxy'] = new Requests_Proxy_HTTP($options['proxy']); + } + if ($options['proxy'] !== false) { + $options['proxy']->register($options['hooks']); + } + + if (is_array($options['cookies'])) { + $options['cookies'] = new Requests_Cookie_Jar($options['cookies']); + } + elseif (empty($options['cookies'])) { + $options['cookies'] = new Requests_Cookie_Jar(); + } + if ($options['cookies'] !== false) { + $options['cookies']->register($options['hooks']); + } + + if ($options['idn'] !== false) { + $iri = new Requests_IRI($url); + $iri->host = Requests_IDNAEncoder::encode($iri->ihost); + $url = $iri->uri; + } + + // Massage the type to ensure we support it. + $type = strtoupper($type); + + if (!isset($options['data_format'])) { + if (in_array($type, array(self::HEAD, self::GET, self::DELETE))) { + $options['data_format'] = 'query'; + } + else { + $options['data_format'] = 'body'; + } + } + } + + /** + * HTTP response parser + * + * @throws Requests_Exception On missing head/body separator (`requests.no_crlf_separator`) + * @throws Requests_Exception On missing head/body separator (`noversion`) + * @throws Requests_Exception On missing head/body separator (`toomanyredirects`) + * + * @param string $headers Full response text including headers and body + * @param string $url Original request URL + * @param array $req_headers Original $headers array passed to {@link request()}, in case we need to follow redirects + * @param array $req_data Original $data array passed to {@link request()}, in case we need to follow redirects + * @param array $options Original $options array passed to {@link request()}, in case we need to follow redirects + * @return Requests_Response + */ + protected static function parse_response($headers, $url, $req_headers, $req_data, $options) { + $return = new Requests_Response(); + if (!$options['blocking']) { + return $return; + } + + $return->raw = $headers; + $return->url = $url; + + if (!$options['filename']) { + if (($pos = strpos($headers, "\r\n\r\n")) === false) { + // Crap! + throw new Requests_Exception('Missing header/body separator', 'requests.no_crlf_separator'); + } + + $headers = substr($return->raw, 0, $pos); + $return->body = substr($return->raw, $pos + strlen("\n\r\n\r")); + } + else { + $return->body = ''; + } + // Pretend CRLF = LF for compatibility (RFC 2616, section 19.3) + $headers = str_replace("\r\n", "\n", $headers); + // Unfold headers (replace [CRLF] 1*( SP | HT ) with SP) as per RFC 2616 (section 2.2) + $headers = preg_replace('/\n[ \t]/', ' ', $headers); + $headers = explode("\n", $headers); + preg_match('#^HTTP/(1\.\d)[ \t]+(\d+)#i', array_shift($headers), $matches); + if (empty($matches)) { + throw new Requests_Exception('Response could not be parsed', 'noversion', $headers); + } + $return->protocol_version = (float) $matches[1]; + $return->status_code = (int) $matches[2]; + if ($return->status_code >= 200 && $return->status_code < 300) { + $return->success = true; + } + + foreach ($headers as $header) { + list($key, $value) = explode(':', $header, 2); + $value = trim($value); + preg_replace('#(\s+)#i', ' ', $value); + $return->headers[$key] = $value; + } + if (isset($return->headers['transfer-encoding'])) { + $return->body = self::decode_chunked($return->body); + unset($return->headers['transfer-encoding']); + } + if (isset($return->headers['content-encoding'])) { + $return->body = self::decompress($return->body); + } + + //fsockopen and cURL compatibility + if (isset($return->headers['connection'])) { + unset($return->headers['connection']); + } + + $options['hooks']->dispatch('requests.before_redirect_check', array(&$return, $req_headers, $req_data, $options)); + + if ($return->is_redirect() && $options['follow_redirects'] === true) { + if (isset($return->headers['location']) && $options['redirected'] < $options['redirects']) { + if ($return->status_code === 303) { + $options['type'] = self::GET; + } + $options['redirected']++; + $location = $return->headers['location']; + if (strpos($location, 'http://') !== 0 && strpos($location, 'https://') !== 0) { + // relative redirect, for compatibility make it absolute + $location = Requests_IRI::absolutize($url, $location); + $location = $location->uri; + } + + $hook_args = array( + &$location, + &$req_headers, + &$req_data, + &$options, + $return + ); + $options['hooks']->dispatch('requests.before_redirect', $hook_args); + $redirected = self::request($location, $req_headers, $req_data, $options['type'], $options); + $redirected->history[] = $return; + return $redirected; + } + elseif ($options['redirected'] >= $options['redirects']) { + throw new Requests_Exception('Too many redirects', 'toomanyredirects', $return); + } + } + + $return->redirects = $options['redirected']; + + $options['hooks']->dispatch('requests.after_request', array(&$return, $req_headers, $req_data, $options)); + return $return; + } + + /** + * Callback for `transport.internal.parse_response` + * + * Internal use only. Converts a raw HTTP response to a Requests_Response + * while still executing a multiple request. + * + * @param string $response Full response text including headers and body (will be overwritten with Response instance) + * @param array $request Request data as passed into {@see Requests::request_multiple()} + * @return null `$response` is either set to a Requests_Response instance, or a Requests_Exception object + */ + public static function parse_multiple(&$response, $request) { + try { + $url = $request['url']; + $headers = $request['headers']; + $data = $request['data']; + $options = $request['options']; + $response = self::parse_response($response, $url, $headers, $data, $options); + } + catch (Requests_Exception $e) { + $response = $e; + } + } + + /** + * Decoded a chunked body as per RFC 2616 + * + * @see https://tools.ietf.org/html/rfc2616#section-3.6.1 + * @param string $data Chunked body + * @return string Decoded body + */ + protected static function decode_chunked($data) { + if (!preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', trim($data))) { + return $data; + } + + + + $decoded = ''; + $encoded = $data; + + while (true) { + $is_chunked = (bool) preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', $encoded, $matches); + if (!$is_chunked) { + // Looks like it's not chunked after all + return $data; + } + + $length = hexdec(trim($matches[1])); + if ($length === 0) { + // Ignore trailer headers + return $decoded; + } + + $chunk_length = strlen($matches[0]); + $decoded .= substr($encoded, $chunk_length, $length); + $encoded = substr($encoded, $chunk_length + $length + 2); + + if (trim($encoded) === '0' || empty($encoded)) { + return $decoded; + } + } + + // We'll never actually get down here + // @codeCoverageIgnoreStart + } + // @codeCoverageIgnoreEnd + + /** + * Convert a key => value array to a 'key: value' array for headers + * + * @param array $array Dictionary of header values + * @return array List of headers + */ + public static function flatten($array) { + $return = array(); + foreach ($array as $key => $value) { + $return[] = sprintf('%s: %s', $key, $value); + } + return $return; + } + + /** + * Convert a key => value array to a 'key: value' array for headers + * + * @codeCoverageIgnore + * @deprecated Misspelling of {@see Requests::flatten} + * @param array $array Dictionary of header values + * @return array List of headers + */ + public static function flattern($array) { + return self::flatten($array); + } + + /** + * Decompress an encoded body + * + * Implements gzip, compress and deflate. Guesses which it is by attempting + * to decode. + * + * @param string $data Compressed data in one of the above formats + * @return string Decompressed string + */ + public static function decompress($data) { + if (substr($data, 0, 2) !== "\x1f\x8b" && substr($data, 0, 2) !== "\x78\x9c") { + // Not actually compressed. Probably cURL ruining this for us. + return $data; + } + + if (function_exists('gzdecode') && ($decoded = @gzdecode($data)) !== false) { + return $decoded; + } + elseif (function_exists('gzinflate') && ($decoded = @gzinflate($data)) !== false) { + return $decoded; + } + elseif (($decoded = self::compatible_gzinflate($data)) !== false) { + return $decoded; + } + elseif (function_exists('gzuncompress') && ($decoded = @gzuncompress($data)) !== false) { + return $decoded; + } + + return $data; + } + + /** + * Decompression of deflated string while staying compatible with the majority of servers. + * + * Certain Servers will return deflated data with headers which PHP's gzinflate() + * function cannot handle out of the box. The following function has been created from + * various snippets on the gzinflate() PHP documentation. + * + * Warning: Magic numbers within. Due to the potential different formats that the compressed + * data may be returned in, some "magic offsets" are needed to ensure proper decompression + * takes place. For a simple progmatic way to determine the magic offset in use, see: + * https://core.trac.wordpress.org/ticket/18273 + * + * @since 2.8.1 + * @link https://core.trac.wordpress.org/ticket/18273 + * @link https://secure.php.net/manual/en/function.gzinflate.php#70875 + * @link https://secure.php.net/manual/en/function.gzinflate.php#77336 + * + * @param string $gzData String to decompress. + * @return string|bool False on failure. + */ + public static function compatible_gzinflate($gzData) { + // Compressed data might contain a full zlib header, if so strip it for + // gzinflate() + if (substr($gzData, 0, 3) == "\x1f\x8b\x08") { + $i = 10; + $flg = ord(substr($gzData, 3, 1)); + if ($flg > 0) { + if ($flg & 4) { + list($xlen) = unpack('v', substr($gzData, $i, 2)); + $i = $i + 2 + $xlen; + } + if ($flg & 8) { + $i = strpos($gzData, "\0", $i) + 1; + } + if ($flg & 16) { + $i = strpos($gzData, "\0", $i) + 1; + } + if ($flg & 2) { + $i = $i + 2; + } + } + $decompressed = self::compatible_gzinflate(substr($gzData, $i)); + if (false !== $decompressed) { + return $decompressed; + } + } + + // If the data is Huffman Encoded, we must first strip the leading 2 + // byte Huffman marker for gzinflate() + // The response is Huffman coded by many compressors such as + // java.util.zip.Deflater, Ruby’s Zlib::Deflate, and .NET's + // System.IO.Compression.DeflateStream. + // + // See https://decompres.blogspot.com/ for a quick explanation of this + // data type + $huffman_encoded = false; + + // low nibble of first byte should be 0x08 + list(, $first_nibble) = unpack('h', $gzData); + + // First 2 bytes should be divisible by 0x1F + list(, $first_two_bytes) = unpack('n', $gzData); + + if (0x08 == $first_nibble && 0 == ($first_two_bytes % 0x1F)) { + $huffman_encoded = true; + } + + if ($huffman_encoded) { + if (false !== ($decompressed = @gzinflate(substr($gzData, 2)))) { + return $decompressed; + } + } + + if ("\x50\x4b\x03\x04" == substr($gzData, 0, 4)) { + // ZIP file format header + // Offset 6: 2 bytes, General-purpose field + // Offset 26: 2 bytes, filename length + // Offset 28: 2 bytes, optional field length + // Offset 30: Filename field, followed by optional field, followed + // immediately by data + list(, $general_purpose_flag) = unpack('v', substr($gzData, 6, 2)); + + // If the file has been compressed on the fly, 0x08 bit is set of + // the general purpose field. We can use this to differentiate + // between a compressed document, and a ZIP file + $zip_compressed_on_the_fly = (0x08 == (0x08 & $general_purpose_flag)); + + if (!$zip_compressed_on_the_fly) { + // Don't attempt to decode a compressed zip file + return $gzData; + } + + // Determine the first byte of data, based on the above ZIP header + // offsets: + $first_file_start = array_sum(unpack('v2', substr($gzData, 26, 4))); + if (false !== ($decompressed = @gzinflate(substr($gzData, 30 + $first_file_start)))) { + return $decompressed; + } + return false; + } + + // Finally fall back to straight gzinflate + if (false !== ($decompressed = @gzinflate($gzData))) { + return $decompressed; + } + + // Fallback for all above failing, not expected, but included for + // debugging and preventing regressions and to track stats + if (false !== ($decompressed = @gzinflate(substr($gzData, 2)))) { + return $decompressed; + } + + return false; + } + + public static function match_domain($host, $reference) { + // Check for a direct match + if ($host === $reference) { + return true; + } + + // Calculate the valid wildcard match if the host is not an IP address + // Also validates that the host has 3 parts or more, as per Firefox's + // ruleset. + $parts = explode('.', $host); + if (ip2long($host) === false && count($parts) >= 3) { + $parts[0] = '*'; + $wildcard = implode('.', $parts); + if ($wildcard === $reference) { + return true; + } + } + + return false; + } +} diff --git a/vendor/requests/library/Requests/Auth.php b/vendor/requests/library/Requests/Auth.php new file mode 100644 index 00000000..bca41092 --- /dev/null +++ b/vendor/requests/library/Requests/Auth.php @@ -0,0 +1,33 @@ +user, $this->pass) = $args; + } + } + + /** + * Register the necessary callbacks + * + * @see curl_before_send + * @see fsockopen_header + * @param Requests_Hooks $hooks Hook system + */ + public function register(Requests_Hooks &$hooks) { + $hooks->register('curl.before_send', array(&$this, 'curl_before_send')); + $hooks->register('fsockopen.after_headers', array(&$this, 'fsockopen_header')); + } + + /** + * Set cURL parameters before the data is sent + * + * @param resource $handle cURL resource + */ + public function curl_before_send(&$handle) { + curl_setopt($handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_setopt($handle, CURLOPT_USERPWD, $this->getAuthString()); + } + + /** + * Add extra headers to the request before sending + * + * @param string $out HTTP header string + */ + public function fsockopen_header(&$out) { + $out .= sprintf("Authorization: Basic %s\r\n", base64_encode($this->getAuthString())); + } + + /** + * Get the authentication string (user:pass) + * + * @return string + */ + public function getAuthString() { + return $this->user . ':' . $this->pass; + } +} \ No newline at end of file diff --git a/vendor/requests/library/Requests/Cookie.php b/vendor/requests/library/Requests/Cookie.php new file mode 100644 index 00000000..00fbbc73 --- /dev/null +++ b/vendor/requests/library/Requests/Cookie.php @@ -0,0 +1,500 @@ +name = $name; + $this->value = $value; + $this->attributes = $attributes; + $default_flags = array( + 'creation' => time(), + 'last-access' => time(), + 'persistent' => false, + 'host-only' => true, + ); + $this->flags = array_merge($default_flags, $flags); + + $this->reference_time = time(); + if ($reference_time !== null) { + $this->reference_time = $reference_time; + } + + $this->normalize(); + } + + /** + * Check if a cookie is expired. + * + * Checks the age against $this->reference_time to determine if the cookie + * is expired. + * + * @return boolean True if expired, false if time is valid. + */ + public function is_expired() { + // RFC6265, s. 4.1.2.2: + // If a cookie has both the Max-Age and the Expires attribute, the Max- + // Age attribute has precedence and controls the expiration date of the + // cookie. + if (isset($this->attributes['max-age'])) { + $max_age = $this->attributes['max-age']; + return $max_age < $this->reference_time; + } + + if (isset($this->attributes['expires'])) { + $expires = $this->attributes['expires']; + return $expires < $this->reference_time; + } + + return false; + } + + /** + * Check if a cookie is valid for a given URI + * + * @param Requests_IRI $uri URI to check + * @return boolean Whether the cookie is valid for the given URI + */ + public function uri_matches(Requests_IRI $uri) { + if (!$this->domain_matches($uri->host)) { + return false; + } + + if (!$this->path_matches($uri->path)) { + return false; + } + + return empty($this->attributes['secure']) || $uri->scheme === 'https'; + } + + /** + * Check if a cookie is valid for a given domain + * + * @param string $string Domain to check + * @return boolean Whether the cookie is valid for the given domain + */ + public function domain_matches($string) { + if (!isset($this->attributes['domain'])) { + // Cookies created manually; cookies created by Requests will set + // the domain to the requested domain + return true; + } + + $domain_string = $this->attributes['domain']; + if ($domain_string === $string) { + // The domain string and the string are identical. + return true; + } + + // If the cookie is marked as host-only and we don't have an exact + // match, reject the cookie + if ($this->flags['host-only'] === true) { + return false; + } + + if (strlen($string) <= strlen($domain_string)) { + // For obvious reasons, the string cannot be a suffix if the domain + // is shorter than the domain string + return false; + } + + if (substr($string, -1 * strlen($domain_string)) !== $domain_string) { + // The domain string should be a suffix of the string. + return false; + } + + $prefix = substr($string, 0, strlen($string) - strlen($domain_string)); + if (substr($prefix, -1) !== '.') { + // The last character of the string that is not included in the + // domain string should be a %x2E (".") character. + return false; + } + + // The string should be a host name (i.e., not an IP address). + return !preg_match('#^(.+\.)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $string); + } + + /** + * Check if a cookie is valid for a given path + * + * From the path-match check in RFC 6265 section 5.1.4 + * + * @param string $request_path Path to check + * @return boolean Whether the cookie is valid for the given path + */ + public function path_matches($request_path) { + if (empty($request_path)) { + // Normalize empty path to root + $request_path = '/'; + } + + if (!isset($this->attributes['path'])) { + // Cookies created manually; cookies created by Requests will set + // the path to the requested path + return true; + } + + $cookie_path = $this->attributes['path']; + + if ($cookie_path === $request_path) { + // The cookie-path and the request-path are identical. + return true; + } + + if (strlen($request_path) > strlen($cookie_path) && substr($request_path, 0, strlen($cookie_path)) === $cookie_path) { + if (substr($cookie_path, -1) === '/') { + // The cookie-path is a prefix of the request-path, and the last + // character of the cookie-path is %x2F ("/"). + return true; + } + + if (substr($request_path, strlen($cookie_path), 1) === '/') { + // The cookie-path is a prefix of the request-path, and the + // first character of the request-path that is not included in + // the cookie-path is a %x2F ("/") character. + return true; + } + } + + return false; + } + + /** + * Normalize cookie and attributes + * + * @return boolean Whether the cookie was successfully normalized + */ + public function normalize() { + foreach ($this->attributes as $key => $value) { + $orig_value = $value; + $value = $this->normalize_attribute($key, $value); + if ($value === null) { + unset($this->attributes[$key]); + continue; + } + + if ($value !== $orig_value) { + $this->attributes[$key] = $value; + } + } + + return true; + } + + /** + * Parse an individual cookie attribute + * + * Handles parsing individual attributes from the cookie values. + * + * @param string $name Attribute name + * @param string|boolean $value Attribute value (string value, or true if empty/flag) + * @return mixed Value if available, or null if the attribute value is invalid (and should be skipped) + */ + protected function normalize_attribute($name, $value) { + switch (strtolower($name)) { + case 'expires': + // Expiration parsing, as per RFC 6265 section 5.2.1 + if (is_int($value)) { + return $value; + } + + $expiry_time = strtotime($value); + if ($expiry_time === false) { + return null; + } + + return $expiry_time; + + case 'max-age': + // Expiration parsing, as per RFC 6265 section 5.2.2 + if (is_int($value)) { + return $value; + } + + // Check that we have a valid age + if (!preg_match('/^-?\d+$/', $value)) { + return null; + } + + $delta_seconds = (int) $value; + if ($delta_seconds <= 0) { + $expiry_time = 0; + } + else { + $expiry_time = $this->reference_time + $delta_seconds; + } + + return $expiry_time; + + case 'domain': + // Domain normalization, as per RFC 6265 section 5.2.3 + if ($value[0] === '.') { + $value = substr($value, 1); + } + + return $value; + + default: + return $value; + } + } + + /** + * Format a cookie for a Cookie header + * + * This is used when sending cookies to a server. + * + * @return string Cookie formatted for Cookie header + */ + public function format_for_header() { + return sprintf('%s=%s', $this->name, $this->value); + } + + /** + * Format a cookie for a Cookie header + * + * @codeCoverageIgnore + * @deprecated Use {@see Requests_Cookie::format_for_header} + * @return string + */ + public function formatForHeader() { + return $this->format_for_header(); + } + + /** + * Format a cookie for a Set-Cookie header + * + * This is used when sending cookies to clients. This isn't really + * applicable to client-side usage, but might be handy for debugging. + * + * @return string Cookie formatted for Set-Cookie header + */ + public function format_for_set_cookie() { + $header_value = $this->format_for_header(); + if (!empty($this->attributes)) { + $parts = array(); + foreach ($this->attributes as $key => $value) { + // Ignore non-associative attributes + if (is_numeric($key)) { + $parts[] = $value; + } + else { + $parts[] = sprintf('%s=%s', $key, $value); + } + } + + $header_value .= '; ' . implode('; ', $parts); + } + return $header_value; + } + + /** + * Format a cookie for a Set-Cookie header + * + * @codeCoverageIgnore + * @deprecated Use {@see Requests_Cookie::format_for_set_cookie} + * @return string + */ + public function formatForSetCookie() { + return $this->format_for_set_cookie(); + } + + /** + * Get the cookie value + * + * Attributes and other data can be accessed via methods. + */ + public function __toString() { + return $this->value; + } + + /** + * Parse a cookie string into a cookie object + * + * Based on Mozilla's parsing code in Firefox and related projects, which + * is an intentional deviation from RFC 2109 and RFC 2616. RFC 6265 + * specifies some of this handling, but not in a thorough manner. + * + * @param string Cookie header value (from a Set-Cookie header) + * @return Requests_Cookie Parsed cookie object + */ + public static function parse($string, $name = '', $reference_time = null) { + $parts = explode(';', $string); + $kvparts = array_shift($parts); + + if (!empty($name)) { + $value = $string; + } + elseif (strpos($kvparts, '=') === false) { + // Some sites might only have a value without the equals separator. + // Deviate from RFC 6265 and pretend it was actually a blank name + // (`=foo`) + // + // https://bugzilla.mozilla.org/show_bug.cgi?id=169091 + $name = ''; + $value = $kvparts; + } + else { + list($name, $value) = explode('=', $kvparts, 2); + } + $name = trim($name); + $value = trim($value); + + // Attribute key are handled case-insensitively + $attributes = new Requests_Utility_CaseInsensitiveDictionary(); + + if (!empty($parts)) { + foreach ($parts as $part) { + if (strpos($part, '=') === false) { + $part_key = $part; + $part_value = true; + } + else { + list($part_key, $part_value) = explode('=', $part, 2); + $part_value = trim($part_value); + } + + $part_key = trim($part_key); + $attributes[$part_key] = $part_value; + } + } + + return new Requests_Cookie($name, $value, $attributes, array(), $reference_time); + } + + /** + * Parse all Set-Cookie headers from request headers + * + * @param Requests_Response_Headers $headers Headers to parse from + * @param Requests_IRI|null $origin URI for comparing cookie origins + * @param int|null $time Reference time for expiration calculation + * @return array + */ + public static function parse_from_headers(Requests_Response_Headers $headers, Requests_IRI $origin = null, $time = null) { + $cookie_headers = $headers->getValues('Set-Cookie'); + if (empty($cookie_headers)) { + return array(); + } + + $cookies = array(); + foreach ($cookie_headers as $header) { + $parsed = self::parse($header, '', $time); + + // Default domain/path attributes + if (empty($parsed->attributes['domain']) && !empty($origin)) { + $parsed->attributes['domain'] = $origin->host; + $parsed->flags['host-only'] = true; + } + else { + $parsed->flags['host-only'] = false; + } + + $path_is_valid = (!empty($parsed->attributes['path']) && $parsed->attributes['path'][0] === '/'); + if (!$path_is_valid && !empty($origin)) { + $path = $origin->path; + + // Default path normalization as per RFC 6265 section 5.1.4 + if (substr($path, 0, 1) !== '/') { + // If the uri-path is empty or if the first character of + // the uri-path is not a %x2F ("/") character, output + // %x2F ("/") and skip the remaining steps. + $path = '/'; + } + elseif (substr_count($path, '/') === 1) { + // If the uri-path contains no more than one %x2F ("/") + // character, output %x2F ("/") and skip the remaining + // step. + $path = '/'; + } + else { + // Output the characters of the uri-path from the first + // character up to, but not including, the right-most + // %x2F ("/"). + $path = substr($path, 0, strrpos($path, '/')); + } + $parsed->attributes['path'] = $path; + } + + // Reject invalid cookie domains + if (!empty($origin) && !$parsed->domain_matches($origin->host)) { + continue; + } + + $cookies[$parsed->name] = $parsed; + } + + return $cookies; + } + + /** + * Parse all Set-Cookie headers from request headers + * + * @codeCoverageIgnore + * @deprecated Use {@see Requests_Cookie::parse_from_headers} + * @return string + */ + public static function parseFromHeaders(Requests_Response_Headers $headers) { + return self::parse_from_headers($headers); + } +} diff --git a/vendor/requests/library/Requests/Cookie/Jar.php b/vendor/requests/library/Requests/Cookie/Jar.php new file mode 100644 index 00000000..69be0fb5 --- /dev/null +++ b/vendor/requests/library/Requests/Cookie/Jar.php @@ -0,0 +1,175 @@ +cookies = $cookies; + } + + /** + * Normalise cookie data into a Requests_Cookie + * + * @param string|Requests_Cookie $cookie + * @return Requests_Cookie + */ + public function normalize_cookie($cookie, $key = null) { + if ($cookie instanceof Requests_Cookie) { + return $cookie; + } + + return Requests_Cookie::parse($cookie, $key); + } + + /** + * Normalise cookie data into a Requests_Cookie + * + * @codeCoverageIgnore + * @deprecated Use {@see Requests_Cookie_Jar::normalize_cookie} + * @return Requests_Cookie + */ + public function normalizeCookie($cookie, $key = null) { + return $this->normalize_cookie($cookie, $key); + } + + /** + * Check if the given item exists + * + * @param string $key Item key + * @return boolean Does the item exist? + */ + public function offsetExists($key) { + return isset($this->cookies[$key]); + } + + /** + * Get the value for the item + * + * @param string $key Item key + * @return string Item value + */ + public function offsetGet($key) { + if (!isset($this->cookies[$key])) { + return null; + } + + return $this->cookies[$key]; + } + + /** + * Set the given item + * + * @throws Requests_Exception On attempting to use dictionary as list (`invalidset`) + * + * @param string $key Item name + * @param string $value Item value + */ + public function offsetSet($key, $value) { + if ($key === null) { + throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset'); + } + + $this->cookies[$key] = $value; + } + + /** + * Unset the given header + * + * @param string $key + */ + public function offsetUnset($key) { + unset($this->cookies[$key]); + } + + /** + * Get an iterator for the data + * + * @return ArrayIterator + */ + public function getIterator() { + return new ArrayIterator($this->cookies); + } + + /** + * Register the cookie handler with the request's hooking system + * + * @param Requests_Hooker $hooks Hooking system + */ + public function register(Requests_Hooker $hooks) { + $hooks->register('requests.before_request', array($this, 'before_request')); + $hooks->register('requests.before_redirect_check', array($this, 'before_redirect_check')); + } + + /** + * Add Cookie header to a request if we have any + * + * As per RFC 6265, cookies are separated by '; ' + * + * @param string $url + * @param array $headers + * @param array $data + * @param string $type + * @param array $options + */ + public function before_request($url, &$headers, &$data, &$type, &$options) { + if (!$url instanceof Requests_IRI) { + $url = new Requests_IRI($url); + } + + if (!empty($this->cookies)) { + $cookies = array(); + foreach ($this->cookies as $key => $cookie) { + $cookie = $this->normalize_cookie($cookie, $key); + + // Skip expired cookies + if ($cookie->is_expired()) { + continue; + } + + if ($cookie->domain_matches($url->host)) { + $cookies[] = $cookie->format_for_header(); + } + } + + $headers['Cookie'] = implode('; ', $cookies); + } + } + + /** + * Parse all cookies from a response and attach them to the response + * + * @var Requests_Response $response + */ + public function before_redirect_check(Requests_Response &$return) { + $url = $return->url; + if (!$url instanceof Requests_IRI) { + $url = new Requests_IRI($url); + } + + $cookies = Requests_Cookie::parse_from_headers($return->headers, $url); + $this->cookies = array_merge($this->cookies, $cookies); + $return->cookies = $this; + } +} \ No newline at end of file diff --git a/vendor/requests/library/Requests/Exception.php b/vendor/requests/library/Requests/Exception.php new file mode 100644 index 00000000..37d4711c --- /dev/null +++ b/vendor/requests/library/Requests/Exception.php @@ -0,0 +1,62 @@ +type = $type; + $this->data = $data; + } + + /** + * Like {@see getCode()}, but a string code. + * + * @codeCoverageIgnore + * @return string + */ + public function getType() { + return $this->type; + } + + /** + * Gives any relevant data + * + * @codeCoverageIgnore + * @return mixed + */ + public function getData() { + return $this->data; + } +} \ No newline at end of file diff --git a/vendor/requests/library/Requests/Exception/HTTP.php b/vendor/requests/library/Requests/Exception/HTTP.php new file mode 100644 index 00000000..9ac6a873 --- /dev/null +++ b/vendor/requests/library/Requests/Exception/HTTP.php @@ -0,0 +1,71 @@ +reason = $reason; + } + + $message = sprintf('%d %s', $this->code, $this->reason); + parent::__construct($message, 'httpresponse', $data, $this->code); + } + + /** + * Get the status message + */ + public function getReason() { + return $this->reason; + } + + /** + * Get the correct exception class for a given error code + * + * @param int|bool $code HTTP status code, or false if unavailable + * @return string Exception class name to use + */ + public static function get_class($code) { + if (!$code) { + return 'Requests_Exception_HTTP_Unknown'; + } + + $class = sprintf('Requests_Exception_HTTP_%d', $code); + if (class_exists($class)) { + return $class; + } + + return 'Requests_Exception_HTTP_Unknown'; + } +} \ No newline at end of file diff --git a/vendor/requests/library/Requests/Exception/HTTP/304.php b/vendor/requests/library/Requests/Exception/HTTP/304.php new file mode 100644 index 00000000..67990335 --- /dev/null +++ b/vendor/requests/library/Requests/Exception/HTTP/304.php @@ -0,0 +1,27 @@ +code = $data->status_code; + } + + parent::__construct($reason, $data); + } +} \ No newline at end of file diff --git a/vendor/requests/library/Requests/Exception/Transport.php b/vendor/requests/library/Requests/Exception/Transport.php new file mode 100644 index 00000000..e60b4884 --- /dev/null +++ b/vendor/requests/library/Requests/Exception/Transport.php @@ -0,0 +1,5 @@ +type = $type; + } + + if ($code !== null) { + $this->code = $code; + } + + if ($message !== null) { + $this->reason = $message; + } + + $message = sprintf('%d %s', $this->code, $this->reason); + parent::__construct($message, $this->type, $data, $this->code); + } + + /** + * Get the error message + */ + public function getReason() { + return $this->reason; + } + +} diff --git a/vendor/requests/library/Requests/Hooker.php b/vendor/requests/library/Requests/Hooker.php new file mode 100644 index 00000000..f667ae9c --- /dev/null +++ b/vendor/requests/library/Requests/Hooker.php @@ -0,0 +1,33 @@ +0 is executed later + */ + public function register($hook, $callback, $priority = 0); + + /** + * Dispatch a message + * + * @param string $hook Hook name + * @param array $parameters Parameters to pass to callbacks + * @return boolean Successfulness + */ + public function dispatch($hook, $parameters = array()); +} \ No newline at end of file diff --git a/vendor/requests/library/Requests/Hooks.php b/vendor/requests/library/Requests/Hooks.php new file mode 100644 index 00000000..2e61c734 --- /dev/null +++ b/vendor/requests/library/Requests/Hooks.php @@ -0,0 +1,68 @@ +0 is executed later + */ + public function register($hook, $callback, $priority = 0) { + if (!isset($this->hooks[$hook])) { + $this->hooks[$hook] = array(); + } + if (!isset($this->hooks[$hook][$priority])) { + $this->hooks[$hook][$priority] = array(); + } + + $this->hooks[$hook][$priority][] = $callback; + } + + /** + * Dispatch a message + * + * @param string $hook Hook name + * @param array $parameters Parameters to pass to callbacks + * @return boolean Successfulness + */ + public function dispatch($hook, $parameters = array()) { + if (empty($this->hooks[$hook])) { + return false; + } + + foreach ($this->hooks[$hook] as $priority => $hooked) { + foreach ($hooked as $callback) { + call_user_func_array($callback, $parameters); + } + } + + return true; + } +} \ No newline at end of file diff --git a/vendor/requests/library/Requests/IDNAEncoder.php b/vendor/requests/library/Requests/IDNAEncoder.php new file mode 100644 index 00000000..ebbe2111 --- /dev/null +++ b/vendor/requests/library/Requests/IDNAEncoder.php @@ -0,0 +1,388 @@ + 0) { + if ($position + $length > $strlen) { + throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); + } + for ($position++; $remaining > 0; $position++) { + $value = ord($input[$position]); + + // If it is invalid, count the sequence as invalid and reprocess the current byte: + if (($value & 0xC0) !== 0x80) { + throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); + } + + $character |= ($value & 0x3F) << (--$remaining * 6); + } + $position--; + } + + if ( + // Non-shortest form sequences are invalid + $length > 1 && $character <= 0x7F + || $length > 2 && $character <= 0x7FF + || $length > 3 && $character <= 0xFFFF + // Outside of range of ucschar codepoints + // Noncharacters + || ($character & 0xFFFE) === 0xFFFE + || $character >= 0xFDD0 && $character <= 0xFDEF + || ( + // Everything else not in ucschar + $character > 0xD7FF && $character < 0xF900 + || $character < 0x20 + || $character > 0x7E && $character < 0xA0 + || $character > 0xEFFFD + ) + ) { + throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); + } + + $codepoints[] = $character; + } + + return $codepoints; + } + + /** + * RFC3492-compliant encoder + * + * @internal Pseudo-code from Section 6.3 is commented with "#" next to relevant code + * @throws Requests_Exception On character outside of the domain (never happens with Punycode) (`idna.character_outside_domain`) + * + * @param string $input UTF-8 encoded string to encode + * @return string Punycode-encoded string + */ + public static function punycode_encode($input) { + $output = ''; +# let n = initial_n + $n = self::BOOTSTRAP_INITIAL_N; +# let delta = 0 + $delta = 0; +# let bias = initial_bias + $bias = self::BOOTSTRAP_INITIAL_BIAS; +# let h = b = the number of basic code points in the input + $h = $b = 0; // see loop +# copy them to the output in order + $codepoints = self::utf8_to_codepoints($input); + $extended = array(); + + foreach ($codepoints as $char) { + if ($char < 128) { + // Character is valid ASCII + // TODO: this should also check if it's valid for a URL + $output .= chr($char); + $h++; + } + // Check if the character is non-ASCII, but below initial n + // This never occurs for Punycode, so ignore in coverage + // @codeCoverageIgnoreStart + elseif ($char < $n) { + throw new Requests_Exception('Invalid character', 'idna.character_outside_domain', $char); + } + // @codeCoverageIgnoreEnd + else { + $extended[$char] = true; + } + } + $extended = array_keys($extended); + sort($extended); + $b = $h; +# [copy them] followed by a delimiter if b > 0 + if (strlen($output) > 0) { + $output .= '-'; + } +# {if the input contains a non-basic code point < n then fail} +# while h < length(input) do begin + while ($h < count($codepoints)) { +# let m = the minimum code point >= n in the input + $m = array_shift($extended); + //printf('next code point to insert is %s' . PHP_EOL, dechex($m)); +# let delta = delta + (m - n) * (h + 1), fail on overflow + $delta += ($m - $n) * ($h + 1); +# let n = m + $n = $m; +# for each code point c in the input (in order) do begin + for ($num = 0; $num < count($codepoints); $num++) { + $c = $codepoints[$num]; +# if c < n then increment delta, fail on overflow + if ($c < $n) { + $delta++; + } +# if c == n then begin + elseif ($c === $n) { +# let q = delta + $q = $delta; +# for k = base to infinity in steps of base do begin + for ($k = self::BOOTSTRAP_BASE; ; $k += self::BOOTSTRAP_BASE) { +# let t = tmin if k <= bias {+ tmin}, or +# tmax if k >= bias + tmax, or k - bias otherwise + if ($k <= ($bias + self::BOOTSTRAP_TMIN)) { + $t = self::BOOTSTRAP_TMIN; + } + elseif ($k >= ($bias + self::BOOTSTRAP_TMAX)) { + $t = self::BOOTSTRAP_TMAX; + } + else { + $t = $k - $bias; + } +# if q < t then break + if ($q < $t) { + break; + } +# output the code point for digit t + ((q - t) mod (base - t)) + $digit = $t + (($q - $t) % (self::BOOTSTRAP_BASE - $t)); + $output .= self::digit_to_char($digit); +# let q = (q - t) div (base - t) + $q = floor(($q - $t) / (self::BOOTSTRAP_BASE - $t)); +# end + } +# output the code point for digit q + $output .= self::digit_to_char($q); +# let bias = adapt(delta, h + 1, test h equals b?) + $bias = self::adapt($delta, $h + 1, $h === $b); +# let delta = 0 + $delta = 0; +# increment h + $h++; +# end + } +# end + } +# increment delta and n + $delta++; + $n++; +# end + } + + return $output; + } + + /** + * Convert a digit to its respective character + * + * @see https://tools.ietf.org/html/rfc3492#section-5 + * @throws Requests_Exception On invalid digit (`idna.invalid_digit`) + * + * @param int $digit Digit in the range 0-35 + * @return string Single character corresponding to digit + */ + protected static function digit_to_char($digit) { + // @codeCoverageIgnoreStart + // As far as I know, this never happens, but still good to be sure. + if ($digit < 0 || $digit > 35) { + throw new Requests_Exception(sprintf('Invalid digit %d', $digit), 'idna.invalid_digit', $digit); + } + // @codeCoverageIgnoreEnd + $digits = 'abcdefghijklmnopqrstuvwxyz0123456789'; + return substr($digits, $digit, 1); + } + + /** + * Adapt the bias + * + * @see https://tools.ietf.org/html/rfc3492#section-6.1 + * @param int $delta + * @param int $numpoints + * @param bool $firsttime + * @return int New bias + */ + protected static function adapt($delta, $numpoints, $firsttime) { +# function adapt(delta,numpoints,firsttime): +# if firsttime then let delta = delta div damp + if ($firsttime) { + $delta = floor($delta / self::BOOTSTRAP_DAMP); + } +# else let delta = delta div 2 + else { + $delta = floor($delta / 2); + } +# let delta = delta + (delta div numpoints) + $delta += floor($delta / $numpoints); +# let k = 0 + $k = 0; +# while delta > ((base - tmin) * tmax) div 2 do begin + $max = floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN) * self::BOOTSTRAP_TMAX) / 2); + while ($delta > $max) { +# let delta = delta div (base - tmin) + $delta = floor($delta / (self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN)); +# let k = k + base + $k += self::BOOTSTRAP_BASE; +# end + } +# return k + (((base - tmin + 1) * delta) div (delta + skew)) + return $k + floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN + 1) * $delta) / ($delta + self::BOOTSTRAP_SKEW)); + } +} \ No newline at end of file diff --git a/vendor/requests/library/Requests/IPv6.php b/vendor/requests/library/Requests/IPv6.php new file mode 100644 index 00000000..204dbd7e --- /dev/null +++ b/vendor/requests/library/Requests/IPv6.php @@ -0,0 +1,190 @@ + FF01:0:0:0:0:0:0:101 + * ::1 -> 0:0:0:0:0:0:0:1 + * + * @author Alexander Merz + * @author elfrink at introweb dot nl + * @author Josh Peck + * @copyright 2003-2005 The PHP Group + * @license http://www.opensource.org/licenses/bsd-license.php + * @param string $ip An IPv6 address + * @return string The uncompressed IPv6 address + */ + public static function uncompress($ip) { + if (substr_count($ip, '::') !== 1) { + return $ip; + } + + list($ip1, $ip2) = explode('::', $ip); + $c1 = ($ip1 === '') ? -1 : substr_count($ip1, ':'); + $c2 = ($ip2 === '') ? -1 : substr_count($ip2, ':'); + + if (strpos($ip2, '.') !== false) { + $c2++; + } + // :: + if ($c1 === -1 && $c2 === -1) { + $ip = '0:0:0:0:0:0:0:0'; + } + // ::xxx + else if ($c1 === -1) { + $fill = str_repeat('0:', 7 - $c2); + $ip = str_replace('::', $fill, $ip); + } + // xxx:: + else if ($c2 === -1) { + $fill = str_repeat(':0', 7 - $c1); + $ip = str_replace('::', $fill, $ip); + } + // xxx::xxx + else { + $fill = ':' . str_repeat('0:', 6 - $c2 - $c1); + $ip = str_replace('::', $fill, $ip); + } + return $ip; + } + + /** + * Compresses an IPv6 address + * + * RFC 4291 allows you to compress consecutive zero pieces in an address to + * '::'. This method expects a valid IPv6 address and compresses consecutive + * zero pieces to '::'. + * + * Example: FF01:0:0:0:0:0:0:101 -> FF01::101 + * 0:0:0:0:0:0:0:1 -> ::1 + * + * @see uncompress() + * @param string $ip An IPv6 address + * @return string The compressed IPv6 address + */ + public static function compress($ip) { + // Prepare the IP to be compressed + $ip = self::uncompress($ip); + $ip_parts = self::split_v6_v4($ip); + + // Replace all leading zeros + $ip_parts[0] = preg_replace('/(^|:)0+([0-9])/', '\1\2', $ip_parts[0]); + + // Find bunches of zeros + if (preg_match_all('/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE)) { + $max = 0; + $pos = null; + foreach ($matches[0] as $match) { + if (strlen($match[0]) > $max) { + $max = strlen($match[0]); + $pos = $match[1]; + } + } + + $ip_parts[0] = substr_replace($ip_parts[0], '::', $pos, $max); + } + + if ($ip_parts[1] !== '') { + return implode(':', $ip_parts); + } + else { + return $ip_parts[0]; + } + } + + /** + * Splits an IPv6 address into the IPv6 and IPv4 representation parts + * + * RFC 4291 allows you to represent the last two parts of an IPv6 address + * using the standard IPv4 representation + * + * Example: 0:0:0:0:0:0:13.1.68.3 + * 0:0:0:0:0:FFFF:129.144.52.38 + * + * @param string $ip An IPv6 address + * @return string[] [0] contains the IPv6 represented part, and [1] the IPv4 represented part + */ + protected static function split_v6_v4($ip) { + if (strpos($ip, '.') !== false) { + $pos = strrpos($ip, ':'); + $ipv6_part = substr($ip, 0, $pos); + $ipv4_part = substr($ip, $pos + 1); + return array($ipv6_part, $ipv4_part); + } + else { + return array($ip, ''); + } + } + + /** + * Checks an IPv6 address + * + * Checks if the given IP is a valid IPv6 address + * + * @param string $ip An IPv6 address + * @return bool true if $ip is a valid IPv6 address + */ + public static function check_ipv6($ip) { + $ip = self::uncompress($ip); + list($ipv6, $ipv4) = self::split_v6_v4($ip); + $ipv6 = explode(':', $ipv6); + $ipv4 = explode('.', $ipv4); + if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4) { + foreach ($ipv6 as $ipv6_part) { + // The section can't be empty + if ($ipv6_part === '') { + return false; + } + + // Nor can it be over four characters + if (strlen($ipv6_part) > 4) { + return false; + } + + // Remove leading zeros (this is safe because of the above) + $ipv6_part = ltrim($ipv6_part, '0'); + if ($ipv6_part === '') { + $ipv6_part = '0'; + } + + // Check the value is valid + $value = hexdec($ipv6_part); + if (dechex($value) !== strtolower($ipv6_part) || $value < 0 || $value > 0xFFFF) { + return false; + } + } + if (count($ipv4) === 4) { + foreach ($ipv4 as $ipv4_part) { + $value = (int) $ipv4_part; + if ((string) $value !== $ipv4_part || $value < 0 || $value > 0xFF) { + return false; + } + } + } + return true; + } + else { + return false; + } + } +} diff --git a/vendor/requests/library/Requests/IRI.php b/vendor/requests/library/Requests/IRI.php new file mode 100644 index 00000000..8dc2fa28 --- /dev/null +++ b/vendor/requests/library/Requests/IRI.php @@ -0,0 +1,1084 @@ + array( + 'port' => 674 + ), + 'dict' => array( + 'port' => 2628 + ), + 'file' => array( + 'ihost' => 'localhost' + ), + 'http' => array( + 'port' => 80, + ), + 'https' => array( + 'port' => 443, + ), + ); + + /** + * Return the entire IRI when you try and read the object as a string + * + * @return string + */ + public function __toString() { + return $this->get_iri(); + } + + /** + * Overload __set() to provide access via properties + * + * @param string $name Property name + * @param mixed $value Property value + */ + public function __set($name, $value) { + if (method_exists($this, 'set_' . $name)) { + call_user_func(array($this, 'set_' . $name), $value); + } + elseif ( + $name === 'iauthority' + || $name === 'iuserinfo' + || $name === 'ihost' + || $name === 'ipath' + || $name === 'iquery' + || $name === 'ifragment' + ) { + call_user_func(array($this, 'set_' . substr($name, 1)), $value); + } + } + + /** + * Overload __get() to provide access via properties + * + * @param string $name Property name + * @return mixed + */ + public function __get($name) { + // isset() returns false for null, we don't want to do that + // Also why we use array_key_exists below instead of isset() + $props = get_object_vars($this); + + if ( + $name === 'iri' || + $name === 'uri' || + $name === 'iauthority' || + $name === 'authority' + ) { + $method = 'get_' . $name; + $return = $this->$method(); + } + elseif (array_key_exists($name, $props)) { + $return = $this->$name; + } + // host -> ihost + elseif (($prop = 'i' . $name) && array_key_exists($prop, $props)) { + $name = $prop; + $return = $this->$prop; + } + // ischeme -> scheme + elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props)) { + $name = $prop; + $return = $this->$prop; + } + else { + trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE); + $return = null; + } + + if ($return === null && isset($this->normalization[$this->scheme][$name])) { + return $this->normalization[$this->scheme][$name]; + } + else { + return $return; + } + } + + /** + * Overload __isset() to provide access via properties + * + * @param string $name Property name + * @return bool + */ + public function __isset($name) { + return (method_exists($this, 'get_' . $name) || isset($this->$name)); + } + + /** + * Overload __unset() to provide access via properties + * + * @param string $name Property name + */ + public function __unset($name) { + if (method_exists($this, 'set_' . $name)) { + call_user_func(array($this, 'set_' . $name), ''); + } + } + + /** + * Create a new IRI object, from a specified string + * + * @param string|null $iri + */ + public function __construct($iri = null) { + $this->set_iri($iri); + } + + /** + * Create a new IRI object by resolving a relative IRI + * + * Returns false if $base is not absolute, otherwise an IRI. + * + * @param IRI|string $base (Absolute) Base IRI + * @param IRI|string $relative Relative IRI + * @return IRI|false + */ + public static function absolutize($base, $relative) { + if (!($relative instanceof Requests_IRI)) { + $relative = new Requests_IRI($relative); + } + if (!$relative->is_valid()) { + return false; + } + elseif ($relative->scheme !== null) { + return clone $relative; + } + + if (!($base instanceof Requests_IRI)) { + $base = new Requests_IRI($base); + } + if ($base->scheme === null || !$base->is_valid()) { + return false; + } + + if ($relative->get_iri() !== '') { + if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null) { + $target = clone $relative; + $target->scheme = $base->scheme; + } + else { + $target = new Requests_IRI; + $target->scheme = $base->scheme; + $target->iuserinfo = $base->iuserinfo; + $target->ihost = $base->ihost; + $target->port = $base->port; + if ($relative->ipath !== '') { + if ($relative->ipath[0] === '/') { + $target->ipath = $relative->ipath; + } + elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '') { + $target->ipath = '/' . $relative->ipath; + } + elseif (($last_segment = strrpos($base->ipath, '/')) !== false) { + $target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath; + } + else { + $target->ipath = $relative->ipath; + } + $target->ipath = $target->remove_dot_segments($target->ipath); + $target->iquery = $relative->iquery; + } + else { + $target->ipath = $base->ipath; + if ($relative->iquery !== null) { + $target->iquery = $relative->iquery; + } + elseif ($base->iquery !== null) { + $target->iquery = $base->iquery; + } + } + $target->ifragment = $relative->ifragment; + } + } + else { + $target = clone $base; + $target->ifragment = null; + } + $target->scheme_normalization(); + return $target; + } + + /** + * Parse an IRI into scheme/authority/path/query/fragment segments + * + * @param string $iri + * @return array + */ + protected function parse_iri($iri) { + $iri = trim($iri, "\x20\x09\x0A\x0C\x0D"); + $has_match = preg_match('/^((?P[^:\/?#]+):)?(\/\/(?P[^\/?#]*))?(?P[^?#]*)(\?(?P[^#]*))?(#(?P.*))?$/', $iri, $match); + if (!$has_match) { + throw new Requests_Exception('Cannot parse supplied IRI', 'iri.cannot_parse', $iri); + } + + if ($match[1] === '') { + $match['scheme'] = null; + } + if (!isset($match[3]) || $match[3] === '') { + $match['authority'] = null; + } + if (!isset($match[5])) { + $match['path'] = ''; + } + if (!isset($match[6]) || $match[6] === '') { + $match['query'] = null; + } + if (!isset($match[8]) || $match[8] === '') { + $match['fragment'] = null; + } + return $match; + } + + /** + * Remove dot segments from a path + * + * @param string $input + * @return string + */ + protected function remove_dot_segments($input) { + $output = ''; + while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..') { + // A: If the input buffer begins with a prefix of "../" or "./", + // then remove that prefix from the input buffer; otherwise, + if (strpos($input, '../') === 0) { + $input = substr($input, 3); + } + elseif (strpos($input, './') === 0) { + $input = substr($input, 2); + } + // B: if the input buffer begins with a prefix of "/./" or "/.", + // where "." is a complete path segment, then replace that prefix + // with "/" in the input buffer; otherwise, + elseif (strpos($input, '/./') === 0) { + $input = substr($input, 2); + } + elseif ($input === '/.') { + $input = '/'; + } + // C: if the input buffer begins with a prefix of "/../" or "/..", + // where ".." is a complete path segment, then replace that prefix + // with "/" in the input buffer and remove the last segment and its + // preceding "/" (if any) from the output buffer; otherwise, + elseif (strpos($input, '/../') === 0) { + $input = substr($input, 3); + $output = substr_replace($output, '', strrpos($output, '/')); + } + elseif ($input === '/..') { + $input = '/'; + $output = substr_replace($output, '', strrpos($output, '/')); + } + // D: if the input buffer consists only of "." or "..", then remove + // that from the input buffer; otherwise, + elseif ($input === '.' || $input === '..') { + $input = ''; + } + // E: move the first path segment in the input buffer to the end of + // the output buffer, including the initial "/" character (if any) + // and any subsequent characters up to, but not including, the next + // "/" character or the end of the input buffer + elseif (($pos = strpos($input, '/', 1)) !== false) { + $output .= substr($input, 0, $pos); + $input = substr_replace($input, '', 0, $pos); + } + else { + $output .= $input; + $input = ''; + } + } + return $output . $input; + } + + /** + * Replace invalid character with percent encoding + * + * @param string $string Input string + * @param string $extra_chars Valid characters not in iunreserved or + * iprivate (this is ASCII-only) + * @param bool $iprivate Allow iprivate + * @return string + */ + protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false) { + // Normalize as many pct-encoded sections as possible + $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string); + + // Replace invalid percent characters + $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string); + + // Add unreserved and % to $extra_chars (the latter is safe because all + // pct-encoded sections are now valid). + $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%'; + + // Now replace any bytes that aren't allowed with their pct-encoded versions + $position = 0; + $strlen = strlen($string); + while (($position += strspn($string, $extra_chars, $position)) < $strlen) { + $value = ord($string[$position]); + + // Start position + $start = $position; + + // By default we are valid + $valid = true; + + // No one byte sequences are valid due to the while. + // Two byte sequence: + if (($value & 0xE0) === 0xC0) { + $character = ($value & 0x1F) << 6; + $length = 2; + $remaining = 1; + } + // Three byte sequence: + elseif (($value & 0xF0) === 0xE0) { + $character = ($value & 0x0F) << 12; + $length = 3; + $remaining = 2; + } + // Four byte sequence: + elseif (($value & 0xF8) === 0xF0) { + $character = ($value & 0x07) << 18; + $length = 4; + $remaining = 3; + } + // Invalid byte: + else { + $valid = false; + $length = 1; + $remaining = 0; + } + + if ($remaining) { + if ($position + $length <= $strlen) { + for ($position++; $remaining; $position++) { + $value = ord($string[$position]); + + // Check that the byte is valid, then add it to the character: + if (($value & 0xC0) === 0x80) { + $character |= ($value & 0x3F) << (--$remaining * 6); + } + // If it is invalid, count the sequence as invalid and reprocess the current byte: + else { + $valid = false; + $position--; + break; + } + } + } + else { + $position = $strlen - 1; + $valid = false; + } + } + + // Percent encode anything invalid or not in ucschar + if ( + // Invalid sequences + !$valid + // Non-shortest form sequences are invalid + || $length > 1 && $character <= 0x7F + || $length > 2 && $character <= 0x7FF + || $length > 3 && $character <= 0xFFFF + // Outside of range of ucschar codepoints + // Noncharacters + || ($character & 0xFFFE) === 0xFFFE + || $character >= 0xFDD0 && $character <= 0xFDEF + || ( + // Everything else not in ucschar + $character > 0xD7FF && $character < 0xF900 + || $character < 0xA0 + || $character > 0xEFFFD + ) + && ( + // Everything not in iprivate, if it applies + !$iprivate + || $character < 0xE000 + || $character > 0x10FFFD + ) + ) { + // If we were a character, pretend we weren't, but rather an error. + if ($valid) { + $position--; + } + + for ($j = $start; $j <= $position; $j++) { + $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1); + $j += 2; + $position += 2; + $strlen += 2; + } + } + } + + return $string; + } + + /** + * Callback function for preg_replace_callback. + * + * Removes sequences of percent encoded bytes that represent UTF-8 + * encoded characters in iunreserved + * + * @param array $match PCRE match + * @return string Replacement + */ + protected function remove_iunreserved_percent_encoded($match) { + // As we just have valid percent encoded sequences we can just explode + // and ignore the first member of the returned array (an empty string). + $bytes = explode('%', $match[0]); + + // Initialize the new string (this is what will be returned) and that + // there are no bytes remaining in the current sequence (unsurprising + // at the first byte!). + $string = ''; + $remaining = 0; + + // Loop over each and every byte, and set $value to its value + for ($i = 1, $len = count($bytes); $i < $len; $i++) { + $value = hexdec($bytes[$i]); + + // If we're the first byte of sequence: + if (!$remaining) { + // Start position + $start = $i; + + // By default we are valid + $valid = true; + + // One byte sequence: + if ($value <= 0x7F) { + $character = $value; + $length = 1; + } + // Two byte sequence: + elseif (($value & 0xE0) === 0xC0) { + $character = ($value & 0x1F) << 6; + $length = 2; + $remaining = 1; + } + // Three byte sequence: + elseif (($value & 0xF0) === 0xE0) { + $character = ($value & 0x0F) << 12; + $length = 3; + $remaining = 2; + } + // Four byte sequence: + elseif (($value & 0xF8) === 0xF0) { + $character = ($value & 0x07) << 18; + $length = 4; + $remaining = 3; + } + // Invalid byte: + else { + $valid = false; + $remaining = 0; + } + } + // Continuation byte: + else { + // Check that the byte is valid, then add it to the character: + if (($value & 0xC0) === 0x80) { + $remaining--; + $character |= ($value & 0x3F) << ($remaining * 6); + } + // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence: + else { + $valid = false; + $remaining = 0; + $i--; + } + } + + // If we've reached the end of the current byte sequence, append it to Unicode::$data + if (!$remaining) { + // Percent encode anything invalid or not in iunreserved + if ( + // Invalid sequences + !$valid + // Non-shortest form sequences are invalid + || $length > 1 && $character <= 0x7F + || $length > 2 && $character <= 0x7FF + || $length > 3 && $character <= 0xFFFF + // Outside of range of iunreserved codepoints + || $character < 0x2D + || $character > 0xEFFFD + // Noncharacters + || ($character & 0xFFFE) === 0xFFFE + || $character >= 0xFDD0 && $character <= 0xFDEF + // Everything else not in iunreserved (this is all BMP) + || $character === 0x2F + || $character > 0x39 && $character < 0x41 + || $character > 0x5A && $character < 0x61 + || $character > 0x7A && $character < 0x7E + || $character > 0x7E && $character < 0xA0 + || $character > 0xD7FF && $character < 0xF900 + ) { + for ($j = $start; $j <= $i; $j++) { + $string .= '%' . strtoupper($bytes[$j]); + } + } + else { + for ($j = $start; $j <= $i; $j++) { + $string .= chr(hexdec($bytes[$j])); + } + } + } + } + + // If we have any bytes left over they are invalid (i.e., we are + // mid-way through a multi-byte sequence) + if ($remaining) { + for ($j = $start; $j < $len; $j++) { + $string .= '%' . strtoupper($bytes[$j]); + } + } + + return $string; + } + + protected function scheme_normalization() { + if (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo']) { + $this->iuserinfo = null; + } + if (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost']) { + $this->ihost = null; + } + if (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port']) { + $this->port = null; + } + if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath']) { + $this->ipath = ''; + } + if (isset($this->ihost) && empty($this->ipath)) { + $this->ipath = '/'; + } + if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery']) { + $this->iquery = null; + } + if (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment']) { + $this->ifragment = null; + } + } + + /** + * Check if the object represents a valid IRI. This needs to be done on each + * call as some things change depending on another part of the IRI. + * + * @return bool + */ + public function is_valid() { + $isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null; + if ($this->ipath !== '' && + ( + $isauthority && $this->ipath[0] !== '/' || + ( + $this->scheme === null && + !$isauthority && + strpos($this->ipath, ':') !== false && + (strpos($this->ipath, '/') === false ? true : strpos($this->ipath, ':') < strpos($this->ipath, '/')) + ) + ) + ) { + return false; + } + + return true; + } + + /** + * Set the entire IRI. Returns true on success, false on failure (if there + * are any invalid characters). + * + * @param string $iri + * @return bool + */ + protected function set_iri($iri) { + static $cache; + if (!$cache) { + $cache = array(); + } + + if ($iri === null) { + return true; + } + if (isset($cache[$iri])) { + list($this->scheme, + $this->iuserinfo, + $this->ihost, + $this->port, + $this->ipath, + $this->iquery, + $this->ifragment, + $return) = $cache[$iri]; + return $return; + } + + $parsed = $this->parse_iri((string) $iri); + + $return = $this->set_scheme($parsed['scheme']) + && $this->set_authority($parsed['authority']) + && $this->set_path($parsed['path']) + && $this->set_query($parsed['query']) + && $this->set_fragment($parsed['fragment']); + + $cache[$iri] = array($this->scheme, + $this->iuserinfo, + $this->ihost, + $this->port, + $this->ipath, + $this->iquery, + $this->ifragment, + $return); + return $return; + } + + /** + * Set the scheme. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $scheme + * @return bool + */ + protected function set_scheme($scheme) { + if ($scheme === null) { + $this->scheme = null; + } + elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme)) { + $this->scheme = null; + return false; + } + else { + $this->scheme = strtolower($scheme); + } + return true; + } + + /** + * Set the authority. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $authority + * @return bool + */ + protected function set_authority($authority) { + static $cache; + if (!$cache) { + $cache = array(); + } + + if ($authority === null) { + $this->iuserinfo = null; + $this->ihost = null; + $this->port = null; + return true; + } + if (isset($cache[$authority])) { + list($this->iuserinfo, + $this->ihost, + $this->port, + $return) = $cache[$authority]; + + return $return; + } + + $remaining = $authority; + if (($iuserinfo_end = strrpos($remaining, '@')) !== false) { + $iuserinfo = substr($remaining, 0, $iuserinfo_end); + $remaining = substr($remaining, $iuserinfo_end + 1); + } + else { + $iuserinfo = null; + } + if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false) { + $port = substr($remaining, $port_start + 1); + if ($port === false || $port === '') { + $port = null; + } + $remaining = substr($remaining, 0, $port_start); + } + else { + $port = null; + } + + $return = $this->set_userinfo($iuserinfo) && + $this->set_host($remaining) && + $this->set_port($port); + + $cache[$authority] = array($this->iuserinfo, + $this->ihost, + $this->port, + $return); + + return $return; + } + + /** + * Set the iuserinfo. + * + * @param string $iuserinfo + * @return bool + */ + protected function set_userinfo($iuserinfo) { + if ($iuserinfo === null) { + $this->iuserinfo = null; + } + else { + $this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:'); + $this->scheme_normalization(); + } + + return true; + } + + /** + * Set the ihost. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $ihost + * @return bool + */ + protected function set_host($ihost) { + if ($ihost === null) { + $this->ihost = null; + return true; + } + if (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']') { + if (Requests_IPv6::check_ipv6(substr($ihost, 1, -1))) { + $this->ihost = '[' . Requests_IPv6::compress(substr($ihost, 1, -1)) . ']'; + } + else { + $this->ihost = null; + return false; + } + } + else { + $ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;='); + + // Lowercase, but ignore pct-encoded sections (as they should + // remain uppercase). This must be done after the previous step + // as that can add unescaped characters. + $position = 0; + $strlen = strlen($ihost); + while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen) { + if ($ihost[$position] === '%') { + $position += 3; + } + else { + $ihost[$position] = strtolower($ihost[$position]); + $position++; + } + } + + $this->ihost = $ihost; + } + + $this->scheme_normalization(); + + return true; + } + + /** + * Set the port. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $port + * @return bool + */ + protected function set_port($port) { + if ($port === null) { + $this->port = null; + return true; + } + + if (strspn($port, '0123456789') === strlen($port)) { + $this->port = (int) $port; + $this->scheme_normalization(); + return true; + } + + $this->port = null; + return false; + } + + /** + * Set the ipath. + * + * @param string $ipath + * @return bool + */ + protected function set_path($ipath) { + static $cache; + if (!$cache) { + $cache = array(); + } + + $ipath = (string) $ipath; + + if (isset($cache[$ipath])) { + $this->ipath = $cache[$ipath][(int) ($this->scheme !== null)]; + } + else { + $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/'); + $removed = $this->remove_dot_segments($valid); + + $cache[$ipath] = array($valid, $removed); + $this->ipath = ($this->scheme !== null) ? $removed : $valid; + } + $this->scheme_normalization(); + return true; + } + + /** + * Set the iquery. + * + * @param string $iquery + * @return bool + */ + protected function set_query($iquery) { + if ($iquery === null) { + $this->iquery = null; + } + else { + $this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true); + $this->scheme_normalization(); + } + return true; + } + + /** + * Set the ifragment. + * + * @param string $ifragment + * @return bool + */ + protected function set_fragment($ifragment) { + if ($ifragment === null) { + $this->ifragment = null; + } + else { + $this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?'); + $this->scheme_normalization(); + } + return true; + } + + /** + * Convert an IRI to a URI (or parts thereof) + * + * @param string|bool IRI to convert (or false from {@see get_iri}) + * @return string|false URI if IRI is valid, false otherwise. + */ + protected function to_uri($string) { + if (!is_string($string)) { + return false; + } + + static $non_ascii; + if (!$non_ascii) { + $non_ascii = implode('', range("\x80", "\xFF")); + } + + $position = 0; + $strlen = strlen($string); + while (($position += strcspn($string, $non_ascii, $position)) < $strlen) { + $string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1); + $position += 3; + $strlen += 2; + } + + return $string; + } + + /** + * Get the complete IRI + * + * @return string + */ + protected function get_iri() { + if (!$this->is_valid()) { + return false; + } + + $iri = ''; + if ($this->scheme !== null) { + $iri .= $this->scheme . ':'; + } + if (($iauthority = $this->get_iauthority()) !== null) { + $iri .= '//' . $iauthority; + } + $iri .= $this->ipath; + if ($this->iquery !== null) { + $iri .= '?' . $this->iquery; + } + if ($this->ifragment !== null) { + $iri .= '#' . $this->ifragment; + } + + return $iri; + } + + /** + * Get the complete URI + * + * @return string + */ + protected function get_uri() { + return $this->to_uri($this->get_iri()); + } + + /** + * Get the complete iauthority + * + * @return string + */ + protected function get_iauthority() { + if ($this->iuserinfo === null && $this->ihost === null && $this->port === null) { + return null; + } + + $iauthority = ''; + if ($this->iuserinfo !== null) { + $iauthority .= $this->iuserinfo . '@'; + } + if ($this->ihost !== null) { + $iauthority .= $this->ihost; + } + if ($this->port !== null) { + $iauthority .= ':' . $this->port; + } + return $iauthority; + } + + /** + * Get the complete authority + * + * @return string + */ + protected function get_authority() { + $iauthority = $this->get_iauthority(); + if (is_string($iauthority)) { + return $this->to_uri($iauthority); + } + else { + return $iauthority; + } + } +} diff --git a/vendor/requests/library/Requests/Proxy.php b/vendor/requests/library/Requests/Proxy.php new file mode 100644 index 00000000..ac7c1d6b --- /dev/null +++ b/vendor/requests/library/Requests/Proxy.php @@ -0,0 +1,35 @@ +proxy = $args; + } + elseif (is_array($args)) { + if (count($args) == 1) { + list($this->proxy) = $args; + } + elseif (count($args) == 3) { + list($this->proxy, $this->user, $this->pass) = $args; + $this->use_authentication = true; + } + else { + throw new Requests_Exception('Invalid number of arguments', 'proxyhttpbadargs'); + } + } + } + + /** + * Register the necessary callbacks + * + * @since 1.6 + * @see curl_before_send + * @see fsockopen_remote_socket + * @see fsockopen_remote_host_path + * @see fsockopen_header + * @param Requests_Hooks $hooks Hook system + */ + public function register(Requests_Hooks &$hooks) { + $hooks->register('curl.before_send', array(&$this, 'curl_before_send')); + + $hooks->register('fsockopen.remote_socket', array(&$this, 'fsockopen_remote_socket')); + $hooks->register('fsockopen.remote_host_path', array(&$this, 'fsockopen_remote_host_path')); + if ($this->use_authentication) { + $hooks->register('fsockopen.after_headers', array(&$this, 'fsockopen_header')); + } + } + + /** + * Set cURL parameters before the data is sent + * + * @since 1.6 + * @param resource $handle cURL resource + */ + public function curl_before_send(&$handle) { + curl_setopt($handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + curl_setopt($handle, CURLOPT_PROXY, $this->proxy); + + if ($this->use_authentication) { + curl_setopt($handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); + curl_setopt($handle, CURLOPT_PROXYUSERPWD, $this->get_auth_string()); + } + } + + /** + * Alter remote socket information before opening socket connection + * + * @since 1.6 + * @param string $remote_socket Socket connection string + */ + public function fsockopen_remote_socket(&$remote_socket) { + $remote_socket = $this->proxy; + } + + /** + * Alter remote path before getting stream data + * + * @since 1.6 + * @param string $path Path to send in HTTP request string ("GET ...") + * @param string $url Full URL we're requesting + */ + public function fsockopen_remote_host_path(&$path, $url) { + $path = $url; + } + + /** + * Add extra headers to the request before sending + * + * @since 1.6 + * @param string $out HTTP header string + */ + public function fsockopen_header(&$out) { + $out .= sprintf("Proxy-Authorization: Basic %s\r\n", base64_encode($this->get_auth_string())); + } + + /** + * Get the authentication string (user:pass) + * + * @since 1.6 + * @return string + */ + public function get_auth_string() { + return $this->user . ':' . $this->pass; + } +} \ No newline at end of file diff --git a/vendor/requests/library/Requests/Response.php b/vendor/requests/library/Requests/Response.php new file mode 100644 index 00000000..3152fb6d --- /dev/null +++ b/vendor/requests/library/Requests/Response.php @@ -0,0 +1,121 @@ +headers = new Requests_Response_Headers(); + $this->cookies = new Requests_Cookie_Jar(); + } + + /** + * Response body + * + * @var string + */ + public $body = ''; + + /** + * Raw HTTP data from the transport + * + * @var string + */ + public $raw = ''; + + /** + * Headers, as an associative array + * + * @var Requests_Response_Headers Array-like object representing headers + */ + public $headers = array(); + + /** + * Status code, false if non-blocking + * + * @var integer|boolean + */ + public $status_code = false; + + /** + * Protocol version, false if non-blocking + * @var float|boolean + */ + public $protocol_version = false; + + /** + * Whether the request succeeded or not + * + * @var boolean + */ + public $success = false; + + /** + * Number of redirects the request used + * + * @var integer + */ + public $redirects = 0; + + /** + * URL requested + * + * @var string + */ + public $url = ''; + + /** + * Previous requests (from redirects) + * + * @var array Array of Requests_Response objects + */ + public $history = array(); + + /** + * Cookies from the request + * + * @var Requests_Cookie_Jar Array-like object representing a cookie jar + */ + public $cookies = array(); + + /** + * Is the response a redirect? + * + * @return boolean True if redirect (3xx status), false if not. + */ + public function is_redirect() { + $code = $this->status_code; + return in_array($code, array(300, 301, 302, 303, 307)) || $code > 307 && $code < 400; + } + + /** + * Throws an exception if the request was not successful + * + * @throws Requests_Exception If `$allow_redirects` is false, and code is 3xx (`response.no_redirects`) + * @throws Requests_Exception_HTTP On non-successful status code. Exception class corresponds to code (e.g. {@see Requests_Exception_HTTP_404}) + * @param boolean $allow_redirects Set to false to throw on a 3xx as well + */ + public function throw_for_status($allow_redirects = true) { + if ($this->is_redirect()) { + if (!$allow_redirects) { + throw new Requests_Exception('Redirection not allowed', 'response.no_redirects', $this); + } + } + elseif (!$this->success) { + $exception = Requests_Exception_HTTP::get_class($this->status_code); + throw new $exception(null, $this); + } + } +} diff --git a/vendor/requests/library/Requests/Response/Headers.php b/vendor/requests/library/Requests/Response/Headers.php new file mode 100644 index 00000000..cc6a2087 --- /dev/null +++ b/vendor/requests/library/Requests/Response/Headers.php @@ -0,0 +1,98 @@ +data[$key])) { + return null; + } + + return $this->flatten($this->data[$key]); + } + + /** + * Set the given item + * + * @throws Requests_Exception On attempting to use dictionary as list (`invalidset`) + * + * @param string $key Item name + * @param string $value Item value + */ + public function offsetSet($key, $value) { + if ($key === null) { + throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset'); + } + + $key = strtolower($key); + + if (!isset($this->data[$key])) { + $this->data[$key] = array(); + } + + $this->data[$key][] = $value; + } + + /** + * Get all values for a given header + * + * @param string $key + * @return array Header values + */ + public function getValues($key) { + $key = strtolower($key); + if (!isset($this->data[$key])) { + return null; + } + + return $this->data[$key]; + } + + /** + * Flattens a value into a string + * + * Converts an array into a string by imploding values with a comma, as per + * RFC2616's rules for folding headers. + * + * @param string|array $value Value to flatten + * @return string Flattened value + */ + public function flatten($value) { + if (is_array($value)) { + $value = implode(',', $value); + } + + return $value; + } + + /** + * Get an iterator for the data + * + * Converts the internal + * @return ArrayIterator + */ + public function getIterator() { + return new Requests_Utility_FilteredIterator($this->data, array($this, 'flatten')); + } +} diff --git a/vendor/requests/library/Requests/SSL.php b/vendor/requests/library/Requests/SSL.php new file mode 100644 index 00000000..2b037685 --- /dev/null +++ b/vendor/requests/library/Requests/SSL.php @@ -0,0 +1,152 @@ +useragent = 'X';` + * + * @var array + */ + public $options = array(); + + /** + * Create a new session + * + * @param string|null $url Base URL for requests + * @param array $headers Default headers for requests + * @param array $data Default data for requests + * @param array $options Default options for requests + */ + public function __construct($url = null, $headers = array(), $data = array(), $options = array()) { + $this->url = $url; + $this->headers = $headers; + $this->data = $data; + $this->options = $options; + + if (empty($this->options['cookies'])) { + $this->options['cookies'] = new Requests_Cookie_Jar(); + } + } + + /** + * Get a property's value + * + * @param string $key Property key + * @return mixed|null Property value, null if none found + */ + public function __get($key) { + if (isset($this->options[$key])) { + return $this->options[$key]; + } + + return null; + } + + /** + * Set a property's value + * + * @param string $key Property key + * @param mixed $value Property value + */ + public function __set($key, $value) { + $this->options[$key] = $value; + } + + /** + * Remove a property's value + * + * @param string $key Property key + */ + public function __isset($key) { + return isset($this->options[$key]); + } + + /** + * Remove a property's value + * + * @param string $key Property key + */ + public function __unset($key) { + if (isset($this->options[$key])) { + unset($this->options[$key]); + } + } + + /**#@+ + * @see request() + * @param string $url + * @param array $headers + * @param array $options + * @return Requests_Response + */ + /** + * Send a GET request + */ + public function get($url, $headers = array(), $options = array()) { + return $this->request($url, $headers, null, Requests::GET, $options); + } + + /** + * Send a HEAD request + */ + public function head($url, $headers = array(), $options = array()) { + return $this->request($url, $headers, null, Requests::HEAD, $options); + } + + /** + * Send a DELETE request + */ + public function delete($url, $headers = array(), $options = array()) { + return $this->request($url, $headers, null, Requests::DELETE, $options); + } + /**#@-*/ + + /**#@+ + * @see request() + * @param string $url + * @param array $headers + * @param array $data + * @param array $options + * @return Requests_Response + */ + /** + * Send a POST request + */ + public function post($url, $headers = array(), $data = array(), $options = array()) { + return $this->request($url, $headers, $data, Requests::POST, $options); + } + + /** + * Send a PUT request + */ + public function put($url, $headers = array(), $data = array(), $options = array()) { + return $this->request($url, $headers, $data, Requests::PUT, $options); + } + + /** + * Send a PATCH request + * + * Note: Unlike {@see post} and {@see put}, `$headers` is required, as the + * specification recommends that should send an ETag + * + * @link https://tools.ietf.org/html/rfc5789 + */ + public function patch($url, $headers, $data = array(), $options = array()) { + return $this->request($url, $headers, $data, Requests::PATCH, $options); + } + /**#@-*/ + + /** + * Main interface for HTTP requests + * + * This method initiates a request and sends it via a transport before + * parsing. + * + * @see Requests::request() + * + * @throws Requests_Exception On invalid URLs (`nonhttp`) + * + * @param string $url URL to request + * @param array $headers Extra headers to send with the request + * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests + * @param string $type HTTP request type (use Requests constants) + * @param array $options Options for the request (see {@see Requests::request}) + * @return Requests_Response + */ + public function request($url, $headers = array(), $data = array(), $type = Requests::GET, $options = array()) { + $request = $this->merge_request(compact('url', 'headers', 'data', 'options')); + + return Requests::request($request['url'], $request['headers'], $request['data'], $type, $request['options']); + } + + /** + * Send multiple HTTP requests simultaneously + * + * @see Requests::request_multiple() + * + * @param array $requests Requests data (see {@see Requests::request_multiple}) + * @param array $options Global and default options (see {@see Requests::request}) + * @return array Responses (either Requests_Response or a Requests_Exception object) + */ + public function request_multiple($requests, $options = array()) { + foreach ($requests as $key => $request) { + $requests[$key] = $this->merge_request($request, false); + } + + $options = array_merge($this->options, $options); + + // Disallow forcing the type, as that's a per request setting + unset($options['type']); + + return Requests::request_multiple($requests, $options); + } + + /** + * Merge a request's data with the default data + * + * @param array $request Request data (same form as {@see request_multiple}) + * @param boolean $merge_options Should we merge options as well? + * @return array Request data + */ + protected function merge_request($request, $merge_options = true) { + if ($this->url !== null) { + $request['url'] = Requests_IRI::absolutize($this->url, $request['url']); + $request['url'] = $request['url']->uri; + } + + if (empty($request['headers'])) { + $request['headers'] = array(); + } + $request['headers'] = array_merge($this->headers, $request['headers']); + + if (empty($request['data'])) { + if (is_array($this->data)) { + $request['data'] = $this->data; + } + } + elseif (is_array($request['data']) && is_array($this->data)) { + $request['data'] = array_merge($this->data, $request['data']); + } + + if ($merge_options !== false) { + $request['options'] = array_merge($this->options, $request['options']); + + // Disallow forcing the type, as that's a per request setting + unset($request['options']['type']); + } + + return $request; + } +} diff --git a/vendor/requests/library/Requests/Transport.php b/vendor/requests/library/Requests/Transport.php new file mode 100644 index 00000000..7e4a2629 --- /dev/null +++ b/vendor/requests/library/Requests/Transport.php @@ -0,0 +1,41 @@ +version = $curl['version_number']; + $this->handle = curl_init(); + + curl_setopt($this->handle, CURLOPT_HEADER, false); + curl_setopt($this->handle, CURLOPT_RETURNTRANSFER, 1); + if ($this->version >= self::CURL_7_10_5) { + curl_setopt($this->handle, CURLOPT_ENCODING, ''); + } + if (defined('CURLOPT_PROTOCOLS')) { + curl_setopt($this->handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + } + if (defined('CURLOPT_REDIR_PROTOCOLS')) { + curl_setopt($this->handle, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + } + } + + /** + * Destructor + */ + public function __destruct() { + if (is_resource($this->handle)) { + curl_close($this->handle); + } + } + + /** + * Perform a request + * + * @throws Requests_Exception On a cURL error (`curlerror`) + * + * @param string $url URL to request + * @param array $headers Associative array of request headers + * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD + * @param array $options Request options, see {@see Requests::response()} for documentation + * @return string Raw HTTP result + */ + public function request($url, $headers = array(), $data = array(), $options = array()) { + $this->hooks = $options['hooks']; + + $this->setup_handle($url, $headers, $data, $options); + + $options['hooks']->dispatch('curl.before_send', array(&$this->handle)); + + if ($options['filename'] !== false) { + $this->stream_handle = fopen($options['filename'], 'wb'); + } + + $this->response_data = ''; + $this->response_bytes = 0; + $this->response_byte_limit = false; + if ($options['max_bytes'] !== false) { + $this->response_byte_limit = $options['max_bytes']; + } + + if (isset($options['verify'])) { + if ($options['verify'] === false) { + curl_setopt($this->handle, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($this->handle, CURLOPT_SSL_VERIFYPEER, 0); + } + elseif (is_string($options['verify'])) { + curl_setopt($this->handle, CURLOPT_CAINFO, $options['verify']); + } + } + + if (isset($options['verifyname']) && $options['verifyname'] === false) { + curl_setopt($this->handle, CURLOPT_SSL_VERIFYHOST, 0); + } + + curl_exec($this->handle); + $response = $this->response_data; + + $options['hooks']->dispatch('curl.after_send', array()); + + if (curl_errno($this->handle) === 23 || curl_errno($this->handle) === 61) { + // Reset encoding and try again + curl_setopt($this->handle, CURLOPT_ENCODING, 'none'); + + $this->response_data = ''; + $this->response_bytes = 0; + curl_exec($this->handle); + $response = $this->response_data; + } + + $this->process_response($response, $options); + + // Need to remove the $this reference from the curl handle. + // Otherwise Requests_Transport_cURL wont be garbage collected and the curl_close() will never be called. + curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, null); + curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, null); + + return $this->headers; + } + + /** + * Send multiple requests simultaneously + * + * @param array $requests Request data + * @param array $options Global options + * @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well) + */ + public function request_multiple($requests, $options) { + // If you're not requesting, we can't get any responses ¯\_(ツ)_/¯ + if (empty($requests)) { + return array(); + } + + $multihandle = curl_multi_init(); + $subrequests = array(); + $subhandles = array(); + + $class = get_class($this); + foreach ($requests as $id => $request) { + $subrequests[$id] = new $class(); + $subhandles[$id] = $subrequests[$id]->get_subrequest_handle($request['url'], $request['headers'], $request['data'], $request['options']); + $request['options']['hooks']->dispatch('curl.before_multi_add', array(&$subhandles[$id])); + curl_multi_add_handle($multihandle, $subhandles[$id]); + } + + $completed = 0; + $responses = array(); + + $request['options']['hooks']->dispatch('curl.before_multi_exec', array(&$multihandle)); + + do { + $active = false; + + do { + $status = curl_multi_exec($multihandle, $active); + } + while ($status === CURLM_CALL_MULTI_PERFORM); + + $to_process = array(); + + // Read the information as needed + while ($done = curl_multi_info_read($multihandle)) { + $key = array_search($done['handle'], $subhandles, true); + if (!isset($to_process[$key])) { + $to_process[$key] = $done; + } + } + + // Parse the finished requests before we start getting the new ones + foreach ($to_process as $key => $done) { + $options = $requests[$key]['options']; + if (CURLE_OK !== $done['result']) { + //get error string for handle. + $reason = curl_error($done['handle']); + $exception = new Requests_Exception_Transport_cURL( + $reason, + Requests_Exception_Transport_cURL::EASY, + $done['handle'], + $done['result'] + ); + $responses[$key] = $exception; + $options['hooks']->dispatch('transport.internal.parse_error', array(&$responses[$key], $requests[$key])); + } + else { + $responses[$key] = $subrequests[$key]->process_response($subrequests[$key]->response_data, $options); + + $options['hooks']->dispatch('transport.internal.parse_response', array(&$responses[$key], $requests[$key])); + } + + curl_multi_remove_handle($multihandle, $done['handle']); + curl_close($done['handle']); + + if (!is_string($responses[$key])) { + $options['hooks']->dispatch('multiple.request.complete', array(&$responses[$key], $key)); + } + $completed++; + } + } + while ($active || $completed < count($subrequests)); + + $request['options']['hooks']->dispatch('curl.after_multi_exec', array(&$multihandle)); + + curl_multi_close($multihandle); + + return $responses; + } + + /** + * Get the cURL handle for use in a multi-request + * + * @param string $url URL to request + * @param array $headers Associative array of request headers + * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD + * @param array $options Request options, see {@see Requests::response()} for documentation + * @return resource Subrequest's cURL handle + */ + public function &get_subrequest_handle($url, $headers, $data, $options) { + $this->setup_handle($url, $headers, $data, $options); + + if ($options['filename'] !== false) { + $this->stream_handle = fopen($options['filename'], 'wb'); + } + + $this->response_data = ''; + $this->response_bytes = 0; + $this->response_byte_limit = false; + if ($options['max_bytes'] !== false) { + $this->response_byte_limit = $options['max_bytes']; + } + $this->hooks = $options['hooks']; + + return $this->handle; + } + + /** + * Setup the cURL handle for the given data + * + * @param string $url URL to request + * @param array $headers Associative array of request headers + * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD + * @param array $options Request options, see {@see Requests::response()} for documentation + */ + protected function setup_handle($url, $headers, $data, $options) { + $options['hooks']->dispatch('curl.before_request', array(&$this->handle)); + + // Force closing the connection for old versions of cURL (<7.22). + if ( ! isset( $headers['Connection'] ) ) { + $headers['Connection'] = 'close'; + } + + $headers = Requests::flatten($headers); + + if (!empty($data)) { + $data_format = $options['data_format']; + + if ($data_format === 'query') { + $url = self::format_get($url, $data); + $data = ''; + } + elseif (!is_string($data)) { + $data = http_build_query($data, null, '&'); + } + } + + switch ($options['type']) { + case Requests::POST: + curl_setopt($this->handle, CURLOPT_POST, true); + curl_setopt($this->handle, CURLOPT_POSTFIELDS, $data); + break; + case Requests::HEAD: + curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, $options['type']); + curl_setopt($this->handle, CURLOPT_NOBODY, true); + break; + case Requests::TRACE: + curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, $options['type']); + break; + case Requests::PATCH: + case Requests::PUT: + case Requests::DELETE: + case Requests::OPTIONS: + default: + curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, $options['type']); + if (!empty($data)) { + curl_setopt($this->handle, CURLOPT_POSTFIELDS, $data); + } + } + + // cURL requires a minimum timeout of 1 second when using the system + // DNS resolver, as it uses `alarm()`, which is second resolution only. + // There's no way to detect which DNS resolver is being used from our + // end, so we need to round up regardless of the supplied timeout. + // + // https://github.com/curl/curl/blob/4f45240bc84a9aa648c8f7243be7b79e9f9323a5/lib/hostip.c#L606-L609 + $timeout = max($options['timeout'], 1); + + if (is_int($timeout) || $this->version < self::CURL_7_16_2) { + curl_setopt($this->handle, CURLOPT_TIMEOUT, ceil($timeout)); + } + else { + curl_setopt($this->handle, CURLOPT_TIMEOUT_MS, round($timeout * 1000)); + } + + if (is_int($options['connect_timeout']) || $this->version < self::CURL_7_16_2) { + curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT, ceil($options['connect_timeout'])); + } + else { + curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT_MS, round($options['connect_timeout'] * 1000)); + } + curl_setopt($this->handle, CURLOPT_URL, $url); + curl_setopt($this->handle, CURLOPT_REFERER, $url); + curl_setopt($this->handle, CURLOPT_USERAGENT, $options['useragent']); + if (!empty($headers)) { + curl_setopt($this->handle, CURLOPT_HTTPHEADER, $headers); + } + if ($options['protocol_version'] === 1.1) { + curl_setopt($this->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + } + else { + curl_setopt($this->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + } + + if (true === $options['blocking']) { + curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, array(&$this, 'stream_headers')); + curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, array(&$this, 'stream_body')); + curl_setopt($this->handle, CURLOPT_BUFFERSIZE, Requests::BUFFER_SIZE); + } + } + + /** + * Process a response + * + * @param string $response Response data from the body + * @param array $options Request options + * @return string HTTP response data including headers + */ + public function process_response($response, $options) { + if ($options['blocking'] === false) { + $fake_headers = ''; + $options['hooks']->dispatch('curl.after_request', array(&$fake_headers)); + return false; + } + if ($options['filename'] !== false) { + fclose($this->stream_handle); + $this->headers = trim($this->headers); + } + else { + $this->headers .= $response; + } + + if (curl_errno($this->handle)) { + $error = sprintf( + 'cURL error %s: %s', + curl_errno($this->handle), + curl_error($this->handle) + ); + throw new Requests_Exception($error, 'curlerror', $this->handle); + } + $this->info = curl_getinfo($this->handle); + + $options['hooks']->dispatch('curl.after_request', array(&$this->headers, &$this->info)); + return $this->headers; + } + + /** + * Collect the headers as they are received + * + * @param resource $handle cURL resource + * @param string $headers Header string + * @return integer Length of provided header + */ + public function stream_headers($handle, $headers) { + // Why do we do this? cURL will send both the final response and any + // interim responses, such as a 100 Continue. We don't need that. + // (We may want to keep this somewhere just in case) + if ($this->done_headers) { + $this->headers = ''; + $this->done_headers = false; + } + $this->headers .= $headers; + + if ($headers === "\r\n") { + $this->done_headers = true; + } + return strlen($headers); + } + + /** + * Collect data as it's received + * + * @since 1.6.1 + * + * @param resource $handle cURL resource + * @param string $data Body data + * @return integer Length of provided data + */ + public function stream_body($handle, $data) { + $this->hooks->dispatch('request.progress', array($data, $this->response_bytes, $this->response_byte_limit)); + $data_length = strlen($data); + + // Are we limiting the response size? + if ($this->response_byte_limit) { + if ($this->response_bytes === $this->response_byte_limit) { + // Already at maximum, move on + return $data_length; + } + + if (($this->response_bytes + $data_length) > $this->response_byte_limit) { + // Limit the length + $limited_length = ($this->response_byte_limit - $this->response_bytes); + $data = substr($data, 0, $limited_length); + } + } + + if ($this->stream_handle) { + fwrite($this->stream_handle, $data); + } + else { + $this->response_data .= $data; + } + + $this->response_bytes += strlen($data); + return $data_length; + } + + /** + * Format a URL given GET data + * + * @param string $url + * @param array|object $data Data to build query using, see {@see https://secure.php.net/http_build_query} + * @return string URL with data + */ + protected static function format_get($url, $data) { + if (!empty($data)) { + $url_parts = parse_url($url); + if (empty($url_parts['query'])) { + $query = $url_parts['query'] = ''; + } + else { + $query = $url_parts['query']; + } + + $query .= '&' . http_build_query($data, null, '&'); + $query = trim($query, '&'); + + if (empty($url_parts['query'])) { + $url .= '?' . $query; + } + else { + $url = str_replace($url_parts['query'], $query, $url); + } + } + return $url; + } + + /** + * Whether this transport is valid + * + * @codeCoverageIgnore + * @return boolean True if the transport is valid, false otherwise. + */ + public static function test($capabilities = array()) { + if (!function_exists('curl_init') || !function_exists('curl_exec')) { + return false; + } + + // If needed, check that our installed curl version supports SSL + if (isset($capabilities['ssl']) && $capabilities['ssl']) { + $curl_version = curl_version(); + if (!(CURL_VERSION_SSL & $curl_version['features'])) { + return false; + } + } + + return true; + } +} diff --git a/vendor/requests/library/Requests/Transport/cacert.pem b/vendor/requests/library/Requests/Transport/cacert.pem new file mode 100644 index 00000000..56ece1a0 --- /dev/null +++ b/vendor/requests/library/Requests/Transport/cacert.pem @@ -0,0 +1,3554 @@ +## +## ca-bundle.crt -- Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Sat Dec 29 20:03:40 2012 +## +## This is a bundle of X.509 certificates of public Certificate Authorities +## (CA). These were automatically extracted from Mozilla's root certificates +## file (certdata.txt). This file can be found in the mozilla source tree: +## http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1 +## +## It contains the certificates in PEM format and therefore +## can be directly used with curl / libcurl / php_curl, or with +## an Apache+mod_ssl webserver for SSL client authentication. +## Just configure this file as the SSLCACertificateFile. +## + +# @(#) $RCSfile: certdata.txt,v $ $Revision: 1.87 $ $Date: 2012/12/29 16:32:45 $ + +EE Certification Centre Root CA +=============================== +-----BEGIN CERTIFICATE----- +MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG +EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy +dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw +MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB +UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy +ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM +TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2 +rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw +93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN +P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ +MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF +BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj +xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM +lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u +uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU +3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM +dcGWxZ0= +-----END CERTIFICATE----- + +GTE CyberTrust Global Root +========================== +-----BEGIN CERTIFICATE----- +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg +Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG +A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz +MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL +Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0 +IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u +sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql +HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID +AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW +M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF +NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +-----END CERTIFICATE----- + +Thawte Server CA +================ +-----BEGIN CERTIFICATE----- +MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs +dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UE +AxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5j +b20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNV +BAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29u +c3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcG +A1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0 +ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl +/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg7 +1CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzAR +MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9J +GubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZ +GCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc= +-----END CERTIFICATE----- + +Thawte Premium Server CA +======================== +-----BEGIN CERTIFICATE----- +MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs +dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE +AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl +ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT +AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU +VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2 +aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ +cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2 +aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh +Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/ +qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm +SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf +8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t +UCemDaYj+bvLpgcUQg== +-----END CERTIFICATE----- + +Equifax Secure CA +================= +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE +ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT +B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR +fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW +8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG +A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE +CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG +A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS +spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB +Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961 +zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB +BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95 +70+sB3c4 +-----END CERTIFICATE----- + +Digital Signature Trust Co. Global CA 1 +======================================= +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE +ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMTAeFw05ODEy +MTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs +IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJE +NySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2i +o74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo +BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0 +dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw +IoAPMTk5ODEyMTAxODEwMjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQY +MBaAFGp5fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i+DAM +BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB +ACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lNQseSJqBcNJo4cvj9axY+IO6CizEq +kzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4 +RbyhkwS7hp86W0N6w4pl +-----END CERTIFICATE----- + +Digital Signature Trust Co. Global CA 3 +======================================= +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE +ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMjAeFw05ODEy +MDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs +IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGOD +VvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JS +xhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo +BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0 +dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw +IoAPMTk5ODEyMDkxOTE3MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQY +MBaAFB6CTShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5WzAM +BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB +AEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHRxdf0CiUPPXiBng+xZ8SQTGPdXqfi +up/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVLB3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1 +mPnHfxsb1gYgAlihw6ID +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority +======================================================= +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMx +FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVow +XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz +IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94 +f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol +hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBAgUAA4GBALtMEivPLCYA +TxQT3ab7/AoRhIzzKBxnki98tsX63/Dolbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59Ah +WM1pF+NEHJwZRDmJXNycAA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2Omuf +Tqj/ZA1k +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority - G2 +============================================================ +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz +dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz +dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCO +FoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71 +lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQAB +MA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01UbSuvDV1Ai2TT +1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7iF6YM40AIOw7n60RzKprxaZLvcRTD +Oaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpYoJ2daZH9 +-----END CERTIFICATE----- + +GlobalSign Root CA +================== +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx +GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds +b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD +VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa +DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc +THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb +Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP +c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX +gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF +AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj +Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG +j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH +hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC +X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +GlobalSign Root CA - R2 +======================= +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6 +ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp +s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN +S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL +TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C +ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i +YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN +BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp +9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu +01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7 +9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +ValiCert Class 1 VA +=================== +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp +b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh +bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIy +MjM0OFoXDTE5MDYyNTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 +d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEg +UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 +LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIi +GQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCm +DuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0LBwG +lN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLWI8sogTLDAHkY7FkX +icnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPwnXS3qT6gpf+2SQMT2iLM7XGCK5nP +Orf1LXLI +-----END CERTIFICATE----- + +ValiCert Class 2 VA +=================== +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp +b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh +bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw +MTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 +d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIg +UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 +LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVC +CSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7Rf +ZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZ +SWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbV +UjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8 +W9ViH0Pd +-----END CERTIFICATE----- + +RSA Root Certificate 1 +====================== +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp +b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh +bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw +MjIzM1oXDTE5MDYyNjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 +d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMg +UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 +LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td +3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89H +BFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliEZwgs +3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJn0WuPIqpsHEzXcjF +V9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/APhmcGcwTTYJBtYze4D1gCCAPRX5r +on+jjBXu +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority - G3 +============================================================ +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy +dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1 +EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc +cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw +EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj +055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA +ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f +j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0 +xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa +t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- + +Verisign Class 4 Public Primary Certification Authority - G3 +============================================================ +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy +dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS +tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM +8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW +Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX +Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA +j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt +mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm +fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd +RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG +UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== +-----END CERTIFICATE----- + +Entrust.net Secure Server CA +============================ +-----BEGIN CERTIFICATE----- +MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMCVVMxFDASBgNV +BAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5uZXQvQ1BTIGluY29ycC4gYnkg +cmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRl +ZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eTAeFw05OTA1MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIG +A1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBi +eSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1p +dGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQ +aO2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5 +gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OCAdcw +ggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHboIHYpIHVMIHSMQsw +CQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5l +dC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF +bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu +dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0MFqBDzIwMTkw +NTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0Bow +HQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAaMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA +BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyN +Ewr75Ji174z4xRAN95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9 +n9cd2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= +-----END CERTIFICATE----- + +Entrust.net Premium 2048 Secure Server CA +========================================= +-----BEGIN CERTIFICATE----- +MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u +ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp +bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx +NzUwNTFaFw0xOTEyMjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 +d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u +ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL +Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr +hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW +nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi +VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo3QwcjARBglghkgBhvhC +AQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGAvtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdER +gL7YibkIozH5oSQJFrlwMB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0B +AQUFAAOCAQEAWUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo +oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQh7A6tcOdBTcS +o8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18f3v/rxzP5tsHrV7bhZ3QKw0z +2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfNB/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjX +OP/swNlQ8C5LWK5Gb9Auw2DaclVyvUxFnmG6v4SBkgPR0ml8xQ== +-----END CERTIFICATE----- + +Baltimore CyberTrust Root +========================= +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE +ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li +ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC +SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs +dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME +uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB +UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C +G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 +XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr +l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI +VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB +BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh +cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 +hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa +Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H +RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +Equifax Secure Global eBusiness CA +================================== +-----BEGIN CERTIFICATE----- +MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +RXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNp +bmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMx +HDAaBgNVBAoTE0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEds +b2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRV +PEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzN +qfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxn +hcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j +BBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hs +MA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okEN +I7SS+RkAZ70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIY +NMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV +-----END CERTIFICATE----- + +Equifax Secure eBusiness CA 1 +============================= +-----BEGIN CERTIFICATE----- +MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +RXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENB +LTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UE +ChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNz +IENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ +1MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBuWqDZQu4a +IZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKwEnv+j6YDAgMBAAGjZjBk +MBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEp4MlIR21kW +Nl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQF +AAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5 +lSE/9dR+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+ +KpYrtWKmpj29f5JZzVoqgrI3eQ== +-----END CERTIFICATE----- + +Equifax Secure eBusiness CA 2 +============================= +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEXMBUGA1UE +ChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0y +MB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoT +DkVxdWlmYXggU2VjdXJlMSYwJAYDVQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn +2Z0GvxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/BPO3QSQ5 +BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0CAwEAAaOCAQkwggEFMHAG +A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUx +JjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoG +A1UdEAQTMBGBDzIwMTkwNjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9e +uSBIplBqy/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQFMAMB +Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAAyGgq3oThr1 +jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia +78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUm +V+GRMOrN +-----END CERTIFICATE----- + +AddTrust Low-Value Services Root +================================ +-----BEGIN CERTIFICATE----- +MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU +cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw +CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO +ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6 +54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr +oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1 +Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui +GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w +HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT +RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw +HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt +ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph +iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY +eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr +mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj +ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= +-----END CERTIFICATE----- + +AddTrust External Root +====================== +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD +VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw +NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU +cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg +Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821 ++iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw +Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo +aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy +2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7 +7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL +VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk +VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB +IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl +j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355 +e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u +G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE----- + +AddTrust Public Services Root +============================= +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU +cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ +BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l +dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu +nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i +d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG +Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw +HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G +A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G +A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4 +JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL ++YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao +GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9 +Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H +EufOX1362KqxMy3ZdvJOOjMMK7MtkAY= +-----END CERTIFICATE----- + +AddTrust Qualified Certificates Root +==================================== +-----BEGIN CERTIFICATE----- +MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU +cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx +CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ +IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx +64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3 +KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o +L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR +wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU +MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE +BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y +azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG +GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X +dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze +RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB +iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE= +-----END CERTIFICATE----- + +Entrust Root Certification Authority +==================================== +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw +b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG +A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 +MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu +MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu +Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz +A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww +Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 +j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN +rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 +MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH +hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM +Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa +v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS +W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 +tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +RSA Security 2048 v3 +==================== +-----BEGIN CERTIFICATE----- +MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYDVQQK +ExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAy +MjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAb +BgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7 +Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgb +WhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iH +KrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP ++Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4E +FgQUB8NRMKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmY +v/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj +0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwj +VAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395 +nzIlQnQFgCi/vcEkllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA +pKnXwiJPZ9d37CAFYd4= +-----END CERTIFICATE----- + +GeoTrust Global CA +================== +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw +MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j +LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo +BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet +8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc +T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU +vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk +DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q +zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4 +d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2 +mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p +XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm +Mw== +-----END CERTIFICATE----- + +GeoTrust Global CA 2 +==================== +-----BEGIN CERTIFICATE----- +MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw +MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j +LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/ +NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k +LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA +Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b +HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH +K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7 +srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh +ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL +OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC +x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF +H4z1Ir+rzoPz4iIprn2DQKi6bA== +-----END CERTIFICATE----- + +GeoTrust Universal CA +===================== +-----BEGIN CERTIFICATE----- +MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1 +MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu +Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t +JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e +RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs +7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d +8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V +qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga +Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB +Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu +KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08 +ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0 +XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB +hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc +aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2 +qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL +oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK +xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF +KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2 +DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK +xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU +p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI +P/rmMuGNG2+k5o7Y+SlIis5z/iw= +-----END CERTIFICATE----- + +GeoTrust Universal CA 2 +======================= +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0 +MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg +SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0 +DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17 +j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q +JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a +QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2 +WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP +20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn +ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC +SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG +8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2 ++/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E +BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z +dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ +4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+ +mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq +A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg +Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP +pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d +FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp +gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm +X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS +-----END CERTIFICATE----- + +America Online Root Certification Authority 1 +============================================= +-----BEGIN CERTIFICATE----- +MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkG +A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg +T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lkhsmj76CG +v2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym1BW32J/X3HGrfpq/m44z +DyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsWOqMFf6Dch9Wc/HKpoH145LcxVR5lu9Rh +sCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP +8c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Z +o/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQB8itEf +GDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkFZu90821fnZmv9ov761KyBZiibyrF +VL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft +3OJvx8Fi8eNy1gTIdGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43g +Kd8hdIaC2y+CMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds +sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 +-----END CERTIFICATE----- + +America Online Root Certification Authority 2 +============================================= +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkG +A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg +T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC206B89en +fHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFciKtZHgVdEglZTvYYUAQv8 +f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2JxhP7JsowtS013wMPgwr38oE18aO6lhO +qKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JN +RvCAOVIyD+OEsnpD8l7eXz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0 +gBe4lL8BPeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67Xnfn +6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEqZ8A9W6Wa6897Gqid +FEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZo2C7HK2JNDJiuEMhBnIMoVxtRsX6 +Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnj +B453cMor9H124HhnAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3Op +aaEg5+31IqEjFNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmnxPBUlgtk87FY +T15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2LHo1YGwRgJfMqZJS5ivmae2p ++DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzcccobGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXg +JXUjhx5c3LqdsKyzadsXg8n33gy8CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//Zoy +zH1kUQ7rVyZ2OuMeIjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgO +ZtMADjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2FAjgQ5ANh +1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUXOm/9riW99XJZZLF0Kjhf +GEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPbAZO1XB4Y3WRayhgoPmMEEf0cjQAPuDff +Z4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQlZvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuP +cX/9XhmgD0uRuMRUvAawRY8mkaKO/qk= +-----END CERTIFICATE----- + +Visa eCommerce Root +=================== +-----BEGIN CERTIFICATE----- +MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG +EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug +QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2 +WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm +VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv +bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL +F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b +RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0 +TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI +/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs +GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG +MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc +CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW +YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz +zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu +YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt +398znM/jra6O1I7mT1GvFpLgXPYHDw== +-----END CERTIFICATE----- + +Certum Root CA +============== +-----BEGIN CERTIFICATE----- +MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK +ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla +Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u +by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x +wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL +kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ +89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K +Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P +NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+ +GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg +GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/ +0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS +qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw== +-----END CERTIFICATE----- + +Comodo AAA Services root +======================== +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw +MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl +c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV +BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG +C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs +i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW +Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH +Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK +Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f +BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl +cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz +LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm +7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z +8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C +12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +Comodo Secure Services root +=========================== +-----BEGIN CERTIFICATE----- +MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw +MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu +Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi +BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP +9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc +rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC +oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V +p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E +FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj +YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm +aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm +4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj +Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL +DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw +pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H +RR3B7Hzs/Sk= +-----END CERTIFICATE----- + +Comodo Trusted Services root +============================ +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw +MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h +bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw +IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7 +3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y +/9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6 +juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS +ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud +DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp +ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl +cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw +uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 +pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA +BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l +R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O +9y5Xt5hwXsjEeLBi +-----END CERTIFICATE----- + +QuoVadis Root CA +================ +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE +ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz +MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp +cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD +EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk +J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL +F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL +YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen +AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w +PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y +ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7 +MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj +YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs +ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW +Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu +BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw +FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6 +tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo +fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul +LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x +gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi +5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi +5nrQNiOKSnQ2+Q== +-----END CERTIFICATE----- + +QuoVadis Root CA 2 +================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +QuoVadis Root CA 3 +================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Security Communication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw +8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM +DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX +5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd +DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 +JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g +0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a +mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ +s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ +6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi +FL39vmwLAw== +-----END CERTIFICATE----- + +Sonera Class 2 Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG +U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw +NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh +IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3 +/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT +dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG +f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P +tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH +nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT +XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt +0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI +cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph +Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx +EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH +llpwrN9M +-----END CERTIFICATE----- + +Staat der Nederlanden Root CA +============================= +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE +ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g +Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w +HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh +bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt +vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P +jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca +C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth +vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6 +22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV +HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v +dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN +BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR +EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw +MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y +nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR +iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== +-----END CERTIFICATE----- + +TDC Internet Root CA +==================== +-----BEGIN CERTIFICATE----- +MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJESzEVMBMGA1UE +ChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTAeFw0wMTA0MDUx +NjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNVBAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJu +ZXQxHTAbBgNVBAsTFFREQyBJbnRlcm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxLhAvJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20j +xsNuZp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a0vnRrEvL +znWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc14izbSysseLlJ28TQx5yc +5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGNeGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6 +otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcDR0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZI +AYb4QgEBBAQDAgAHMGUGA1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMM +VERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxMEQ1JM +MTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3WjALBgNVHQ8EBAMC +AQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAwHQYDVR0OBBYEFGxkAcf9hW2syNqe +UAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJKoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0G +CSqGSIb3DQEBBQUAA4IBAQBOQ8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540m +gwV5dOy0uaOXwTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ +2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm899qNLPg7kbWzb +O0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0jUNAE4z9mQNUecYu6oah9jrU +Cbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38aQNiuJkFBT1reBK9sG9l +-----END CERTIFICATE----- + +UTN DATACorp SGC Root CA +======================== +-----BEGIN CERTIFICATE----- +MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE +BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl +IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ +BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa +MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w +HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy +dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys +raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo +wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA +9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv +33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud +DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9 +BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD +LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3 +DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft +Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0 +I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx +EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP +DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI +-----END CERTIFICATE----- + +UTN USERFirst Hardware Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE +BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl +IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd +BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx +OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0 +eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz +ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI +wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd +tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8 +i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf +Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw +gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF +lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF +UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF +BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW +XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2 +lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn +iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67 +nfhmqA== +-----END CERTIFICATE----- + +Camerfirma Chambers of Commerce Root +==================================== +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe +QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i +ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx +NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp +cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn +MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC +AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU +xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH +NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW +DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV +d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud +EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v +cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P +AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh +bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD +VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz +aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi +fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD +L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN +UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n +ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1 +erfutGWaIZDgqtCYvDi1czyL+Nw= +-----END CERTIFICATE----- + +Camerfirma Global Chambersign Root +================================== +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe +QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i +ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx +NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt +YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg +MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw +ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J +1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O +by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl +6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c +8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/ +BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j +aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B +Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj +aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y +ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh +bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA +PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y +gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ +PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4 +IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes +t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== +-----END CERTIFICATE----- + +NetLock Notary (Class A) Root +============================= +-----BEGIN CERTIFICATE----- +MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI +EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 +dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j +ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX +DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH +EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD +VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz +cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM +D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ +z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC +/tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7 +tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6 +4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG +A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC +Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv +bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu +IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn +LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0 +ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz +IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh +IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu +b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh +bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg +Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp +bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5 +ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP +ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB +CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr +KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM +8CgHrTwXZoi1/baI +-----END CERTIFICATE----- + +NetLock Business (Class B) Root +=============================== +-----BEGIN CERTIFICATE----- +MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUxETAPBgNVBAcT +CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV +BAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQDEylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikg +VGFudXNpdHZhbnlraWFkbzAeFw05OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYD +VQQGEwJIVTERMA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRv +bnNhZ2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5ldExvY2sg +VXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB +iQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2S +o/1bXHQawEfKOml2mrriRBf8TKPV/riXiK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr +1nGTLbO/CVRY7QbrqHvcQ7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV +HQ8BAf8EBAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZ +RUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRh +dGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQuIEEgaGl0 +ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRv +c2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUg +YXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh +c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBz +Oi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6ZXNA +bmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhl +IHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2 +YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBj +cHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06sPgzTEdM +43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXan3BukxowOR0w2y7jfLKR +stE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKSNitjrFgBazMpUIaD8QFI +-----END CERTIFICATE----- + +NetLock Express (Class C) Root +============================== +-----BEGIN CERTIFICATE----- +MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUxETAPBgNVBAcT +CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV +BAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQDEytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBD +KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJ +BgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 +dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMrTmV0TG9j +ayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzANBgkqhkiG9w0BAQEFAAOB +jQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNAOoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3Z +W3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63 +euyucYT2BDMIJTLrdKwWRMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQw +DgYDVR0PAQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEWggJN +RklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0YWxhbm9zIFN6b2xn +YWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBB +IGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBOZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1i +aXp0b3NpdGFzYSB2ZWRpLiBBIGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0 +ZWxlIGF6IGVsb2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs +ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25sYXBqYW4gYSBo +dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kga2VyaGV0byBheiBlbGxlbm9y +emVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4gSU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5k +IHRoZSB1c2Ugb2YgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQ +UyBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwg +YXQgY3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmYta3UzbM2 +xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2gpO0u9f38vf5NNwgMvOOW +gyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4Fp1hBWeAyNDYpQcCNJgEjTME1A== +-----END CERTIFICATE----- + +XRamp Global CA Root +==================== +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE +BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj +dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx +HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg +U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu +IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx +foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE +zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs +AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry +xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap +oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC +AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc +/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n +nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz +8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +Go Daddy Class 2 CA +=================== +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY +VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG +A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g +RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD +ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv +2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 +qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j +YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY +vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O +BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o +atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu +MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim +PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt +I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI +Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b +vZ8= +-----END CERTIFICATE----- + +Starfield Class 2 CA +==================== +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc +U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo +MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG +A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG +SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY +bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ +JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm +epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN +F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF +MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f +hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo +bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs +afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM +PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD +KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 +QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +StartCom Certification Authority +================================ +-----BEGIN CERTIFICATE----- +MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu +ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 +NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk +LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg +U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y +o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ +Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d +eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt +2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z +6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ +osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ +untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc +UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT +37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE +FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0 +Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj +YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH +AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw +Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg +U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5 +LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh +cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT +dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC +AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh +3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm +vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk +fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3 +fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ +EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq +yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl +1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/ +lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro +g14= +-----END CERTIFICATE----- + +Taiwan GRCA +=========== +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG +EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X +DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv +dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN +w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5 +BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O +1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO +htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov +J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7 +Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t +B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB +O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8 +lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV +HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2 +09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ +TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj +Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2 +Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU +D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz +DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk +Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk +7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ +CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy ++fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS +-----END CERTIFICATE----- + +Firmaprofesional Root CA +======================== +-----BEGIN CERTIFICATE----- +MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMxIjAgBgNVBAcT +GUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1dG9yaWRhZCBkZSBDZXJ0aWZp +Y2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FA +ZmlybWFwcm9mZXNpb25hbC5jb20wHhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTEL +MAkGA1UEBhMCRVMxIjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMT +OUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2 +ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20wggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5uCp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5V +j1H5WuretXDE7aTt/6MNbg9kUDGvASdYrv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJH +lShbz++AbOCQl4oBPB3zhxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf +3H5idPayBQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcLiam8 +NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcbAgMBAAGjgZ8wgZww +KgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lvbmFsLmNvbTASBgNVHRMBAf8ECDAG +AQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQAD +ggEBAEdz/o0nVPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq +u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36mhoEyIwOdyPdf +wUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzflZKG+TQyTmAyX9odtsz/ny4Cm +7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBpQWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YG +VM+h4k0460tQtcsm9MracEpqoeJ5quGnM/b9Sh/22WA= +-----END CERTIFICATE----- + +Wells Fargo Root CA +=================== +-----BEGIN CERTIFICATE----- +MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCVVMxFDASBgNV +BAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN +MDAxMDExMTY0MTI4WhcNMjEwMTE0MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dl +bGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEv +MC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n135zHCLielTWi5MbqNQ1mX +x3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHESxP9cMIlrCL1dQu3U+SlK93OvRw6esP3 +E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4OJgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5 +OEL8pahbSCOz6+MlsoCultQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4j +sNtlAHCEAQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMBAAGj +YTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcBCzAyMDAGCCsGAQUF +BwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRwb2xpY3kwDQYJKoZIhvcNAQEFBQAD +ggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrv +m+0fazbuSCUlFLZWohDo7qd/0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0R +OhPs7fpvcmR7nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx +x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ33ZwmVxwQ023 +tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s= +-----END CERTIFICATE----- + +Swisscom Root CA 1 +================== +-----BEGIN CERTIFICATE----- +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 +NY6E0F/6MBr1mmz0DlP5OlvRHA== +-----END CERTIFICATE----- + +DigiCert Assured ID Root CA +=========================== +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx +MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO +9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy +UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW +/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy +oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf +GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF +66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq +hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc +EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn +SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i +8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +DigiCert Global Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw +MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn +TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 +BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H +4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y +7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB +o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm +8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF +BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr +EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt +tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 +UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +DigiCert High Assurance EV Root CA +================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw +KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw +MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ +MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu +Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t +Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS +OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 +MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ +NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe +h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB +Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY +JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ +V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp +myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK +mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K +-----END CERTIFICATE----- + +Certplus Class 2 Primary CA +=========================== +-----BEGIN CERTIFICATE----- +MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE +BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN +OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy +dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR +5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ +Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO +YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e +e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME +CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ +YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t +L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD +P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R +TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+ +7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW +//1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 +l7+ijrRU +-----END CERTIFICATE----- + +DST Root CA X3 +============== +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK +ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X +DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1 +cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT +rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9 +UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy +xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d +utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ +MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug +dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE +GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw +RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS +fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + +DST ACES CA X6 +============== +-----BEGIN CERTIFICATE----- +MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT +MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha +MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE +CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI +DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa +pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow +GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy +MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu +Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy +dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU +CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2 +5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t +Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq +nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs +vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3 +oKfN5XozNmr6mis= +-----END CERTIFICATE----- + +TURKTRUST Certificate Services Provider Root 1 +============================================== +-----BEGIN CERTIFICATE----- +MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVTVCBF +bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGDAJUUjEP +MA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0 +acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMx +MDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsg +U2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYDVQQHDAZB +TktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBC +aWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GX +yGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8i +Si9BB35JYbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ +8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4 +W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRME +BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46 +sWrv7/hg0Uw2ZkUd82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxE +q8Sn5RTOPEFhfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy +B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgY +nNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H +-----END CERTIFICATE----- + +TURKTRUST Certificate Services Provider Root 2 +============================================== +-----BEGIN CERTIFICATE----- +MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBF +bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP +MA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg +QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcN +MDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVr +dHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEPMA0G +A1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls +acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqe +LCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKI +x+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2g +QrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr +5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMB +AAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8G +A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/ntt +Rbj2hWyfIvwqECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 +Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+ +hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P +9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5 +UrbnBEI= +-----END CERTIFICATE----- + +SwissSign Gold CA - G2 +====================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +SwissSign Silver CA - G2 +======================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority +======================================== +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx +CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ +cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN +b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9 +nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge +RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt +tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI +hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K +Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN +NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa +Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG +1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= +-----END CERTIFICATE----- + +thawte Primary Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE +BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 +aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3 +MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg +SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv +KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT +FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs +oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ +1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc +q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K +aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p +afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF +AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE +uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX +xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89 +jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH +z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA== +-----END CERTIFICATE----- + +VeriSign Class 3 Public Primary Certification Authority - G5 +============================================================ +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE +BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO +ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk +IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln +biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh +dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz +j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD +Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/ +Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r +fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/ +BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv +Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG +SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+ +X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE +KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC +Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE +ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----END CERTIFICATE----- + +SecureTrust CA +============== +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy +dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe +BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX +OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t +DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH +GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b +01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH +ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj +aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ +KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu +SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf +mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ +nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +Secure Global CA +================ +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH +bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg +MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg +Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx +YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ +bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g +8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV +HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi +0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn +oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA +MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ +OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn +CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 +3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +COMODO Certification Authority +============================== +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb +MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD +T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH ++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww +xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV +4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA +1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI +rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k +b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC +AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP +OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc +IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN ++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== +-----END CERTIFICATE----- + +Network Solutions Certificate Authority +======================================= +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG +EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr +IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx +MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx +jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT +aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT +crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc +/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB +AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv +bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA +A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q +4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ +GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD +ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- + +WellsSecure Public Root Certificate Authority +============================================= +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM +F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw +NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN +MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl +bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD +VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1 +iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13 +i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8 +bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB +K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB +AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu +cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm +lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB +i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww +GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI +K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0 +bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj +qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es +E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ +tylv2G0xffX8oRAHh84vWdw+WNs= +-----END CERTIFICATE----- + +COMODO ECC Certification Authority +================================== +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix +GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X +4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni +wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG +FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA +U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +IGC/A +===== +-----BEGIN CERTIFICATE----- +MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAkZSMQ8wDQYD +VQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVE +Q1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZy +MB4XDTAyMTIxMzE0MjkyM1oXDTIwMTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQI +EwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NT +STEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaIs9z4iPf930Pfeo2aSVz2 +TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCW +So7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYy +HF2fYPepraX/z9E0+X1bF8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNd +frGoRpAxVs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGdPDPQ +tQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNVHSAEDjAMMAoGCCqB +egF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAxNjAfBgNVHSMEGDAWgBSjBS8YYFDC +iQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUFAAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RK +q89toB9RlPhJy3Q2FLwV3duJL92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3Q +MZsyK10XZZOYYLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg +Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2aNjSaTFR+FwNI +lQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R0982gaEbeC9xs/FZTEYYKKuF +0mBWWg== +-----END CERTIFICATE----- + +Security Communication EV RootCA1 +================================= +-----BEGIN CERTIFICATE----- +MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh +dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE +BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl +Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO +/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX +WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z +ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4 +bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK +9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG +SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm +iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG +Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW +mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW +T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GA CA +=============================== +-----BEGIN CERTIFICATE----- +MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE +BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG +A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH +bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD +VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw +IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5 +IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9 +Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg +Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD +d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ +/yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R +LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ +KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm +MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4 ++vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa +hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY +okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0= +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA +========================= +-----BEGIN CERTIFICATE----- +MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE +BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL +EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0 +MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz +dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT +GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG +d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N +oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc +QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ +PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb +MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG +IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD +VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3 +LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A +dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn +AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA +4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg +AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA +egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6 +Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO +PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv +c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h +cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw +IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT +WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV +MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER +MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp +Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal +HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT +nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE +aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a +86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK +yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB +S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= +-----END CERTIFICATE----- + +Certigna +======== +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw +EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 +MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI +Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q +XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH +GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p +ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg +DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf +Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ +tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ +BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J +SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA +hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ +ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu +PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY +1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +AC Ra\xC3\xADz Certic\xC3\xA1mara S.A. +====================================== +-----BEGIN CERTIFICATE----- +MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNVBAYT +AkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRpZmljYWNpw7NuIERpZ2l0YWwg +LSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwaQUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4w +HhcNMDYxMTI3MjA0NjI5WhcNMzAwNDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+ +U29jaWVkYWQgQ2FtZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJh +IFMuQS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeGqentLhM0R7LQcNzJPNCN +yu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzLfDe3fezTf3MZsGqy2IiKLUV0qPezuMDU +2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQY5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU3 +4ojC2I+GdV75LaeHM/J4Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP +2yYe68yQ54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+bMMCm +8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48jilSH5L887uvDdUhf +HjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++EjYfDIJss2yKHzMI+ko6Kh3VOz3vCa +Mh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/ztA/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK +5lw1omdMEWux+IBkAC1vImHFrEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1b +czwmPS9KvqfJpxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE +AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCBlTCBkgYEVR0g +ADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFyYS5jb20vZHBjLzBaBggrBgEF +BQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW507WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2Ug +cHVlZGVuIGVuY29udHJhciBlbiBsYSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEf +AygPU3zmpFmps4p6xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuX +EpBcunvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/Jre7Ir5v +/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dpezy4ydV/NgIlqmjCMRW3 +MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42gzmRkBDI8ck1fj+404HGIGQatlDCIaR4 +3NAvO2STdPCWkPHv+wlaNECW8DYSwaN0jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wk +eZBWN7PGKX6jD/EpOe9+XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f +/RWmnkJDW2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/RL5h +RqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35rMDOhYil/SrnhLecU +Iw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxkBYn8eNZcLCZDqQ== +-----END CERTIFICATE----- + +TC TrustCenter Class 2 CA II +============================ +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy +IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw +MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 +c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE +AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw +IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2 +xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ +Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u +SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB +7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 +Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU +cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i +SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u +TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G +dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ +KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj +TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP +JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk +vQ== +-----END CERTIFICATE----- + +TC TrustCenter Class 3 CA II +============================ +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy +IENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYw +MTEyMTQ0MTU3WhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 +c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UE +AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJWHt4bNwcwIi9v8Qbxq63W +yKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+QVl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo +6SI7dYnWRBpl8huXJh0obazovVkdKyT21oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZ +uV3bOx4a+9P/FRQI2AlqukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk +2ZyqBwi1Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NXXAek0CSnwPIA1DCB +7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 +Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU +cnVzdENlbnRlciUyMENsYXNzJTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i +SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u +TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlNirTzwppVMXzE +O2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8TtXqluJucsG7Kv5sbviRmEb8 +yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9 +IJqDnxrcOfHFcqMRA/07QlIp2+gB95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal +092Y+tTmBvTwtiBjS+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc +5A== +-----END CERTIFICATE----- + +TC TrustCenter Universal CA I +============================= +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy +IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN +MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg +VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw +JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC +qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv +xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw +ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O +gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j +BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG +1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy +vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3 +ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT +ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a +7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY +-----END CERTIFICATE----- + +Deutsche Telekom Root CA 2 +========================== +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT +RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG +A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5 +MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G +A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS +b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5 +bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI +KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY +AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK +Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV +jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV +HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr +E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy +zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8 +rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G +dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU +Cm26OWMohpLzGITY+9HPBVZkVw== +-----END CERTIFICATE----- + +ComSign Secured CA +================== +-----BEGIN CERTIFICATE----- +MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE +AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w +NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD +QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs +49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH +7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB +kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1 +9guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw +AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t +U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA +j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC +AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a +BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp +FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP +51qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz +OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== +-----END CERTIFICATE----- + +Cybertrust Global Root +====================== +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li +ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4 +MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD +ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA ++Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW +0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL +AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin +89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT +8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2 +MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G +A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO +lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi +5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2 +hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T +X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----END CERTIFICATE----- + +ePKI Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG +EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx +MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq +MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs +IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi +lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv +qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX +12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O +WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ +ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao +lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ +vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi +Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi +MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 +1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq +KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV +xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP +NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r +GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE +xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx +gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy +sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD +BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3 +============================================================================================================================= +-----BEGIN CERTIFICATE----- +MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH +DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q +aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry +b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV +BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg +S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4 +MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl +IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF +n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl +IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft +dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl +cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO +Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1 +xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR +6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL +hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd +BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4 +N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT +y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh +LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M +dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI= +-----END CERTIFICATE----- + +Buypass Class 2 CA 1 +==================== +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAxMB4XDTA2 +MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh +c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7M +cXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLXl18xoS83 +0r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVBHfCuuCkslFJgNJQ72uA4 +0Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/R +uFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0P +AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV +1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt +7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2 +fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w +wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho +-----END CERTIFICATE----- + +Buypass Class 3 CA 1 +==================== +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1 +MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh +c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx +ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0 +n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia +AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c +1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P +AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7 +pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA +EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5 +htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj +el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 +-----END CERTIFICATE----- + +EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 +========================================================================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +certSIGN ROOT CA +================ +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD +VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa +Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE +CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I +JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH +rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 +ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD +0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 +AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B +Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB +AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 +SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 +x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt +vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz +TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +CNNIC ROOT +========== +-----BEGIN CERTIFICATE----- +MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE +ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw +OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD +o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz +VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT +VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or +czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK +y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC +wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S +lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5 +Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM +O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8 +BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2 +G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m +mxE= +-----END CERTIFICATE----- + +ApplicationCA - Japanese Government +=================================== +-----BEGIN CERTIFICATE----- +MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT +SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw +MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl +cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4 +fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN +wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE +jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu +nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU +WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV +BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD +vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs +o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g +/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD +io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW +dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL +rosot4LKGAfmt1t06SAZf7IbiVQ= +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G3 +============================================= +-----BEGIN CERTIFICATE----- +MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE +BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0 +IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz +NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo +YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT +LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j +K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE +c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C +IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu +dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr +2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9 +cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE +Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD +AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s +t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt +-----END CERTIFICATE----- + +thawte Primary Root CA - G2 +=========================== +-----BEGIN CERTIFICATE----- +MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC +VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu +IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg +Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV +MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG +b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt +IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS +LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5 +8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU +mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN +G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K +rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== +-----END CERTIFICATE----- + +thawte Primary Root CA - G3 +=========================== +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE +BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 +aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w +ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh +d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD +VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG +A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At +P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC ++BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY +7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW +vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ +KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK +A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu +t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC +8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm +er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A= +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G2 +============================================= +-----BEGIN CERTIFICATE----- +MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu +Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1 +OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg +MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl +b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG +BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc +KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+ +EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m +ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2 +npaqBA+K +-----END CERTIFICATE----- + +VeriSign Universal Root Certification Authority +=============================================== +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE +BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO +ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk +IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj +1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP +MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72 +9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I +AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR +tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G +CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O +a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud +DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3 +Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx +Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx +P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P +wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4 +mJO37M2CYfE45k+XmCpajQ== +-----END CERTIFICATE----- + +VeriSign Class 3 Public Primary Certification Authority - G4 +============================================================ +-----BEGIN CERTIFICATE----- +MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC +VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3 +b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz +ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU +cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo +b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8 +Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz +rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw +HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u +Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD +A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx +AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== +-----END CERTIFICATE----- + +NetLock Arany (Class Gold) FÅ‘tanúsítvány +============================================ +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G +A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 +dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB +cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx +MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO +ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 +c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu +0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw +/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk +H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw +fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 +neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW +qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta +YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna +NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu +dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +Staat der Nederlanden Root CA - G2 +================================== +-----BEGIN CERTIFICATE----- +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 +66+KAQ== +-----END CERTIFICATE----- + +CA Disig +======== +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK +QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw +MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz +bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm +GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD +Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo +hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt +ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w +gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P +AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz +aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff +ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa +BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t +WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3 +mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ +CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K +ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA +4Z7CRneC9VkGjCFMhwnN5ag= +-----END CERTIFICATE----- + +Juur-SK +======= +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcNAQkBFglwa2lA +c2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMRAw +DgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMwMVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqG +SIb3DQEJARYJcGtpQHNrLmVlMQswCQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVy +aW1pc2tlc2t1czEQMA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOBSvZiF3tf +TQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkzABpTpyHhOEvWgxutr2TC ++Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvHLCu3GFH+4Hv2qEivbDtPL+/40UceJlfw +UR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMPPbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDa +Tpxt4brNj3pssAki14sL2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQF +MAMBAf8wggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwICMIHD +HoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDkAGwAagBhAHMAdABh +AHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0AHMAZQBlAHIAaQBtAGkAcwBrAGUA +cwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABzAGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABr +AGkAbgBuAGkAdABhAG0AaQBzAGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nw +cy8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE +FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcYP2/v6X2+MA4G +A1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOiCfP+JmeaUOTDBS8rNXiRTHyo +ERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+gkcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyL +abVAyJRld/JXIWY7zoVAtjNjGr95HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678 +IIbsSt4beDI3poHSna9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkh +Mp6qqIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0ZTbvGRNs2 +yyqcjg== +-----END CERTIFICATE----- + +Hongkong Post Root CA 1 +======================= +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT +DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx +NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n +IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 +ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr +auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh +qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY +V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV +HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i +h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio +l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei +IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps +T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT +c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== +-----END CERTIFICATE----- + +SecureSign RootCA11 +=================== +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi +SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS +b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw +KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 +cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL +TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO +wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq +g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP +O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA +bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX +t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh +OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r +bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ +Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 +y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 +lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +ACEDICOM Root +============= +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority +======================================================= +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx +FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow +XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz +IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94 +f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol +hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBABByUqkFFBky +CEHwxWsKzH4PIRnN5GfcX6kb5sroc50i2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWX +bj9T/UWZYB2oK0z5XqcJ2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/ +D/xwzoiQ +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER +MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv +c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE +BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt +U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA +fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG +0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA +pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm +1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC +AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf +QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE +FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o +lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX +I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 +yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi +LXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi +=================================================== +-----BEGIN CERTIFICATE----- +MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG +EwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE8MDoGA1UEAxMz +ZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3 +MDEwNDExMzI0OFoXDTE3MDEwNDExMzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0 +cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9u +aWsgU2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdUMZTe1RK6UxYC6lhj71vY +8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlTL/jDj/6z/P2douNffb7tC+Bg62nsM+3Y +jfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAI +JjjcJRFHLfO6IxClv7wC90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk +9Ok0oSy1c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/BAQD +AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoEVtstxNulMA0GCSqG +SIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLPqk/CaOv/gKlR6D1id4k9CnU58W5d +F4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwq +D2fK/A+JYZ1lpTzlvBNbCNvj/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4 +Vwpm+Vganf2XKWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq +fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX +-----END CERTIFICATE----- + +GlobalSign Root CA - R3 +======================= +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt +iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ +0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 +rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl +OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 +xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 +lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 +EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E +bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 +YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r +kpeDMdmztcpHWD9f +-----END CERTIFICATE----- + +TC TrustCenter Universal CA III +=============================== +-----BEGIN CERTIFICATE----- +MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy +IFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAe +Fw0wOTA5MDkwODE1MjdaFw0yOTEyMzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNU +QyBUcnVzdENlbnRlciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0Ex +KDAmBgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF5+cvAqBNLaT6hdqbJYUt +QCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYvDIRlzg9uwliT6CwLOunBjvvya8o84pxO +juT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8vzArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+Eut +CHnNaYlAJ/Uqwa1D7KRTyGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1 +M4BDj5yjdipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBhMB8G +A1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI4jANBgkqhkiG9w0BAQUFAAOCAQEA +g8ev6n9NCjw5sWi+e22JLumzCecYV42FmhfzdkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+ +KGwWaODIl0YgoGhnYIg5IFHYaAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhK +BgePxLcHsU0GDeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV +CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPHLQNjO9Po5KIq +woIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg== +-----END CERTIFICATE----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +========================================================= +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw +QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB +NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD +Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P +B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY +7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH +ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI +plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX +MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX +LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK +bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU +vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud +EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH +DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA +bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx +ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx +51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk +R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP +T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f +Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl +osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR +crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR +saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD +KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi +6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +Izenpe.com +========== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Chambers of Commerce Root - 2008 +================================ +-----BEGIN CERTIFICATE----- +MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD +MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv +bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu +QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy +Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl +ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF +EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl +cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA +XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj +h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/ +ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk +NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g +D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331 +lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ +0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj +ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2 +EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI +G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ +BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh +bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh +bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC +CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH +AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1 +wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH +3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU +RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6 +M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1 +YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF +9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK +zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG +nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg +OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ +-----END CERTIFICATE----- + +Global Chambersign Root - 2008 +============================== +-----BEGIN CERTIFICATE----- +MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD +MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv +bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu +QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx +NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg +Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ +QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf +VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf +XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0 +ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB +/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA +TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M +H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe +Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF +HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB +AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT +BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE +BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm +aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm +aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp +1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0 +dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG +/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6 +ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s +dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg +9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH +foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du +qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr +P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq +c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +-----END CERTIFICATE----- + +Go Daddy Root Certificate Authority - G2 +======================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu +MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G +A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq +9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD ++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd +fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl +NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 +BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac +vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r +5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV +N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 +-----END CERTIFICATE----- + +Starfield Root Certificate Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 +eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw +DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg +VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB +dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv +W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs +bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk +N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf +ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU +JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol +TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx +4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw +F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ +c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +Starfield Services Root Certificate Authority - G2 +================================================== +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl +IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT +dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 +h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa +hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP +LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB +rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG +SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP +E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy +xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza +YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 +-----END CERTIFICATE----- + +AffirmTrust Commercial +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw +MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb +DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV +C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 +BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww +MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV +HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG +hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi +qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv +0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh +sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +AffirmTrust Networking +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw +MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE +Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI +dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 +/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb +h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV +HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu +UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 +12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 +WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 +/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +AffirmTrust Premium +=================== +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy +OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy +dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn +BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV +5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs ++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd +GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R +p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI +S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 +6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 +/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo ++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv +MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC +6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S +L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK ++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV +BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg +IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 +g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb +zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== +-----END CERTIFICATE----- + +AffirmTrust Premium ECC +======================= +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV +BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx +MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U +cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ +N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW +BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK +BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X +57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM +eQ== +-----END CERTIFICATE----- + +Certum Trusted Network CA +========================= +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK +ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy +MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU +ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC +l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J +J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 +fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 +cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB +Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw +DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj +jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 +mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj +Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +Certinomis - Autorité Racine +============================= +-----BEGIN CERTIFICATE----- +MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK +Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg +LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG +A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw +JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa +wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly +Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw +2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N +jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q +c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC +lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb +xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g +530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna +4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ +KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x +WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva +R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40 +nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B +CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv +JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE +qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b +WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE +wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/ +vgt2Fl43N+bYdJeimUV5 +-----END CERTIFICATE----- + +Root CA Generalitat Valenciana +============================== +-----BEGIN CERTIFICATE----- +MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJFUzEfMB0GA1UE +ChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290 +IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcNMDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3 +WjBoMQswCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UE +CxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+WmmmO3I2 +F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKjSgbwJ/BXufjpTjJ3Cj9B +ZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGlu6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQ +D0EbtFpKd71ng+CT516nDOeB0/RSrFOyA8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXte +JajCq+TA81yc477OMUxkHl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMB +AAGjggM7MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBraS5n +dmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIICIwYKKwYBBAG/VQIB +ADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBl +AHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIAYQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIA +YQBsAGkAdABhAHQAIABWAGEAbABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQBy +AGEAYwBpAPMAbgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA +aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMAaQBvAG4AYQBt +AGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQAZQAgAEEAdQB0AG8AcgBpAGQA +YQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBu +AHQAcgBhACAAZQBuACAAbABhACAAZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAA +OgAvAC8AdwB3AHcALgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0 +dHA6Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+yeAT8MIGV +BgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQswCQYDVQQGEwJFUzEfMB0G +A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5S +b290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRh +TvW1yEICKrNcda3FbcrnlD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdz +Ckj+IHLtb8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg9J63 +NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XFducTZnV+ZfsBn5OH +iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt ++GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= +-----END CERTIFICATE----- + +A-Trust-nQual-03 +================ +-----BEGIN CERTIFICATE----- +MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYGA1UE +Cgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy +a2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5R +dWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgw +RgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0 +ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMMEEEtVHJ1 +c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtPWFuA/OQO8BBC4SA +zewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUjlUC5B3ilJfYKvUWG6Nm9wASOhURh73+n +yfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPE +SU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4 +iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3V +cuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdV +eRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40 +ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmr +sQd7TZjTXLDR8KdCoLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZd +JXDRZslo+S4RFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS +mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6 +ahq97BvIxYSazQ== +-----END CERTIFICATE----- + +TWCA Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ +VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG +EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB +IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx +QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC +oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP +4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r +y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG +9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC +mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW +QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY +T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny +Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +Security Communication RootCA2 +============================== +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh +dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC +SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy +aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ ++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R +3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV +spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K +EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 +QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB +CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj +u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk +3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q +tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 +mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +EC-ACC +====== +-----BEGIN CERTIFICATE----- +MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE +BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w +ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD +VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE +CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT +BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7 +MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt +SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl +Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh +cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK +w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT +ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4 +HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a +E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw +0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD +VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0 +Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l +dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ +lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa +Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe +l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2 +E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D +5EI= +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2011 +======================================================= +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT +O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y +aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z +IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT +AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z +IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo +IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI +1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa +71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u +8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH +3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/ +MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8 +MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu +b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt +XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD +/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N +7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----END CERTIFICATE----- + +Actalis Authentication Root CA +============================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Trustis FPS Root CA +=================== +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG +EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290 +IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV +BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ +RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk +H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa +cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt +o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA +AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd +BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c +GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC +yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P +8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV +l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl +iB6XzCGcKQENZetX2fNXlrtIzYE= +-----END CERTIFICATE----- + +StartCom Certification Authority +================================ +-----BEGIN CERTIFICATE----- +MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu +ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 +NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk +LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg +U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y +o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ +Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d +eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt +2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z +6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ +osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ +untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc +UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT +37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ +Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0 +dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu +c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv +bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0 +aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t +L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG +cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5 +fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm +N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN +Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T +tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX +e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA +2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs +HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE +JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib +D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8= +-----END CERTIFICATE----- + +StartCom Certification Authority G2 +=================================== +-----BEGIN CERTIFICATE----- +MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE +ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O +o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG +4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi +Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul +Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs +O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H +vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L +nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS +FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa +z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ +KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K +2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk +J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+ +JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG +/+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc +nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld +blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc +l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm +7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm +obp573PYtlNXLfbQ4ddI +-----END CERTIFICATE----- + +Buypass Class 2 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X +DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 +g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn +9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b +/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU +CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff +awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI +zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn +Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX +Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs +M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI +osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S +aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd +DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD +LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 +oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC +wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS +CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN +rJgWVqA= +-----END CERTIFICATE----- + +Buypass Class 3 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X +DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH +sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR +5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh +7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ +ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH +2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV +/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ +RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA +Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq +j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G +uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG +Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 +ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 +KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz +6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug +UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe +eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi +Cp/HuZc= +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 3 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx +MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK +9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU +NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF +iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W +0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr +AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb +fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT +ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h +P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== +-----END CERTIFICATE----- diff --git a/vendor/requests/library/Requests/Transport/fsockopen.php b/vendor/requests/library/Requests/Transport/fsockopen.php new file mode 100644 index 00000000..21cb56d5 --- /dev/null +++ b/vendor/requests/library/Requests/Transport/fsockopen.php @@ -0,0 +1,444 @@ +dispatch('fsockopen.before_request'); + + $url_parts = parse_url($url); + if (empty($url_parts)) { + throw new Requests_Exception('Invalid URL.', 'invalidurl', $url); + } + $host = $url_parts['host']; + $context = stream_context_create(); + $verifyname = false; + $case_insensitive_headers = new Requests_Utility_CaseInsensitiveDictionary($headers); + + // HTTPS support + if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https') { + $remote_socket = 'ssl://' . $host; + if (!isset($url_parts['port'])) { + $url_parts['port'] = 443; + } + + $context_options = array( + 'verify_peer' => true, + // 'CN_match' => $host, + 'capture_peer_cert' => true + ); + $verifyname = true; + + // SNI, if enabled (OpenSSL >=0.9.8j) + if (defined('OPENSSL_TLSEXT_SERVER_NAME') && OPENSSL_TLSEXT_SERVER_NAME) { + $context_options['SNI_enabled'] = true; + if (isset($options['verifyname']) && $options['verifyname'] === false) { + $context_options['SNI_enabled'] = false; + } + } + + if (isset($options['verify'])) { + if ($options['verify'] === false) { + $context_options['verify_peer'] = false; + } + elseif (is_string($options['verify'])) { + $context_options['cafile'] = $options['verify']; + } + } + + if (isset($options['verifyname']) && $options['verifyname'] === false) { + $context_options['verify_peer_name'] = false; + $verifyname = false; + } + + stream_context_set_option($context, array('ssl' => $context_options)); + } + else { + $remote_socket = 'tcp://' . $host; + } + + $this->max_bytes = $options['max_bytes']; + + if (!isset($url_parts['port'])) { + $url_parts['port'] = 80; + } + $remote_socket .= ':' . $url_parts['port']; + + set_error_handler(array($this, 'connect_error_handler'), E_WARNING | E_NOTICE); + + $options['hooks']->dispatch('fsockopen.remote_socket', array(&$remote_socket)); + + $socket = stream_socket_client($remote_socket, $errno, $errstr, ceil($options['connect_timeout']), STREAM_CLIENT_CONNECT, $context); + + restore_error_handler(); + + if ($verifyname && !$this->verify_certificate_from_context($host, $context)) { + throw new Requests_Exception('SSL certificate did not match the requested domain name', 'ssl.no_match'); + } + + if (!$socket) { + if ($errno === 0) { + // Connection issue + throw new Requests_Exception(rtrim($this->connect_error), 'fsockopen.connect_error'); + } + + throw new Requests_Exception($errstr, 'fsockopenerror', null, $errno); + } + + $data_format = $options['data_format']; + + if ($data_format === 'query') { + $path = self::format_get($url_parts, $data); + $data = ''; + } + else { + $path = self::format_get($url_parts, array()); + } + + $options['hooks']->dispatch('fsockopen.remote_host_path', array(&$path, $url)); + + $request_body = ''; + $out = sprintf("%s %s HTTP/%.1f\r\n", $options['type'], $path, $options['protocol_version']); + + if ($options['type'] !== Requests::TRACE) { + if (is_array($data)) { + $request_body = http_build_query($data, null, '&'); + } + else { + $request_body = $data; + } + + if (!empty($data)) { + if (!isset($case_insensitive_headers['Content-Length'])) { + $headers['Content-Length'] = strlen($request_body); + } + + if (!isset($case_insensitive_headers['Content-Type'])) { + $headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; + } + } + } + + if (!isset($case_insensitive_headers['Host'])) { + $out .= sprintf('Host: %s', $url_parts['host']); + + if (( 'http' === strtolower($url_parts['scheme']) && $url_parts['port'] !== 80 ) || ( 'https' === strtolower($url_parts['scheme']) && $url_parts['port'] !== 443 )) { + $out .= ':' . $url_parts['port']; + } + $out .= "\r\n"; + } + + if (!isset($case_insensitive_headers['User-Agent'])) { + $out .= sprintf("User-Agent: %s\r\n", $options['useragent']); + } + + $accept_encoding = $this->accept_encoding(); + if (!isset($case_insensitive_headers['Accept-Encoding']) && !empty($accept_encoding)) { + $out .= sprintf("Accept-Encoding: %s\r\n", $accept_encoding); + } + + $headers = Requests::flatten($headers); + + if (!empty($headers)) { + $out .= implode($headers, "\r\n") . "\r\n"; + } + + $options['hooks']->dispatch('fsockopen.after_headers', array(&$out)); + + if (substr($out, -2) !== "\r\n") { + $out .= "\r\n"; + } + + if (!isset($case_insensitive_headers['Connection'])) { + $out .= "Connection: Close\r\n"; + } + + $out .= "\r\n" . $request_body; + + $options['hooks']->dispatch('fsockopen.before_send', array(&$out)); + + fwrite($socket, $out); + $options['hooks']->dispatch('fsockopen.after_send', array($out)); + + if (!$options['blocking']) { + fclose($socket); + $fake_headers = ''; + $options['hooks']->dispatch('fsockopen.after_request', array(&$fake_headers)); + return ''; + } + + $timeout_sec = (int) floor($options['timeout']); + if ($timeout_sec == $options['timeout']) { + $timeout_msec = 0; + } + else { + $timeout_msec = self::SECOND_IN_MICROSECONDS * $options['timeout'] % self::SECOND_IN_MICROSECONDS; + } + stream_set_timeout($socket, $timeout_sec, $timeout_msec); + + $response = $body = $headers = ''; + $this->info = stream_get_meta_data($socket); + $size = 0; + $doingbody = false; + $download = false; + if ($options['filename']) { + $download = fopen($options['filename'], 'wb'); + } + + while (!feof($socket)) { + $this->info = stream_get_meta_data($socket); + if ($this->info['timed_out']) { + throw new Requests_Exception('fsocket timed out', 'timeout'); + } + + $block = fread($socket, Requests::BUFFER_SIZE); + if (!$doingbody) { + $response .= $block; + if (strpos($response, "\r\n\r\n")) { + list($headers, $block) = explode("\r\n\r\n", $response, 2); + $doingbody = true; + } + } + + // Are we in body mode now? + if ($doingbody) { + $options['hooks']->dispatch('request.progress', array($block, $size, $this->max_bytes)); + $data_length = strlen($block); + if ($this->max_bytes) { + // Have we already hit a limit? + if ($size === $this->max_bytes) { + continue; + } + if (($size + $data_length) > $this->max_bytes) { + // Limit the length + $limited_length = ($this->max_bytes - $size); + $block = substr($block, 0, $limited_length); + } + } + + $size += strlen($block); + if ($download) { + fwrite($download, $block); + } + else { + $body .= $block; + } + } + } + $this->headers = $headers; + + if ($download) { + fclose($download); + } + else { + $this->headers .= "\r\n\r\n" . $body; + } + fclose($socket); + + $options['hooks']->dispatch('fsockopen.after_request', array(&$this->headers, &$this->info)); + return $this->headers; + } + + /** + * Send multiple requests simultaneously + * + * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see Requests_Transport::request} + * @param array $options Global options, see {@see Requests::response()} for documentation + * @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well) + */ + public function request_multiple($requests, $options) { + $responses = array(); + $class = get_class($this); + foreach ($requests as $id => $request) { + try { + $handler = new $class(); + $responses[$id] = $handler->request($request['url'], $request['headers'], $request['data'], $request['options']); + + $request['options']['hooks']->dispatch('transport.internal.parse_response', array(&$responses[$id], $request)); + } + catch (Requests_Exception $e) { + $responses[$id] = $e; + } + + if (!is_string($responses[$id])) { + $request['options']['hooks']->dispatch('multiple.request.complete', array(&$responses[$id], $id)); + } + } + + return $responses; + } + + /** + * Retrieve the encodings we can accept + * + * @return string Accept-Encoding header value + */ + protected static function accept_encoding() { + $type = array(); + if (function_exists('gzinflate')) { + $type[] = 'deflate;q=1.0'; + } + + if (function_exists('gzuncompress')) { + $type[] = 'compress;q=0.5'; + } + + $type[] = 'gzip;q=0.5'; + + return implode(', ', $type); + } + + /** + * Format a URL given GET data + * + * @param array $url_parts + * @param array|object $data Data to build query using, see {@see https://secure.php.net/http_build_query} + * @return string URL with data + */ + protected static function format_get($url_parts, $data) { + if (!empty($data)) { + if (empty($url_parts['query'])) { + $url_parts['query'] = ''; + } + + $url_parts['query'] .= '&' . http_build_query($data, null, '&'); + $url_parts['query'] = trim($url_parts['query'], '&'); + } + if (isset($url_parts['path'])) { + if (isset($url_parts['query'])) { + $get = $url_parts['path'] . '?' . $url_parts['query']; + } + else { + $get = $url_parts['path']; + } + } + else { + $get = '/'; + } + return $get; + } + + /** + * Error handler for stream_socket_client() + * + * @param int $errno Error number (e.g. E_WARNING) + * @param string $errstr Error message + */ + public function connect_error_handler($errno, $errstr) { + // Double-check we can handle it + if (($errno & E_WARNING) === 0 && ($errno & E_NOTICE) === 0) { + // Return false to indicate the default error handler should engage + return false; + } + + $this->connect_error .= $errstr . "\n"; + return true; + } + + /** + * Verify the certificate against common name and subject alternative names + * + * Unfortunately, PHP doesn't check the certificate against the alternative + * names, leading things like 'https://www.github.com/' to be invalid. + * Instead + * + * @see https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1 + * + * @throws Requests_Exception On failure to connect via TLS (`fsockopen.ssl.connect_error`) + * @throws Requests_Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`) + * @param string $host Host name to verify against + * @param resource $context Stream context + * @return bool + */ + public function verify_certificate_from_context($host, $context) { + $meta = stream_context_get_options($context); + + // If we don't have SSL options, then we couldn't make the connection at + // all + if (empty($meta) || empty($meta['ssl']) || empty($meta['ssl']['peer_certificate'])) { + throw new Requests_Exception(rtrim($this->connect_error), 'ssl.connect_error'); + } + + $cert = openssl_x509_parse($meta['ssl']['peer_certificate']); + + return Requests_SSL::verify_certificate($host, $cert); + } + + /** + * Whether this transport is valid + * + * @codeCoverageIgnore + * @return boolean True if the transport is valid, false otherwise. + */ + public static function test($capabilities = array()) { + if (!function_exists('fsockopen')) { + return false; + } + + // If needed, check that streams support SSL + if (isset($capabilities['ssl']) && $capabilities['ssl']) { + if (!extension_loaded('openssl') || !function_exists('openssl_x509_parse')) { + return false; + } + + // Currently broken, thanks to https://github.com/facebook/hhvm/issues/2156 + if (defined('HHVM_VERSION')) { + return false; + } + } + + return true; + } +} diff --git a/vendor/requests/library/Requests/Utility/CaseInsensitiveDictionary.php b/vendor/requests/library/Requests/Utility/CaseInsensitiveDictionary.php new file mode 100644 index 00000000..2c97893a --- /dev/null +++ b/vendor/requests/library/Requests/Utility/CaseInsensitiveDictionary.php @@ -0,0 +1,103 @@ + $value) { + $this->offsetSet($key, $value); + } + } + + /** + * Check if the given item exists + * + * @param string $key Item key + * @return boolean Does the item exist? + */ + public function offsetExists($key) { + $key = strtolower($key); + return isset($this->data[$key]); + } + + /** + * Get the value for the item + * + * @param string $key Item key + * @return string Item value + */ + public function offsetGet($key) { + $key = strtolower($key); + if (!isset($this->data[$key])) { + return null; + } + + return $this->data[$key]; + } + + /** + * Set the given item + * + * @throws Requests_Exception On attempting to use dictionary as list (`invalidset`) + * + * @param string $key Item name + * @param string $value Item value + */ + public function offsetSet($key, $value) { + if ($key === null) { + throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset'); + } + + $key = strtolower($key); + $this->data[$key] = $value; + } + + /** + * Unset the given header + * + * @param string $key + */ + public function offsetUnset($key) { + unset($this->data[strtolower($key)]); + } + + /** + * Get an iterator for the data + * + * @return ArrayIterator + */ + public function getIterator() { + return new ArrayIterator($this->data); + } + + /** + * Get the headers as an array + * + * @return array Header data + */ + public function getAll() { + return $this->data; + } +} diff --git a/vendor/requests/library/Requests/Utility/FilteredIterator.php b/vendor/requests/library/Requests/Utility/FilteredIterator.php new file mode 100644 index 00000000..76a29e72 --- /dev/null +++ b/vendor/requests/library/Requests/Utility/FilteredIterator.php @@ -0,0 +1,45 @@ +callback = $callback; + } + + /** + * Get the current item's value after filtering + * + * @return string + */ + public function current() { + $value = parent::current(); + $value = call_user_func($this->callback, $value); + return $value; + } +} diff --git a/views/inc.header.php b/views/inc.header.php index b0495198..aeb7a385 100644 --- a/views/inc.header.php +++ b/views/inc.header.php @@ -1,7 +1,7 @@ -".esc_html($title).""; - } -?> \ No newline at end of file +" . esc_html($title) . ""; +} diff --git a/views/index.php b/views/index.php index b4962229..c9199655 100644 --- a/views/index.php +++ b/views/index.php @@ -1,2 +1,3 @@ - - -

        - -
        \ No newline at end of file + + + +
        + +
        diff --git a/views/packages/details/controller.php b/views/packages/details/controller.php index 230f1e94..cbb3cb3d 100644 --- a/views/packages/details/controller.php +++ b/views/packages/details/controller.php @@ -1,57 +1,65 @@ -Status < 100); -$link_log = DUP_Settings::getSsdirUrl()."/{$package->NameHash}.log"; -$err_link_log = "" . esc_html__('package log', 'duplicator') . ''; -$err_link_faq = '' . esc_html__('FAQ', 'duplicator') . ''; -$err_link_ticket = '' . esc_html__('resources page', 'duplicator') . ''; -?> - - - -
        - Name}", 'duplicator')); - ?> - - -
        -

        - - -

        -
        - - - - - - -
        +Status < 100); +$link_log = DUP_Settings::getSsdirUrl() . "/{$package->NameHash}.log"; +$err_link_log = "" . esc_html__('package log', 'duplicator') . ''; +$err_link_faq = '' . + esc_html__('FAQ', 'duplicator') . + ''; +$err_link_ticket = '' . + esc_html__('resources page', 'duplicator') . + ''; +?> + + + +
        + Name}", 'duplicator')); + ?> + + +
        +

        + + +

        +
        + + + + + + +
        diff --git a/views/packages/details/detail.php b/views/packages/details/detail.php index c0aae064..eed27c98 100644 --- a/views/packages/details/detail.php +++ b/views/packages/details/detail.php @@ -1,530 +1,590 @@ -getPackageFileDownloadInfo(DUP_PackageFileType::Archive); -$logDownloadInfo = $package->getPackageFileDownloadInfo(DUP_PackageFileType::Log); -$installerDownloadInfo = $package->getInstallerDownloadInfo(); -$archiveDownloadInfoJson = DupLiteSnapJsonU::json_encode_esc_attr($archiveDownloadInfo); -$logDownloadInfoJson = DupLiteSnapJsonU::json_encode_esc_attr($logDownloadInfo); -$installerDownloadInfoJson = DupLiteSnapJsonU::json_encode_esc_attr($installerDownloadInfo); -$showLinksDialogJson = DupLiteSnapJsonU::json_encode_esc_attr(array( - "archive" => $archiveDownloadInfo["url"], - "log" => $logDownloadInfo["url"], -)); - -$debug_on = DUP_Settings::Get('package_debug'); -$mysqldump_on = DUP_Settings::Get('package_mysqldump') && DUP_DB::getMySqlDumpPath(); -$mysqlcompat_on = isset($Package->Database->Compatible) && strlen($Package->Database->Compatible); -$mysqlcompat_on = ($mysqldump_on && $mysqlcompat_on) ? true : false; -$dbbuild_mode = ($mysqldump_on) ? 'mysqldump' : 'PHP'; -$archive_build_mode = ($package->Archive->Format === 'ZIP') ? 'ZipArchive (zip)' : 'DupArchive (daf)'; -$dup_install_secure_on = isset($package->Installer->OptsSecureOn) ? $package->Installer->OptsSecureOn : 0; -$dup_install_secure_pass = isset($package->Installer->OptsSecurePass) ? DUP_Util::installerUnscramble($package->Installer->OptsSecurePass) : ''; -?> - - - - -

        - - - - - -
        -
        - -
        -
        -
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        : - Name); ?> -
        - - - - - - - - - - - - - -
        :ID); ?>
        :Hash); ?>
        :NameHash); ?>
        -
        -
        :Notes) ? $package->Notes : esc_html__('- no notes -', 'duplicator') ?>
        :Created; ?>
        : - Version); ?> -
        - - - - - - - - - - - - - -
        :VersionWP) ? esc_html($package->VersionWP) : esc_html__('- unknown -', 'duplicator') ?>
        : VersionPHP) ? esc_html($package->VersionPHP) : esc_html__('- unknown -', 'duplicator') ?>
        : - VersionDB) ? esc_html($package->VersionDB) : esc_html__('- unknown -', 'duplicator') ?> | - Database->Comments) ? esc_html($package->Database->Comments) : esc_html__('- unknown -', 'duplicator') ?> -
        -
        -
        :Runtime) ? esc_html($package->Runtime) : esc_html__("error running", 'duplicator'); ?>
        :Status >= 100) ? esc_html__('completed', 'duplicator') : esc_html__('in-complete', 'duplicator') ?>
        :WPUser) ? esc_html($package->WPUser) : esc_html__('- unknown -', 'duplicator') ?>
        : -
        - - - - - - - - -
        - - - - - - - - - - - - - - - - - -
        : ">Archive->File); ?>
        : - - Installer->File, '.bak')) ?> - -
        : " target="file_results">
        - -
        - -
        -
        -
        - - - - - - -
        -
        - - -
        -
        -
        - - - - - - - - - - - - - - - - - - - -
        - - - - - - - -
        -
        - -  ' .'Amazon', - ' ' . 'Dropbox', - ' ' . 'Google Drive', - ' ' . 'OneDrive', - ' ' . 'FTP/SFTP'); - ?> - - " - data-tooltip=""> - - -
        -
        - -
        -
        - - -
        -
        - -
        -
        -
        - - -
        - - -
        - - - - - - - - Archive->ExportOnlyDB) : ?> - - - - - - - - - - -
        :
        :
        : - Archive->FilterOn == 1 ? 'On' : 'Off'; ?> -
        - :
        - Archive->FilterDirs) - ? str_replace(';', ";\n", $package->Archive->FilterDirs) - : esc_html__('- no filters -', 'duplicator'); - ?> - -
        - -
        - :
        - Archive->FilterExts) && strlen($package->Archive->FilterExts) - ? esc_html($package->Archive->FilterExts) - : esc_html__('- no filters -', 'duplicator'); - ?> -
        - -
        - :
        - Archive->FilterFiles) - ? str_replace(';', ";\n", $package->Archive->FilterFiles) - : esc_html__('- no filters -', 'duplicator'); - ?> - -
        -

        - - -
        - - -
        - - - - - - - - - - - - - - - - - - - - - -
        : Database->info->name); ?>
        : Database->Type); ?>
        : - - -
        - - - [] - - -
        : Database->FilterOn == 1 ? 'On' : 'Off'; ?>
          - :
        - Database->FilterTables) && strlen($package->Database->FilterTables) - ? str_replace(',', "
        \n", $package->Database->FilterTables) - : esc_html__('- no filters -', 'duplicator'); - ?> -
        -
        -
        - - - -
        -
        - -
        -
        -
        - - - - - - - - - - - - - -
        - : - -
        -
        - - -
        -
        -

        - - - - - - - - - - - - - - - - - -
        :Installer->OptsDBHost) ? esc_html($package->Installer->OptsDBHost) : esc_html__('- not set -', 'duplicator') ?>
        :Installer->OptsDBName) ? esc_html($package->Installer->OptsDBName) : esc_html__('- not set -', 'duplicator') ?>
        :Installer->OptsDBUser) ? esc_html($package->Installer->OptsDBUser) : esc_html__('- not set -', 'duplicator') ?>
        -
        -
        - - -
        - []
        - -
        - - - - \ No newline at end of file +getPackageFileDownloadInfo(DUP_PackageFileType::Archive); +$logDownloadInfo = $package->getPackageFileDownloadInfo(DUP_PackageFileType::Log); +$installerDownloadInfo = $package->getInstallerDownloadInfo(); +$archiveDownloadInfoJson = SnapJson::jsonEncodeEscAttr($archiveDownloadInfo); +$logDownloadInfoJson = SnapJson::jsonEncodeEscAttr($logDownloadInfo); +$installerDownloadInfoJson = SnapJson::jsonEncodeEscAttr($installerDownloadInfo); +$showLinksDialogJson = SnapJson::jsonEncodeEscAttr(array( + "archive" => $archiveDownloadInfo["url"], + "log" => $logDownloadInfo["url"], +)); + +$debug_on = DUP_Settings::Get('package_debug'); +$mysqldump_on = DUP_Settings::Get('package_mysqldump') && DUP_DB::getMySqlDumpPath(); +$mysqlcompat_on = isset($Package->Database->Compatible) && strlen($Package->Database->Compatible); +$mysqlcompat_on = ($mysqldump_on && $mysqlcompat_on) ? true : false; +$dbbuild_mode = ($mysqldump_on) ? 'mysqldump' : 'PHP'; +$archive_build_mode = ($package->Archive->Format === 'ZIP') ? 'ZipArchive (zip)' : 'DupArchive (daf)'; +$dup_install_secure_on = isset($package->Installer->OptsSecureOn) ? $package->Installer->OptsSecureOn : 0; +$dup_install_secure_pass = isset($package->Installer->OptsSecurePass) ? DUP_Util::installerUnscramble($package->Installer->OptsSecurePass) : ''; +$installerNameMode = DUP_Settings::Get('installer_name_mode'); + +$currentStoreURLPath = DUP_Settings::getSsdirUrl(); +$installerSecureName = $package->getInstDownloadName(true); +$installerDirectLink = "{$currentStoreURLPath}/" . pathinfo($installerSecureName, PATHINFO_FILENAME) .DUP_Installer::INSTALLER_SERVER_EXTENSION; +?> + + + + +

        + + +
        + [open all]   + [close all] +
        + + +
        +
        + +
        +
        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        : + + Name); ?> + +
        + + + + + + + + + + + + + +
        :ID); ?>
        :Hash); ?>
        :NameHash); ?>
        +
        +
        :Notes) ? $package->Notes : esc_html__('- no notes -', 'duplicator') ?>
        :Created) ?>
        : + + Version); ?> + +
        + + + + + + + + + + + + + +
        :VersionWP) ? esc_html($package->VersionWP) : esc_html__('- unknown -', 'duplicator') ?>
        : VersionPHP) ? esc_html($package->VersionPHP) : esc_html__('- unknown -', 'duplicator') ?>
        : + VersionDB) ? esc_html($package->VersionDB) : esc_html__('- unknown -', 'duplicator') ?> | + Database->Comments) ? esc_html($package->Database->Comments) : esc_html__('- unknown -', 'duplicator') ?> +
        +
        +
        :Runtime) ? esc_html($package->Runtime) : esc_html__("error running", 'duplicator'); ?>
        :Status >= 100) ? esc_html__('completed', 'duplicator') : esc_html__('in-complete', 'duplicator') ?>
        :WPUser) ? esc_html($package->WPUser) : esc_html__('- unknown -', 'duplicator') ?>
        : +
        + + '; + } else { + $installBtnTooltip = __('Download basic installer (installer.php)', 'duplicator'); + $installBtnIcon = ''; + } + ?> +
        + + +

        +
        + + + + + + +
        + + + + + + + + + + + + + + + + + +
        : + " class="link-style"> + Archive->File); ?> + +
        : + " target="file_results" class="link-style"> + + +
        :
        + +
        + +
        +
        +
        + + + + + + +
        +
        + + +
        +
        +
        + + + + + + + + + + + + + + + + + + + +
        + + + + + + + + + '; + echo DUP_Settings:: getSsdirUrl(); + ?> +
        +
        + +  ' . 'Amazon', + ' ' . 'Dropbox', + ' ' . 'Google Drive', + ' ' . 'OneDrive', + ' ' . 'FTP/SFTP' + ); + ?> + + + + " + data-tooltip=""> + + +
        +
        + +
        +
        + + +
        +
        + +
        +
        +
        + + +
        + + +
        + + + + + + + + Archive->ExportOnlyDB) : ?> + + + + + + + + + + +
        :
        :
        : + Archive->FilterOn == 1 ? 'On' : 'Off'; ?> +
        + :
        + Archive->FilterDirs) + ? str_replace(';', ";\n", $package->Archive->FilterDirs) + : esc_html__('- no filters -', 'duplicator'); + ?> + +
        + +
        + :
        + Archive->FilterExts) && strlen($package->Archive->FilterExts) + ? esc_html($package->Archive->FilterExts) + : esc_html__('- no filters -', 'duplicator'); + ?> +
        + +
        + :
        + Archive->FilterFiles) + ? str_replace(';', ";\n", $package->Archive->FilterFiles) + : esc_html__('- no filters -', 'duplicator'); + ?> + +
        +

        + + +
        + + +
        + + + + + + + + + + + + + + + + + + + + + +
        : Database->info->name); ?>
        : Database->Type); ?>
        : + + +
        + + + [] + + +
        : Database->FilterOn == 1 ? 'On' : 'Off'; ?>
          + :
        + Database->FilterTables) && strlen($package->Database->FilterTables) + ? str_replace(',', "
        \n", $package->Database->FilterTables) + : esc_html__('- no filters -', 'duplicator'); + ?> +
        +
        +
        + + + +
        +
        + +
        +
        +
        + + + + + + + + + + + + + +
        + : + + +
        +
        + + +
        +
        +

        + + + + + + + + + + + + + + + + + +
        :Installer->OptsDBHost) ? esc_html($package->Installer->OptsDBHost) : esc_html__('- not set -', 'duplicator') ?>
        :Installer->OptsDBName) ? esc_html($package->Installer->OptsDBName) : esc_html__('- not set -', 'duplicator') ?>
        :Installer->OptsDBUser) ? esc_html($package->Installer->OptsDBUser) : esc_html__('- not set -', 'duplicator') ?>
        +
        +
        + + +
        + []
        + +
        + + + + diff --git a/views/packages/details/index.php b/views/packages/details/index.php index b4962229..c9199655 100644 --- a/views/packages/details/index.php +++ b/views/packages/details/index.php @@ -1,2 +1,3 @@ - - -
        -
        -
        - -

        - -

        - -
        -
          -
        • -
        • -
        • -
        • -
        • -
        • -
        -
        - -

        - -

        - - - -

        -
        + + + +
        +
        +
        + +

        + +

        + +
        +
          +
        • +
        • +
        • +
        • +
        • +
        • +
        +
        + +

        + +

        + + + +

        +
        diff --git a/views/packages/index.php b/views/packages/index.php index b4962229..c9199655 100644 --- a/views/packages/index.php +++ b/views/packages/index.php @@ -1,2 +1,3 @@ %s %s.", $txt_invalid_msg1, $txt_invalid_msg2, $txt_invalid_lnk)); - } - break; - case 'new2': - if (!wp_verify_nonce($_GET['_wpnonce'], 'new2-package')) { - die(printf("%s
        %s %s.", $txt_invalid_msg1, $txt_invalid_msg2, $txt_invalid_lnk)); - } - break; - case 'new3': - if (!wp_verify_nonce($_GET['_wpnonce'], 'new3-package')) { - die(printf("%s
        %s %s.", $txt_invalid_msg1, $txt_invalid_msg2, $txt_invalid_lnk)); - } - break; -} -?> - - - - \ No newline at end of file +%s %s.", $txt_invalid_msg1, $txt_invalid_msg2, $txt_invalid_lnk)); + } + break; + case 'new2': + if (!wp_verify_nonce($_GET['_wpnonce'], 'new2-package')) { + die(printf("%s
        %s %s.", $txt_invalid_msg1, $txt_invalid_msg2, $txt_invalid_lnk)); + } + break; + case 'new3': + if (!wp_verify_nonce($_GET['_wpnonce'], 'new3-package')) { + die(printf("%s
        %s %s.", $txt_invalid_msg1, $txt_invalid_msg2, $txt_invalid_lnk)); + } + break; +} +?> + + + + diff --git a/views/packages/main/index.php b/views/packages/main/index.php index b4962229..c9199655 100644 --- a/views/packages/main/index.php +++ b/views/packages/main/index.php @@ -1,2 +1,3 @@ Packages Tab > Installer > Name option or click on the gear icon at the top of this page.", 'duplicator'); + . "To improve the security and get more information, go to: Settings > Packages Tab > Installer > Name option or click on the gear icon at the top of this page.", 'duplicator'); } else { - $packageExeNameModeMsg = __("When clicking the Installer download button, the 'Save as' dialog is defaulting the name to '[name]_[hash]_[date]_installer.php'. " - ."This is the secure and recommended option. For more information, go to: Settings > Packages Tab > Installer > Name or click on the gear icon at the top of this page.

        " - ."To quickly copy the hashed installer name, to your clipboard use the copy icon link or click the installer name and manually copy the selected text.", 'duplicator'); + $packageExeNameModeMsg = __("When clicking the Installer download button, the 'Save as' dialog is defaulting the name to '[name]_[hash]_[time]_installer.php'. " + . "This is the secure and recommended option. For more information, go to: Settings > Packages Tab > Installer > Name or click on the gear icon at the top of this page.

        " + . "To quickly copy the hashed installer name, to your clipboard use the copy icon link or click the installer name and manually copy the selected text.", 'duplicator'); } ?> @@ -83,19 +86,37 @@ - " onclick="Duplicator.Pack.ConfirmDelete()"> + " + onclick="Duplicator.Pack.ConfirmDelete()" + > - " onclick="Duplicator.Pack.showHelp()"> - "> - "> + " onclick="Duplicator.Pack.showHelp()"> + + + "> + + + "> + + - "> - "> + "> + + + "> + + - + ">
        @@ -136,7 +159,7 @@ class="button "> esc_html_e('We strongly recommend upgrading to ', 'duplicator'); echo " [" . esc_html__('Duplicator Pro', 'duplicator') . "]."; echo ''; - } + } ?>
         
        @@ -145,7 +168,7 @@ class="button ">   - + @@ -200,7 +223,7 @@ function tablePackageRow(DUP_Package $Package) //Links $uniqueid = $Package->NameHash; - $packagepath = DUP_Settings::getSsdirUrl().'/'.$Package->Archive->File; + $packagepath = DUP_Settings::getSsdirUrl() . '/' . $Package->Archive->File; $css_alt = ($packageTablerowCount % 2 != 0) ? '' : 'alternate'; @@ -211,14 +234,14 @@ function tablePackageRow(DUP_Package $Package)
        Created, DUP_Settings::get_create_date_format()); - echo ' '.($pack_build_mode ? - "zip" : - "daf"); + echo ' ' . ($pack_build_mode ? + "zip" : + "daf"); ?> - DB" : esc_html($pack_name); ?>
        + DB" : esc_html($pack_name); ?>
        Building Package %   getInstDownloadName(); ?> - "> + ">
        - - - + title = __('Bulk Action Required', 'duplicator'); -$alert1->message = ' '; +$alert1 = new DUP_UI_Dialog(); +$alert1->title = __('Bulk Action Required', 'duplicator'); +$alert1->message = ' '; $alert1->message .= __('No selections made! Please select an action from the "Bulk Actions" drop down menu.', 'duplicator'); $alert1->initAlert(); -$alert2 = new DUP_UI_Dialog(); -$alert2->title = __('Selection Required', 'duplicator', 'duplicator'); -$alert2->message = ' '; +$alert2 = new DUP_UI_Dialog(); +$alert2->title = __('Selection Required', 'duplicator', 'duplicator'); +$alert2->message = ' '; $alert2->message .= __('No selections made! Please select at least one package to delete.', 'duplicator'); $alert2->initAlert(); @@ -361,9 +391,16 @@ function tablePackageRow(DUP_Package $Package) DIALOG: HELP DIALOG -->
        - - - - -
        - -
        - - -
        - -
        - - \ No newline at end of file +setResponseType('PHP'); +$data = $ctrl_ui->GetViewStateList(); + +$ui_css_storage = (isset($data->payload['dup-pack-storage-panel']) && $data->payload['dup-pack-storage-panel']) ? 'display:block' : 'display:none'; +$ui_css_archive = (isset($data->payload['dup-pack-archive-panel']) && $data->payload['dup-pack-archive-panel']) ? 'display:block' : 'display:none'; +$ui_css_installer = (isset($data->payload['dup-pack-installer-panel']) && $data->payload['dup-pack-installer-panel']) ? 'display:block' : 'display:none'; +$dup_intaller_files = implode(", ", array_keys(DUP_Server::getInstallerFiles())); +$dbbuild_mode = (DUP_Settings::Get('package_mysqldump') && DUP_DB::getMySqlDumpPath()) ? 'mysqldump' : 'PHP'; +$archive_build_mode = DUP_Settings::Get('archive_build_mode') == DUP_Archive_Build_Mode::ZipArchive ? 'zip' : 'daf'; + +//="No Selection", 1="Try Again", 2="Two-Part Install" +$retry_state = isset($_GET['retry']) ? $_GET['retry'] : 0; +?> + + + + + + + + + + +
        +
        +
        + + + +
        +
        +
        + + +
        +
         
        +
        + + +

        + + + + + +
        +
        + Pass
        ' : '
        Fail
        '; + ?> +
        +
        + +
        + +
        + +
        + + +
        +
        + +
        +
        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + %s %s", + esc_html__("ZipArchive extension is required or", 'duplicator'), + esc_html__("Switch to DupArchive", 'duplicator'), + esc_html__("to by-pass this requirement.", 'duplicator') + ); + ?> +
        file_get_contents
        file_put_contents
        mb_strlen
        + + + +
        +
        + + +
        +
        + +
        + +
        +
        +
        + %s   [%s]
        ", $dup_tests['IO']['SSDIR'], DUP_Settings::getSsdirPath()); + printf("%s   [%s]
        ", $dup_tests['IO']['SSTMP'], DUP_Settings::getSsdirTmpPath()); + printf("%s   [%s]
        ", $dup_tests['IO']['WPROOT'], $abs_path); + ?> +
        + '; + } + esc_html_e("If Duplicator does not have enough permissions then you will need to manually create the paths above.   ", 'duplicator'); + ?> +
        +
        +
        + + +
        +
        + +
        +
        +
        + + + + + + + + + +
        + + [" . esc_html__('more info', 'duplicator') . "]"; + ?> + +
        + + + + + +
        mysqli_real_escape_string
        + + + +
        +
        + + +
        +
        +
        +
        +
        + + + +
        + +
        + +
        ' style='font-size:10px; margin-top:5px;' /> +
        + +
        +
        + +
        +
        + + + + +
        + +
        + + +
        + +
        + + diff --git a/views/packages/main/s1.setup2.php b/views/packages/main/s1.setup2.php index c0668a76..668c70cb 100644 --- a/views/packages/main/s1.setup2.php +++ b/views/packages/main/s1.setup2.php @@ -9,10 +9,10 @@ form#dup-form-opts textarea, input[type="text"] {width:100%} textarea#package-notes {height:75px;} - div.dup-notes-add {float:right; margin:-4px 2px 4px 0;} + div.dup-notes-add {float:right; margin:-4px 2px 4px 0;} div#dup-notes-area {display:none} - input#package-name {padding:4px; height: 2em; font-size: 1.2em; line-height: 100%; width: 100%; margin: 0 0 3px;} - tr.dup-store-path td {padding:14px} + input#package-name {padding:4px; height: 2em; font-size: 1.2em; line-height: 100%; width: 100%; margin: 0 0 3px;} + tr.dup-store-path td {padding:14px} label.lbl-larger {font-size:1.2em} form#dup-form-opts ul li.tabs {font-size:16px} div.tab-hdr-title {font-size: 16px; font-weight: bold; padding: 1px; margin:2px 0 5px 0; border-bottom:1px solid #dcdcde } @@ -23,98 +23,99 @@ div.dup-title-icons { margin-top:-5px; font-weight:normal; font-size:13px; float:left} div.dup-box-title div.dup-title-icons > span {border-left:1px solid silver; padding:2px 14px 5px 14px; user-select:none} span#dup-installer-secure-lock, span#dup-installer-secure-unlock {border:none; padding:0 12px 5px 2px;} + span#dup-installer-secure-lock {border:none; padding:0 12px 5px 2px;} /*TAB-1: ARCHIVE SECTION*/ form#dup-form-opts div.tabs-panel{max-height:800px; padding:15px 20px 20px 20px; min-height:280px} form#dup-form-opts ul li.tabs{font-weight:bold} - sup.archive-ext {font-style:italic;font-size:10px; cursor: pointer; vertical-align: baseline; position: relative; top: -0.8em; font-weight: normal} + sup.archive-ext {font-style:italic;font-size:10px; cursor: pointer; vertical-align: baseline; position: relative; top: -0.8em; font-weight: normal} ul.category-tabs li {padding:4px 15px 4px 15px} select#archive-format {min-width:100px; margin:1px 0 4px 0} span#dup-archive-filter-file {color:#A62426; display:none} span#dup-archive-filter-db {color:#A62426; display:none} - span#dup-archive-db-only {color:#A62426; display:none; font-weight: normal} + span#dup-archive-db-only {color:#A62426; display:none; font-weight: normal} div#dup-file-filter-items {padding:5px 0 0;} div#dup-db-filter-items {padding:0; margin-top:-15px} - div#dup-db-filter-items {font-stretch:ultra-condensed; font-family:Calibri; } + div#dup-db-filter-items {font-stretch:ultra-condensed; font-family:Calibri; } form#dup-form-opts textarea#filter-dirs {height:125px; background:#fafafa; padding:5px 10px 5px 10px;} form#dup-form-opts textarea#filter-exts {height:30px; background:#fafafa; padding:3px 10px 1px 10px;} - form#dup-form-opts textarea#filter-files {height:125px; background:#fafafa; padding:5px 10px 5px 10px;} - div.dup-quick-links {font-size:11px; float:right; display:inline-block; margin-top:2px; font-style:italic} + form#dup-form-opts textarea#filter-files {height:125px; background:#fafafa; padding:5px 10px 5px 10px;} + div.dup-quick-links {font-size:11px; display:inline-block; margin-top:2px; font-style:italic; float:right } div.dup-tabs-opts-help {font-style:italic; font-size:11px; margin:10px 0 0 2px; color:#777;} /* TAB-2: DATABASE */ table#dup-dbtables td {padding:0 20px 5px 10px;} label.core-table, label.non-core-table {padding:2px 0 2px 0; font-size:14px; display: inline-block} - label.core-table {color:#9A1E26;font-style:italic;font-weight:bold} - i.core-table-info {color:#9A1E26;font-style:italic;} - label.non-core-table {color:#000} - label.non-core-table:hover, label.core-table:hover {text-decoration:line-through} - table.dbmysql-compatibility {margin-top:-10px} + label.core-table {color:#9A1E26;font-style:italic;font-weight:bold} + i.core-table-info {color:#9A1E26;font-style:italic;} + label.non-core-table {color:#000} + label.non-core-table:hover, label.core-table:hover {text-decoration:line-through} + table.dbmysql-compatibility {margin-top:-10px} table.dbmysql-compatibility td{padding:0 20px 0 2px} - div.dup-store-pro {font-size:12px; font-style:italic;} - div.dup-store-pro img {height:14px; width:14px; vertical-align:text-top} - div.dup-store-pro a {text-decoration:underline} - span.dup-pro-text {font-style:italic; font-size:12px; color:#555; font-style:italic } - div#dup-exportdb-items-checked, div#dup-exportdb-items-off {min-height:275px; display:none} - div#dup-exportdb-items-checked {padding: 5px; max-width:700px} + div.dup-store-pro {font-size:12px; font-style:italic;} + div.dup-store-pro img {height:14px; width:14px; vertical-align:text-top} + div.dup-store-pro a {text-decoration:underline} + span.dup-pro-text {font-style:italic; font-size:12px; color:#555; font-style:italic } + div#dup-exportdb-items-checked, div#dup-exportdb-items-off {min-height:275px; display:none} + div#dup-exportdb-items-checked {padding: 5px; max-width:700px} div.dup-tbl-scroll {white-space:nowrap; height:350px; overflow-y: scroll; border:1px solid silver; padding:5px 10px; border-radius: 2px; background:#fafafa; margin:3px 0 0 0; width:98%} /*INSTALLER SECTION*/ div.dup-installer-header-1 {font-weight:bold; padding-bottom:2px; width:100%} div.dup-install-hdr-2 {font-weight:bold; border-bottom:1px solid #dfdfdf; padding-bottom:2px; width:100%} - span#dup-installer-secure-lock {color:#A62426; display:none; font-size:14px} - span#dup-installer-secure-unlock {color:#A62426; display:none; font-size:14px} + span#dup-installer-secure-lock {color:#A62426; display:none; font-size:14px} + span#dup-installer-secure-unlock {display:none; font-size:14px} + span#dup-installer-secure-lock {display:none; font-size:14px} label.chk-labels {display:inline-block; margin-top:1px} - table.dup-install-setup {width:100%; margin-left:2px} - table.dup-install-setup tr{vertical-align: top} - div.dup-installer-panel-optional {text-align: center; font-style: italic; font-size: 12px; color:maroon} - div.secure-pass-area {} - label.secure-pass-lbl {display:inline-block; width:125px} - div#dup-pass-toggle {position: relative; margin:8px 0 0 0; width:243px} - input#secure-pass {border-radius:4px 0 0 4px; width:217px; height: 23px; min-height: auto; margin:0; padding: 0 4px;} - button.pass-toggle {height: 23px; width: 27px; position:absolute; top:0px; right:0px; border:1px solid silver; border-radius:0 4px 4px 0; cursor:pointer} + table.dup-install-setup {width:100%; margin-left:2px} + table.dup-install-setup tr{vertical-align: top} + div.dup-installer-panel-optional {text-align: center; font-style: italic; font-size: 12px; color:maroon} + label.secure-pass-lbl {display:inline-block; width:125px} + div#dup-pass-toggle {position: relative; margin:8px 0 0 0; width:243px} + input#secure-pass {border-radius:4px 0 0 4px; width:214px; height:30px; min-height: auto; margin:0; padding: 0 4px;} + button#secure-btn {height:30px; width:30px; position:absolute; top:0px; right:0px; border:1px solid silver; border-radius:0 4px 4px 0; cursor:pointer;} div.dup-install-prefill-tab-pnl.tabs-panel {overflow:visible;} - - /*TABS*/ - ul.add-menu-item-tabs li, ul.category-tabs li {padding:3px 30px 5px} - div.dup-install-prefill-tab-pnl {min-height:180px !important; } + + /*TABS*/ + ul.add-menu-item-tabs li, ul.category-tabs li {padding:3px 30px 5px} + div.dup-install-prefill-tab-pnl {min-height:180px !important; }
        - - -
        -
        -
        -
        - -
        + + +
        +
        +
        +
        + +

        -
        - +
        + -
        -
        -
        +
        +
        +
        @@ -142,11 +143,11 @@ @@ -160,13 +161,15 @@
        -  ' .'Amazon', - ' ' . 'Dropbox', +  ' . 'Amazon', + ' ' . 'Dropbox', ' ' . 'Google Drive', ' ' . 'OneDrive', - ' ' . 'FTP/SFTP'); - ?> + ' ' . 'FTP/SFTP' + ); + ?> " @@ -179,7 +182,7 @@
        - +
        @@ -189,10 +192,10 @@
        - {$archive_build_mode}"; - ?>     + {$archive_build_mode}"; + ?>    
        @@ -209,7 +212,7 @@
        -
        +
        @@ -228,96 +231,98 @@ Archive->FilterDirs) ? count(explode(";", $Package->Archive->FilterDirs)) -1 : 0; - $filter_file_count = isset($Package->Archive->FilterFiles) ? count(explode(";", $Package->Archive->FilterFiles)) -1 : 0; + $uploads = wp_upload_dir(); + $upload_dir = DUP_Util::safePath($uploads['basedir']); + $filter_dir_count = isset($Package->Archive->FilterDirs) ? count(explode(";", $Package->Archive->FilterDirs)) - 1 : 0; + $filter_file_count = isset($Package->Archive->FilterFiles) ? count(explode(";", $Package->Archive->FilterFiles)) - 1 : 0; ?> - Archive->ExportOnlyDB) ? "checked='checked'" :""; ?> /> - + Archive->ExportOnlyDB) ? "checked='checked'" : ""; ?> /> + -
        - Archive->FilterOn) ? "checked='checked'" :""; ?> /> +
        + Archive->FilterOn) ? "checked='checked'" : ""; ?> /> - " - data-tooltip=""> - - -
        - - - + " + data-tooltip=""> + + +
        + + +

        -
        -
        - -
        - '; - _e("This option has automatically been checked because you have opted for a Two-Part Install Process. Please complete the package build and continue with the ", 'duplicator'); - printf('%s %s.', - '', - esc_html__('Quick Start Two-Part Install Instructions', 'duplicator')); - echo '

        '; - } - - _e("Overview:
        This advanced option excludes all files from the archive. Only the database and a copy of the installer.php " - . "will be included in the archive.zip file. The option can be used for backing up and moving only the database.", 'duplicator'); - - echo '

        '; - - _e(" Notice:
        ", 'duplicator'); - - _e("Please use caution when installing only the database over an existing site and be sure the correct files correspond with the database. For example, " - . "if WordPress 4.6 is on this site and you copy the database to a host that has WordPress 4.8 files then the source code of the files will not be " - . "in sync with the database causing possible errors. If you’re immediately moving the source files with the database then you can ignore this notice. " - . "Please use this advanced feature with caution!", 'duplicator'); - ?> -

        -
        + + + + +
        +
        + +
        +
        +
        + +
        + '; + _e("This option has automatically been checked because you have opted for a Two-Part Install Process. Please complete the package build and continue with the ", 'duplicator'); + printf( + '%s %s.', + '', + esc_html__('Quick Start Two-Part Install Instructions', 'duplicator') + ); + echo '

        '; + } + + _e("Overview:
        This advanced option excludes all files from the archive. Only the database and a copy of the installer.php " + . "will be included in the archive.zip file. The option can be used for backing up and moving only the database.", 'duplicator'); + + echo '

        '; + + _e(" Notice:
        ", 'duplicator'); + + _e("Please use caution when installing only the database over an existing site and be sure the correct files correspond with the database. For example, " + . "if WordPress 4.6 is on this site and you copy the database to a host that has WordPress 4.8 files then the source code of the files will not be " + . "in sync with the database causing possible errors. If you’re immediately moving the source files with the database then you can ignore this notice. " + . "Please use this advanced feature with caution!", 'duplicator'); + ?> +

        +
        @@ -327,71 +332,71 @@ - - - - - -
        Database->FilterOn) ? "checked='checked'" :""; ?> /> - - " - data-tooltip=""> - -
        + + + + + +
        Database->FilterOn) ? "checked='checked'" : ""; ?> /> + + " + data-tooltip=""> + +
         
        - get_results("SHOW FULL TABLES FROM `" . DB_NAME . "` WHERE Table_Type = 'BASE TABLE' ", ARRAY_N); - $num_rows = count($tables); - $next_row = round($num_rows / 4, 0); - $counter = 0; - $tableList = explode(',', $Package->Database->FilterTables); - - echo '
        '; - foreach ($tables as $table) { - if (DUP_Util::isTableExists($table[0])) { - if (DUP_Util::isWPCoreTable($table[0])) { - $core_css = 'core-table'; - $core_note = '*'; - } else { - $core_css = 'non-core-table'; - $core_note = ''; - } - - if (in_array($table[0], $tableList)) { - $checked = 'checked="checked"'; - $css = 'text-decoration:line-through'; - } else { - $checked = ''; - $css = ''; - } - echo "
        "; - $counter++; - if ($next_row <= $counter) { - echo '
        '; - $counter = 0; - } - } - } - echo '
        '; - ?> -
        + get_results("SHOW FULL TABLES FROM `" . DB_NAME . "` WHERE Table_Type = 'BASE TABLE' ", ARRAY_N); + $num_rows = count($tables); + $next_row = round($num_rows / 4, 0); + $counter = 0; + $tableList = explode(',', $Package->Database->FilterTables); + + echo '
        '; + foreach ($tables as $table) { + if (DUP_Util::isTableExists($table[0])) { + if (DUP_Util::isWPCoreTable($table[0])) { + $core_css = 'core-table'; + $core_note = '*'; + } else { + $core_css = 'non-core-table'; + $core_note = ''; + } + + if (in_array($table[0], $tableList)) { + $checked = 'checked="checked"'; + $css = 'text-decoration:line-through'; + } else { + $checked = ''; + $css = ''; + } + echo "
        "; + $counter++; + if ($next_row <= $counter) { + echo '
        '; + $counter = 0; + } + } + } + echo '
        '; + ?> +
        -
        - excluded from the database script. ", 'duplicator'); - _e("Excluding certain tables can cause your site or plugins to not work correctly after install!
        ", 'duplicator'); - _e(" Use caution when excluding tables! It is highly recommended to not exclude WordPress core tables*, unless you know the impact.", 'duplicator'); - ?> -
        +
        + excluded from the database script. ", 'duplicator'); + _e("Excluding certain tables can cause your site or plugins to not work correctly after install!
        ", 'duplicator'); + _e(" Use caution when excluding tables! It is highly recommended to not exclude WordPress core tables*, unless you know the impact.", 'duplicator'); + ?> +

        @@ -417,28 +422,28 @@ Database->Compatible); - $is_mysql40 = in_array('mysql40', $modes); - $is_no_table = in_array('no_table_options', $modes); - $is_no_key = in_array('no_key_options', $modes); - $is_no_field = in_array('no_field_options', $modes); + $modes = explode(',', $Package->Database->Compatible); + $is_mysql40 = in_array('mysql40', $modes); + $is_no_table = in_array('no_table_options', $modes); + $is_no_key = in_array('no_key_options', $modes); + $is_no_field = in_array('no_field_options', $modes); ?> @@ -448,7 +453,7 @@ - +
        @@ -459,312 +464,311 @@
         
        -
        +
        - +
        - -
        -
        +
        +
        -
        +

        - - " - data-tooltip=""> - -
        - -
        - > + > - > + > - > + > - > + >
        - - - - - - - - - - - -
        - - - :" - data-tooltip=""> -

        -
        - Installer->OptsSecureOn) ? $Package->Installer->OptsSecureOn : 0; - $dup_install_secure_pass = isset($Package->Installer->OptsSecurePass) ? DUP_Util::installerUnscramble($Package->Installer->OptsSecurePass) : ''; - ?> - /> - - " - data-tooltip=""> - -
        - - -
        -
        -
        - - - - - -
        - - -
        -
          -
        • -
        • -
        - - -
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        -
        - - -
        -
        - " style="width:16px; height:12px" /> -
        - -
        - -
        -
        - -
        - - -
        + + " + data-tooltip=""> + + + + + + + + + + + + + + + +
        + + + :" + data-tooltip=""> +

        +
        + Installer->OptsSecureOn) ? $Package->Installer->OptsSecureOn : 0; + $dup_install_secure_pass = isset($Package->Installer->OptsSecurePass) ? DUP_Util::installerUnscramble($Package->Installer->OptsSecurePass) : ''; + ?> + /> + + " + data-tooltip=""> + +
        + + +
        +
        +
        + + + + + +
        + + +
        +
          +
        • +
        • +
        + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

        +
        + + +
        +
        + " style="width:16px; height:12px" /> +
        + +
        + +
        +
        + +
        + + +
        -title = __('Reset Package Settings?', 'duplicator'); - $confirm1->message = __('This will clear and reset all of the current package settings. Would you like to continue?', 'duplicator'); - $confirm1->jscallback = 'Duplicator.Pack.ResetSettings()'; - $confirm1->initConfirm(); - - $default_name1 = DUP_Package::getDefaultName(); - $default_name2 = DUP_Package::getDefaultName(false); +title = __('Reset Package Settings?', 'duplicator'); + $confirm1->message = __('This will clear and reset all of the current package settings. Would you like to continue?', 'duplicator'); + $confirm1->jscallback = 'Duplicator.Pack.ResetSettings()'; + $confirm1->initConfirm(); + + $default_name1 = DUP_Package::getDefaultName(); + $default_name2 = DUP_Package::getDefaultName(false); ?> \ No newline at end of file diff --git a/views/packages/main/s2.scan1.php b/views/packages/main/s2.scan1.php index cbf78cb4..704bed77 100644 --- a/views/packages/main/s2.scan1.php +++ b/views/packages/main/s2.scan1.php @@ -1,144 +1,151 @@ window.location.href = '{$reredirect_nonce_url}'"); - } +if (empty($_POST)) { + //F5 Refresh Check + $redirect = admin_url('admin.php?page=duplicator&tab=new1'); + $redirect_nonce_url = wp_nonce_url($redirect, 'new1-package'); + die(""); +} - $Package = new DUP_Package(); - $Package->saveActive($_POST); + $Package = new DUP_Package(); + $Package->saveActive($_POST); DUP_Settings::Set('active_package_id', -1); DUP_Settings::Save(); - - $Package = DUP_Package::getActive(); - - $mysqldump_on = DUP_Settings::Get('package_mysqldump') && DUP_DB::getMySqlDumpPath(); - $mysqlcompat_on = isset($Package->Database->Compatible) && strlen($Package->Database->Compatible); - $mysqlcompat_on = ($mysqldump_on && $mysqlcompat_on) ? true : false; - $dbbuild_mode = ($mysqldump_on) ? 'mysqldump' : 'PHP'; - $zip_check = DUP_Util::getZipPath(); - - $action_url = admin_url('admin.php?page=duplicator&tab=new3'); - $action_nonce_url = wp_nonce_url($action_url, 'new3-package'); + + $Package = DUP_Package::getActive(); + + $mysqldump_on = DUP_Settings::Get('package_mysqldump') && DUP_DB::getMySqlDumpPath(); + $mysqlcompat_on = isset($Package->Database->Compatible) && strlen($Package->Database->Compatible); + $mysqlcompat_on = ($mysqldump_on && $mysqlcompat_on) ? true : false; + $dbbuild_mode = ($mysqldump_on) ? 'mysqldump' : 'PHP'; + $zip_check = DUP_Util::getZipPath(); + + $action_url = admin_url('admin.php?page=duplicator&tab=new3'); + $action_nonce_url = wp_nonce_url($action_url, 'new3-package'); ?> @@ -172,280 +179,282 @@ - - + + + - -
        -
        -
        - - - -
        +
        +
        +
        + + + +
        -
        -
         
        + +
        - -
        -
        -
        -

        -
        -
        -
        - - - - - - + +
        +
        +
        +

        +
        +
        +
        + + + + + +
        \ No newline at end of file diff --git a/views/packages/main/s2.scan2.php b/views/packages/main/s2.scan2.php index dc160bdf..f701a057 100644 --- a/views/packages/main/s2.scan2.php +++ b/views/packages/main/s2.scan2.php @@ -4,11 +4,11 @@
        - -
        -   + +
        +   -
        +
        -
        -
        -
        -
        -
        -  ' . esc_html__('WordPress Version', 'duplicator') . ":  '{$wp_version}'
        "; - printf(__('It is recommended to have a version of WordPress that is greater than %1$s. Older version of WordPress can lead to migration issues and are a security risk. ' - . 'If possible please update your WordPress site to the latest version.', 'duplicator'), DUPLICATOR_SCAN_MIN_WP); - - //CORE FILES - echo '
         ' . esc_html__('Core Files', 'duplicator') . "
        "; - - - $filter_text=""; - if($core_dir_notice) { - echo ''; - esc_html_e("The core WordPress paths below will NOT be included in the archive. These paths are required for WordPress to function!", 'duplicator'); - echo "
        "; - foreach($core_dir_included as $core_dir) { - echo '     '. $core_dir . '
        '; - } - echo '

        '; - $filter_text="directories"; - } - - if($core_file_notice) { - echo ''; - esc_html_e("The core WordPress file below will NOT be included in the archive. This file is required for WordPress to function!", 'duplicator'); - echo "
        "; - foreach($core_files_included as $core_file) { - echo '     '. $core_file . '
        '; - } - echo '

        '; - $filter_text .= (strlen($filter_text) > 0) ? " and file" : "files"; - - } - - if(strlen($filter_text) > 0) { - echo ''; - esc_html_e("Note: Please change the {$filter_text} filters if you wish to include the WordPress core files otherwise the data will have to be manually copied" - . " to the new location for the site to function properly.", 'duplicator'); - echo ''; - } - - - if(!$core_dir_notice && !$core_file_notice): - esc_html_e("If the scanner is unable to locate the wp-config.php file in the root directory, then you will need to manually copy it to its new location. " - . "This check will also look for core WordPress paths that should be included in the archive for WordPress to work correctly.", 'duplicator'); - endif; - - - - //CACHE DIR - /* - $cache_path = DUP_Util::safePath(WP_CONTENT_DIR) . '/cache'; - $cache_size = DUP_Util::byteSize(DUP_Util::getDirectorySize($cache_path)); - echo '
         ' . esc_html__('Cache Path', 'duplicator') . ":  '".esc_html($cache_path)."' (".esc_html($cache_size).")
        "; - _e("Cached data will lead to issues at install time and increases your archive size. Empty your cache directory before building the package by using " - . "your cache plugins clear cache feature. Use caution if manually removing files the cache folder. The cache " - . "size minimum threshold that triggers this warning is currently set at ", 'duplicator'); - echo esc_html(DUP_Util::byteSize(DUPLICATOR_SCAN_CACHESIZE)) . '.'; - */ - - //MU SITE - if (is_multisite()) { - echo '
         ' . esc_html__('Multisite: Unsupported', 'duplicator') . "
        "; - esc_html_e('Duplicator does not support WordPress multisite migrations. We strongly recommend using Duplicator Pro which currently supports full multisite migrations and various other ' - . 'subsite scenarios.', 'duplicator'); - echo '

        '; - - esc_html_e('While it is not recommended you can still continue with the build of this package. At install time additional manual custom configurations will ' - . 'need to be made to finalize this multisite migration. Please note that any support requests for mulitsite with Duplicator Lite will not be supported.', 'duplicator'); - echo " [" . esc_html__('upgrade to pro', 'duplicator') . "]"; - } else { - echo '
         ' . esc_html__('Multisite: N/A', 'duplicator') . "
        "; - esc_html_e('This is not a multisite install so duplication will proceed without issue. Duplicator does not officially support multisite. However, Duplicator Pro supports ' - . 'duplication of a full multisite network and also has the ability to install a multisite subsite as a standalone site.', 'duplicator'); - echo " [" . esc_html__('upgrade to pro', 'duplicator') . "]"; - } - ?> -
        +
        +
        +
        +
        +
        +  ' . esc_html__('WordPress Version', 'duplicator') . ":  '{$wp_version}'
        "; + printf(__('It is recommended to have a version of WordPress that is greater than %1$s. Older version of WordPress can lead to migration issues and are a security risk. ' + . 'If possible please update your WordPress site to the latest version.', 'duplicator'), DUPLICATOR_SCAN_MIN_WP); + + //CORE FILES + echo '
         ' . esc_html__('Core Files', 'duplicator') . "
        "; + + + $filter_text = ""; + if ($core_dir_notice) { + echo ''; + esc_html_e("The core WordPress paths below will NOT be included in the archive. These paths are required for WordPress to function!", 'duplicator'); + echo "
        "; + foreach ($core_dir_included as $core_dir) { + echo '     ' . $core_dir . '
        '; + } + echo '

        '; + $filter_text = "directories"; + } + + if ($core_file_notice) { + echo ''; + esc_html_e("The core WordPress file below will NOT be included in the archive. This file is required for WordPress to function!", 'duplicator'); + echo "
        "; + foreach ($core_files_included as $core_file) { + echo '     ' . $core_file . '
        '; + } + echo '

        '; + $filter_text .= (strlen($filter_text) > 0) ? " and file" : "files"; + } + + if (strlen($filter_text) > 0) { + echo ''; + esc_html_e("Note: Please change the {$filter_text} filters if you wish to include the WordPress core files otherwise the data will have to be manually copied" + . " to the new location for the site to function properly.", 'duplicator'); + echo ''; + } + + + if (!$core_dir_notice && !$core_file_notice) : + esc_html_e("If the scanner is unable to locate the wp-config.php file in the root directory, then you will need to manually copy it to its new location. " + . "This check will also look for core WordPress paths that should be included in the archive for WordPress to work correctly.", 'duplicator'); + endif; + + + + //CACHE DIR + /* + $cache_path = DUP_Util::safePath(WP_CONTENT_DIR) . '/cache'; + $cache_size = DUP_Util::byteSize(DUP_Util::getDirectorySize($cache_path)); + echo '
         ' . esc_html__('Cache Path', 'duplicator') . ":  '".esc_html($cache_path)."' (".esc_html($cache_size).")
        "; + _e("Cached data will lead to issues at install time and increases your archive size. Empty your cache directory before building the package by using " + . "your cache plugins clear cache feature. Use caution if manually removing files the cache folder. The cache " + . "size minimum threshold that triggers this warning is currently set at ", 'duplicator'); + echo esc_html(DUP_Util::byteSize(DUPLICATOR_SCAN_CACHESIZE)) . '.'; + */ + + //MU SITE + if (is_multisite()) { + echo '
         ' . esc_html__('Multisite: Unsupported', 'duplicator') . "
        "; + esc_html_e('Duplicator does not support WordPress multisite migrations. We strongly recommend using Duplicator Pro which currently supports full multisite migrations and various other ' + . 'subsite scenarios.', 'duplicator'); + echo '

        '; + + esc_html_e('While it is not recommended you can still continue with the build of this package. At install time additional manual custom configurations will ' + . 'need to be made to finalize this multisite migration. Please note that any support requests for mulitsite with Duplicator Lite will not be supported.', 'duplicator'); + echo " [" . esc_html__('upgrade to pro', 'duplicator') . "]"; + } else { + echo '
         ' . esc_html__('Multisite: N/A', 'duplicator') . "
        "; + esc_html_e('This is not a multisite install so duplication will proceed without issue. Duplicator does not officially support multisite. However, Duplicator Pro supports ' + . 'duplication of a full multisite network and also has the ability to install a multisite subsite as a standalone site.', 'duplicator'); + echo " [" . esc_html__('upgrade to pro', 'duplicator') . "]"; + } + ?> +
        -
        -
        +
        +
        -
        +
        \ No newline at end of file diff --git a/views/packages/main/s2.scan3.php b/views/packages/main/s2.scan3.php index 15134206..7705a42f 100644 --- a/views/packages/main/s2.scan3.php +++ b/views/packages/main/s2.scan3.php @@ -1,205 +1,210 @@ 50 ? substr($root, 0, 50) . '...' : $root; - echo "
        {$sroot}
        "; - } - -$archive_type_label = DUP_Settings::Get('archive_build_mode') == DUP_Archive_Build_Mode::ZipArchive ? "ZipArchive" : "DupArchive"; + /*IDE Helper*/ + /* @var $Package DUP_Package */ +function _duplicatorGetRootPath() +{ + $txt = __('Root Path', 'duplicator'); + $root = duplicator_get_abs_path(); + $sroot = strlen($root) > 50 ? substr($root, 0, 50) . '...' : $root; + echo "
        {$sroot}
        "; +} + +$archive_type_label = DUP_Settings::Get('archive_build_mode') == DUP_Archive_Build_Mode::ZipArchive ? "ZipArchive" : "DupArchive"; $archive_type_extension = DUP_Settings::Get('archive_build_mode') == DUP_Archive_Build_Mode::ZipArchive ? "zip" : "daf"; $duparchive_max_limit = DUP_Util::readableByteSize(DUPLICATOR_MAX_DUPARCHIVE_SIZE); -$skip_archive_scan = DUP_Settings::Get('skip_archive_scan'); +$skip_archive_scan = DUP_Settings::Get('skip_archive_scan'); ?>
        -   - -
        +   + +
        - - - -
        -
        - Archive->ExportOnlyDB) { - echo ' '; - esc_html_e('Database Only', 'duplicator'); - } elseif ($Package->Archive->FilterOn) { - echo ' '; - esc_html_e('Enabled', 'duplicator'); - } - ?> -
        -
        - - -
        -
        + + + +
        +
        + Archive->ExportOnlyDB) { + echo ' '; + esc_html_e('Database Only', 'duplicator'); + } elseif ($Package->Archive->FilterOn) { + echo ' '; + esc_html_e('Enabled', 'duplicator'); + } + ?> +
        +
        + + +
        +
        Archive->ExportOnlyDB) { ?>
        -
        -
        -
        -
        +
        +
        +
        +
        - +
        -
        -
        -
        -
        +
        +
        +
        +


        - + ?>
        -
        -
        -
        -
        -
        - :   |   - :   |   - :
        - some budget hosts may cause timeouts. ' , 'duplicator'); - echo "  [" . esc_html__('more details...', 'duplicator') . "]"; - ?> -
        - " . esc_html__('Overview', 'duplicator') . ":
        "; - $dup_byte_size = '' . DUP_Util::byteSize(DUPLICATOR_SCAN_SIZE_DEFAULT) . ''; - printf(esc_html__('This notice is triggered at [%s] and can be ignored on most hosts. If during the build process you see a "Host Build Interrupt" message then this ' - . 'host has strict processing limits. Below are some options you can take to overcome constraints set up on this host.', 'duplicator'), $dup_byte_size); - echo '

        '; - - echo "" . esc_html__('Timeout Options', 'duplicator') . ":
        "; - echo ''; - - $hlptxt = sprintf(__('Files over %1$s are listed below. Larger files such as movies or zipped content can cause timeout issues on some budget hosts. If you are having ' - . 'issues creating a package try excluding the directory paths below or go back to Step 1 and add them.', 'duplicator'), - DUP_Util::byteSize(DUPLICATOR_SCAN_WARNFILESIZE)); - ?> -
        - -
        -
        +
        +
        +
        +
        +
        + :   |   + :   |   + :
        + some budget hosts may cause timeouts. ', 'duplicator'); + echo "  [" . esc_html__('more details...', 'duplicator') . "]"; + ?> +
        + " . esc_html__('Overview', 'duplicator') . ":
        "; + $dup_byte_size = '' . DUP_Util::byteSize(DUPLICATOR_SCAN_SIZE_DEFAULT) . ''; + printf(esc_html__('This notice is triggered at [%s] and can be ignored on most hosts. If during the build process you see a "Host Build Interrupt" message then this ' + . 'host has strict processing limits. Below are some options you can take to overcome constraints set up on this host.', 'duplicator'), $dup_byte_size); + echo '

        '; + + echo "" . esc_html__('Timeout Options', 'duplicator') . ":
        "; + echo ''; + + $hlptxt = sprintf( + __('Files over %1$s are listed below. Larger files such as movies or zipped content can cause timeout issues on some budget hosts. If you are having ' + . 'issues creating a package try excluding the directory paths below or go back to Step 1 and add them.', 'duplicator'), + DUP_Util::byteSize(DUPLICATOR_SCAN_WARNFILESIZE) + ); + ?> +
        + +
        +
        -
        -
        -
        -
        +
        +
        +
        +
        -
        -
        + $txt = __('If this environment/system and the system where it will be installed are set up to support Unicode and long paths then these filters can be ignored. ' + . 'If you run into issues with creating or installing a package, then is recommended to filter these paths.', 'duplicator'); + ?> + +
        +
        @@ -331,22 +336,22 @@ function _duplicatorGetRootPath() {
        {{#if ARC.UnreadableItems}} - {{#each ARC.UnreadableItems as |uitem|}} - {{uitem}}
        - {{/each}} + {{#each ARC.UnreadableItems as |uitem|}} + {{uitem}}
        + {{/each}} {{else}} -
        +
        {{/if}}

        {{#if ARC.RecursiveLinks}} - {{#each ARC.RecursiveLinks as |link|}} - {{link}}
        - {{/each}} - {{else}} -
        + {{#each ARC.RecursiveLinks as |link|}} + {{link}}
        + {{/each}} + {{else}} +
        {{/if}}
        @@ -363,72 +368,73 @@ function _duplicatorGetRootPath() {
        -
        - - -
        -
        - Database->FilterOn) { - echo ' '; esc_html_e('Enabled', 'duplicator'); - } - ?> -
        -
        - " - data-tooltip=""> - -
        - -
        -
        - -
        -
        -
        -
        -
        -
        - ' . esc_html__('TOTAL SIZE', 'duplicator') . '   ⇛   '; ?> - :   |   - :   |   - :
        -
        '; - - //TABLE DETAILS - echo '' . __('TABLE DETAILS:', 'duplicator') . '
        '; - $dup_scan_tbl_trigger_size = DUP_Util::byteSize(DUPLICATOR_SCAN_DB_TBL_SIZE) . ', ' . number_format(DUPLICATOR_SCAN_DB_TBL_ROWS); - printf(esc_html__('The notices for tables are %1$s records or names with upper-case characters. Individual tables will not trigger ' - . 'a notice message, but can help narrow down issues if they occur later on.', 'duplicator'), $dup_scan_tbl_trigger_size); - - echo '
        '; - - //RECOMMENDATIONS - echo '

        '; - echo '' . esc_html__('RECOMMENDATIONS:', 'duplicator') . '
        '; - - echo '
        '; - $lnk = '' . esc_html__('repair and optimization', 'duplicator') . ''; - printf(__('1. Run a %1$s on the table to improve the overall size and performance.', 'duplicator'), $lnk); - echo '

        '; - _e('2. Remove post revisions and stale data from tables. Tables such as logs, statistical or other non-critical data should be cleared.', 'duplicator'); - echo '

        '; - $lnk = '' . esc_html__('Enable mysqldump', 'duplicator') . ''; - printf(__('3. %1$s if this host supports the option.', 'duplicator'), $lnk); - echo '

        '; - $lnk = '' . esc_html__('lower_case_table_names', 'duplicator') . ''; - printf(__('4. For table name case sensitivity issues either rename the table with lower case characters or be prepared to work with the %1$s system variable setting.', 'duplicator'), $lnk); - echo '
        '; - - ?> -
        -
        +
        + + +
        +
        + Database->FilterOn) { + echo ' '; + esc_html_e('Enabled', 'duplicator'); + } + ?> +
        +
        + " + data-tooltip=""> + +
        + +
        +
        + +
        +
        +
        +
        +
        +
        + ' . esc_html__('TOTAL SIZE', 'duplicator') . '   ⇛   '; ?> + :   |   + :   |   + :
        +
        '; + + //TABLE DETAILS + echo '' . __('TABLE DETAILS:', 'duplicator') . '
        '; + $dup_scan_tbl_trigger_size = DUP_Util::byteSize(DUPLICATOR_SCAN_DB_TBL_SIZE) . ', ' . number_format(DUPLICATOR_SCAN_DB_TBL_ROWS); + printf(esc_html__('The notices for tables are %1$s records or names with upper-case characters. Individual tables will not trigger ' + . 'a notice message, but can help narrow down issues if they occur later on.', 'duplicator'), $dup_scan_tbl_trigger_size); + + echo '
        '; + + //RECOMMENDATIONS + echo '

        '; + echo '' . esc_html__('RECOMMENDATIONS:', 'duplicator') . '
        '; + + echo '
        '; + $lnk = '' . esc_html__('repair and optimization', 'duplicator') . ''; + printf(__('1. Run a %1$s on the table to improve the overall size and performance.', 'duplicator'), $lnk); + echo '

        '; + _e('2. Remove post revisions and stale data from tables. Tables such as logs, statistical or other non-critical data should be cleared.', 'duplicator'); + echo '

        '; + $lnk = '' . esc_html__('Enable mysqldump', 'duplicator') . ''; + printf(__('3. %1$s if this host supports the option.', 'duplicator'), $lnk); + echo '

        '; + $lnk = '' . esc_html__('lower_case_table_names', 'duplicator') . ''; + printf(__('4. For table name case sensitivity issues either rename the table with lower case characters or be prepared to work with the %1$s system variable setting.', 'duplicator'), $lnk); + echo '
        '; + + ?> +
        +
        get_col("SHOW TRIGGERS", 1); if (count($triggers)) { ?> @@ -446,7 +452,7 @@ function _duplicatorGetRootPath() { $lnk = '' . esc_html__('triggers', 'duplicator') . ''; printf(__('This database makes use of %1$s which can manually be imported at install time. Instructions and SQL statement queries will be ' . 'provided at install time for users to execute. No actions need to be performed at this time, this message is simply a notice.', 'duplicator'), $lnk); - ?> + ?>
        @@ -485,76 +491,76 @@ function _duplicatorGetRootPath() { - + - - - - + +
        + +
        + " + data-tooltip=""> + +
        + +
        + + + + +  '; esc_html_e('Migrate large, multi-gig sites with', 'duplicator'); echo ' ' . esc_html__('Duplicator Pro', 'duplicator') . '!'; echo ''; - ?> + ?>

        @@ -563,145 +569,145 @@ function _duplicatorGetRootPath() { DIALOGS: ========================================== --> height = 600; - $alert1->width = 600; - $alert1->title = __('Scan Details', 'duplicator'); - $alert1->message = "
        "; - $alert1->initAlert(); - - $alert2 = new DUP_UI_Dialog(); - $alert2->height = 450; - $alert2->width = 650; - $alert2->title = __('Copy Quick Filter Paths', 'duplicator'); - $alert2->message = "
        "; - $alert2->initAlert(); + $alert1 = new DUP_UI_Dialog(); + $alert1->height = 600; + $alert1->width = 600; + $alert1->title = __('Scan Details', 'duplicator'); + $alert1->message = "
        "; + $alert1->initAlert(); + + $alert2 = new DUP_UI_Dialog(); + $alert2->height = 450; + $alert2->width = 650; + $alert2->title = __('Copy Quick Filter Paths', 'duplicator'); + $alert2->message = "
        "; + $alert2->initAlert(); ?> @@ -709,98 +715,98 @@ function _duplicatorGetRootPath() { jQuery(document).ready(function($) { - Handlebars.registerHelper('stripWPRoot', function(path) { - return path.replace(, ''); - }); - - //Uncheck file names if directory is checked - Duplicator.Pack.filesOff = function (dir) - { - var $checks = $(dir).parent('div.directory').find('div.files input[type="checkbox"]'); - $(dir).is(':checked') - ? $.each($checks, function() {$(this).attr({disabled : true, checked : false, title : ''});}) - : $.each($checks, function() {$(this).removeAttr('disabled checked title');}); - $('div.apply-warn').show(300); - } - - //Opens a dialog to show scan details - Duplicator.Pack.showDetailsDlg = function () - { - $('#arc-details-dlg').html($('#dup-archive-details').html()); - showAlert(); ?> - Duplicator.UI.loadQtip(); - return; - } - - //Opens a dialog to show scan details - Duplicator.Pack.showPathsDlg = function (type) - { - var id = (type == 'large') ? '#hb-files-large-result' : '#hb-files-utf8-result' - var dirFilters = []; - var fileFilters = []; - $(id + " input[name='dir_paths[]']:checked").each(function() {dirFilters.push($(this).val());}); - $(id + " input[name='file_paths[]']:checked").each(function() {fileFilters.push($(this).val());}); - - var $dirs = $('#dup-archive-paths textarea.path-dirs'); - var $files = $('#dup-archive-paths textarea.path-files'); - (dirFilters.length > 0) - ? $dirs.text(dirFilters.join(";\n")) - : $dirs.text(""); - - (fileFilters.length > 0) - ? $files.text(fileFilters.join(";\n")) - : $files.text(""); - - $('#arc-paths-dlg').html($('#dup-archive-paths').html()); - showAlert(); ?> - - return; - } - - //Toggles a directory path to show files - Duplicator.Pack.toggleDirPath = function(item) - { - var $dir = $(item).parents('div.directory'); - var $files = $dir.find('div.files'); - var $arrow = $dir.find('i.dup-nav'); - if ($files.is(":hidden")) { - $arrow.addClass('fa-caret-down').removeClass('fa-caret-right'); - $files.show(); - } else { - $arrow.addClass('fa-caret-right').removeClass('fa-caret-down'); - $files.hide(250); - } - } - - //Toggles a directory path to show files - Duplicator.Pack.toggleAllDirPath = function(item, toggle) - { - var $dirs = $(item).parents('div.container').find('div.data div.directory'); - (toggle == 'hide') - ? $.each($dirs, function() {$(this).find('div.files').show(); $(this).find('i.dup-nav').trigger('click');}) - : $.each($dirs, function() {$(this).find('div.files').hide(); $(this).find('i.dup-nav').trigger('click');}); - } - - Duplicator.Pack.copyText = function(btn, query) - { - $(query).select(); - try { - document.execCommand('copy'); - $(btn).css({color: '#fff', backgroundColor: 'green'}); - $(btn).text(""); - } catch(err) { - alert("") - } - } - - Duplicator.Pack.applyFilters = function(btn, type) - { - var $btn = $(btn); - $btn.html(' '); - $btn.attr('disabled', 'true'); - - //var id = (type == 'large') ? '#hb-files-large-result' : '#hb-files-utf8-result' - var id = ''; + Handlebars.registerHelper('stripWPRoot', function(path) { + return path.replace(, ''); + }); + + //Uncheck file names if directory is checked + Duplicator.Pack.filesOff = function (dir) + { + var $checks = $(dir).parent('div.directory').find('div.files input[type="checkbox"]'); + $(dir).is(':checked') + ? $.each($checks, function() {$(this).attr({disabled : true, checked : false, title : ''});}) + : $.each($checks, function() {$(this).removeAttr('disabled checked title');}); + $('div.apply-warn').show(300); + } + + //Opens a dialog to show scan details + Duplicator.Pack.showDetailsDlg = function () + { + $('#arc-details-dlg').html($('#dup-archive-details').html()); + showAlert(); ?> + Duplicator.UI.loadQtip(); + return; + } + + //Opens a dialog to show scan details + Duplicator.Pack.showPathsDlg = function (type) + { + var id = (type == 'large') ? '#hb-files-large-result' : '#hb-files-utf8-result' + var dirFilters = []; + var fileFilters = []; + $(id + " input[name='dir_paths[]']:checked").each(function() {dirFilters.push($(this).val());}); + $(id + " input[name='file_paths[]']:checked").each(function() {fileFilters.push($(this).val());}); + + var $dirs = $('#dup-archive-paths textarea.path-dirs'); + var $files = $('#dup-archive-paths textarea.path-files'); + (dirFilters.length > 0) + ? $dirs.text(dirFilters.join(";\n")) + : $dirs.text(""); + + (fileFilters.length > 0) + ? $files.text(fileFilters.join(";\n")) + : $files.text(""); + + $('#arc-paths-dlg').html($('#dup-archive-paths').html()); + showAlert(); ?> + + return; + } + + //Toggles a directory path to show files + Duplicator.Pack.toggleDirPath = function(item) + { + var $dir = $(item).parents('div.directory'); + var $files = $dir.find('div.files'); + var $arrow = $dir.find('i.dup-nav'); + if ($files.is(":hidden")) { + $arrow.addClass('fa-caret-down').removeClass('fa-caret-right'); + $files.show(); + } else { + $arrow.addClass('fa-caret-right').removeClass('fa-caret-down'); + $files.hide(250); + } + } + + //Toggles a directory path to show files + Duplicator.Pack.toggleAllDirPath = function(item, toggle) + { + var $dirs = $(item).parents('div.container').find('div.data div.directory'); + (toggle == 'hide') + ? $.each($dirs, function() {$(this).find('div.files').show(); $(this).find('i.dup-nav').trigger('click');}) + : $.each($dirs, function() {$(this).find('div.files').hide(); $(this).find('i.dup-nav').trigger('click');}); + } + + Duplicator.Pack.copyText = function(btn, query) + { + $(query).select(); + try { + document.execCommand('copy'); + $(btn).css({color: '#fff', backgroundColor: 'green'}); + $(btn).text(""); + } catch(err) { + alert("") + } + } + + Duplicator.Pack.applyFilters = function(btn, type) + { + var $btn = $(btn); + $btn.html(' '); + $btn.attr('disabled', 'true'); + + //var id = (type == 'large') ? '#hb-files-large-result' : '#hb-files-utf8-result' + var id = ''; switch(type){ case 'large': id = '#hb-files-large-result'; @@ -812,76 +818,76 @@ function _duplicatorGetRootPath() { id = '#hb-addon-sites-result'; break; } - var dirFilters = []; - var fileFilters = []; - $(id + " input[name='dir_paths[]']:checked").each(function() {dirFilters.push($(this).val());}); - $(id + " input[name='file_paths[]']:checked").each(function() {fileFilters.push($(this).val());}); - - var data = { - action: 'DUP_CTRL_Package_addQuickFilters', - nonce: '', - dir_paths : dirFilters.join(";"), - file_paths : fileFilters.join(";"), - }; - - $.ajax({ - type: "POST", - cache: false, - dataType: "text", - url: ajaxurl, - timeout: 100000, - data: data, - complete: function() { }, - success: function(respData) { - try { - var data = Duplicator.parseJSON(respData); - } catch(err) { - console.error(err); - console.error('JSON parse failed for response data: ' + respData); - console.log(data); - alert(""); - return false; - } - Duplicator.Pack.rescan(); - }, - error: function(data) { - console.log(data); - alert(""); - } - }); - } - - Duplicator.Pack.initArchiveFilesData = function(data) - { - //TOTAL SIZE - //var sizeChecks = data.ARC.Status.Size == 'Warn' || data.ARC.Status.Big == 'Warn' ? 'Warn' : 'Good'; - $('#data-arc-status-size').html(Duplicator.Pack.setScanStatus(data.ARC.Status.Size)); - $('#data-arc-status-names').html(Duplicator.Pack.setScanStatus(data.ARC.Status.Names)); + var dirFilters = []; + var fileFilters = []; + $(id + " input[name='dir_paths[]']:checked").each(function() {dirFilters.push($(this).val());}); + $(id + " input[name='file_paths[]']:checked").each(function() {fileFilters.push($(this).val());}); + + var data = { + action: 'DUP_CTRL_Package_addQuickFilters', + nonce: '', + dir_paths : dirFilters.join(";"), + file_paths : fileFilters.join(";"), + }; + + $.ajax({ + type: "POST", + cache: false, + dataType: "text", + url: ajaxurl, + timeout: 100000, + data: data, + complete: function() { }, + success: function(respData) { + try { + var data = Duplicator.parseJSON(respData); + } catch(err) { + console.error(err); + console.error('JSON parse failed for response data: ' + respData); + console.log(data); + alert(""); + return false; + } + Duplicator.Pack.rescan(); + }, + error: function(data) { + console.log(data); + alert(""); + } + }); + } + + Duplicator.Pack.initArchiveFilesData = function(data) + { + //TOTAL SIZE + //var sizeChecks = data.ARC.Status.Size == 'Warn' || data.ARC.Status.Big == 'Warn' ? 'Warn' : 'Good'; + $('#data-arc-status-size').html(Duplicator.Pack.setScanStatus(data.ARC.Status.Size)); + $('#data-arc-status-names').html(Duplicator.Pack.setScanStatus(data.ARC.Status.Names)); $('#data-arc-status-unreadablefiles').html(Duplicator.Pack.setScanStatus(data.ARC.Status.UnreadableItems)); $('#data-arc-status-triggers').html(Duplicator.Pack.setScanStatus(data.DB.Status.Triggers)); - $('#data-arc-status-migratepackage').html(Duplicator.Pack.setScanStatus(data.ARC.Status.MigratePackage)); + $('#data-arc-status-migratepackage').html(Duplicator.Pack.setScanStatus(data.ARC.Status.MigratePackage)); + $('#data-arc-status-showcreateprocfunc').html(Duplicator.Pack.setScanStatus(data.ARC.Status.showCreateProcFuncStatus)); - $('#data-arc-size1').text(data.ARC.Size || errMsg); - $('#data-arc-size2').text(data.ARC.Size || errMsg); - $('#data-arc-files').text(data.ARC.FileCount || errMsg); - $('#data-arc-dirs').text(data.ARC.DirCount || errMsg); + $('#data-arc-size1').text(data.ARC.Size || errMsg); + $('#data-arc-size2').text(data.ARC.Size || errMsg); + $('#data-arc-files').text(data.ARC.FileCount || errMsg); + $('#data-arc-dirs').text(data.ARC.DirCount || errMsg); - //LARGE FILES + //LARGE FILES if ($('#hb-files-large').length > 0) { var template = $('#hb-files-large').html(); var templateScript = Handlebars.compile(template); var html = templateScript(data); $('#hb-files-large-result').html(html); } - //ADDON SITES + //ADDON SITES if ($('#hb-addon-sites').length > 0) { var template = $('#hb-addon-sites').html(); var templateScript = Handlebars.compile(template); var html = templateScript(data); $('#hb-addon-sites-result').html(html); } - //NAME CHECKS + //NAME CHECKS if ($('#hb-files-utf8').length > 0) { var template = $('#hb-files-utf8').html(); var templateScript = Handlebars.compile(template); @@ -897,7 +903,7 @@ function _duplicatorGetRootPath() { $('#unreadable-files-result').html(html); } - //SCANNER DETAILS: Dirs + //SCANNER DETAILS: Dirs if ($('#hb-filter-file-list').length > 0) { var template = $('#hb-filter-file-list').html(); var templateScript = Handlebars.compile(template); @@ -905,7 +911,7 @@ function _duplicatorGetRootPath() { $('div.hb-filter-file-list-result').html(html); } - //MIGRATE PACKAGE + //MIGRATE PACKAGE if ($("#hb-migrate-package-result").length) { var template = $('#hb-migrate-package-result').html(); var templateScript = Handlebars.compile(template); @@ -929,60 +935,60 @@ function _duplicatorGetRootPath() { $('#triggers-result').html(html); } - Duplicator.UI.loadQtip(); - } - - Duplicator.Pack.initArchiveDBData = function(data) - { - var errMsg = "unable to read"; - var color; - var html = ""; - var DB_TotalSize = 'Good'; - var DB_TableRowMax = ; - var DB_TableSizeMax = ; - if (data.DB.Status.Success) - { - DB_TotalSize = data.DB.Status.DB_Rows == 'Warn' || data.DB.Status.DB_Size == 'Warn' ? 'Warn' : 'Good'; - $('#data-db-status-size').html(Duplicator.Pack.setScanStatus(DB_TotalSize)); - $('#data-db-size1').text(data.DB.Size || errMsg); - $('#data-db-size2').text(data.DB.Size || errMsg); - $('#data-db-rows').text(data.DB.Rows || errMsg); - $('#data-db-tablecount').text(data.DB.TableCount || errMsg); - //Table Details - if (data.DB.TableList == undefined || data.DB.TableList.length == 0) { - html = ''; - } else { - $.each(data.DB.TableList, function(i) { - html += '' + i + '
        '; - html += ''; - $.each(data.DB.TableList[i], function(key,val) { - switch(key) { - case 'Case': - color = (val == 1) ? 'red' : 'black'; - html += ''; - break; - case 'Rows': - color = (val > DB_TableRowMax) ? 'red' : 'black'; - html += ''; - break; - case 'USize': - color = (parseInt(val) > DB_TableSizeMax) ? 'red' : 'black'; - html += ''; - break; - } - }); - html += '
        Uppercase: ' + val + 'Rows: ' + val + 'Size: ' + data.DB.TableList[i]['Size'] + '
        '; - }); - } - $('#data-db-tablelist').html(html); - } else { - html = ''; - $('#dup-scan-db').html(html); - } - } + Duplicator.UI.loadQtip(); + } + + Duplicator.Pack.initArchiveDBData = function(data) + { + var errMsg = "unable to read"; + var color; + var html = ""; + var DB_TotalSize = 'Good'; + var DB_TableRowMax = ; + var DB_TableSizeMax = ; + if (data.DB.Status.Success) + { + DB_TotalSize = data.DB.Status.DB_Rows == 'Warn' || data.DB.Status.DB_Size == 'Warn' ? 'Warn' : 'Good'; + $('#data-db-status-size').html(Duplicator.Pack.setScanStatus(DB_TotalSize)); + $('#data-db-size1').text(data.DB.EasySize || errMsg); + $('#data-db-size2').text(data.DB.EasySize || errMsg); + $('#data-db-rows').text(data.DB.Rows || errMsg); + $('#data-db-tablecount').text(data.DB.TableCount || errMsg); + //Table Details + if (data.DB.TableList == undefined || data.DB.TableList.length == 0) { + html = ''; + } else { + $.each(data.DB.TableList, function(i) { + html += '' + i + '
        '; + html += ''; + $.each(data.DB.TableList[i], function(key,val) { + switch(key) { + case 'Case': + color = (val == 1) ? 'red' : 'black'; + html += ''; + break; + case 'Rows': + color = (val > DB_TableRowMax) ? 'red' : 'black'; + html += ''; + break; + case 'USize': + color = (parseInt(val) > DB_TableSizeMax) ? 'red' : 'black'; + html += ''; + break; + } + }); + html += '
        Uppercase: ' + val + 'Rows: ' + val + 'Size: ' + data.DB.TableList[i]['Size'] + '
        '; + }); + } + $('#data-db-tablelist').html(html); + } else { + html = ''; + $('#dup-scan-db').html(html); + } + } Duplicator.Pack.initLiteLimitData = function(data) - { + { if(data.LL.Status.TotalSize == 'Fail') { $('.data-ll-section').show(); $('#dup-build-button').hide(); @@ -996,36 +1002,36 @@ function _duplicatorGetRootPath() { // $('#dup-build-button').prop("disabled",true); $('.data-ll-section').hide(); } - } - - - - // alert('before binding ' + $("#form-duplicator").length); - $("#form-duplicator").on('change', "#hb-files-large-result input[type='checkbox'], #hb-files-utf8-result input[type='checkbox'], #hb-addon-sites-result input[type='checkbox']", function() { - if ($("#hb-files-large-result input[type='checkbox']:checked").length) { - var large_disabled_prop = false; - } else { - var large_disabled_prop = true; - } - $("#hb-files-large-result .duplicator-quick-filter-btn").prop("disabled", large_disabled_prop); - - if ($("#hb-files-utf8-result input[type='checkbox']:checked").length) { - var utf8_disabled_prop = false; - } else { - var utf8_disabled_prop = true; - } - $("#hb-files-utf8-result .duplicator-quick-filter-btn").prop("disabled", utf8_disabled_prop); - - if ($("#hb-addon-sites-result input[type='checkbox']:checked").length) { - var addon_disabled_prop = false; - } else { - var addon_disabled_prop = true; - } - $("#hb-addon-sites-result .duplicator-quick-filter-btn").prop("disabled", addon_disabled_prop); - }); + } + + + + // alert('before binding ' + $("#form-duplicator").length); + $("#form-duplicator").on('change', "#hb-files-large-result input[type='checkbox'], #hb-files-utf8-result input[type='checkbox'], #hb-addon-sites-result input[type='checkbox']", function() { + if ($("#hb-files-large-result input[type='checkbox']:checked").length) { + var large_disabled_prop = false; + } else { + var large_disabled_prop = true; + } + $("#hb-files-large-result .duplicator-quick-filter-btn").prop("disabled", large_disabled_prop); + + if ($("#hb-files-utf8-result input[type='checkbox']:checked").length) { + var utf8_disabled_prop = false; + } else { + var utf8_disabled_prop = true; + } + $("#hb-files-utf8-result .duplicator-quick-filter-btn").prop("disabled", utf8_disabled_prop); + + if ($("#hb-addon-sites-result input[type='checkbox']:checked").length) { + var addon_disabled_prop = false; + } else { + var addon_disabled_prop = true; + } + $("#hb-addon-sites-result .duplicator-quick-filter-btn").prop("disabled", addon_disabled_prop); + }); }); diff --git a/views/packages/main/s3.build.php b/views/packages/main/s3.build.php index 4aec7a0c..2f9e3c58 100644 --- a/views/packages/main/s3.build.php +++ b/views/packages/main/s3.build.php @@ -2,9 +2,9 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit; //Nonce Check if (!isset($_POST['dup_form_opts_nonce_field']) || !wp_verify_nonce(sanitize_text_field($_POST['dup_form_opts_nonce_field']), 'dup_form_opts')) { - DUP_UI_Notice::redirect('admin.php?page=duplicator&tab=new1&_wpnonce='.wp_create_nonce('new1-package')); + DUP_UI_Notice::redirect('admin.php?page=duplicator&tab=new1&_wpnonce=' . wp_create_nonce('new1-package')); } -require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/duparchive/class.pack.archive.duparchive.php'); +require_once(DUPLICATOR_PLUGIN_PATH . 'classes/package/duparchive/class.pack.archive.duparchive.php'); $retry_nonuce = wp_create_nonce('new1-package'); $zip_build_nonce = wp_create_nonce('duplicator_package_build'); @@ -16,15 +16,15 @@ $atext0 .= __('Help review the plugin', 'duplicator') . '!'; //Get even more power & features with Duplicator Pro -$atext1 = __('Want more power? Try', 'duplicator'); +$atext1 = __('Want more power? Try', 'duplicator'); $atext1 .= " "; -$atext1 .= __('Duplicator Pro', 'duplicator').'!'; +$atext1 .= __('Duplicator Pro', 'duplicator') . '!'; if (DUP_Settings::Get('installer_name_mode') == DUP_Settings::INSTALLER_NAME_MODE_SIMPLE) { $txtInstallHelpMsg = __("When clicking the Installer download button, the 'Save as' dialog will default the name to 'installer.php'. " . "To improve the security and get more information, goto: Settings ❯ Packages Tab ❯ Installer Name option.", 'duplicator'); } else { - $txtInstallHelpMsg = __("When clicking the Installer download button, the 'Save as' dialog will save the name as '[name]_[hash]_[date]_installer.php'. " + $txtInstallHelpMsg = __("When clicking the Installer download button, the 'Save as' dialog will save the name as '[name]_[hash]_[time]_installer.php'. " . "This is the secure and recommended option. For more information goto: Settings ❯ Packages Tab ❯ Installer Name Option. To quickly copy the hashed " . "installer name, to your clipboard use the copy icon link.", 'duplicator'); } @@ -35,7 +35,7 @@ ?> - - -
        -
        - - - - - -
        - " style='text-align:top; margin:0; height:196px; width:196px' /> - - - - - - - -
        - - - - -
        - -
        -
        -
        - -
        -
        -

        - - -

        - - - - -
        - - - - -
        - -
        -
        - - - - -
        -
        -

        - -
        -




        - \ No newline at end of file + + + + +
        +
        + + + + + +
        + " style='margin-top:-60px; height:176px; width:176px' /> + + +

        + + + + + +
        + + + + +
        + +
        +
        +
        + +
        +
        +

        +

        + + + +
        + + + + +
        + +
        +
        + + + + +
        +
        +

        + +
        +




        + diff --git a/views/settings/controller.php b/views/settings/controller.php index b27b5805..e1afabf7 100644 --- a/views/settings/controller.php +++ b/views/settings/controller.php @@ -15,34 +15,41 @@ $current_tab = isset($_REQUEST['tab']) ? sanitize_text_field($_REQUEST['tab']) : 'general'; ?> -
        +
        - diff --git a/views/settings/general.php b/views/settings/general.php index 0bba4712..8880f740 100644 --- a/views/settings/general.php +++ b/views/settings/general.php @@ -9,7 +9,6 @@ //SAVE RESULTS if (isset($_POST['action']) && $_POST['action'] == 'save') { - //Nonce Check if (!isset($_POST['dup_settings_save_nonce_field']) || !wp_verify_nonce($_POST['dup_settings_save_nonce_field'], 'dup_settings_save')) { die('Invalid token permissions to perform this request.'); @@ -31,33 +30,7 @@ $unhook_third_party_css = filter_input(INPUT_POST, 'unhook_third_party_css', FILTER_VALIDATE_BOOLEAN); DUP_Settings::Set('unhook_third_party_css', $unhook_third_party_css); - switch (filter_input(INPUT_POST, 'storage_position', FILTER_DEFAULT)) { - case DUP_Settings::STORAGE_POSITION_LECAGY: - $setPostion = DUP_Settings::STORAGE_POSITION_LECAGY; - break; - case DUP_Settings::STORAGE_POSITION_WP_CONTENT: - default: - $setPostion = DUP_Settings::STORAGE_POSITION_WP_CONTENT; - break; - } - - if (DUP_Settings::setStoragePosition($setPostion) != true) { - $targetFolder = ($setPostion === DUP_Settings::STORAGE_POSITION_WP_CONTENT) ? DUP_Settings::getSsdirPathWpCont() : DUP_Settings::getSsdirPathLegacy(); - ?> -
        -

        - -

        -

        - %s', 'duplicator'), esc_html($targetFolder)); ?>
        - %s )', 'duplicator'), esc_html(dirname($targetFolder))); ?> -

        -
        - - [" . DUPLICATOR_VERSION_BUILD . "]" : "[" . DUPLICATOR_VERSION_BUILD . "]"; ?> @@ -165,7 +138,7 @@ echo 'disabled'; } ?> onclick="Duplicator.Pack.DownloadTraceLog(); return false"> - + @@ -185,7 +158,7 @@

        " @@ -201,7 +174,7 @@

        @@ -214,9 +187,7 @@

        -
        - '; esc_html_e("Do not modify this setting unless you know the expected result or have talked to support.", 'duplicator'); ?>

        @@ -230,9 +201,7 @@

        -
        - '; esc_html_e("Do not modify this setting unless you know the expected result or have talked to support.", 'duplicator'); ?>

        @@ -243,12 +212,13 @@ /> -

        +

        %s %s' - .' %s %s ' - .' %s. %s' - .' %s.', + printf( + '%s %s %s' + . ' %s %s ' + . ' %s. %s' + . ' %s.', esc_html__('To enable custom roles with Duplicator please install the ', 'duplicator'), esc_html__('User Role Editor Free', 'duplicator'), esc_html__('OR', 'duplicator'), @@ -285,7 +255,11 @@ $reset_confirm->closeOnConfirm = true; $reset_confirm->initConfirm(); -$msg_ajax_error = new DUP_UI_Messages(__('AJAX Call Error!', 'duplicator').'
        '.__('AJAX error encountered when resetting packages. Please see this FAQ entry for possible resolutions.', 'duplicator'), DUP_UI_Messages::ERROR); +$msg_ajax_error = new DUP_UI_Messages( + __('AJAX Call Error!', 'duplicator') . '
        ' . + __('AJAX error encountered when resetting packages. Please see this FAQ entry for possible resolutions.', 'duplicator'), + DUP_UI_Messages::ERROR +); $msg_ajax_error->hide_on_init = true; $msg_ajax_error->is_dismissible = true; $msg_ajax_error->initMessage(); diff --git a/views/settings/gopro.php b/views/settings/gopro.php index c1367ed6..9004a1fd 100644 --- a/views/settings/gopro.php +++ b/views/settings/gopro.php @@ -5,7 +5,7 @@ require_once(DUPLICATOR_PLUGIN_PATH . '/assets/js/javascript.php'); require_once(DUPLICATOR_PLUGIN_PATH . '/views/inc.header.php'); -if(mt_rand(0, 1) == 0) { +if (mt_rand(0, 1) == 0) { $test_text = esc_html__('Check It Out!', 'duplicator'); $test_url = "https://snapcreek.com/duplicator/comparison/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=free_go_pro_checkitout1&utm_campaign=duplicator_pro"; } else { @@ -18,32 +18,32 @@

        - " /> -
        - -
        + " /> +
        + +
        @@ -56,37 +56,37 @@
        - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + + - - - - - + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - - - + + + + + - - - + + + + - - - + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + - - - + + + + - - - - + + + + - - - - - - + + + + + - - - - + + + + + - - - - - - + + + + + - - - - - - - - - + + + + + + + + + +
        diff --git a/views/settings/import.php b/views/settings/import.php index 1f989151..7907c0ea 100644 --- a/views/settings/import.php +++ b/views/settings/import.php @@ -2,7 +2,7 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit; ?>
        @@ -13,10 +13,10 @@
        '; - esc_html_e('Just drag and drop a Duplicator Pro archive to quickly replace an existing WordPress installation!', 'duplicator'); - ?> + esc_html_e('Just drag and drop a Duplicator Pro archive to quickly replace an existing WordPress installation!', 'duplicator'); + ?>
        diff --git a/views/settings/index.php b/views/settings/index.php index b4962229..c9199655 100644 --- a/views/settings/index.php +++ b/views/settings/index.php @@ -1,2 +1,3 @@ -

        -
        - - - - - - - - - - - - - -
        ', ''); ?>
        - -
        -
        -
        -
        -
        -
        - - - -
          -
        • - -
        • -
        • - ' . esc_html__("get a copy here", 'duplicator') . '!'; - ?> -
        • -
        - - -
          -
        • - -
        • -
        • - -
        • - -
        -
        -
        - - - + +

        +
        + + + + + + + + + + + + + +
        ', ''); ?>
        + +
        +
        +
        +
        +
        +
        + + + +
          +
        • + +
        • +
        • + ' . esc_html__("get a copy here", 'duplicator') . '!'; + ?> +
        • +
        + + +
          +
        • + +
        • +
        • + +
        • + +
        +
        +
        + + + diff --git a/views/settings/packages.php b/views/settings/packages.php index 3f96c7b6..0cfcd95e 100644 --- a/views/settings/packages.php +++ b/views/settings/packages.php @@ -1,4 +1,7 @@
        @@ -121,10 +123,12 @@ data-tooltip=""> %s %s", + printf( + "%s %s %s", __("Please visit our recommended", 'duplicator'), __("host list", 'duplicator'), - __("for reliable access to mysqldump", 'duplicator')); + __("for reliable access to mysqldump", 'duplicator') + ); ?> @@ -143,12 +147,14 @@ %s %s", + printf( + "%s %s %s", __("See the", 'duplicator'), __("host list", 'duplicator'), - __("for reliable access to mysqldump.", 'duplicator')); + __("for reliable access to mysqldump.", 'duplicator') + ); ?>

        @@ -157,18 +163,23 @@ " data-tooltip=""> + esc_attr_e('Add a custom path if the path to mysqldump is not properly detected. For all paths use a forward slash as the ' + . 'path seperator. On Linux systems use mysqldump for Windows systems use mysqldump.exe. If the path tried does not work please contact your hosting ' + . 'provider for details on the correct path.', 'duplicator'); + ?>">
        - " /> + " + >
        The custom path provided is not recognized as a valid mysqldump file:
        ', 'duplicator'); $mysqldump_path = esc_html($package_mysqldump_path); - echo "'".esc_html($mysqldump_path)."'"; + echo "'" . esc_html($mysqldump_path) . "'"; } ?>
        @@ -187,29 +198,34 @@ " data-tooltip="
        Multi-Threaded mode is only available in Duplicator Pro.', 'duplicator'); - ?>">
        + esc_attr_e('Single-Threaded mode attempts to create the entire database script in one request. Multi-Threaded mode allows the database script ' + . 'to be chunked over multiple requests. Multi-Threaded mode is typically slower but much more reliable especially for larger databases.', 'duplicator'); + esc_attr_e('

        Multi-Threaded mode is only available in Duplicator Pro.', 'duplicator'); + ?>">
          " - data-tooltip=""> + data-tooltip=""> +
        @@ -239,24 +255,44 @@
        - -
        -
        - - -title = __('Delete Option?', 'duplicator'); - $confirm1->message = __('Delete the option value just selected?', 'duplicator'); - $confirm1->progressText = __('Removing Option, Please Wait...', 'duplicator'); - $confirm1->jscallback = 'Duplicator.Settings.DeleteOption()'; - $confirm1->initConfirm(); - - $confirm2 = new DUP_UI_Dialog(); - $confirm2->title = __('Clear Build Cache?', 'duplicator'); - $confirm2->message = __('This process will remove all build cache files. Be sure no packages are currently building or else they will be cancelled.', 'duplicator'); - $confirm2->jscallback = 'Duplicator.Tools.ClearBuildCache()'; - $confirm2->initConfirm(); -?> - - +prefix}options` WHERE `option_name` LIKE '%duplicator_%' AND `option_name` NOT LIKE '%duplicator_pro%' ORDER BY option_name"; +?> + + +
        +
        + + +
        +
        +
        +
        +

        + + + + + + + + + +
        + + + + []
        + +
        +
        "; + + $installer_files = array_keys($installer_files); + array_push($installer_files, '[HASH]_archive.zip/daf'); + echo '' . implode('
        ', $installer_files) . '
        '; + echo "

        "; + ?> +
        +
        + + [].
        +
        +
        +

        + + + + + + + + + get_results("{$sql}") as $key => $row) { ?> + + + + + + +
        KeyValue
        + option_name, $GLOBALS['DUPLICATOR_OPTS_DELETE'])) + ? "" . esc_html($row->option_name) . "" + : $row->option_name; + ?> +
        +
        + +
        +
        +
        + + +title = __('Delete Option?', 'duplicator'); + $confirm1->message = __('Delete the option value just selected?', 'duplicator'); + $confirm1->progressText = __('Removing Option, Please Wait...', 'duplicator'); + $confirm1->jscallback = 'Duplicator.Settings.DeleteOption()'; + $confirm1->initConfirm(); + + $confirm2 = new DUP_UI_Dialog(); + $confirm2->title = __('Clear Build Cache?', 'duplicator'); + $confirm2->message = __('This process will remove all build cache files. Be sure no packages are currently building or else they will be cancelled.', 'duplicator'); + $confirm2->jscallback = 'Duplicator.Tools.ClearBuildCache()'; + $confirm2->initConfirm(); +?> + + diff --git a/views/tools/diagnostics/inc.phpinfo.php b/views/tools/diagnostics/inc.phpinfo.php index c938bd28..7c630501 100644 --- a/views/tools/diagnostics/inc.phpinfo.php +++ b/views/tools/diagnostics/inc.phpinfo.php @@ -1,29 +1,38 @@ -(.*).*$%ms', '$1', $serverinfo); - $serverinfo = preg_replace( '%^.*(.*).*$%ms','$1', $serverinfo); -?> - - -
        -
        - - -
        -
        -
        -
        - -
        +phpinfo function is not supported on this server, ' + . 'for more details contact your hosting provider.'; + } else { + $serverinfo = preg_replace('%^.*(.*).*$%ms', '$1', $serverinfo); + $serverinfo = preg_replace('%^.*(.*).*$%ms', '$1', $serverinfo); + } +?> + + +
        +
        + + +
        +
        +
        +
        + +
        diff --git a/views/tools/diagnostics/inc.settings.php b/views/tools/diagnostics/inc.settings.php index ea0c7991..628dd9a2 100644 --- a/views/tools/diagnostics/inc.settings.php +++ b/views/tools/diagnostics/inc.settings.php @@ -1,227 +1,240 @@ - - - -
        -
        - - -
        -
        -
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        - - - -
          This is a WordPress setting
        WordPress
        ()
        PHP
        SAPI
        - -
        - - " - data-tooltip=""> -
        - -
        MySQL
        % -- from
        - -
        - -
        -

        - -
        -
        -
        \ No newline at end of file + + + +
        +
        + + +
        +
        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + - + +
          This is a WordPress setting
        WordPress
        ()
        PHP
        SAPI
        + +
        + + " + data-tooltip=""> +
        + +
        MySQL
        + + +

        + + % -- + from
        + +
        + +
        + +

        + +
        +
        +
        diff --git a/views/tools/diagnostics/inc.validator.php b/views/tools/diagnostics/inc.validator.php index 36eef5c6..3655807a 100644 --- a/views/tools/diagnostics/inc.validator.php +++ b/views/tools/diagnostics/inc.validator.php @@ -1,161 +1,161 @@ - - - - - -title = __('Run Validator', 'duplicator'); - $confirm1->message = __('This will run the scan validation check. This may take several minutes. Do you want to Continue?', 'duplicator'); - $confirm1->progressOn = false; - $confirm1->jscallback = 'Duplicator.Tools.runScanValidator()'; - $confirm1->initConfirm(); -?> - - -
        -
        - - -
        -
        -
        - -

        - - - - - -
        - -
        -
        -
        - - - + + + + + +title = __('Run Validator', 'duplicator'); + $confirm1->message = __('This will run the scan validation check. This may take several minutes. Do you want to Continue?', 'duplicator'); + $confirm1->progressOn = false; + $confirm1->jscallback = 'Duplicator.Tools.runScanValidator()'; + $confirm1->initConfirm(); +?> + + +
        +
        + + +
        +
        +
        + +

        + + + + + +
        + +
        +
        +
        + + + diff --git a/views/tools/diagnostics/information.php b/views/tools/diagnostics/information.php index 68db4bb9..e4ad067f 100644 --- a/views/tools/diagnostics/information.php +++ b/views/tools/diagnostics/information.php @@ -1,234 +1,82 @@ - -
        -

        - $path) { - $file_path = ''; - if (stripos($filename, '[hash]') !== false) { - $glob_files = glob($path); - - if (!empty($glob_files)) { - if(count($glob_files) > 10) { - throw new Exception('Trying to delete too many files. Please contact Duplicator support.'); - } - - foreach ($glob_files as $glob_file) { - $file_path = $glob_file; - DUP_IO::deleteFile($file_path); - $removed_files = true; - } - } - } else if (is_file($path)) { - $file_path = $path; - DUP_IO::deleteFile($path); - $removed_files = true; - } else if (is_dir($path)) { - $file_path = $path; - - // Extra protection to ensure we only are deleting the installer directory - if(DUP_STR::contains($path, 'dup-installer')) { - DUP_IO::deleteTree($path); - $removed_files = true; - } - } - - if (!empty($file_path)) { - if (file_exists($file_path)) { - echo "
        {$txt_found} - ".esc_html($file_path)."
        "; - $remove_error = true; - } else { - echo "
        {$txt_removed} - ".esc_html($file_path)."
        "; - } - } - } - - //No way to know exact name of archive file except from installer. - //The only place where the package can be removed is from installer - //So just show a message if removing from plugin. - if (file_exists($package_path)) { - $path_parts = pathinfo($package_name); - $path_parts = (isset($path_parts['extension'])) ? $path_parts['extension'] : ''; - $valid_ext = ($path_parts == "zip" || $path_parts == "daf"); - if ($valid_ext && !is_dir($package_path)) { - $html .= (@unlink($package_path)) - ? "
        ".esc_html($txt_removed)." - ".esc_html($package_path)."
        " - : "
        ".esc_html($txt_found)." - ".esc_html($package_path)."
        "; - } - } - echo $html; - - if (!$removed_files) { - echo '
        ' - . ' ' . esc_html__('No Duplicator installer files found on this WordPress Site.', 'duplicator') . '' - . '
        '; - } - ?> - -
        - ' . esc_html__('Security Notes', 'duplicator') . ': '; - _e('If the installer files do not successfully get removed with this action, then they WILL need to be removed manually through your hosts control panel ' - . 'or FTP. Please remove all installer files to avoid any security issues on this site. For more details please visit ' - . 'the FAQ link Which files need to be removed after an install?', 'duplicator'); - - echo '

        '; - - if ($remove_error) { - echo __('Some of the installer files did not get removed, ', 'duplicator'). - ''. - __('please retry the installer cleanup process', 'duplicator'). - '.'. - __(' If this process continues please see the previous FAQ link.', 'duplicator'). - '

        '; - } - - echo ' ' . esc_html__('Help Support Duplicator', 'duplicator') . ': '; - _e('The Duplicator team has worked many years to make moving a WordPress site a much easier process. Show your support with a ' - . '5 star review! We would be thrilled if you could!', 'duplicator'); - ?> -
        - - -
        - stylesheet != $active_theme->stylesheet){ - $temp_theme = array('stylesheet' => $theme->stylesheet, 'template' => $theme->template); - break; - } - } - - if($temp_theme != null){ - //switch to another theme then backto default - switch_theme($temp_theme['template'], $temp_theme['stylesheet']); - switch_theme($active_theme->template, $active_theme->stylesheet); - } - - break; - } - - if (! DUP_Server::hasInstallerFiles()) { - echo "

        ".esc_html($safe_title)." " - . "

        ".esc_html($safe_msg)."

        "; - } - - delete_option("duplicator_exe_safe_mode"); - } -} -?> - - - - - - -

        ".esc_html($remove_response)."

        "; - } - - include_once 'inc.data.php'; - include_once 'inc.settings.php'; - include_once 'inc.validator.php'; - include_once 'inc.phpinfo.php'; - ?> - + +
        +

        +
        + + + +
        + + + +

        " . esc_html($remove_response) . "

        "; + } + + include_once 'inc.data.php'; + include_once 'inc.settings.php'; + include_once 'inc.validator.php'; + include_once 'inc.phpinfo.php'; + ?> +
        diff --git a/views/tools/diagnostics/logging.php b/views/tools/diagnostics/logging.php index 50474e63..6aad04ff 100644 --- a/views/tools/diagnostics/logging.php +++ b/views/tools/diagnostics/logging.php @@ -1,230 +1,234 @@ - 0) { - unset($logname); - } - unset($validFiles); -} - -if (!isset($logname) || !$logname) { - $logname = (count($logs) > 0) ? basename($logs[0]) : ""; -} - -$logurl = DUP_Settings::getSsdirUrl().'/'.$logname; -$logfound = (strlen($logname) > 0) ? true : false; -?> - - - - - -
        - - - - -
        -

        .

        - .

        - :
        - - .
        - - .
        - - .
        -
        - - - - - - -
        -
        -   |   - " - data-tooltip=""> - - %s %s", - esc_html__("Consider our recommended", 'duplicator'), - esc_html__("host list", 'duplicator'), - esc_html__("if you’re unhappy with your current provider", 'duplicator')); - ?> - -
        -
         
        -
        -
        
        -			
        -

        -
        - " />   - - -
        - -
        - - -
        - -
        - ".esc_html($time)."-".esc_html($name)."" - : "".esc_html($time)."-".esc_html($name).""; - if ($count > 20) break; - } - ?> -
        -
        - -
        + 0) { + unset($logname); + } + unset($validFiles); +} + +if (!isset($logname) || !$logname) { + $logname = (count($logs) > 0) ? basename($logs[0]) : ""; +} + +$logurl = DUP_Settings::getSsdirUrl() . '/' . $logname; +$logfound = (strlen($logname) > 0) ? true : false; +?> + + + + + +
        + + + + +
        +

        .

        + .

        + :
        + - .
        + - .
        + - .
        +
        + + + + + + +
        +
        +   |   + " + data-tooltip=""> + + %s %s", + esc_html__("Consider our recommended", 'duplicator'), + esc_html__("host list", 'duplicator'), + esc_html__("if you’re unhappy with your current provider", 'duplicator') + ); + ?> + +
        +
         
        +
        +
        
        +            
        +

        +
        + " />   + + +
        + +
        + + +
        + +
        + " . esc_html($time) . "-" . esc_html($name) . "" + : "" . esc_html($time) . "-" . esc_html($name) . ""; + if ($count > 20) { + break; + } + } + ?> +
        +
        + +
        diff --git a/views/tools/diagnostics/main.php b/views/tools/diagnostics/main.php index 1e810a1f..df5bbd4a 100644 --- a/views/tools/diagnostics/main.php +++ b/views/tools/diagnostics/main.php @@ -1,64 +1,65 @@ - - - - -setResponseType('PHP'); -$data = $ctrl_ui->GetViewStateList(); - -$ui_css_srv_panel = (isset($data->payload['dup-settings-diag-srv-panel']) && $data->payload['dup-settings-diag-srv-panel']) ? 'display:block' : 'display:none'; -$ui_css_opts_panel = (isset($data->payload['dup-settings-diag-opts-panel']) && $data->payload['dup-settings-diag-opts-panel']) ? 'display:block' : 'display:none'; - -$section = isset($_GET['section']) ? $_GET['section'] : 'info'; -$txt_diagnostic = __('Information', 'duplicator'); -$txt_log = __('Logs', 'duplicator'); -$txt_support = __('Support', 'duplicator');; -$tools_url = 'admin.php?page=duplicator-tools&tab=diagnostics'; - -switch ($section) { - case 'info': - echo "
        ".esc_html($txt_diagnostic)."  |  ".esc_html($txt_log)."  |  ".esc_html($txt_support)."
        "; - include(dirname(__FILE__) . '/information.php'); - break; - - case 'log': - echo ""; - include(dirname(__FILE__) . '/logging.php'); - break; - - case 'support': - echo "
        ".esc_html($txt_diagnostic)."  |  ".esc_html($txt_log)."  |  ".esc_html($txt_support)."
        "; - include(dirname(__FILE__) . '/support.php'); - break; -} -?> \ No newline at end of file + + + + +setResponseType('PHP'); +$data = $ctrl_ui->GetViewStateList(); + +$ui_css_srv_panel = (isset($data->payload['dup-settings-diag-srv-panel']) && $data->payload['dup-settings-diag-srv-panel']) ? 'display:block' : 'display:none'; +$ui_css_opts_panel = (isset($data->payload['dup-settings-diag-opts-panel']) && $data->payload['dup-settings-diag-opts-panel']) ? 'display:block' : 'display:none'; + +$section = isset($_GET['section']) ? $_GET['section'] : 'info'; +$txt_diagnostic = __('Information', 'duplicator'); +$txt_log = __('Logs', 'duplicator'); +$txt_support = __('Support', 'duplicator'); +; +$tools_url = 'admin.php?page=duplicator-tools&tab=diagnostics'; + +switch ($section) { + case 'info': + echo "
        " . esc_html($txt_diagnostic) . "  |  " . esc_html($txt_log) . "  |  " . esc_html($txt_support) . "
        "; + include(dirname(__FILE__) . '/information.php'); + break; + + case 'log': + echo ""; + include(dirname(__FILE__) . '/logging.php'); + break; + + case 'support': + echo "
        " . esc_html($txt_diagnostic) . "  |  " . esc_html($txt_log) . "  |  " . esc_html($txt_support) . "
        "; + include(dirname(__FILE__) . '/support.php'); + break; +} +?> diff --git a/views/tools/diagnostics/support.php b/views/tools/diagnostics/support.php index 00ebe0e8..6c827748 100644 --- a/views/tools/diagnostics/support.php +++ b/views/tools/diagnostics/support.php @@ -1,133 +1,153 @@ - - - - -
        - -
        - - - - - -
        - -
        -

        - - -
        -
        - -
        -
        -
        -
        - -
        -
        - - -
        -
        - -
        -
        -
        - -
        - - Pro Users Support Here -
        -
        -


        - - - -
        - -
        - -
        -
        -
        - -

        - -
        -
        - - -
        - -
        - -
        -
        -
        - -

        - -
        -
        -
        -




        - - \ No newline at end of file + + + + +
        + +
        + + + + + +
        + +
        +

        + + +
        +
        + +
        +
        +
        +
        + +
        +
        + + +
        +
        + +
        +
        +
        + +
        + + Pro Users Support Here +
        +
        +


        + + + +
        + +
        + +
        +
        +
        + +

        + +
        +
        + + +
        + +
        + +
        +
        +
        + +

        + +
        +
        +
        +




        + + diff --git a/views/tools/index.php b/views/tools/index.php index b4962229..c9199655 100644 --- a/views/tools/index.php +++ b/views/tools/index.php @@ -1,2 +1,3 @@ @@ -16,11 +16,11 @@
        - '; esc_html_e('Upgrade plugins or make risky site changes with confidence!', 'duplicator'); - ?> + ?>
        diff --git a/views/tools/templates.php b/views/tools/templates.php index 03f35299..f869ee44 100644 --- a/views/tools/templates.php +++ b/views/tools/templates.php @@ -2,7 +2,7 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit; ?>
        From 6b2943f529b2a451443734fcf0e50790bf3efe92 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Sat, 27 Aug 2022 19:24:27 +0000 Subject: [PATCH 552/585] removing legacy code, version update git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@2776550 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- classes/utilities/class.u.migration.php | 137 - define.php | 2 +- .../dup-installer/classes/Crypt/Base.php | 2660 ----------------- .../dup-installer/classes/Crypt/Random.php | 340 --- .../dup-installer/classes/Crypt/Rijndael.php | 1050 ------- .../dup-installer/classes/Crypt/index.php | 2 - installer/dup-installer/classes/class.db.php | 478 --- .../dup-installer/classes/class.logging.php | 452 --- .../dup-installer/classes/class.s3.func.php | 1342 --------- .../dup-installer/classes/class.view.php | 92 - .../classes/config/class.boot.php | 318 -- .../classes/utilities/class.u.html.php | 551 ---- installer/dup-installer/ctrls/ctrl.s1.php | 7 - .../dup-installer/ctrls/ctrl.s2.base.php | 198 -- .../dup-installer/ctrls/ctrl.s2.dbinstall.php | 732 ----- .../dup-installer/ctrls/ctrl.s2.dbtest.php | 810 ----- installer/dup-installer/ctrls/ctrl.s3.php | 50 - .../favicon/android-chrome-192x192.png | Bin 28559 -> 0 bytes .../favicon/android-chrome-384x384.png | Bin 69783 -> 0 bytes .../favicon/apple-touch-icon.png | Bin 26593 -> 0 bytes .../dup-installer/favicon/favicon-16x16.png | Bin 1498 -> 0 bytes .../dup-installer/favicon/favicon-32x32.png | Bin 2958 -> 0 bytes installer/dup-installer/favicon/favicon.ico | Bin 15086 -> 0 bytes .../dup-installer/favicon/mstile-150x150.png | Bin 15482 -> 0 bytes installer/dup-installer/views/index.php | 2 - .../dup-installer/views/view.exception.php | 39 - installer/dup-installer/views/view.help.php | 714 ----- installer/dup-installer/views/view.init1.php | 159 - .../dup-installer/views/view.s1.base.php | 1544 ---------- .../dup-installer/views/view.s1.terms.php | 83 - .../dup-installer/views/view.s2.base.php | 366 --- .../dup-installer/views/view.s2.basic.php | 342 --- .../dup-installer/views/view.s2.cpnl.lite.php | 39 - .../dup-installer/views/view.s2.dbtest.php | 566 ---- installer/dup-installer/views/view.s3.php | 638 ---- installer/dup-installer/views/view.s4.php | 430 --- .../views/view.security.error.php | 33 - lib/config/class.wp.config.tranformer.php | 459 --- lib/config/class.wp.config.tranformer.src.php | 92 - .../classes/class.duparchive.constants.php | 34 - .../classes/class.duparchive.engine.php | 756 ----- .../classes/class.duparchive.loggerbase.php | 8 - .../class.duparchive.mini.expander.php | 430 --- .../class.duparchive.processing.failure.php | 25 - .../class.duparchive.header.directory.php | 100 - .../headers/class.duparchive.header.file.php | 145 - .../headers/class.duparchive.header.glob.php | 66 - .../headers/class.duparchive.header.php | 74 - .../headers/class.duparchive.header.u.php | 36 - lib/dup_archive/classes/headers/index.php | 2 - lib/dup_archive/classes/index.php | 2 - .../class.duparchive.processor.directory.php | 26 - .../class.duparchive.processor.file.php | 421 --- lib/dup_archive/classes/processors/index.php | 2 - .../states/class.duparchive.state.base.php | 125 - .../states/class.duparchive.state.create.php | 24 - .../states/class.duparchive.state.expand.php | 47 - .../class.duparchive.state.simplecreate.php | 26 - .../class.duparchive.state.simpleexpand.php | 23 - lib/dup_archive/classes/states/index.php | 2 - .../classes/util/class.duparchive.u.json.php | 165 - .../classes/util/class.duparchive.util.php | 190 -- .../util/class.duparchive.util.scan.php | 84 - lib/dup_archive/classes/util/index.php | 2 - lib/dup_archive/daws/class.daws.constants.php | 42 - .../daws/class.daws.state.expand.php | 144 - lib/dup_archive/daws/daws.php | 294 -- lib/dup_archive/daws/dawslock.bin | 0 lib/dup_archive/daws/index.php | 2 - lib/dup_archive/define.php | 7 - lib/dup_archive/index.php | 2 - .../tester/classes/class.datester.logging.php | 85 - .../classes/class.datester.state.create.php | 121 - .../classes/class.datester.state.expand.php | 121 - .../tester/classes/expandstate.json | 1 - lib/dup_archive/tester/classes/index.php | 2 - lib/dup_archive/tester/classes/state.json | 1 - lib/dup_archive/tester/datester.php | 562 ---- lib/dup_archive/tester/index.php | 2 - lib/fileops/class.fileops.constants.php | 36 - lib/fileops/class.fileops.state.php | 99 - lib/fileops/class.fileops.u.delete.php | 46 - lib/fileops/class.fileops.u.move.php | 31 - lib/fileops/fileops.php | 169 -- lib/fileops/index.php | 2 - lib/snaplib/class.snaplib.exceptions.php | 21 - ...lass.snaplib.jsonSerializable.abstract.php | 169 -- lib/snaplib/class.snaplib.logger.php | 144 - lib/snaplib/class.snaplib.u.db.php | 241 -- lib/snaplib/class.snaplib.u.io.php | 1302 -------- lib/snaplib/class.snaplib.u.json.php | 311 -- lib/snaplib/class.snaplib.u.net.php | 65 - .../class.snaplib.u.orig.files.manager.php | 348 --- lib/snaplib/class.snaplib.u.os.php | 66 - lib/snaplib/class.snaplib.u.stream.php | 31 - lib/snaplib/class.snaplib.u.string.php | 129 - lib/snaplib/class.snaplib.u.ui.php | 49 - lib/snaplib/class.snaplib.u.url.php | 182 -- lib/snaplib/class.snaplib.u.util.php | 463 --- lib/snaplib/class.snaplib.u.wp.php | 247 -- lib/snaplib/index.php | 2 - lib/snaplib/snaplib.all.php | 36 - lib/snaplib/wordpress.core.files.php | 2260 -------------- 103 files changed, 1 insertion(+), 25376 deletions(-) delete mode 100644 classes/utilities/class.u.migration.php delete mode 100644 installer/dup-installer/classes/Crypt/Base.php delete mode 100644 installer/dup-installer/classes/Crypt/Random.php delete mode 100644 installer/dup-installer/classes/Crypt/Rijndael.php delete mode 100644 installer/dup-installer/classes/Crypt/index.php delete mode 100644 installer/dup-installer/classes/class.db.php delete mode 100644 installer/dup-installer/classes/class.logging.php delete mode 100644 installer/dup-installer/classes/class.s3.func.php delete mode 100644 installer/dup-installer/classes/class.view.php delete mode 100644 installer/dup-installer/classes/config/class.boot.php delete mode 100644 installer/dup-installer/classes/utilities/class.u.html.php delete mode 100644 installer/dup-installer/ctrls/ctrl.s1.php delete mode 100644 installer/dup-installer/ctrls/ctrl.s2.base.php delete mode 100644 installer/dup-installer/ctrls/ctrl.s2.dbinstall.php delete mode 100644 installer/dup-installer/ctrls/ctrl.s2.dbtest.php delete mode 100644 installer/dup-installer/ctrls/ctrl.s3.php delete mode 100644 installer/dup-installer/favicon/android-chrome-192x192.png delete mode 100644 installer/dup-installer/favicon/android-chrome-384x384.png delete mode 100644 installer/dup-installer/favicon/apple-touch-icon.png delete mode 100644 installer/dup-installer/favicon/favicon-16x16.png delete mode 100644 installer/dup-installer/favicon/favicon-32x32.png delete mode 100644 installer/dup-installer/favicon/favicon.ico delete mode 100644 installer/dup-installer/favicon/mstile-150x150.png delete mode 100644 installer/dup-installer/views/index.php delete mode 100644 installer/dup-installer/views/view.exception.php delete mode 100644 installer/dup-installer/views/view.help.php delete mode 100644 installer/dup-installer/views/view.init1.php delete mode 100644 installer/dup-installer/views/view.s1.base.php delete mode 100644 installer/dup-installer/views/view.s1.terms.php delete mode 100644 installer/dup-installer/views/view.s2.base.php delete mode 100644 installer/dup-installer/views/view.s2.basic.php delete mode 100644 installer/dup-installer/views/view.s2.cpnl.lite.php delete mode 100644 installer/dup-installer/views/view.s2.dbtest.php delete mode 100644 installer/dup-installer/views/view.s3.php delete mode 100644 installer/dup-installer/views/view.s4.php delete mode 100644 installer/dup-installer/views/view.security.error.php delete mode 100644 lib/config/class.wp.config.tranformer.php delete mode 100644 lib/config/class.wp.config.tranformer.src.php delete mode 100644 lib/dup_archive/classes/class.duparchive.constants.php delete mode 100644 lib/dup_archive/classes/class.duparchive.engine.php delete mode 100644 lib/dup_archive/classes/class.duparchive.loggerbase.php delete mode 100644 lib/dup_archive/classes/class.duparchive.mini.expander.php delete mode 100644 lib/dup_archive/classes/class.duparchive.processing.failure.php delete mode 100644 lib/dup_archive/classes/headers/class.duparchive.header.directory.php delete mode 100644 lib/dup_archive/classes/headers/class.duparchive.header.file.php delete mode 100644 lib/dup_archive/classes/headers/class.duparchive.header.glob.php delete mode 100644 lib/dup_archive/classes/headers/class.duparchive.header.php delete mode 100644 lib/dup_archive/classes/headers/class.duparchive.header.u.php delete mode 100644 lib/dup_archive/classes/headers/index.php delete mode 100644 lib/dup_archive/classes/index.php delete mode 100644 lib/dup_archive/classes/processors/class.duparchive.processor.directory.php delete mode 100644 lib/dup_archive/classes/processors/class.duparchive.processor.file.php delete mode 100644 lib/dup_archive/classes/processors/index.php delete mode 100644 lib/dup_archive/classes/states/class.duparchive.state.base.php delete mode 100644 lib/dup_archive/classes/states/class.duparchive.state.create.php delete mode 100644 lib/dup_archive/classes/states/class.duparchive.state.expand.php delete mode 100644 lib/dup_archive/classes/states/class.duparchive.state.simplecreate.php delete mode 100644 lib/dup_archive/classes/states/class.duparchive.state.simpleexpand.php delete mode 100644 lib/dup_archive/classes/states/index.php delete mode 100644 lib/dup_archive/classes/util/class.duparchive.u.json.php delete mode 100644 lib/dup_archive/classes/util/class.duparchive.util.php delete mode 100644 lib/dup_archive/classes/util/class.duparchive.util.scan.php delete mode 100644 lib/dup_archive/classes/util/index.php delete mode 100644 lib/dup_archive/daws/class.daws.constants.php delete mode 100644 lib/dup_archive/daws/class.daws.state.expand.php delete mode 100644 lib/dup_archive/daws/daws.php delete mode 100644 lib/dup_archive/daws/dawslock.bin delete mode 100644 lib/dup_archive/daws/index.php delete mode 100644 lib/dup_archive/define.php delete mode 100644 lib/dup_archive/index.php delete mode 100644 lib/dup_archive/tester/classes/class.datester.logging.php delete mode 100644 lib/dup_archive/tester/classes/class.datester.state.create.php delete mode 100644 lib/dup_archive/tester/classes/class.datester.state.expand.php delete mode 100644 lib/dup_archive/tester/classes/expandstate.json delete mode 100644 lib/dup_archive/tester/classes/index.php delete mode 100644 lib/dup_archive/tester/classes/state.json delete mode 100644 lib/dup_archive/tester/datester.php delete mode 100644 lib/dup_archive/tester/index.php delete mode 100644 lib/fileops/class.fileops.constants.php delete mode 100644 lib/fileops/class.fileops.state.php delete mode 100644 lib/fileops/class.fileops.u.delete.php delete mode 100644 lib/fileops/class.fileops.u.move.php delete mode 100644 lib/fileops/fileops.php delete mode 100644 lib/fileops/index.php delete mode 100644 lib/snaplib/class.snaplib.exceptions.php delete mode 100644 lib/snaplib/class.snaplib.jsonSerializable.abstract.php delete mode 100644 lib/snaplib/class.snaplib.logger.php delete mode 100644 lib/snaplib/class.snaplib.u.db.php delete mode 100644 lib/snaplib/class.snaplib.u.io.php delete mode 100644 lib/snaplib/class.snaplib.u.json.php delete mode 100644 lib/snaplib/class.snaplib.u.net.php delete mode 100644 lib/snaplib/class.snaplib.u.orig.files.manager.php delete mode 100644 lib/snaplib/class.snaplib.u.os.php delete mode 100644 lib/snaplib/class.snaplib.u.stream.php delete mode 100644 lib/snaplib/class.snaplib.u.string.php delete mode 100644 lib/snaplib/class.snaplib.u.ui.php delete mode 100644 lib/snaplib/class.snaplib.u.url.php delete mode 100644 lib/snaplib/class.snaplib.u.util.php delete mode 100644 lib/snaplib/class.snaplib.u.wp.php delete mode 100644 lib/snaplib/index.php delete mode 100644 lib/snaplib/snaplib.all.php delete mode 100644 lib/snaplib/wordpress.core.files.php diff --git a/classes/utilities/class.u.migration.php b/classes/utilities/class.u.migration.php deleted file mode 100644 index 1566a7ec..00000000 --- a/classes/utilities/class.u.migration.php +++ /dev/null @@ -1,137 +0,0 @@ - array(), - 'stored' => array(), - 'instFile' => array() - ); - - /** - * Check the root path and in case there are installer files without hashes rename them. - * - * @return void - */ - public static function renameInstallersPhpFiles() - { - $pathsTocheck = array( - DupLiteSnapLibIOU::safePathTrailingslashit(ABSPATH), - DupLiteSnapLibIOU::safePathTrailingslashit(DupLiteSnapLibUtilWp::getHomePath()), - DupLiteSnapLibIOU::safePathTrailingslashit(WP_CONTENT_DIR) - ); - - $pathsTocheck = array_unique($pathsTocheck); - - $filesToCheck = array(); - foreach ($pathsTocheck as $cFolder) { - if ( - !is_dir($cFolder) || - !is_writable($cFolder) // rename permissions - ) { - continue; - } - $cFile = $cFolder . 'installer.php'; - if ( - !is_file($cFile) || - !DupLiteSnapLibIOU::chmod($cFile, 'u+rw') || - !is_readable($cFile) - ) { - continue; - } - $filesToCheck[] = $cFile; - } - - $installerTplCheck = '/class DUPX_Bootstrap.+const\s+ARCHIVE_FILENAME\s*=\s*[\'"](.+?)[\'"]\s*;.*const\s+PACKAGE_HASH\s*=\s*[\'"](.+?)[\'"];/s'; - - foreach ($filesToCheck as $file) { - $fileName = basename($file); - if (($content = @file_get_contents($file, false, null, 0, 5000)) === false) { - continue; - } - $matches = null; - if (preg_match($installerTplCheck, $content, $matches) !== 1) { - continue; - } - - $archiveName = $matches[1]; - $hash = $matches[2]; - $matches = null; - - if (preg_match(self::ARCHIVE_REGEX_PATTERN, $archiveName, $matches) !== 1) { - if (DupLiteSnapLibIOU::unlink($file)) { - self::$migrationCleanupReport['instFile'][] = "
        " - . " " - . sprintf(__('Installer file %s removed for secority reasons', 'duplicator'), esc_html($fileName)) - . "
        "; - } else { - self::$migrationCleanupReport['instFile'][] = "
        " - . ' ' - . sprintf(__('Can\'t remove installer file %s, please remove it for security reasons', 'duplicator'), esc_html($fileName)) - . '
        '; - } - continue; - } - - $archiveHash = $matches[1]; - if (strpos($file, $archiveHash) === false) { - if (DupLiteSnapLibIOU::rename($file, dirname($file) . '/' . $archiveHash . '_installer.php', true)) { - self::$migrationCleanupReport['instFile'][] = "
        " - . " " - . sprintf(__('Installer file %s renamed with HASH', 'duplicator'), esc_html($fileName)) - . "
        "; - } else { - self::$migrationCleanupReport['instFile'][] = "
        " - . ' ' - . sprintf(__('Can\'t rename installer file %s with HASH, please remove it for security reasons', 'duplicator'), esc_html($fileName)) - . '
        '; - } - } - } - } - - /** - * return cleanup report - * - * @return array - */ - public static function getCleanupReport() - { - $option = get_option(self::CLEAN_INSTALL_REPORT_OPTION); - if (is_array($option)) { - self::$migrationCleanupReport = array_merge(self::$migrationCleanupReport, $option); - } - - return self::$migrationCleanupReport; - } - - /** - * save clean up report in wordpress options - * - * @return boolean - */ - public static function saveCleanupReport() - { - return add_option(self::CLEAN_INSTALL_REPORT_OPTION, self::$migrationCleanupReport, '', 'no'); - } -} diff --git a/define.php b/define.php index fd3e2472..6b89fccc 100644 --- a/define.php +++ b/define.php @@ -6,7 +6,7 @@ if (function_exists('plugin_dir_url')) { define('DUPLICATOR_VERSION', '1.5.0'); - define('DUPLICATOR_VERSION_BUILD', '2022-08-22_18:00'); + define('DUPLICATOR_VERSION_BUILD', '2022-08-28_19:00'); define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__)); define('DUPLICATOR_SITE_URL', get_site_url()); diff --git a/installer/dup-installer/classes/Crypt/Base.php b/installer/dup-installer/classes/Crypt/Base.php deleted file mode 100644 index 4b2f29ff..00000000 --- a/installer/dup-installer/classes/Crypt/Base.php +++ /dev/null @@ -1,2660 +0,0 @@ - - * @author Hans-Juergen Petrich - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -/**#@+ - * @access public - * @see self::encrypt() - * @see self::decrypt() - */ -/** - * Encrypt / decrypt using the Counter mode. - * - * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29 - */ -define('CRYPT_MODE_CTR', -1); -/** - * Encrypt / decrypt using the Electronic Code Book mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29 - */ -define('CRYPT_MODE_ECB', 1); -/** - * Encrypt / decrypt using the Code Book Chaining mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29 - */ -define('CRYPT_MODE_CBC', 2); -/** - * Encrypt / decrypt using the Cipher Feedback mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29 - */ -define('CRYPT_MODE_CFB', 3); -/** - * Encrypt / decrypt using the Output Feedback mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29 - */ -define('CRYPT_MODE_OFB', 4); -/** - * Encrypt / decrypt using streaming mode. - */ -define('CRYPT_MODE_STREAM', 5); -/**#@-*/ - -/**#@+ - * @access private - * @see self::Crypt_Base() - * @internal These constants are for internal use only - */ -/** - * Base value for the internal implementation $engine switch - */ -define('CRYPT_ENGINE_INTERNAL', 1); -/** - * Base value for the mcrypt implementation $engine switch - */ -define('CRYPT_ENGINE_MCRYPT', 2); -/** - * Base value for the OpenSSL implementation $engine switch - */ -define('CRYPT_ENGINE_OPENSSL', 3); -/**#@-*/ - -/** - * Base Class for all Crypt_* cipher classes - * - * @package Crypt_Base - * @author Jim Wigginton - * @author Hans-Juergen Petrich - * @access public - */ -class Crypt_Base -{ - /** - * The Encryption Mode - * - * @see self::Crypt_Base() - * @var int - * @access private - */ - var $mode; - - /** - * The Block Length of the block cipher - * - * @var int - * @access private - */ - var $block_size = 16; - - /** - * The Key - * - * @see self::setKey() - * @var string - * @access private - */ - var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; - - /** - * The Initialization Vector - * - * @see self::setIV() - * @var string - * @access private - */ - var $iv; - - /** - * A "sliding" Initialization Vector - * - * @see self::enableContinuousBuffer() - * @see self::_clearBuffers() - * @var string - * @access private - */ - var $encryptIV; - - /** - * A "sliding" Initialization Vector - * - * @see self::enableContinuousBuffer() - * @see self::_clearBuffers() - * @var string - * @access private - */ - var $decryptIV; - - /** - * Continuous Buffer status - * - * @see self::enableContinuousBuffer() - * @var bool - * @access private - */ - var $continuousBuffer = false; - - /** - * Encryption buffer for CTR, OFB and CFB modes - * - * @see self::encrypt() - * @see self::_clearBuffers() - * @var array - * @access private - */ - var $enbuffer; - - /** - * Decryption buffer for CTR, OFB and CFB modes - * - * @see self::decrypt() - * @see self::_clearBuffers() - * @var array - * @access private - */ - var $debuffer; - - /** - * mcrypt resource for encryption - * - * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. - * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. - * - * @see self::encrypt() - * @var resource - * @access private - */ - var $enmcrypt; - - /** - * mcrypt resource for decryption - * - * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. - * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. - * - * @see self::decrypt() - * @var resource - * @access private - */ - var $demcrypt; - - /** - * Does the enmcrypt resource need to be (re)initialized? - * - * @see Crypt_Twofish::setKey() - * @see Crypt_Twofish::setIV() - * @var bool - * @access private - */ - var $enchanged = true; - - /** - * Does the demcrypt resource need to be (re)initialized? - * - * @see Crypt_Twofish::setKey() - * @see Crypt_Twofish::setIV() - * @var bool - * @access private - */ - var $dechanged = true; - - /** - * mcrypt resource for CFB mode - * - * mcrypt's CFB mode, in (and only in) buffered context, - * is broken, so phpseclib implements the CFB mode by it self, - * even when the mcrypt php extension is available. - * - * In order to do the CFB-mode work (fast) phpseclib - * use a separate ECB-mode mcrypt resource. - * - * @link http://phpseclib.sourceforge.net/cfb-demo.phps - * @see self::encrypt() - * @see self::decrypt() - * @see self::_setupMcrypt() - * @var resource - * @access private - */ - var $ecb; - - /** - * Optimizing value while CFB-encrypting - * - * Only relevant if $continuousBuffer enabled - * and $engine == CRYPT_ENGINE_MCRYPT - * - * It's faster to re-init $enmcrypt if - * $buffer bytes > $cfb_init_len than - * using the $ecb resource furthermore. - * - * This value depends of the chosen cipher - * and the time it would be needed for it's - * initialization [by mcrypt_generic_init()] - * which, typically, depends on the complexity - * on its internaly Key-expanding algorithm. - * - * @see self::encrypt() - * @var int - * @access private - */ - var $cfb_init_len = 600; - - /** - * Does internal cipher state need to be (re)initialized? - * - * @see self::setKey() - * @see self::setIV() - * @see self::disableContinuousBuffer() - * @var bool - * @access private - */ - var $changed = true; - - /** - * Padding status - * - * @see self::enablePadding() - * @var bool - * @access private - */ - var $padding = true; - - /** - * Is the mode one that is paddable? - * - * @see self::Crypt_Base() - * @var bool - * @access private - */ - var $paddable = false; - - /** - * Holds which crypt engine internaly should be use, - * which will be determined automatically on __construct() - * - * Currently available $engines are: - * - CRYPT_ENGINE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required) - * - CRYPT_ENGINE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required) - * - CRYPT_ENGINE_INTERNAL (slower, pure php-engine, no php-extension required) - * - * @see self::_setEngine() - * @see self::encrypt() - * @see self::decrypt() - * @var int - * @access private - */ - var $engine; - - /** - * Holds the preferred crypt engine - * - * @see self::_setEngine() - * @see self::setPreferredEngine() - * @var int - * @access private - */ - var $preferredEngine; - - /** - * The mcrypt specific name of the cipher - * - * Only used if $engine == CRYPT_ENGINE_MCRYPT - * - * @link http://www.php.net/mcrypt_module_open - * @link http://www.php.net/mcrypt_list_algorithms - * @see self::_setupMcrypt() - * @var string - * @access private - */ - var $cipher_name_mcrypt; - - /** - * The openssl specific name of the cipher - * - * Only used if $engine == CRYPT_ENGINE_OPENSSL - * - * @link http://www.php.net/openssl-get-cipher-methods - * @var string - * @access private - */ - var $cipher_name_openssl; - - /** - * The openssl specific name of the cipher in ECB mode - * - * If OpenSSL does not support the mode we're trying to use (CTR) - * it can still be emulated with ECB mode. - * - * @link http://www.php.net/openssl-get-cipher-methods - * @var string - * @access private - */ - var $cipher_name_openssl_ecb; - - /** - * The default salt used by setPassword() - * - * @see self::setPassword() - * @var string - * @access private - */ - var $password_default_salt = 'phpseclib/salt'; - - /** - * The namespace used by the cipher for its constants. - * - * ie: AES.php is using CRYPT_AES_MODE_* for its constants - * so $const_namespace is AES - * - * DES.php is using CRYPT_DES_MODE_* for its constants - * so $const_namespace is DES... and so on - * - * All CRYPT_<$const_namespace>_MODE_* are aliases of - * the generic CRYPT_MODE_* constants, so both could be used - * for each cipher. - * - * Example: - * $aes = new Crypt_AES(CRYPT_AES_MODE_CFB); // $aes will operate in cfb mode - * $aes = new Crypt_AES(CRYPT_MODE_CFB); // identical - * - * @see self::Crypt_Base() - * @var string - * @access private - */ - var $const_namespace; - - /** - * The name of the performance-optimized callback function - * - * Used by encrypt() / decrypt() - * only if $engine == CRYPT_ENGINE_INTERNAL - * - * @see self::encrypt() - * @see self::decrypt() - * @see self::_setupInlineCrypt() - * @see self::$use_inline_crypt - * @var Callback - * @access private - */ - var $inline_crypt; - - /** - * Holds whether performance-optimized $inline_crypt() can/should be used. - * - * @see self::encrypt() - * @see self::decrypt() - * @see self::inline_crypt - * @var mixed - * @access private - */ - var $use_inline_crypt; - - /** - * If OpenSSL can be used in ECB but not in CTR we can emulate CTR - * - * @see self::_openssl_ctr_process() - * @var bool - * @access private - */ - var $openssl_emulate_ctr = false; - - /** - * Determines what options are passed to openssl_encrypt/decrypt - * - * @see self::isValidEngine() - * @var mixed - * @access private - */ - var $openssl_options; - - /** - * Has the key length explicitly been set or should it be derived from the key, itself? - * - * @see self::setKeyLength() - * @var bool - * @access private - */ - var $explicit_key_length = false; - - /** - * Don't truncate / null pad key - * - * @see self::_clearBuffers() - * @var bool - * @access private - */ - var $skip_key_adjustment = false; - - /** - * Default Constructor. - * - * Determines whether or not the mcrypt extension should be used. - * - * $mode could be: - * - * - CRYPT_MODE_ECB - * - * - CRYPT_MODE_CBC - * - * - CRYPT_MODE_CTR - * - * - CRYPT_MODE_CFB - * - * - CRYPT_MODE_OFB - * - * (or the alias constants of the chosen cipher, for example for AES: CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC ...) - * - * If not explicitly set, CRYPT_MODE_CBC will be used. - * - * @param int $mode - * @access public - */ - function __construct($mode = CRYPT_MODE_CBC) - { - // $mode dependent settings - switch ($mode) { - case CRYPT_MODE_ECB: - $this->paddable = true; - $this->mode = CRYPT_MODE_ECB; - break; - case CRYPT_MODE_CTR: - case CRYPT_MODE_CFB: - case CRYPT_MODE_OFB: - case CRYPT_MODE_STREAM: - $this->mode = $mode; - break; - case CRYPT_MODE_CBC: - default: - $this->paddable = true; - $this->mode = CRYPT_MODE_CBC; - } - - $this->_setEngine(); - - // Determining whether inline crypting can be used by the cipher - if ($this->use_inline_crypt !== false) { - $this->use_inline_crypt = version_compare(PHP_VERSION, '5.3.0') >= 0 || function_exists('create_function'); - } - } - - /** - * PHP4 compatible Default Constructor. - * - * @see self::__construct() - * @param int $mode - * @access public - */ - function Crypt_Base($mode = CRYPT_MODE_CBC) - { - $this->__construct($mode); - } - - /** - * Sets the initialization vector. (optional) - * - * SetIV is not required when CRYPT_MODE_ECB (or ie for AES: CRYPT_AES_MODE_ECB) is being used. If not explicitly set, it'll be assumed - * to be all zero's. - * - * @access public - * @param string $iv - * @internal Can be overwritten by a sub class, but does not have to be - */ - function setIV($iv) - { - if ($this->mode == CRYPT_MODE_ECB) { - return; - } - - $this->iv = $iv; - $this->changed = true; - } - - /** - * Sets the key length. - * - * Keys with explicitly set lengths need to be treated accordingly - * - * @access public - * @param int $length - */ - function setKeyLength($length) - { - $this->explicit_key_length = true; - $this->changed = true; - $this->_setEngine(); - } - - /** - * Returns the current key length in bits - * - * @access public - * @return int - */ - function getKeyLength() - { - return $this->key_length << 3; - } - - /** - * Returns the current block length in bits - * - * @access public - * @return int - */ - function getBlockLength() - { - return $this->block_size << 3; - } - - /** - * Sets the key. - * - * The min/max length(s) of the key depends on the cipher which is used. - * If the key not fits the length(s) of the cipher it will paded with null bytes - * up to the closest valid key length. If the key is more than max length, - * we trim the excess bits. - * - * If the key is not explicitly set, it'll be assumed to be all null bytes. - * - * @access public - * @param string $key - * @internal Could, but not must, extend by the child Crypt_* class - */ - function setKey($key) - { - if (!$this->explicit_key_length) { - $this->setKeyLength(strlen($key) << 3); - $this->explicit_key_length = false; - } - - $this->key = $key; - $this->changed = true; - $this->_setEngine(); - } - - /** - * Sets the password. - * - * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows: - * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1: - * $hash, $salt, $count, $dkLen - * - * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php - * - * @see Crypt/Hash.php - * @param string $password - * @param string $method - * @return bool - * @access public - * @internal Could, but not must, extend by the child Crypt_* class - */ - function setPassword($password, $method = 'pbkdf2') - { - $key = ''; - - switch ($method) { - default: // 'pbkdf2' or 'pbkdf1' - $func_args = func_get_args(); - - // Hash function - $hash = isset($func_args[2]) ? $func_args[2] : 'sha1'; - - // WPA and WPA2 use the SSID as the salt - $salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt; - - // RFC2898#section-4.2 uses 1,000 iterations by default - // WPA and WPA2 use 4,096. - $count = isset($func_args[4]) ? $func_args[4] : 1000; - - // Keylength - if (isset($func_args[5]) && $func_args[5] > 0) { - $dkLen = $func_args[5]; - } else { - $dkLen = $method == 'pbkdf1' ? 2 * $this->key_length : $this->key_length; - } - - switch (true) { - case $method == 'pbkdf1': - if (!class_exists('Crypt_Hash')) { - include_once 'Crypt/Hash.php'; - } - $hashObj = new Crypt_Hash(); - $hashObj->setHash($hash); - if ($dkLen > $hashObj->getLength()) { - user_error('Derived key too long'); - return false; - } - $t = $password . $salt; - for ($i = 0; $i < $count; ++$i) { - $t = $hashObj->hash($t); - } - $key = substr($t, 0, $dkLen); - - $this->setKey(substr($key, 0, $dkLen >> 1)); - $this->setIV(substr($key, $dkLen >> 1)); - - return true; - // Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable - case !function_exists('hash_pbkdf2'): - case !function_exists('hash_algos'): - case !in_array($hash, hash_algos()): - if (!class_exists('Crypt_Hash')) { - include_once 'Crypt/Hash.php'; - } - $i = 1; - $hmac = new Crypt_Hash(); - $hmac->setHash($hash); - $hmac->setKey($password); - while (strlen($key) < $dkLen) { - $f = $u = $hmac->hash($salt . pack('N', $i++)); - for ($j = 2; $j <= $count; ++$j) { - $u = $hmac->hash($u); - $f^= $u; - } - $key.= $f; - } - $key = substr($key, 0, $dkLen); - break; - default: - $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true); - } - } - - $this->setKey($key); - - return true; - } - - /** - * Encrypts a message. - * - * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher - * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's - * necessary are discussed in the following - * URL: - * - * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html} - * - * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does. - * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that - * length. - * - * @see self::decrypt() - * @access public - * @param string $plaintext - * @return string $ciphertext - * @internal Could, but not must, extend by the child Crypt_* class - */ - function encrypt($plaintext) - { - if ($this->paddable) { - $plaintext = $this->_pad($plaintext); - } - - if ($this->engine === CRYPT_ENGINE_OPENSSL) { - if ($this->changed) { - $this->_clearBuffers(); - $this->changed = false; - } - switch ($this->mode) { - case CRYPT_MODE_STREAM: - return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options); - case CRYPT_MODE_ECB: - $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options); - return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result; - case CRYPT_MODE_CBC: - $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV); - if (!defined('OPENSSL_RAW_DATA')) { - $result = substr($result, 0, -$this->block_size); - } - if ($this->continuousBuffer) { - $this->encryptIV = substr($result, -$this->block_size); - } - return $result; - case CRYPT_MODE_CTR: - return $this->_openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer); - case CRYPT_MODE_CFB: - // cfb loosely routines inspired by openssl's: - // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1} - $ciphertext = ''; - if ($this->continuousBuffer) { - $iv = &$this->encryptIV; - $pos = &$this->enbuffer['pos']; - } else { - $iv = $this->encryptIV; - $pos = 0; - } - $len = strlen($plaintext); - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $this->block_size - $pos; - if ($len >= $max) { - $i = $max; - $len-= $max; - $pos = 0; - } else { - $i = $len; - $pos+= $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize - $ciphertext = substr($iv, $orig_pos) ^ $plaintext; - $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); - $plaintext = substr($plaintext, $i); - } - - $overflow = $len % $this->block_size; - - if ($overflow) { - $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv); - $iv = $this->_string_pop($ciphertext, $this->block_size); - - $size = $len - $overflow; - $block = $iv ^ substr($plaintext, -$overflow); - $iv = substr_replace($iv, $block, 0, $overflow); - $ciphertext.= $block; - $pos = $overflow; - } elseif ($len) { - $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv); - $iv = substr($ciphertext, -$this->block_size); - } - - return $ciphertext; - case CRYPT_MODE_OFB: - return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer); - } - } - - if ($this->engine === CRYPT_ENGINE_MCRYPT) { - if ($this->changed) { - $this->_setupMcrypt(); - $this->changed = false; - } - if ($this->enchanged) { - @mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); - $this->enchanged = false; - } - - // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps} - // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's - // rewritten CFB implementation the above outputs the same thing twice. - if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) { - $block_size = $this->block_size; - $iv = &$this->encryptIV; - $pos = &$this->enbuffer['pos']; - $len = strlen($plaintext); - $ciphertext = ''; - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $block_size - $pos; - if ($len >= $max) { - $i = $max; - $len-= $max; - $pos = 0; - } else { - $i = $len; - $pos+= $len; - $len = 0; - } - $ciphertext = substr($iv, $orig_pos) ^ $plaintext; - $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); - $this->enbuffer['enmcrypt_init'] = true; - } - if ($len >= $block_size) { - if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) { - if ($this->enbuffer['enmcrypt_init'] === true) { - @mcrypt_generic_init($this->enmcrypt, $this->key, $iv); - $this->enbuffer['enmcrypt_init'] = false; - } - $ciphertext.= @mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size)); - $iv = substr($ciphertext, -$block_size); - $len%= $block_size; - } else { - while ($len >= $block_size) { - $iv = @mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size); - $ciphertext.= $iv; - $len-= $block_size; - $i+= $block_size; - } - } - } - - if ($len) { - $iv = @mcrypt_generic($this->ecb, $iv); - $block = $iv ^ substr($plaintext, -$len); - $iv = substr_replace($iv, $block, 0, $len); - $ciphertext.= $block; - $pos = $len; - } - - return $ciphertext; - } - - $ciphertext = @mcrypt_generic($this->enmcrypt, $plaintext); - - if (!$this->continuousBuffer) { - @mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); - } - - return $ciphertext; - } - - if ($this->changed) { - $this->_setup(); - $this->changed = false; - } - if ($this->use_inline_crypt) { - $inline = $this->inline_crypt; - return $inline('encrypt', $this, $plaintext); - } - - $buffer = &$this->enbuffer; - $block_size = $this->block_size; - $ciphertext = ''; - switch ($this->mode) { - case CRYPT_MODE_ECB: - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size)); - } - break; - case CRYPT_MODE_CBC: - $xor = $this->encryptIV; - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $block = substr($plaintext, $i, $block_size); - $block = $this->_encryptBlock($block ^ $xor); - $xor = $block; - $ciphertext.= $block; - } - if ($this->continuousBuffer) { - $this->encryptIV = $xor; - } - break; - case CRYPT_MODE_CTR: - $xor = $this->encryptIV; - if (strlen($buffer['ciphertext'])) { - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $block = substr($plaintext, $i, $block_size); - if (strlen($block) > strlen($buffer['ciphertext'])) { - $buffer['ciphertext'].= $this->_encryptBlock($xor); - } - $this->_increment_str($xor); - $key = $this->_string_shift($buffer['ciphertext'], $block_size); - $ciphertext.= $block ^ $key; - } - } else { - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $block = substr($plaintext, $i, $block_size); - $key = $this->_encryptBlock($xor); - $this->_increment_str($xor); - $ciphertext.= $block ^ $key; - } - } - if ($this->continuousBuffer) { - $this->encryptIV = $xor; - if ($start = strlen($plaintext) % $block_size) { - $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; - } - } - break; - case CRYPT_MODE_CFB: - // cfb loosely routines inspired by openssl's: - // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1} - if ($this->continuousBuffer) { - $iv = &$this->encryptIV; - $pos = &$buffer['pos']; - } else { - $iv = $this->encryptIV; - $pos = 0; - } - $len = strlen($plaintext); - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $block_size - $pos; - if ($len >= $max) { - $i = $max; - $len-= $max; - $pos = 0; - } else { - $i = $len; - $pos+= $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize - $ciphertext = substr($iv, $orig_pos) ^ $plaintext; - $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); - } - while ($len >= $block_size) { - $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size); - $ciphertext.= $iv; - $len-= $block_size; - $i+= $block_size; - } - if ($len) { - $iv = $this->_encryptBlock($iv); - $block = $iv ^ substr($plaintext, $i); - $iv = substr_replace($iv, $block, 0, $len); - $ciphertext.= $block; - $pos = $len; - } - break; - case CRYPT_MODE_OFB: - $xor = $this->encryptIV; - if (strlen($buffer['xor'])) { - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $block = substr($plaintext, $i, $block_size); - if (strlen($block) > strlen($buffer['xor'])) { - $xor = $this->_encryptBlock($xor); - $buffer['xor'].= $xor; - } - $key = $this->_string_shift($buffer['xor'], $block_size); - $ciphertext.= $block ^ $key; - } - } else { - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $xor = $this->_encryptBlock($xor); - $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor; - } - $key = $xor; - } - if ($this->continuousBuffer) { - $this->encryptIV = $xor; - if ($start = strlen($plaintext) % $block_size) { - $buffer['xor'] = substr($key, $start) . $buffer['xor']; - } - } - break; - case CRYPT_MODE_STREAM: - $ciphertext = $this->_encryptBlock($plaintext); - break; - } - - return $ciphertext; - } - - /** - * Decrypts a message. - * - * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until - * it is. - * - * @see self::encrypt() - * @access public - * @param string $ciphertext - * @return string $plaintext - * @internal Could, but not must, extend by the child Crypt_* class - */ - function decrypt($ciphertext) - { - if ($this->paddable) { - // we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://www.php.net/function.mcrypt-generic}: - // "The data is padded with "\0" to make sure the length of the data is n * blocksize." - $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0)); - } - - if ($this->engine === CRYPT_ENGINE_OPENSSL) { - if ($this->changed) { - $this->_clearBuffers(); - $this->changed = false; - } - switch ($this->mode) { - case CRYPT_MODE_STREAM: - $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options); - break; - case CRYPT_MODE_ECB: - if (!defined('OPENSSL_RAW_DATA')) { - $ciphertext.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true); - } - $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options); - break; - case CRYPT_MODE_CBC: - if (!defined('OPENSSL_RAW_DATA')) { - $padding = str_repeat(chr($this->block_size), $this->block_size) ^ substr($ciphertext, -$this->block_size); - $ciphertext.= substr(openssl_encrypt($padding, $this->cipher_name_openssl_ecb, $this->key, true), 0, $this->block_size); - $offset = 2 * $this->block_size; - } else { - $offset = $this->block_size; - } - $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV); - if ($this->continuousBuffer) { - $this->decryptIV = substr($ciphertext, -$offset, $this->block_size); - } - break; - case CRYPT_MODE_CTR: - $plaintext = $this->_openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer); - break; - case CRYPT_MODE_CFB: - // cfb loosely routines inspired by openssl's: - // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1} - $plaintext = ''; - if ($this->continuousBuffer) { - $iv = &$this->decryptIV; - $pos = &$this->buffer['pos']; - } else { - $iv = $this->decryptIV; - $pos = 0; - } - $len = strlen($ciphertext); - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $this->block_size - $pos; - if ($len >= $max) { - $i = $max; - $len-= $max; - $pos = 0; - } else { - $i = $len; - $pos+= $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize - $plaintext = substr($iv, $orig_pos) ^ $ciphertext; - $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); - $ciphertext = substr($ciphertext, $i); - } - $overflow = $len % $this->block_size; - if ($overflow) { - $plaintext.= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv); - if ($len - $overflow) { - $iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow); - } - $iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv); - $plaintext.= $iv ^ substr($ciphertext, -$overflow); - $iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow); - $pos = $overflow; - } elseif ($len) { - $plaintext.= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv); - $iv = substr($ciphertext, -$this->block_size); - } - break; - case CRYPT_MODE_OFB: - $plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer); - } - - return $this->paddable ? $this->_unpad($plaintext) : $plaintext; - } - - if ($this->engine === CRYPT_ENGINE_MCRYPT) { - $block_size = $this->block_size; - if ($this->changed) { - $this->_setupMcrypt(); - $this->changed = false; - } - if ($this->dechanged) { - @mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); - $this->dechanged = false; - } - - if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) { - $iv = &$this->decryptIV; - $pos = &$this->debuffer['pos']; - $len = strlen($ciphertext); - $plaintext = ''; - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $block_size - $pos; - if ($len >= $max) { - $i = $max; - $len-= $max; - $pos = 0; - } else { - $i = $len; - $pos+= $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize - $plaintext = substr($iv, $orig_pos) ^ $ciphertext; - $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); - } - if ($len >= $block_size) { - $cb = substr($ciphertext, $i, $len - $len % $block_size); - $plaintext.= @mcrypt_generic($this->ecb, $iv . $cb) ^ $cb; - $iv = substr($cb, -$block_size); - $len%= $block_size; - } - if ($len) { - $iv = @mcrypt_generic($this->ecb, $iv); - $plaintext.= $iv ^ substr($ciphertext, -$len); - $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len); - $pos = $len; - } - - return $plaintext; - } - - $plaintext = @mdecrypt_generic($this->demcrypt, $ciphertext); - - if (!$this->continuousBuffer) { - @mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); - } - - return $this->paddable ? $this->_unpad($plaintext) : $plaintext; - } - - if ($this->changed) { - $this->_setup(); - $this->changed = false; - } - if ($this->use_inline_crypt) { - $inline = $this->inline_crypt; - return $inline('decrypt', $this, $ciphertext); - } - - $block_size = $this->block_size; - - $buffer = &$this->debuffer; - $plaintext = ''; - switch ($this->mode) { - case CRYPT_MODE_ECB: - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { - $plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size)); - } - break; - case CRYPT_MODE_CBC: - $xor = $this->decryptIV; - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { - $block = substr($ciphertext, $i, $block_size); - $plaintext.= $this->_decryptBlock($block) ^ $xor; - $xor = $block; - } - if ($this->continuousBuffer) { - $this->decryptIV = $xor; - } - break; - case CRYPT_MODE_CTR: - $xor = $this->decryptIV; - if (strlen($buffer['ciphertext'])) { - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { - $block = substr($ciphertext, $i, $block_size); - if (strlen($block) > strlen($buffer['ciphertext'])) { - $buffer['ciphertext'].= $this->_encryptBlock($xor); - $this->_increment_str($xor); - } - $key = $this->_string_shift($buffer['ciphertext'], $block_size); - $plaintext.= $block ^ $key; - } - } else { - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { - $block = substr($ciphertext, $i, $block_size); - $key = $this->_encryptBlock($xor); - $this->_increment_str($xor); - $plaintext.= $block ^ $key; - } - } - if ($this->continuousBuffer) { - $this->decryptIV = $xor; - if ($start = strlen($ciphertext) % $block_size) { - $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; - } - } - break; - case CRYPT_MODE_CFB: - if ($this->continuousBuffer) { - $iv = &$this->decryptIV; - $pos = &$buffer['pos']; - } else { - $iv = $this->decryptIV; - $pos = 0; - } - $len = strlen($ciphertext); - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $block_size - $pos; - if ($len >= $max) { - $i = $max; - $len-= $max; - $pos = 0; - } else { - $i = $len; - $pos+= $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize - $plaintext = substr($iv, $orig_pos) ^ $ciphertext; - $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); - } - while ($len >= $block_size) { - $iv = $this->_encryptBlock($iv); - $cb = substr($ciphertext, $i, $block_size); - $plaintext.= $iv ^ $cb; - $iv = $cb; - $len-= $block_size; - $i+= $block_size; - } - if ($len) { - $iv = $this->_encryptBlock($iv); - $plaintext.= $iv ^ substr($ciphertext, $i); - $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len); - $pos = $len; - } - break; - case CRYPT_MODE_OFB: - $xor = $this->decryptIV; - if (strlen($buffer['xor'])) { - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { - $block = substr($ciphertext, $i, $block_size); - if (strlen($block) > strlen($buffer['xor'])) { - $xor = $this->_encryptBlock($xor); - $buffer['xor'].= $xor; - } - $key = $this->_string_shift($buffer['xor'], $block_size); - $plaintext.= $block ^ $key; - } - } else { - for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { - $xor = $this->_encryptBlock($xor); - $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor; - } - $key = $xor; - } - if ($this->continuousBuffer) { - $this->decryptIV = $xor; - if ($start = strlen($ciphertext) % $block_size) { - $buffer['xor'] = substr($key, $start) . $buffer['xor']; - } - } - break; - case CRYPT_MODE_STREAM: - $plaintext = $this->_decryptBlock($ciphertext); - break; - } - return $this->paddable ? $this->_unpad($plaintext) : $plaintext; - } - - /** - * OpenSSL CTR Processor - * - * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream - * for CTR is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt() - * and Crypt_Base::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this - * function will emulate CTR with ECB when necessary. - * - * @see self::encrypt() - * @see self::decrypt() - * @param string $plaintext - * @param string $encryptIV - * @param array $buffer - * @return string - * @access private - */ - function _openssl_ctr_process($plaintext, &$encryptIV, &$buffer) - { - $ciphertext = ''; - - $block_size = $this->block_size; - $key = $this->key; - - if ($this->openssl_emulate_ctr) { - $xor = $encryptIV; - if (strlen($buffer['ciphertext'])) { - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $block = substr($plaintext, $i, $block_size); - if (strlen($block) > strlen($buffer['ciphertext'])) { - $result = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options); - $result = !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result; - $buffer['ciphertext'].= $result; - } - $this->_increment_str($xor); - $otp = $this->_string_shift($buffer['ciphertext'], $block_size); - $ciphertext.= $block ^ $otp; - } - } else { - for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { - $block = substr($plaintext, $i, $block_size); - $otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options); - $otp = !defined('OPENSSL_RAW_DATA') ? substr($otp, 0, -$this->block_size) : $otp; - $this->_increment_str($xor); - $ciphertext.= $block ^ $otp; - } - } - if ($this->continuousBuffer) { - $encryptIV = $xor; - if ($start = strlen($plaintext) % $block_size) { - $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; - } - } - - return $ciphertext; - } - - if (strlen($buffer['ciphertext'])) { - $ciphertext = $plaintext ^ $this->_string_shift($buffer['ciphertext'], strlen($plaintext)); - $plaintext = substr($plaintext, strlen($ciphertext)); - - if (!strlen($plaintext)) { - return $ciphertext; - } - } - - $overflow = strlen($plaintext) % $block_size; - if ($overflow) { - $plaintext2 = $this->_string_pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2 - $encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV); - $temp = $this->_string_pop($encrypted, $block_size); - $ciphertext.= $encrypted . ($plaintext2 ^ $temp); - if ($this->continuousBuffer) { - $buffer['ciphertext'] = substr($temp, $overflow); - $encryptIV = $temp; - } - } elseif (!strlen($buffer['ciphertext'])) { - $ciphertext.= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV); - $temp = $this->_string_pop($ciphertext, $block_size); - if ($this->continuousBuffer) { - $encryptIV = $temp; - } - } - if ($this->continuousBuffer) { - if (!defined('OPENSSL_RAW_DATA')) { - $encryptIV.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $key, $this->openssl_options); - } - $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, $this->openssl_options); - if ($overflow) { - $this->_increment_str($encryptIV); - } - } - - return $ciphertext; - } - - /** - * OpenSSL OFB Processor - * - * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream - * for OFB is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt() - * and Crypt_Base::decrypt(). - * - * @see self::encrypt() - * @see self::decrypt() - * @param string $plaintext - * @param string $encryptIV - * @param array $buffer - * @return string - * @access private - */ - function _openssl_ofb_process($plaintext, &$encryptIV, &$buffer) - { - if (strlen($buffer['xor'])) { - $ciphertext = $plaintext ^ $buffer['xor']; - $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext)); - $plaintext = substr($plaintext, strlen($ciphertext)); - } else { - $ciphertext = ''; - } - - $block_size = $this->block_size; - - $len = strlen($plaintext); - $key = $this->key; - $overflow = $len % $block_size; - - if (strlen($plaintext)) { - if ($overflow) { - $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV); - $xor = $this->_string_pop($ciphertext, $block_size); - if ($this->continuousBuffer) { - $encryptIV = $xor; - } - $ciphertext.= $this->_string_shift($xor, $overflow) ^ substr($plaintext, -$overflow); - if ($this->continuousBuffer) { - $buffer['xor'] = $xor; - } - } else { - $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV); - if ($this->continuousBuffer) { - $encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size); - } - } - } - - return $ciphertext; - } - - /** - * phpseclib <-> OpenSSL Mode Mapper - * - * May need to be overwritten by classes extending this one in some cases - * - * @return int - * @access private - */ - function _openssl_translate_mode() - { - switch ($this->mode) { - case CRYPT_MODE_ECB: - return 'ecb'; - case CRYPT_MODE_CBC: - return 'cbc'; - case CRYPT_MODE_CTR: - return 'ctr'; - case CRYPT_MODE_CFB: - return 'cfb'; - case CRYPT_MODE_OFB: - return 'ofb'; - } - } - - /** - * Pad "packets". - * - * Block ciphers working by encrypting between their specified [$this->]block_size at a time - * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to - * pad the input so that it is of the proper length. - * - * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH, - * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping - * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is - * transmitted separately) - * - * @see self::disablePadding() - * @access public - */ - function enablePadding() - { - $this->padding = true; - } - - /** - * Do not pad packets. - * - * @see self::enablePadding() - * @access public - */ - function disablePadding() - { - $this->padding = false; - } - - /** - * Treat consecutive "packets" as if they are a continuous buffer. - * - * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets - * will yield different outputs: - * - * - * echo $rijndael->encrypt(substr($plaintext, 0, 16)); - * echo $rijndael->encrypt(substr($plaintext, 16, 16)); - * - * - * echo $rijndael->encrypt($plaintext); - * - * - * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates - * another, as demonstrated with the following: - * - * - * $rijndael->encrypt(substr($plaintext, 0, 16)); - * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16))); - * - * - * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16))); - * - * - * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different - * outputs. The reason is due to the fact that the initialization vector's change after every encryption / - * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant. - * - * Put another way, when the continuous buffer is enabled, the state of the Crypt_*() object changes after each - * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that - * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them), - * however, they are also less intuitive and more likely to cause you problems. - * - * @see self::disableContinuousBuffer() - * @access public - * @internal Could, but not must, extend by the child Crypt_* class - */ - function enableContinuousBuffer() - { - if ($this->mode == CRYPT_MODE_ECB) { - return; - } - - $this->continuousBuffer = true; - - $this->_setEngine(); - } - - /** - * Treat consecutive packets as if they are a discontinuous buffer. - * - * The default behavior. - * - * @see self::enableContinuousBuffer() - * @access public - * @internal Could, but not must, extend by the child Crypt_* class - */ - function disableContinuousBuffer() - { - if ($this->mode == CRYPT_MODE_ECB) { - return; - } - if (!$this->continuousBuffer) { - return; - } - - $this->continuousBuffer = false; - $this->changed = true; - - $this->_setEngine(); - } - - /** - * Test for engine validity - * - * @see self::Crypt_Base() - * @param int $engine - * @access public - * @return bool - */ - function isValidEngine($engine) - { - switch ($engine) { - case CRYPT_ENGINE_OPENSSL: - if ($this->mode == CRYPT_MODE_STREAM && $this->continuousBuffer) { - return false; - } - $this->openssl_emulate_ctr = false; - $result = $this->cipher_name_openssl && - extension_loaded('openssl') && - // PHP 5.3.0 - 5.3.2 did not let you set IV's - version_compare(PHP_VERSION, '5.3.3', '>='); - if (!$result) { - return false; - } - - // prior to PHP 5.4.0 OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING were not defined. instead of expecting an integer - // $options openssl_encrypt expected a boolean $raw_data. - if (!defined('OPENSSL_RAW_DATA')) { - $this->openssl_options = true; - } else { - $this->openssl_options = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING; - } - - $methods = openssl_get_cipher_methods(); - if (in_array($this->cipher_name_openssl, $methods)) { - return true; - } - // not all of openssl's symmetric cipher's support ctr. for those - // that don't we'll emulate it - switch ($this->mode) { - case CRYPT_MODE_CTR: - if (in_array($this->cipher_name_openssl_ecb, $methods)) { - $this->openssl_emulate_ctr = true; - return true; - } - } - return false; - case CRYPT_ENGINE_MCRYPT: - return $this->cipher_name_mcrypt && - extension_loaded('mcrypt') && - in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms()); - case CRYPT_ENGINE_INTERNAL: - return true; - } - - return false; - } - - /** - * Sets the preferred crypt engine - * - * Currently, $engine could be: - * - * - CRYPT_ENGINE_OPENSSL [very fast] - * - * - CRYPT_ENGINE_MCRYPT [fast] - * - * - CRYPT_ENGINE_INTERNAL [slow] - * - * If the preferred crypt engine is not available the fastest available one will be used - * - * @see self::Crypt_Base() - * @param int $engine - * @access public - */ - function setPreferredEngine($engine) - { - switch ($engine) { - //case CRYPT_ENGINE_OPENSSL: - case CRYPT_ENGINE_MCRYPT: - case CRYPT_ENGINE_INTERNAL: - $this->preferredEngine = $engine; - break; - default: - $this->preferredEngine = CRYPT_ENGINE_OPENSSL; - } - - $this->_setEngine(); - } - - /** - * Returns the engine currently being utilized - * - * @see self::_setEngine() - * @access public - */ - function getEngine() - { - return $this->engine; - } - - /** - * Sets the engine as appropriate - * - * @see self::Crypt_Base() - * @access private - */ - function _setEngine() - { - $this->engine = null; - - $candidateEngines = array( - $this->preferredEngine, - CRYPT_ENGINE_OPENSSL, - CRYPT_ENGINE_MCRYPT - ); - foreach ($candidateEngines as $engine) { - if ($this->isValidEngine($engine)) { - $this->engine = $engine; - break; - } - } - if (!$this->engine) { - $this->engine = CRYPT_ENGINE_INTERNAL; - } - - if ($this->engine != CRYPT_ENGINE_MCRYPT && $this->enmcrypt) { - // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed, - // (re)open them with the module named in $this->cipher_name_mcrypt - @mcrypt_module_close($this->enmcrypt); - @mcrypt_module_close($this->demcrypt); - $this->enmcrypt = null; - $this->demcrypt = null; - - if ($this->ecb) { - @mcrypt_module_close($this->ecb); - $this->ecb = null; - } - } - - $this->changed = true; - } - - /** - * Encrypts a block - * - * @access private - * @param string $in - * @return string - * @internal Must be extended by the child Crypt_* class - */ - function _encryptBlock($in) - { - user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR); - } - - /** - * Decrypts a block - * - * @access private - * @param string $in - * @return string - * @internal Must be extended by the child Crypt_* class - */ - function _decryptBlock($in) - { - user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR); - } - - /** - * Setup the key (expansion) - * - * Only used if $engine == CRYPT_ENGINE_INTERNAL - * - * @see self::_setup() - * @access private - * @internal Must be extended by the child Crypt_* class - */ - function _setupKey() - { - user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR); - } - - /** - * Setup the CRYPT_ENGINE_INTERNAL $engine - * - * (re)init, if necessary, the internal cipher $engine and flush all $buffers - * Used (only) if $engine == CRYPT_ENGINE_INTERNAL - * - * _setup() will be called each time if $changed === true - * typically this happens when using one or more of following public methods: - * - * - setKey() - * - * - setIV() - * - * - disableContinuousBuffer() - * - * - First run of encrypt() / decrypt() with no init-settings - * - * @see self::setKey() - * @see self::setIV() - * @see self::disableContinuousBuffer() - * @access private - * @internal _setup() is always called before en/decryption. - * @internal Could, but not must, extend by the child Crypt_* class - */ - function _setup() - { - $this->_clearBuffers(); - $this->_setupKey(); - - if ($this->use_inline_crypt) { - $this->_setupInlineCrypt(); - } - } - - /** - * Setup the CRYPT_ENGINE_MCRYPT $engine - * - * (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers - * Used (only) if $engine = CRYPT_ENGINE_MCRYPT - * - * _setupMcrypt() will be called each time if $changed === true - * typically this happens when using one or more of following public methods: - * - * - setKey() - * - * - setIV() - * - * - disableContinuousBuffer() - * - * - First run of encrypt() / decrypt() - * - * @see self::setKey() - * @see self::setIV() - * @see self::disableContinuousBuffer() - * @access private - * @internal Could, but not must, extend by the child Crypt_* class - */ - function _setupMcrypt() - { - $this->_clearBuffers(); - $this->enchanged = $this->dechanged = true; - - if (!isset($this->enmcrypt)) { - static $mcrypt_modes = array( - CRYPT_MODE_CTR => 'ctr', - CRYPT_MODE_ECB => MCRYPT_MODE_ECB, - CRYPT_MODE_CBC => MCRYPT_MODE_CBC, - CRYPT_MODE_CFB => 'ncfb', - CRYPT_MODE_OFB => MCRYPT_MODE_NOFB, - CRYPT_MODE_STREAM => MCRYPT_MODE_STREAM, - ); - - $this->demcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); - $this->enmcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); - - // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer() - // to workaround mcrypt's broken ncfb implementation in buffered mode - // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps} - if ($this->mode == CRYPT_MODE_CFB) { - $this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, ''); - } - } // else should mcrypt_generic_deinit be called? - - if ($this->mode == CRYPT_MODE_CFB) { - @mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size)); - } - } - - /** - * Pads a string - * - * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize. - * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to - * chr($this->block_size - (strlen($text) % $this->block_size) - * - * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless - * and padding will, hence forth, be enabled. - * - * @see self::_unpad() - * @param string $text - * @access private - * @return string - */ - function _pad($text) - { - $length = strlen($text); - - if (!$this->padding) { - if ($length % $this->block_size == 0) { - return $text; - } else { - user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})"); - $this->padding = true; - } - } - - $pad = $this->block_size - ($length % $this->block_size); - - return str_pad($text, $length + $pad, chr($pad)); - } - - /** - * Unpads a string. - * - * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong - * and false will be returned. - * - * @see self::_pad() - * @param string $text - * @access private - * @return string - */ - function _unpad($text) - { - if (!$this->padding) { - return $text; - } - - $length = ord($text[strlen($text) - 1]); - - if (!$length || $length > $this->block_size) { - return false; - } - - return substr($text, 0, -$length); - } - - /** - * Clears internal buffers - * - * Clearing/resetting the internal buffers is done everytime - * after disableContinuousBuffer() or on cipher $engine (re)init - * ie after setKey() or setIV() - * - * @access public - * @internal Could, but not must, extend by the child Crypt_* class - */ - function _clearBuffers() - { - $this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true); - - // mcrypt's handling of invalid's $iv: - // $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size); - $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0"); - - if (!$this->skip_key_adjustment) { - $this->key = str_pad(substr($this->key, 0, $this->key_length), $this->key_length, "\0"); - } - } - - /** - * String Shift - * - * Inspired by array_shift - * - * @param string $string - * @param int $index - * @access private - * @return string - */ - function _string_shift(&$string, $index = 1) - { - $substr = substr($string, 0, $index); - $string = substr($string, $index); - return $substr; - } - - /** - * String Pop - * - * Inspired by array_pop - * - * @param string $string - * @param int $index - * @access private - * @return string - */ - function _string_pop(&$string, $index = 1) - { - $substr = substr($string, -$index); - $string = substr($string, 0, -$index); - return $substr; - } - - /** - * Increment the current string - * - * @see self::decrypt() - * @see self::encrypt() - * @param string $var - * @access private - */ - function _increment_str(&$var) - { - for ($i = 4; $i <= strlen($var); $i+= 4) { - $temp = substr($var, -$i, 4); - switch ($temp) { - case "\xFF\xFF\xFF\xFF": - $var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4); - break; - case "\x7F\xFF\xFF\xFF": - $var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4); - return; - default: - $temp = unpack('Nnum', $temp); - $var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4); - return; - } - } - - $remainder = strlen($var) % 4; - - if ($remainder == 0) { - return; - } - - $temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT)); - $temp = substr(pack('N', $temp['num'] + 1), -$remainder); - $var = substr_replace($var, $temp, 0, $remainder); - } - - /** - * Setup the performance-optimized function for de/encrypt() - * - * Stores the created (or existing) callback function-name - * in $this->inline_crypt - * - * Internally for phpseclib developers: - * - * _setupInlineCrypt() would be called only if: - * - * - $engine == CRYPT_ENGINE_INTERNAL and - * - * - $use_inline_crypt === true - * - * - each time on _setup(), after(!) _setupKey() - * - * - * This ensures that _setupInlineCrypt() has always a - * full ready2go initializated internal cipher $engine state - * where, for example, the keys allready expanded, - * keys/block_size calculated and such. - * - * It is, each time if called, the responsibility of _setupInlineCrypt(): - * - * - to set $this->inline_crypt to a valid and fully working callback function - * as a (faster) replacement for encrypt() / decrypt() - * - * - NOT to create unlimited callback functions (for memory reasons!) - * no matter how often _setupInlineCrypt() would be called. At some - * point of amount they must be generic re-useable. - * - * - the code of _setupInlineCrypt() it self, - * and the generated callback code, - * must be, in following order: - * - 100% safe - * - 100% compatible to encrypt()/decrypt() - * - using only php5+ features/lang-constructs/php-extensions if - * compatibility (down to php4) or fallback is provided - * - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-) - * - >= 10% faster than encrypt()/decrypt() [which is, by the way, - * the reason for the existence of _setupInlineCrypt() :-)] - * - memory-nice - * - short (as good as possible) - * - * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code. - * - In case of using inline crypting, _setupInlineCrypt() must extend by the child Crypt_* class. - * - The following variable names are reserved: - * - $_* (all variable names prefixed with an underscore) - * - $self (object reference to it self. Do not use $this, but $self instead) - * - $in (the content of $in has to en/decrypt by the generated code) - * - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only - * - * - * @see self::_setup() - * @see self::_createInlineCryptFunction() - * @see self::encrypt() - * @see self::decrypt() - * @access private - * @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt() - */ - function _setupInlineCrypt() - { - // If, for any reason, an extending Crypt_Base() Crypt_* class - // not using inline crypting then it must be ensured that: $this->use_inline_crypt = false - // ie in the class var declaration of $use_inline_crypt in general for the Crypt_* class, - // in the constructor at object instance-time - // or, if it's runtime-specific, at runtime - - $this->use_inline_crypt = false; - } - - /** - * Creates the performance-optimized function for en/decrypt() - * - * Internally for phpseclib developers: - * - * _createInlineCryptFunction(): - * - * - merge the $cipher_code [setup'ed by _setupInlineCrypt()] - * with the current [$this->]mode of operation code - * - * - create the $inline function, which called by encrypt() / decrypt() - * as its replacement to speed up the en/decryption operations. - * - * - return the name of the created $inline callback function - * - * - used to speed up en/decryption - * - * - * - * The main reason why can speed up things [up to 50%] this way are: - * - * - using variables more effective then regular. - * (ie no use of expensive arrays but integers $k_0, $k_1 ... - * or even, for example, the pure $key[] values hardcoded) - * - * - avoiding 1000's of function calls of ie _encryptBlock() - * but inlining the crypt operations. - * in the mode of operation for() loop. - * - * - full loop unroll the (sometimes key-dependent) rounds - * avoiding this way ++$i counters and runtime-if's etc... - * - * The basic code architectur of the generated $inline en/decrypt() - * lambda function, in pseudo php, is: - * - * - * +----------------------------------------------------------------------------------------------+ - * | callback $inline = create_function: | - * | lambda_function_0001_crypt_ECB($action, $text) | - * | { | - * | INSERT PHP CODE OF: | - * | $cipher_code['init_crypt']; // general init code. | - * | // ie: $sbox'es declarations used for | - * | // encrypt and decrypt'ing. | - * | | - * | switch ($action) { | - * | case 'encrypt': | - * | INSERT PHP CODE OF: | - * | $cipher_code['init_encrypt']; // encrypt sepcific init code. | - * | ie: specified $key or $box | - * | declarations for encrypt'ing. | - * | | - * | foreach ($ciphertext) { | - * | $in = $block_size of $ciphertext; | - * | | - * | INSERT PHP CODE OF: | - * | $cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: | - * | // strlen($in) == $this->block_size | - * | // here comes the cipher algorithm in action | - * | // for encryption. | - * | // $cipher_code['encrypt_block'] has to | - * | // encrypt the content of the $in variable | - * | | - * | $plaintext .= $in; | - * | } | - * | return $plaintext; | - * | | - * | case 'decrypt': | - * | INSERT PHP CODE OF: | - * | $cipher_code['init_decrypt']; // decrypt sepcific init code | - * | ie: specified $key or $box | - * | declarations for decrypt'ing. | - * | foreach ($plaintext) { | - * | $in = $block_size of $plaintext; | - * | | - * | INSERT PHP CODE OF: | - * | $cipher_code['decrypt_block']; // decrypt's (string) $in, which is always | - * | // strlen($in) == $this->block_size | - * | // here comes the cipher algorithm in action | - * | // for decryption. | - * | // $cipher_code['decrypt_block'] has to | - * | // decrypt the content of the $in variable | - * | $ciphertext .= $in; | - * | } | - * | return $ciphertext; | - * | } | - * | } | - * +----------------------------------------------------------------------------------------------+ - * - * - * See also the Crypt_*::_setupInlineCrypt()'s for - * productive inline $cipher_code's how they works. - * - * Structure of: - * - * $cipher_code = array( - * 'init_crypt' => (string) '', // optional - * 'init_encrypt' => (string) '', // optional - * 'init_decrypt' => (string) '', // optional - * 'encrypt_block' => (string) '', // required - * 'decrypt_block' => (string) '' // required - * ); - * - * - * @see self::_setupInlineCrypt() - * @see self::encrypt() - * @see self::decrypt() - * @param array $cipher_code - * @access private - * @return string (the name of the created callback function) - */ - function _createInlineCryptFunction($cipher_code) - { - $block_size = $this->block_size; - - // optional - $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : ''; - $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : ''; - $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : ''; - // required - $encrypt_block = $cipher_code['encrypt_block']; - $decrypt_block = $cipher_code['decrypt_block']; - - // Generating mode of operation inline code, - // merged with the $cipher_code algorithm - // for encrypt- and decryption. - switch ($this->mode) { - case CRYPT_MODE_ECB: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_plaintext_len = strlen($_text); - - for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { - $in = substr($_text, $_i, '.$block_size.'); - '.$encrypt_block.' - $_ciphertext.= $in; - } - - return $_ciphertext; - '; - - $decrypt = $init_decrypt . ' - $_plaintext = ""; - $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0)); - $_ciphertext_len = strlen($_text); - - for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { - $in = substr($_text, $_i, '.$block_size.'); - '.$decrypt_block.' - $_plaintext.= $in; - } - - return $self->_unpad($_plaintext); - '; - break; - case CRYPT_MODE_CTR: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_plaintext_len = strlen($_text); - $_xor = $self->encryptIV; - $_buffer = &$self->enbuffer; - if (strlen($_buffer["ciphertext"])) { - for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { - $_block = substr($_text, $_i, '.$block_size.'); - if (strlen($_block) > strlen($_buffer["ciphertext"])) { - $in = $_xor; - '.$encrypt_block.' - $self->_increment_str($_xor); - $_buffer["ciphertext"].= $in; - } - $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.'); - $_ciphertext.= $_block ^ $_key; - } - } else { - for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { - $_block = substr($_text, $_i, '.$block_size.'); - $in = $_xor; - '.$encrypt_block.' - $self->_increment_str($_xor); - $_key = $in; - $_ciphertext.= $_block ^ $_key; - } - } - if ($self->continuousBuffer) { - $self->encryptIV = $_xor; - if ($_start = $_plaintext_len % '.$block_size.') { - $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"]; - } - } - - return $_ciphertext; - '; - - $decrypt = $init_encrypt . ' - $_plaintext = ""; - $_ciphertext_len = strlen($_text); - $_xor = $self->decryptIV; - $_buffer = &$self->debuffer; - - if (strlen($_buffer["ciphertext"])) { - for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { - $_block = substr($_text, $_i, '.$block_size.'); - if (strlen($_block) > strlen($_buffer["ciphertext"])) { - $in = $_xor; - '.$encrypt_block.' - $self->_increment_str($_xor); - $_buffer["ciphertext"].= $in; - } - $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.'); - $_plaintext.= $_block ^ $_key; - } - } else { - for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { - $_block = substr($_text, $_i, '.$block_size.'); - $in = $_xor; - '.$encrypt_block.' - $self->_increment_str($_xor); - $_key = $in; - $_plaintext.= $_block ^ $_key; - } - } - if ($self->continuousBuffer) { - $self->decryptIV = $_xor; - if ($_start = $_ciphertext_len % '.$block_size.') { - $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"]; - } - } - - return $_plaintext; - '; - break; - case CRYPT_MODE_CFB: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_buffer = &$self->enbuffer; - - if ($self->continuousBuffer) { - $_iv = &$self->encryptIV; - $_pos = &$_buffer["pos"]; - } else { - $_iv = $self->encryptIV; - $_pos = 0; - } - $_len = strlen($_text); - $_i = 0; - if ($_pos) { - $_orig_pos = $_pos; - $_max = '.$block_size.' - $_pos; - if ($_len >= $_max) { - $_i = $_max; - $_len-= $_max; - $_pos = 0; - } else { - $_i = $_len; - $_pos+= $_len; - $_len = 0; - } - $_ciphertext = substr($_iv, $_orig_pos) ^ $_text; - $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i); - } - while ($_len >= '.$block_size.') { - $in = $_iv; - '.$encrypt_block.'; - $_iv = $in ^ substr($_text, $_i, '.$block_size.'); - $_ciphertext.= $_iv; - $_len-= '.$block_size.'; - $_i+= '.$block_size.'; - } - if ($_len) { - $in = $_iv; - '.$encrypt_block.' - $_iv = $in; - $_block = $_iv ^ substr($_text, $_i); - $_iv = substr_replace($_iv, $_block, 0, $_len); - $_ciphertext.= $_block; - $_pos = $_len; - } - return $_ciphertext; - '; - - $decrypt = $init_encrypt . ' - $_plaintext = ""; - $_buffer = &$self->debuffer; - - if ($self->continuousBuffer) { - $_iv = &$self->decryptIV; - $_pos = &$_buffer["pos"]; - } else { - $_iv = $self->decryptIV; - $_pos = 0; - } - $_len = strlen($_text); - $_i = 0; - if ($_pos) { - $_orig_pos = $_pos; - $_max = '.$block_size.' - $_pos; - if ($_len >= $_max) { - $_i = $_max; - $_len-= $_max; - $_pos = 0; - } else { - $_i = $_len; - $_pos+= $_len; - $_len = 0; - } - $_plaintext = substr($_iv, $_orig_pos) ^ $_text; - $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i); - } - while ($_len >= '.$block_size.') { - $in = $_iv; - '.$encrypt_block.' - $_iv = $in; - $cb = substr($_text, $_i, '.$block_size.'); - $_plaintext.= $_iv ^ $cb; - $_iv = $cb; - $_len-= '.$block_size.'; - $_i+= '.$block_size.'; - } - if ($_len) { - $in = $_iv; - '.$encrypt_block.' - $_iv = $in; - $_plaintext.= $_iv ^ substr($_text, $_i); - $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len); - $_pos = $_len; - } - - return $_plaintext; - '; - break; - case CRYPT_MODE_OFB: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_plaintext_len = strlen($_text); - $_xor = $self->encryptIV; - $_buffer = &$self->enbuffer; - - if (strlen($_buffer["xor"])) { - for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { - $_block = substr($_text, $_i, '.$block_size.'); - if (strlen($_block) > strlen($_buffer["xor"])) { - $in = $_xor; - '.$encrypt_block.' - $_xor = $in; - $_buffer["xor"].= $_xor; - } - $_key = $self->_string_shift($_buffer["xor"], '.$block_size.'); - $_ciphertext.= $_block ^ $_key; - } - } else { - for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { - $in = $_xor; - '.$encrypt_block.' - $_xor = $in; - $_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor; - } - $_key = $_xor; - } - if ($self->continuousBuffer) { - $self->encryptIV = $_xor; - if ($_start = $_plaintext_len % '.$block_size.') { - $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"]; - } - } - return $_ciphertext; - '; - - $decrypt = $init_encrypt . ' - $_plaintext = ""; - $_ciphertext_len = strlen($_text); - $_xor = $self->decryptIV; - $_buffer = &$self->debuffer; - - if (strlen($_buffer["xor"])) { - for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { - $_block = substr($_text, $_i, '.$block_size.'); - if (strlen($_block) > strlen($_buffer["xor"])) { - $in = $_xor; - '.$encrypt_block.' - $_xor = $in; - $_buffer["xor"].= $_xor; - } - $_key = $self->_string_shift($_buffer["xor"], '.$block_size.'); - $_plaintext.= $_block ^ $_key; - } - } else { - for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { - $in = $_xor; - '.$encrypt_block.' - $_xor = $in; - $_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor; - } - $_key = $_xor; - } - if ($self->continuousBuffer) { - $self->decryptIV = $_xor; - if ($_start = $_ciphertext_len % '.$block_size.') { - $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"]; - } - } - return $_plaintext; - '; - break; - case CRYPT_MODE_STREAM: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - '.$encrypt_block.' - return $_ciphertext; - '; - $decrypt = $init_decrypt . ' - $_plaintext = ""; - '.$decrypt_block.' - return $_plaintext; - '; - break; - // case CRYPT_MODE_CBC: - default: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_plaintext_len = strlen($_text); - - $in = $self->encryptIV; - - for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { - $in = substr($_text, $_i, '.$block_size.') ^ $in; - '.$encrypt_block.' - $_ciphertext.= $in; - } - - if ($self->continuousBuffer) { - $self->encryptIV = $in; - } - - return $_ciphertext; - '; - - $decrypt = $init_decrypt . ' - $_plaintext = ""; - $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0)); - $_ciphertext_len = strlen($_text); - - $_iv = $self->decryptIV; - - for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { - $in = $_block = substr($_text, $_i, '.$block_size.'); - '.$decrypt_block.' - $_plaintext.= $in ^ $_iv; - $_iv = $_block; - } - - if ($self->continuousBuffer) { - $self->decryptIV = $_iv; - } - - return $self->_unpad($_plaintext); - '; - break; - } - - // Create the $inline function and return its name as string. Ready to run! - if (version_compare(PHP_VERSION, '5.3.0') >= 0) { - eval('$func = function ($_action, &$self, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' } };'); - return $func; - } - - return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }'); - } - - /** - * Holds the lambda_functions table (classwide) - * - * Each name of the lambda function, created from - * _setupInlineCrypt() && _createInlineCryptFunction() - * is stored, classwide (!), here for reusing. - * - * The string-based index of $function is a classwide - * unique value representing, at least, the $mode of - * operation (or more... depends of the optimizing level) - * for which $mode the lambda function was created. - * - * @access private - * @return array &$functions - */ - function &_getLambdaFunctions() - { - static $functions = array(); - return $functions; - } - - /** - * Generates a digest from $bytes - * - * @see self::_setupInlineCrypt() - * @access private - * @param $bytes - * @return string - */ - function _hashInlineCryptFunction($bytes) - { - if (!defined('CRYPT_BASE_WHIRLPOOL_AVAILABLE')) { - define('CRYPT_BASE_WHIRLPOOL_AVAILABLE', (bool)(extension_loaded('hash') && in_array('whirlpool', hash_algos()))); - } - - $result = ''; - $hash = $bytes; - - switch (true) { - case CRYPT_BASE_WHIRLPOOL_AVAILABLE: - foreach (str_split($bytes, 64) as $t) { - $hash = hash('whirlpool', $hash, true); - $result .= $t ^ $hash; - } - return $result . hash('whirlpool', $hash, true); - default: - $len = strlen($bytes); - for ($i = 0; $i < $len; $i+=20) { - $t = substr($bytes, $i, 20); - $hash = pack('H*', sha1($hash)); - $result .= $t ^ $hash; - } - return $result . pack('H*', sha1($hash)); - } - } - - /** - * Convert float to int - * - * On 32-bit Linux installs running PHP < 5.3 converting floats to ints doesn't always work - * - * @access private - * @param string $x - * @return int - */ - function safe_intval($x) - { - switch (true) { - case is_int($x): - // PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding" - case version_compare(PHP_VERSION, '5.3.0') >= 0 && (php_uname('m') & "\xDF\xDF\xDF") != 'ARM': - // PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster - case (PHP_OS & "\xDF\xDF\xDF") === 'WIN': - return $x; - } - return (fmod($x, 0x80000000) & 0x7FFFFFFF) | - ((fmod(floor($x / 0x80000000), 2) & 1) << 31); - } - - /** - * eval()'able string for in-line float to int - * - * @access private - * @return string - */ - function safe_intval_inline() - { - // on 32-bit linux systems with PHP < 5.3 float to integer conversion is bad - switch (true) { - case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8: - case version_compare(PHP_VERSION, '5.3.0') >= 0 && (php_uname('m') & "\xDF\xDF\xDF") != 'ARM': - case (PHP_OS & "\xDF\xDF\xDF") === 'WIN': - return '%s'; - break; - default: - $safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | '; - return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))'; - } - } -} diff --git a/installer/dup-installer/classes/Crypt/Random.php b/installer/dup-installer/classes/Crypt/Random.php deleted file mode 100644 index ec89801b..00000000 --- a/installer/dup-installer/classes/Crypt/Random.php +++ /dev/null @@ -1,340 +0,0 @@ - - * - * - * - * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @category Crypt - * @package Crypt_Random - * @author Jim Wigginton - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -// laravel is a PHP framework that utilizes phpseclib. laravel workbenches may, independently, -// have phpseclib as a requirement as well. if you're developing such a program you may encounter -// a "Cannot redeclare crypt_random_string()" error. -if (!function_exists('crypt_random_string')) { - /** - * "Is Windows" test - * - * @access private - */ - define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'); - - /** - * Generate a random string. - * - * Although microoptimizations are generally discouraged as they impair readability this function is ripe with - * microoptimizations because this function has the potential of being called a huge number of times. - * eg. for RSA key generation. - * - * @param int $length - * @return string - * @access public - */ - function crypt_random_string($length) - { - if (!$length) { - return ''; - } - - if (CRYPT_RANDOM_IS_WINDOWS) { - // method 1. prior to PHP 5.3, mcrypt_create_iv() would call rand() on windows - if (extension_loaded('mcrypt') && version_compare(PHP_VERSION, '5.3.0', '>=')) { - return @mcrypt_create_iv($length); - } - // method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was, - // to quote , "possible blocking behavior". as of 5.3.4 - // openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both - // call php_win32_get_random_bytes(): - // - // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008 - // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392 - // - // php_win32_get_random_bytes() is defined thusly: - // - // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80 - // - // we're calling it, all the same, in the off chance that the mcrypt extension is not available - if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.4', '>=')) { - return openssl_random_pseudo_bytes($length); - } - } else { - // method 1. the fastest - if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.0', '>=')) { - return openssl_random_pseudo_bytes($length); - } - // method 2 - static $fp = true; - if ($fp === true) { - // warning's will be output unles the error suppression operator is used. errors such as - // "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc. - $fp = @fopen('/dev/urandom', 'rb'); - } - if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource() - return fread($fp, $length); - } - // method 3. pretty much does the same thing as method 2 per the following url: - // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391 - // surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're - // not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir - // restrictions or some such - if (extension_loaded('mcrypt')) { - return @mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); - } - } - // at this point we have no choice but to use a pure-PHP CSPRNG - - // cascade entropy across multiple PHP instances by fixing the session and collecting all - // environmental variables, including the previous session data and the current session - // data. - // - // mt_rand seeds itself by looking at the PID and the time, both of which are (relatively) - // easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but - // PHP isn't low level to be able to use those as sources and on a web server there's not likely - // going to be a ton of keyboard or mouse action. web servers do have one thing that we can use - // however, a ton of people visiting the website. obviously you don't want to base your seeding - // soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled - // by the user and (2) this isn't just looking at the data sent by the current user - it's based - // on the data sent by all users. one user requests the page and a hash of their info is saved. - // another user visits the page and the serialization of their data is utilized along with the - // server envirnment stuff and a hash of the previous http request data (which itself utilizes - // a hash of the session data before that). certainly an attacker should be assumed to have - // full control over his own http requests. he, however, is not going to have control over - // everyone's http requests. - static $crypto = false, $v; - if ($crypto === false) { - // save old session data - $old_session_id = session_id(); - $old_use_cookies = ini_get('session.use_cookies'); - $old_session_cache_limiter = session_cache_limiter(); - $_OLD_SESSION = isset($_SESSION) ? $_SESSION : false; - if ($old_session_id != '') { - session_write_close(); - } - - session_id(1); - if (DupLiteSnapLibUtil::wp_is_ini_value_changeable('session.use_cookies')) - ini_set('session.use_cookies', 0); - session_cache_limiter(''); - session_start(); - - $v = $seed = $_SESSION['seed'] = pack('H*', sha1( - (isset($_SERVER) ? phpseclib_safe_serialize($_SERVER) : '') . - (isset($_POST) ? phpseclib_safe_serialize($_POST) : '') . - (isset($_GET) ? phpseclib_safe_serialize($_GET) : '') . - (isset($_COOKIE) ? phpseclib_safe_serialize($_COOKIE) : '') . - phpseclib_safe_serialize($GLOBALS) . - phpseclib_safe_serialize($_SESSION) . - phpseclib_safe_serialize($_OLD_SESSION) - )); - if (!isset($_SESSION['count'])) { - $_SESSION['count'] = 0; - } - $_SESSION['count']++; - - session_write_close(); - - // restore old session data - if ($old_session_id != '') { - session_id($old_session_id); - session_start(); - if (DupLiteSnapLibUtil::wp_is_ini_value_changeable('session.use_cookies')) - ini_set('session.use_cookies', $old_use_cookies); - session_cache_limiter($old_session_cache_limiter); - } else { - if ($_OLD_SESSION !== false) { - $_SESSION = $_OLD_SESSION; - unset($_OLD_SESSION); - } else { - unset($_SESSION); - } - } - - // in SSH2 a shared secret and an exchange hash are generated through the key exchange process. - // the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C. - // if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the - // original hash and the current hash. we'll be emulating that. for more info see the following URL: - // - // http://tools.ietf.org/html/rfc4253#section-7.2 - // - // see the is_string($crypto) part for an example of how to expand the keys - $key = pack('H*', sha1($seed . 'A')); - $iv = pack('H*', sha1($seed . 'C')); - - // ciphers are used as per the nist.gov link below. also, see this link: - // - // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives - switch (true) { - case phpseclib_resolve_include_path('Crypt/AES.php'): - if (!class_exists('Crypt_AES')) { - include_once 'AES.php'; - } - $crypto = new Crypt_AES(CRYPT_AES_MODE_CTR); - break; - case phpseclib_resolve_include_path('Crypt/Twofish.php'): - if (!class_exists('Crypt_Twofish')) { - include_once 'Twofish.php'; - } - $crypto = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR); - break; - case phpseclib_resolve_include_path('Crypt/Blowfish.php'): - if (!class_exists('Crypt_Blowfish')) { - include_once 'Blowfish.php'; - } - $crypto = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR); - break; - case phpseclib_resolve_include_path('Crypt/TripleDES.php'): - if (!class_exists('Crypt_TripleDES')) { - include_once 'TripleDES.php'; - } - $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR); - break; - case phpseclib_resolve_include_path('Crypt/DES.php'): - if (!class_exists('Crypt_DES')) { - include_once 'DES.php'; - } - $crypto = new Crypt_DES(CRYPT_DES_MODE_CTR); - break; - case phpseclib_resolve_include_path('Crypt/RC4.php'): - if (!class_exists('Crypt_RC4')) { - include_once 'RC4.php'; - } - $crypto = new Crypt_RC4(); - break; - default: - user_error('crypt_random_string requires at least one symmetric cipher be loaded'); - return false; - } - - $crypto->setKey($key); - $crypto->setIV($iv); - $crypto->enableContinuousBuffer(); - } - - //return $crypto->encrypt(str_repeat("\0", $length)); - - // the following is based off of ANSI X9.31: - // - // http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf - // - // OpenSSL uses that same standard for it's random numbers: - // - // http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c - // (do a search for "ANS X9.31 A.2.4") - $result = ''; - while (strlen($result) < $length) { - $i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21 - $r = $crypto->encrypt($i ^ $v); // strlen($v) == 20 - $v = $crypto->encrypt($r ^ $i); // strlen($r) == 20 - $result.= $r; - } - return substr($result, 0, $length); - } -} - -if (!function_exists('phpseclib_safe_serialize')) { - /** - * Safely serialize variables - * - * If a class has a private __sleep() method it'll give a fatal error on PHP 5.2 and earlier. - * PHP 5.3 will emit a warning. - * - * @param mixed $arr - * @access public - */ - function phpseclib_safe_serialize(&$arr) - { - if (is_object($arr)) { - return ''; - } - if (!is_array($arr)) { - return serialize($arr); - } - // prevent circular array recursion - if (isset($arr['__phpseclib_marker'])) { - return ''; - } - $safearr = array(); - $arr['__phpseclib_marker'] = true; - foreach (array_keys($arr) as $key) { - // do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage - if ($key !== '__phpseclib_marker') { - $safearr[$key] = phpseclib_safe_serialize($arr[$key]); - } - } - unset($arr['__phpseclib_marker']); - return serialize($safearr); - } -} - -if (!function_exists('phpseclib_resolve_include_path')) { - /** - * Resolve filename against the include path. - * - * Wrapper around stream_resolve_include_path() (which was introduced in - * PHP 5.3.2) with fallback implementation for earlier PHP versions. - * - * @param string $filename - * @return string|false - * @access public - */ - function phpseclib_resolve_include_path($filename) - { - if (function_exists('stream_resolve_include_path')) { - return stream_resolve_include_path($filename); - } - - // handle non-relative paths - if (file_exists($filename)) { - return realpath($filename); - } - - $paths = PATH_SEPARATOR == ':' ? - preg_split('#(? - * setKey('abcdefghijklmnop'); - * - * $size = 10 * 1024; - * $plaintext = ''; - * for ($i = 0; $i < $size; $i++) { - * $plaintext.= 'a'; - * } - * - * echo $rijndael->decrypt($rijndael->encrypt($plaintext)); - * ?> - * - * - * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @category Crypt - * @package Crypt_Rijndael - * @author Jim Wigginton - * @copyright 2008 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -/** - * Include Crypt_Base - * - * Base cipher class - */ -if (!class_exists('Crypt_Base')) { - include_once 'Base.php'; -} - -/**#@+ - * @access public - * @see self::encrypt() - * @see self::decrypt() - */ -/** - * Encrypt / decrypt using the Counter mode. - * - * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29 - */ -define('CRYPT_RIJNDAEL_MODE_CTR', CRYPT_MODE_CTR); -/** - * Encrypt / decrypt using the Electronic Code Book mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29 - */ -define('CRYPT_RIJNDAEL_MODE_ECB', CRYPT_MODE_ECB); -/** - * Encrypt / decrypt using the Code Book Chaining mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29 - */ -define('CRYPT_RIJNDAEL_MODE_CBC', CRYPT_MODE_CBC); -/** - * Encrypt / decrypt using the Cipher Feedback mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29 - */ -define('CRYPT_RIJNDAEL_MODE_CFB', CRYPT_MODE_CFB); -/** - * Encrypt / decrypt using the Cipher Feedback mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29 - */ -define('CRYPT_RIJNDAEL_MODE_OFB', CRYPT_MODE_OFB); -/**#@-*/ - -/** - * Pure-PHP implementation of Rijndael. - * - * @package Crypt_Rijndael - * @author Jim Wigginton - * @access public - */ -class Crypt_Rijndael extends Crypt_Base -{ - /** - * The namespace used by the cipher for its constants. - * - * @see Crypt_Base::const_namespace - * @var string - * @access private - */ - var $const_namespace = 'RIJNDAEL'; - - /** - * The mcrypt specific name of the cipher - * - * Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not. - * Crypt_Rijndael determines automatically whether mcrypt is useable - * or not for the current $block_size/$key_length. - * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly. - * - * @see Crypt_Base::cipher_name_mcrypt - * @see Crypt_Base::engine - * @see self::isValidEngine() - * @var string - * @access private - */ - var $cipher_name_mcrypt = 'rijndael-128'; - - /** - * The default salt used by setPassword() - * - * @see Crypt_Base::password_default_salt - * @see Crypt_Base::setPassword() - * @var string - * @access private - */ - var $password_default_salt = 'phpseclib'; - - /** - * The Key Schedule - * - * @see self::_setup() - * @var array - * @access private - */ - var $w; - - /** - * The Inverse Key Schedule - * - * @see self::_setup() - * @var array - * @access private - */ - var $dw; - - /** - * The Block Length divided by 32 - * - * @see self::setBlockLength() - * @var int - * @access private - * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size - * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could - * derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu - * of that, we'll just precompute it once. - */ - var $Nb = 4; - - /** - * The Key Length (in bytes) - * - * @see self::setKeyLength() - * @var int - * @access private - * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk - * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could - * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu - * of that, we'll just precompute it once. - */ - var $key_length = 16; - - /** - * The Key Length divided by 32 - * - * @see self::setKeyLength() - * @var int - * @access private - * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4 - */ - var $Nk = 4; - - /** - * The Number of Rounds - * - * @var int - * @access private - * @internal The max value is 14, the min value is 10. - */ - var $Nr; - - /** - * Shift offsets - * - * @var array - * @access private - */ - var $c; - - /** - * Holds the last used key- and block_size information - * - * @var array - * @access private - */ - var $kl; - - /** - * Sets the key. - * - * Keys can be of any length. Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and - * whose length is a multiple of 32. If the key is less than 256-bits and the key length isn't set, we round the length - * up to the closest valid key length, padding $key with null bytes. If the key is more than 256-bits, we trim the - * excess bits. - * - * If the key is not explicitly set, it'll be assumed to be all null bytes. - * - * Note: 160/224-bit keys must explicitly set by setKeyLength(), otherwise they will be round/pad up to 192/256 bits. - * - * @see Crypt_Base:setKey() - * @see self::setKeyLength() - * @access public - * @param string $key - */ - function setKey($key) - { - if (!$this->explicit_key_length) { - $length = strlen($key); - switch (true) { - case $length <= 16: - $this->key_size = 16; - break; - case $length <= 20: - $this->key_size = 20; - break; - case $length <= 24: - $this->key_size = 24; - break; - case $length <= 28: - $this->key_size = 28; - break; - default: - $this->key_size = 32; - } - } - parent::setKey($key); - } - - /** - * Sets the key length - * - * Valid key lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to - * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount. - * - * Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined - * and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to - * 192/256 bits as, for example, mcrypt will do. - * - * That said, if you want be compatible with other Rijndael and AES implementations, - * you should not setKeyLength(160) or setKeyLength(224). - * - * Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use - * the mcrypt php extension, even if available. - * This results then in slower encryption. - * - * @access public - * @param int $length - */ - function setKeyLength($length) - { - switch (true) { - case $length <= 128: - $this->key_length = 16; - break; - case $length <= 160: - $this->key_length = 20; - break; - case $length <= 192: - $this->key_length = 24; - break; - case $length <= 224: - $this->key_length = 28; - break; - default: - $this->key_length = 32; - } - - parent::setKeyLength($length); - } - - /** - * Sets the block length - * - * Valid block lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to - * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount. - * - * @access public - * @param int $length - */ - function setBlockLength($length) - { - $length >>= 5; - if ($length > 8) { - $length = 8; - } elseif ($length < 4) { - $length = 4; - } - $this->Nb = $length; - $this->block_size = $length << 2; - $this->changed = true; - $this->_setEngine(); - } - - /** - * Test for engine validity - * - * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine() - * - * @see Crypt_Base::Crypt_Base() - * @param int $engine - * @access public - * @return bool - */ - function isValidEngine($engine) - { - switch ($engine) { - case CRYPT_ENGINE_OPENSSL: - if ($this->block_size != 16) { - return false; - } - $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb'; - $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->_openssl_translate_mode(); - break; - case CRYPT_ENGINE_MCRYPT: - $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3); - if ($this->key_length % 8) { // is it a 160/224-bit key? - // mcrypt is not usable for them, only for 128/192/256-bit keys - return false; - } - } - - return parent::isValidEngine($engine); - } - - /** - * Encrypts a block - * - * @access private - * @param string $in - * @return string - */ - function _encryptBlock($in) - { - static $tables; - if (empty($tables)) { - $tables = &$this->_getTables(); - } - $t0 = $tables[0]; - $t1 = $tables[1]; - $t2 = $tables[2]; - $t3 = $tables[3]; - $sbox = $tables[4]; - - $state = array(); - $words = unpack('N*', $in); - - $c = $this->c; - $w = $this->w; - $Nb = $this->Nb; - $Nr = $this->Nr; - - // addRoundKey - $wc = $Nb - 1; - foreach ($words as $word) { - $state[] = $word ^ $w[++$wc]; - } - - // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components - - // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding - // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf. - // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization. - // Unfortunately, the description given there is not quite correct. Per aes.spec.v316.pdf#page=19 [1], - // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well. - - // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf - $temp = array(); - for ($round = 1; $round < $Nr; ++$round) { - $i = 0; // $c[0] == 0 - $j = $c[1]; - $k = $c[2]; - $l = $c[3]; - - while ($i < $Nb) { - $temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^ - $t1[$state[$j] >> 16 & 0x000000FF] ^ - $t2[$state[$k] >> 8 & 0x000000FF] ^ - $t3[$state[$l] & 0x000000FF] ^ - $w[++$wc]; - ++$i; - $j = ($j + 1) % $Nb; - $k = ($k + 1) % $Nb; - $l = ($l + 1) % $Nb; - } - $state = $temp; - } - - // subWord - for ($i = 0; $i < $Nb; ++$i) { - $state[$i] = $sbox[$state[$i] & 0x000000FF] | - ($sbox[$state[$i] >> 8 & 0x000000FF] << 8) | - ($sbox[$state[$i] >> 16 & 0x000000FF] << 16) | - ($sbox[$state[$i] >> 24 & 0x000000FF] << 24); - } - - // shiftRows + addRoundKey - $i = 0; // $c[0] == 0 - $j = $c[1]; - $k = $c[2]; - $l = $c[3]; - while ($i < $Nb) { - $temp[$i] = ($state[$i] & 0xFF000000) ^ - ($state[$j] & 0x00FF0000) ^ - ($state[$k] & 0x0000FF00) ^ - ($state[$l] & 0x000000FF) ^ - $w[$i]; - ++$i; - $j = ($j + 1) % $Nb; - $k = ($k + 1) % $Nb; - $l = ($l + 1) % $Nb; - } - - switch ($Nb) { - case 8: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]); - case 7: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]); - case 6: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]); - case 5: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]); - default: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]); - } - } - - /** - * Decrypts a block - * - * @access private - * @param string $in - * @return string - */ - function _decryptBlock($in) - { - static $invtables; - if (empty($invtables)) { - $invtables = &$this->_getInvTables(); - } - $dt0 = $invtables[0]; - $dt1 = $invtables[1]; - $dt2 = $invtables[2]; - $dt3 = $invtables[3]; - $isbox = $invtables[4]; - - $state = array(); - $words = unpack('N*', $in); - - $c = $this->c; - $dw = $this->dw; - $Nb = $this->Nb; - $Nr = $this->Nr; - - // addRoundKey - $wc = $Nb - 1; - foreach ($words as $word) { - $state[] = $word ^ $dw[++$wc]; - } - - $temp = array(); - for ($round = $Nr - 1; $round > 0; --$round) { - $i = 0; // $c[0] == 0 - $j = $Nb - $c[1]; - $k = $Nb - $c[2]; - $l = $Nb - $c[3]; - - while ($i < $Nb) { - $temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^ - $dt1[$state[$j] >> 16 & 0x000000FF] ^ - $dt2[$state[$k] >> 8 & 0x000000FF] ^ - $dt3[$state[$l] & 0x000000FF] ^ - $dw[++$wc]; - ++$i; - $j = ($j + 1) % $Nb; - $k = ($k + 1) % $Nb; - $l = ($l + 1) % $Nb; - } - $state = $temp; - } - - // invShiftRows + invSubWord + addRoundKey - $i = 0; // $c[0] == 0 - $j = $Nb - $c[1]; - $k = $Nb - $c[2]; - $l = $Nb - $c[3]; - - while ($i < $Nb) { - $word = ($state[$i] & 0xFF000000) | - ($state[$j] & 0x00FF0000) | - ($state[$k] & 0x0000FF00) | - ($state[$l] & 0x000000FF); - - $temp[$i] = $dw[$i] ^ ($isbox[$word & 0x000000FF] | - ($isbox[$word >> 8 & 0x000000FF] << 8) | - ($isbox[$word >> 16 & 0x000000FF] << 16) | - ($isbox[$word >> 24 & 0x000000FF] << 24)); - ++$i; - $j = ($j + 1) % $Nb; - $k = ($k + 1) % $Nb; - $l = ($l + 1) % $Nb; - } - - switch ($Nb) { - case 8: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]); - case 7: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]); - case 6: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]); - case 5: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]); - default: - return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]); - } - } - - /** - * Setup the key (expansion) - * - * @see Crypt_Base::_setupKey() - * @access private - */ - function _setupKey() - { - // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field. - // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse - static $rcon = array(0, - 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, - 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, - 0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000, - 0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000, - 0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000, - 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000 - ); - - if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) { - // already expanded - return; - } - $this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size); - - $this->Nk = $this->key_length >> 2; - // see Rijndael-ammended.pdf#page=44 - $this->Nr = max($this->Nk, $this->Nb) + 6; - - // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44, - // "Table 8: Shift offsets in Shiftrow for the alternative block lengths" - // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14, - // "Table 2: Shift offsets for different block lengths" - switch ($this->Nb) { - case 4: - case 5: - case 6: - $this->c = array(0, 1, 2, 3); - break; - case 7: - $this->c = array(0, 1, 2, 4); - break; - case 8: - $this->c = array(0, 1, 3, 4); - } - - $w = array_values(unpack('N*words', $this->key)); - - $length = $this->Nb * ($this->Nr + 1); - for ($i = $this->Nk; $i < $length; $i++) { - $temp = $w[$i - 1]; - if ($i % $this->Nk == 0) { - // according to , "the size of an integer is platform-dependent". - // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine, - // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and' - // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is. - $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord - $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk]; - } elseif ($this->Nk > 6 && $i % $this->Nk == 4) { - $temp = $this->_subWord($temp); - } - $w[$i] = $w[$i - $this->Nk] ^ $temp; - } - - // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns - // and generate the inverse key schedule. more specifically, - // according to (section 5.3.3), - // "The key expansion for the Inverse Cipher is defined as follows: - // 1. Apply the Key Expansion. - // 2. Apply InvMixColumn to all Round Keys except the first and the last one." - // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher" - list($dt0, $dt1, $dt2, $dt3) = $this->_getInvTables(); - $temp = $this->w = $this->dw = array(); - for ($i = $row = $col = 0; $i < $length; $i++, $col++) { - if ($col == $this->Nb) { - if ($row == 0) { - $this->dw[0] = $this->w[0]; - } else { - // subWord + invMixColumn + invSubWord = invMixColumn - $j = 0; - while ($j < $this->Nb) { - $dw = $this->_subWord($this->w[$row][$j]); - $temp[$j] = $dt0[$dw >> 24 & 0x000000FF] ^ - $dt1[$dw >> 16 & 0x000000FF] ^ - $dt2[$dw >> 8 & 0x000000FF] ^ - $dt3[$dw & 0x000000FF]; - $j++; - } - $this->dw[$row] = $temp; - } - - $col = 0; - $row++; - } - $this->w[$row][$col] = $w[$i]; - } - - $this->dw[$row] = $this->w[$row]; - - // Converting to 1-dim key arrays (both ascending) - $this->dw = array_reverse($this->dw); - $w = array_pop($this->w); - $dw = array_pop($this->dw); - foreach ($this->w as $r => $wr) { - foreach ($wr as $c => $wc) { - $w[] = $wc; - $dw[] = $this->dw[$r][$c]; - } - } - $this->w = $w; - $this->dw = $dw; - } - - /** - * Performs S-Box substitutions - * - * @access private - * @param int $word - */ - function _subWord($word) - { - static $sbox; - if (empty($sbox)) { - list(, , , , $sbox) = $this->_getTables(); - } - - return $sbox[$word & 0x000000FF] | - ($sbox[$word >> 8 & 0x000000FF] << 8) | - ($sbox[$word >> 16 & 0x000000FF] << 16) | - ($sbox[$word >> 24 & 0x000000FF] << 24); - } - - /** - * Provides the mixColumns and sboxes tables - * - * @see Crypt_Rijndael:_encryptBlock() - * @see Crypt_Rijndael:_setupInlineCrypt() - * @see Crypt_Rijndael:_subWord() - * @access private - * @return array &$tables - */ - function &_getTables() - { - static $tables; - if (empty($tables)) { - // according to (section 5.2.1), - // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so - // those are the names we'll use. - $t3 = array_map('intval', array( - // with array_map('intval', ...) we ensure we have only int's and not - // some slower floats converted by php automatically on high values - 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491, - 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC, - 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB, - 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B, - 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, - 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A, - 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F, - 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, - 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B, - 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713, - 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, - 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85, - 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411, - 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B, - 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1, - 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF, - 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E, - 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6, - 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B, - 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, - 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8, - 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2, - 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, - 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810, - 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197, - 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, - 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C, - 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927, - 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733, - 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5, - 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0, - 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C - )); - - foreach ($t3 as $t3i) { - $t0[] = (($t3i << 24) & 0xFF000000) | (($t3i >> 8) & 0x00FFFFFF); - $t1[] = (($t3i << 16) & 0xFFFF0000) | (($t3i >> 16) & 0x0000FFFF); - $t2[] = (($t3i << 8) & 0xFFFFFF00) | (($t3i >> 24) & 0x000000FF); - } - - $tables = array( - // The Precomputed mixColumns tables t0 - t3 - $t0, - $t1, - $t2, - $t3, - // The SubByte S-Box - array( - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, - 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, - 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, - 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, - 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, - 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, - 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, - 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, - 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 - ) - ); - } - return $tables; - } - - /** - * Provides the inverse mixColumns and inverse sboxes tables - * - * @see Crypt_Rijndael:_decryptBlock() - * @see Crypt_Rijndael:_setupInlineCrypt() - * @see Crypt_Rijndael:_setupKey() - * @access private - * @return array &$tables - */ - function &_getInvTables() - { - static $tables; - if (empty($tables)) { - $dt3 = array_map('intval', array( - 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B, - 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5, - 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B, - 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E, - 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D, - 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9, - 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66, - 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED, - 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4, - 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD, - 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60, - 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79, - 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C, - 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24, - 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C, - 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814, - 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B, - 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084, - 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077, - 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22, - 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F, - 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582, - 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB, - 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF, - 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035, - 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17, - 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46, - 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D, - 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A, - 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678, - 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF, - 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0 - )); - - foreach ($dt3 as $dt3i) { - $dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >> 8) & 0x00FFFFFF); - $dt1[] = (($dt3i << 16) & 0xFFFF0000) | (($dt3i >> 16) & 0x0000FFFF); - $dt2[] = (($dt3i << 8) & 0xFFFFFF00) | (($dt3i >> 24) & 0x000000FF); - }; - - $tables = array( - // The Precomputed inverse mixColumns tables dt0 - dt3 - $dt0, - $dt1, - $dt2, - $dt3, - // The inverse SubByte S-Box - array( - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, - 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, - 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, - 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, - 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, - 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, - 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, - 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, - 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, - 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, - 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D - ) - ); - } - return $tables; - } - - /** - * Setup the performance-optimized function for de/encrypt() - * - * @see Crypt_Base::_setupInlineCrypt() - * @access private - */ - function _setupInlineCrypt() - { - // Note: _setupInlineCrypt() will be called only if $this->changed === true - // So here we are'nt under the same heavy timing-stress as we are in _de/encryptBlock() or de/encrypt(). - // However...the here generated function- $code, stored as php callback in $this->inline_crypt, must work as fast as even possible. - - $lambda_functions =& Crypt_Rijndael::_getLambdaFunctions(); - - // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function. - // (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit) - // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one. - $gen_hi_opt_code = (bool)(count($lambda_functions) < 10); - - // Generation of a uniqe hash for our generated code - $code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}"; - if ($gen_hi_opt_code) { - $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key); - } - - if (!isset($lambda_functions[$code_hash])) { - switch (true) { - case $gen_hi_opt_code: - // The hi-optimized $lambda_functions will use the key-words hardcoded for better performance. - $w = $this->w; - $dw = $this->dw; - $init_encrypt = ''; - $init_decrypt = ''; - break; - default: - for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) { - $w[] = '$w[' . $i . ']'; - $dw[] = '$dw[' . $i . ']'; - } - $init_encrypt = '$w = $self->w;'; - $init_decrypt = '$dw = $self->dw;'; - } - - $Nr = $this->Nr; - $Nb = $this->Nb; - $c = $this->c; - - // Generating encrypt code: - $init_encrypt.= ' - static $tables; - if (empty($tables)) { - $tables = &$self->_getTables(); - } - $t0 = $tables[0]; - $t1 = $tables[1]; - $t2 = $tables[2]; - $t3 = $tables[3]; - $sbox = $tables[4]; - '; - - $s = 'e'; - $e = 's'; - $wc = $Nb - 1; - - // Preround: addRoundKey - $encrypt_block = '$in = unpack("N*", $in);'."\n"; - for ($i = 0; $i < $Nb; ++$i) { - $encrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$w[++$wc].";\n"; - } - - // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey - for ($round = 1; $round < $Nr; ++$round) { - list($s, $e) = array($e, $s); - for ($i = 0; $i < $Nb; ++$i) { - $encrypt_block.= - '$'.$e.$i.' = - $t0[($'.$s.$i .' >> 24) & 0xff] ^ - $t1[($'.$s.(($i + $c[1]) % $Nb).' >> 16) & 0xff] ^ - $t2[($'.$s.(($i + $c[2]) % $Nb).' >> 8) & 0xff] ^ - $t3[ $'.$s.(($i + $c[3]) % $Nb).' & 0xff] ^ - '.$w[++$wc].";\n"; - } - } - - // Finalround: subWord + shiftRows + addRoundKey - for ($i = 0; $i < $Nb; ++$i) { - $encrypt_block.= - '$'.$e.$i.' = - $sbox[ $'.$e.$i.' & 0xff] | - ($sbox[($'.$e.$i.' >> 8) & 0xff] << 8) | - ($sbox[($'.$e.$i.' >> 16) & 0xff] << 16) | - ($sbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n"; - } - $encrypt_block .= '$in = pack("N*"'."\n"; - for ($i = 0; $i < $Nb; ++$i) { - $encrypt_block.= ', - ($'.$e.$i .' & '.((int)0xFF000000).') ^ - ($'.$e.(($i + $c[1]) % $Nb).' & 0x00FF0000 ) ^ - ($'.$e.(($i + $c[2]) % $Nb).' & 0x0000FF00 ) ^ - ($'.$e.(($i + $c[3]) % $Nb).' & 0x000000FF ) ^ - '.$w[$i]."\n"; - } - $encrypt_block .= ');'; - - // Generating decrypt code: - $init_decrypt.= ' - static $invtables; - if (empty($invtables)) { - $invtables = &$self->_getInvTables(); - } - $dt0 = $invtables[0]; - $dt1 = $invtables[1]; - $dt2 = $invtables[2]; - $dt3 = $invtables[3]; - $isbox = $invtables[4]; - '; - - $s = 'e'; - $e = 's'; - $wc = $Nb - 1; - - // Preround: addRoundKey - $decrypt_block = '$in = unpack("N*", $in);'."\n"; - for ($i = 0; $i < $Nb; ++$i) { - $decrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$dw[++$wc].';'."\n"; - } - - // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey - for ($round = 1; $round < $Nr; ++$round) { - list($s, $e) = array($e, $s); - for ($i = 0; $i < $Nb; ++$i) { - $decrypt_block.= - '$'.$e.$i.' = - $dt0[($'.$s.$i .' >> 24) & 0xff] ^ - $dt1[($'.$s.(($Nb + $i - $c[1]) % $Nb).' >> 16) & 0xff] ^ - $dt2[($'.$s.(($Nb + $i - $c[2]) % $Nb).' >> 8) & 0xff] ^ - $dt3[ $'.$s.(($Nb + $i - $c[3]) % $Nb).' & 0xff] ^ - '.$dw[++$wc].";\n"; - } - } - - // Finalround: subWord + shiftRows + addRoundKey - for ($i = 0; $i < $Nb; ++$i) { - $decrypt_block.= - '$'.$e.$i.' = - $isbox[ $'.$e.$i.' & 0xff] | - ($isbox[($'.$e.$i.' >> 8) & 0xff] << 8) | - ($isbox[($'.$e.$i.' >> 16) & 0xff] << 16) | - ($isbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n"; - } - $decrypt_block .= '$in = pack("N*"'."\n"; - for ($i = 0; $i < $Nb; ++$i) { - $decrypt_block.= ', - ($'.$e.$i. ' & '.((int)0xFF000000).') ^ - ($'.$e.(($Nb + $i - $c[1]) % $Nb).' & 0x00FF0000 ) ^ - ($'.$e.(($Nb + $i - $c[2]) % $Nb).' & 0x0000FF00 ) ^ - ($'.$e.(($Nb + $i - $c[3]) % $Nb).' & 0x000000FF ) ^ - '.$dw[$i]."\n"; - } - $decrypt_block .= ');'; - - $lambda_functions[$code_hash] = $this->_createInlineCryptFunction( - array( - 'init_crypt' => '', - 'init_encrypt' => $init_encrypt, - 'init_decrypt' => $init_decrypt, - 'encrypt_block' => $encrypt_block, - 'decrypt_block' => $decrypt_block - ) - ); - } - $this->inline_crypt = $lambda_functions[$code_hash]; - } -} diff --git a/installer/dup-installer/classes/Crypt/index.php b/installer/dup-installer/classes/Crypt/index.php deleted file mode 100644 index b4962229..00000000 --- a/installer/dup-installer/classes/Crypt/index.php +++ /dev/null @@ -1,2 +0,0 @@ -options(MYSQLI_OPT_LOCAL_INFILE, false); - } - } - } - catch (Exception $e) { - DUPX_Log::info('DATABASE CONNECTION EXCEPTION ERROR: '.$e->getMessage()); - } - return $dbh; - } - - /** - * Modified version of https://developer.wordpress.org/reference/classes/wpdb/parse_db_host/ - * - * @param string $host The DB_HOST setting to parse - * @return array|bool Array containing the host, the port, the socket and whether it is an IPv6 address, in that order. If $host couldn't be parsed, returns false - */ - public static function parseDBHost($host) - { - $port = null; - $socket = null; - $is_ipv6 = false; - - // First peel off the socket parameter from the right, if it exists. - $socket_pos = strpos($host, ':/'); - if (false !== $socket_pos) { - $socket = substr($host, $socket_pos + 1); - $host = substr($host, 0, $socket_pos); - } - - // We need to check for an IPv6 address first. - // An IPv6 address will always contain at least two colons. - if (substr_count($host, ':') > 1) { - $pattern = '#^(?:\[)?(?P[0-9a-fA-F:]+)(?:\]:(?P[\d]+))?#'; - $is_ipv6 = true; - } else { - // We seem to be dealing with an IPv4 address. - $pattern = '#^(?P[^:/]*)(?::(?P[\d]+))?#'; - } - - $matches = array(); - $result = preg_match($pattern, $host, $matches); - - if (1 !== $result) { - // Couldn't parse the address, bail. - return false; - } - - $host = ''; - foreach (array('host', 'port') as $component) { - if (!empty($matches[$component])) { - $$component = $matches[$component]; - } - } - - return array($host, $port, $socket, $is_ipv6); - } - - /** - * Count the tables in a given database - * - * @param obj $dbh A valid database link handle - * @param string $dbname Database to count tables in - * - * @return int The number of tables in the database - */ - public static function countTables($dbh, $dbname) - { - $res = mysqli_query($dbh, "SELECT COUNT(*) AS count FROM information_schema.tables WHERE table_schema = '".mysqli_real_escape_string($dbh, $dbname)."' "); - $row = mysqli_fetch_row($res); - return is_null($row) ? 0 : $row[0]; - } - - /** - * Returns the number of rows in a table - * - * @param obj $dbh A valid database link handle - * @param string $name A valid table name - */ - public static function countTableRows($dbh, $name) - { - $total = mysqli_query($dbh, "SELECT COUNT(*) FROM `".mysqli_real_escape_string($dbh, $name)."`"); - if ($total) { - $total = @mysqli_fetch_array($total); - return $total[0]; - } else { - return 0; - } - } - - /** - * Drops the table given - * - * @param obj $dbh A valid database link handle - * @param string $name A valid table name to remove - * - * @return null - */ - public static function dropTable($dbh, $name) - { - self::queryNoReturn($dbh, "DROP TABLE IF EXISTS $name"); - } - - /** - * Validates if the $collations exist in the current database - * - * @param obj $dbh A valid database link handle - * @param array $collations An array of collation names to search on - * - * @return array Returns the original $collations array with the original names and a found status - * $status[name], $status[found] - */ - public static function getCollationStatus($dbh, $collations) - { - $localhost = array(); - $status = array(); - - $query = "SHOW COLLATION"; - if ($result = $dbh->query($query)) { - - while ($row = $result->fetch_assoc()) { - $localhost[] = $row["Collation"]; - } - - if (DUPX_U::isTraversable($collations)) { - foreach ($collations as $key => $val) { - $status[$key]['name'] = $val; - $status[$key]['found'] = (in_array($val, $localhost)) ? 1 : 0; - } - } - } - $result->free(); - - return $status; - } - - /** - * Returns the database names as an array - * - * @param obj $dbh A valid database link handle - * @param string $dbuser An optional dbuser name to search by - * - * @return array A list of all database names - */ - public static function getDatabases($dbh, $dbuser = '') - { - $sql = strlen($dbuser) ? "SHOW DATABASES LIKE '%".mysqli_real_escape_string($dbh, $dbuser)."%'" : 'SHOW DATABASES'; - $query = @mysqli_query($dbh, $sql); - if ($query) { - while ($db = @mysqli_fetch_array($query)) { - $all_dbs[] = $db[0]; - } - if (isset($all_dbs) && is_array($all_dbs)) { - return $all_dbs; - } - } - return array(); - } - - /** - * Returns the tables for a database as an array - * - * @param obj $dbh A valid database link handle - * - * @return array A list of all table names - */ - public static function getTables($dbh) - { - $query = @mysqli_query($dbh, 'SHOW TABLES'); - if ($query) { - while ($table = @mysqli_fetch_array($query)) { - $all_tables[] = $table[0]; - } - if (isset($all_tables) && is_array($all_tables)) { - return $all_tables; - } - } - return array(); - } - - /** - * Get the requested MySQL system variable - * - * @param obj $dbh A valid database link handle - * @param string $name The database variable name to lookup - * - * @return string the server variable to query for - */ - public static function getVariable($dbh, $name) - { - $result = @mysqli_query($dbh, "SHOW VARIABLES LIKE '".mysqli_real_escape_string($dbh, $name)."'"); - $row = @mysqli_fetch_array($result); - @mysqli_free_result($result); - return isset($row[1]) ? $row[1] : null; - } - - /** - * Gets the MySQL database version number - * - * @param obj $dbh A valid database link handle - * @param bool $full True: Gets the full version - * False: Gets only the numeric portion i.e. 5.5.6 or 10.1.2 (for MariaDB) - * - * @return false|string 0 on failure, version number on success - */ - public static function getVersion($dbh, $full = false) - { - if ($full) { - $version = self::getVariable($dbh, 'version'); - } else { - $version = preg_replace('/[^0-9.].*/', '', self::getVariable($dbh, 'version')); - } - - //Fall-back for servers that have restricted SQL for SHOW statement - //Note: For MariaDB this will report something like 5.5.5 when it is really 10.2.1. - //This mainly is due to mysqli_get_server_info method which gets the version comment - //and uses a regex vs getting just the int version of the value. So while the former - //code above is much more accurate it may fail in rare situations - if (empty($version)) { - $version = mysqli_get_server_info($dbh); - $version = preg_replace('/[^0-9.].*/', '', $version); - } - - $version = is_null($version) ? null : $version; - return empty($version) ? 0 : $version; - } - - /** - * Returns a more detailed string about the msyql server version - * For example on some systems the result is 5.5.5-10.1.21-MariaDB - * this format is helpful for providing the user a full overview - * - * @param conn $dbh Database connection handle - * - * @return string The full details of mysql - */ - public static function getInfo($dbh) - { - return mysqli_get_server_info($dbh); - } - - /** - * Determine if a MySQL database supports a particular feature - * - * @param conn $dbh Database connection handle - * @param string $feature the feature to check for - * @return bool - */ - public static function hasAbility($dbh, $feature) - { - $version = self::getVersion($dbh); - - switch (strtolower($feature)) { - case 'collation' : - case 'group_concat' : - case 'subqueries' : - return version_compare($version, '4.1', '>='); - case 'set_charset' : - return version_compare($version, '5.0.7', '>='); - } - return false; - } - - /** - * Runs a query and returns the results as an array with the column names - * - * @param obj $dbh A valid database link handle - * @param string $sql The sql to run - * - * @return array The result of the query as an array with the column name as the key - */ - public static function queryColumnToArray($dbh, $sql, $column_index = 0) - { - $result_array = array(); - $full_result_array = self::queryToArray($dbh, $sql); - - for ($i = 0; $i < count($full_result_array); $i++) { - $result_array[] = $full_result_array[$i][$column_index]; - } - return $result_array; - } - - /** - * Runs a query with no result - * - * @param obj $dbh A valid database link handle - * @param string $sql The sql to run - * - * @return array The result of the query as an array - */ - public static function queryToArray($dbh, $sql) - { - $result = array(); - - DUPX_Log::info("calling mysqli query on $sql", DUPX_Log::LV_HARD_DEBUG); - $query_result = mysqli_query($dbh, $sql); - - if ($query_result !== false) { - if (mysqli_num_rows($query_result) > 0) { - while ($row = mysqli_fetch_row($query_result)) { - $result[] = $row; - } - } - } else { - $error = mysqli_error($dbh); - - throw new Exception("Error executing query {$sql}.
        {$error}"); - } - - return $result; - } - - /** - * Runs a query with no result - * - * @param obj $dbh A valid database link handle - * @param string $sql The sql to run - * - * @return null - */ - public static function queryNoReturn($dbh, $sql) - { - $query_result = mysqli_query($dbh, $sql); - - if ($query_result === false) { - $error = mysqli_error($dbh); - - throw new Exception("Error executing query {$sql}.
        {$error}"); - } - } - - /** - * Renames an existing table - * - * @param obj $dbh A valid database link handle - * @param string $existing_name The current tables name - * @param string $new_name The new table name to replace the existing name - * @param string $delete_if_conflict Delete the table name if there is a conflict - * - * @return null - */ - public static function renameTable($dbh, $existing_name, $new_name, $delete_if_conflict = false) - { - if ($delete_if_conflict) { - if (self::tableExists($dbh, $new_name)) { - self::dropTable($dbh, $new_name); - } - } - - self::queryNoReturn($dbh, "RENAME TABLE $existing_name TO $new_name"); - } - - /** - * Sets the MySQL connection's character set. - * - * @param resource $dbh The resource given by mysqli_connect - * @param string $charset The character set (optional) - * @param string $collate The collation (optional) - */ - public static function setCharset($dbh, $charset = null, $collate = null) - { - $charset = (!isset($charset) ) ? $GLOBALS['DBCHARSET_DEFAULT'] : $charset; - $collate = (!isset($collate) ) ? $GLOBALS['DBCOLLATE_DEFAULT'] : $collate; - - if (self::hasAbility($dbh, 'collation') && !empty($charset)) { - if (function_exists('mysqli_set_charset') && self::hasAbility($dbh, 'set_charset')) { - if (($result = mysqli_set_charset($dbh, mysqli_real_escape_string($dbh, $charset))) === false) { - $errMsg = mysqli_error($dbh); - DUPX_Log::info('DATABASE ERROR: mysqli_set_charset '.DUPX_Log::varToString($charset).' MSG: '.$errMsg); - } else { - DUPX_Log::info('DATABASE: mysqli_set_charset '.DUPX_Log::varToString($charset), DUPX_Log::LV_DETAILED); - } - return $result; - } else { - $sql = " SET NAMES ".mysqli_real_escape_string($dbh, $charset); - if (!empty($collate)) { - $sql .= " COLLATE ".mysqli_real_escape_string($dbh, $collate); - } - - if (($result = mysqli_query($dbh, $sql)) === false) { - $errMsg = mysqli_error($dbh); - DUPX_Log::info('DATABASE SQL ERROR: '.DUPX_Log::varToString($sql).' MSG: '.$errMsg); - } else { - DUPX_Log::info('DATABASE SQL: '.DUPX_Log::varToString($sql), DUPX_Log::LV_DETAILED); - } - - return $result; - } - } - } - - /** - * If cached_table_names is null re-query the database, otherwise use those for the list - * - * @param obj $dbh A valid database link handle - * @param string $table_name Name of table to check for - * - * @return bool Does the table name exist in the database - */ - public static function tableExists($dbh, $table_name, $cached_table_names = null) - { - if ($cached_table_names === null) { - // RSR TODO: retrieve full list of tables - $cached_table_names = self::queryColumnToArray($dbh, "SHOW TABLES"); - } - return in_array($table_name, $cached_table_names); - } - - /** - * mysqli_query wrapper with logging - * - * @param mysqli $link - * @param string $sql - * @return type - */ - public static function mysqli_query($link, $sql, $file = '', $line = '') - { - if (($result = mysqli_query($link, $sql)) === false) { - DUPX_Log::info('DB QUERY [ERROR]['.$file.':'.$line.'] SQL: '.DUPX_Log::varToString($sql)."\n\t MSG: ".mysqli_error($link)); - } else { - DUPX_Log::info('DB QUERY ['.$file.':'.$line.']: '.DUPX_Log::varToString($sql), DUPX_Log::LV_HARD_DEBUG); - } - - return $result; - } -} \ No newline at end of file diff --git a/installer/dup-installer/classes/class.logging.php b/installer/dup-installer/classes/class.logging.php deleted file mode 100644 index 7b77bf25..00000000 --- a/installer/dup-installer/classes/class.logging.php +++ /dev/null @@ -1,452 +0,0 @@ -= self::LV_DETAILED) { - $preLog .= sprintf('[DELTA:%10.5f] ', microtime(true) - self::$microtimeStart); - } - if (is_callable(self::$postprocessCallback)) { - $msg = call_user_func(self::$postprocessCallback, $msg); - } - @fwrite($GLOBALS["LOG_FILE_HANDLE"], $preLog.$msg."\n", self::MAX_LENGTH_FWRITE); - } - - if ($flush) { - self::flush(); - } - } - } - - /** - * - * @param callable $callback - */ - public static function setPostProcessCallback($callback) - { - if (is_callable($callback)) { - self::$postprocessCallback = $callback; - } else { - self::$postprocessCallback = null; - } - } - - /** - * set $microtimeStart at current time - */ - public static function resetTime($logging = self::LV_DEFAULT) - { - self::$microtimeStart = microtime(true); - if ($logging > self::$logLevel) { - return; - } - $callers = debug_backtrace(); - $file = $callers[0]['file']; - $line = $callers[0]['line']; - DUPX_Log::info('LOG-TIME['.$file.':'.$line.'] RESET TIME', $logging); - } - - /** - * log time delta from last resetTime call - * - * @return void - */ - public static function logTime($msg = '', $logging = self::LV_DEFAULT) - { - if ($logging > self::$logLevel) { - return; - } - $callers = debug_backtrace(); - $file = $callers[0]['file']; - $line = $callers[0]['line']; - DUPX_Log::info(sprintf('LOG-TIME[%s:%s][DELTA:%10.5f] ', $file, $line, microtime(true) - self::$microtimeStart).(empty($msg) ? '' : ' MESSAGE:'.$msg), $logging); - } - - public static function incIndent() - { - self::$indentation++; - } - - public static function decIndent() - { - if (self::$indentation > 0) { - self::$indentation--; - } - } - - public static function resetIndent() - { - self::$indentation = 0; - } - - public static function isLevel($logging) - { - return $logging <= self::$logLevel; - } - - public static function infoObject($msg, &$object, $logging = self::LV_DEFAULT) - { - $msg = $msg."\n".print_r($object, true); - self::info($msg, $logging); - } - - public static function flush() - { - if (is_resource($GLOBALS['LOG_FILE_HANDLE'])) { - @fflush($GLOBALS['LOG_FILE_HANDLE']); - } - } - - public static function close() - { - if (is_resource($GLOBALS['LOG_FILE_HANDLE'])) { - @fclose($GLOBALS["LOG_FILE_HANDLE"]); - $GLOBALS["LOG_FILE_HANDLE"] = null; - } - } - - public static function getFileHandle() - { - return is_resource($GLOBALS["LOG_FILE_HANDLE"]) ? $GLOBALS["LOG_FILE_HANDLE"] : false; - } - - public static function error($errorMessage) - { - $breaks = array("
        ", "
        ", "
        "); - $spaces = array(" "); - $log_msg = str_ireplace($breaks, "\r\n", $errorMessage); - $log_msg = str_ireplace($spaces, " ", $log_msg); - $log_msg = strip_tags($log_msg); - - self::info("\nINSTALLER ERROR:\n{$log_msg}\n"); - - if (self::$thowExceptionOnError) { - throw new Exception($errorMessage); - } else { - self::close(); - die("

        INSTALL ERROR!
        {$errorMessage}
        "); - } - } - - /** - * - * @param Exception $e - * @param string $title - */ - public static function logException($e, $logging = self::LV_DEFAULT, $title = 'EXCEPTION ERROR: ') - { - if ($logging <= self::$logLevel) { - DUPX_Log::info("\n".$title.' '.$e->getMessage()); - DUPX_Log::info("\tFILE:".$e->getFile().'['.$e->getLIne().']'); - DUPX_Log::info("\tTRACE:\n".$e->getTraceAsString()."\n"); - } - } - - /** - * - * @param boolean $set - */ - public static function setThrowExceptionOnError($set) - { - self::$thowExceptionOnError = (bool) $set; - } - - /** - * - * @param mixed $var - * @param bool $checkCallable // if true check if var is callable and display it - * @return string - */ - public static function varToString($var, $checkCallable = false) - { - if ($checkCallable && is_callable($var)) { - return '(callable) '.print_r($var, true); - } - switch (gettype($var)) { - case "boolean": - return $var ? 'true' : 'false'; - case "integer": - case "double": - return (string) $var; - case "string": - return '"'.$var.'"'; - case "array": - case "object": - return print_r($var, true); - case "resource": - case "resource (closed)": - case "NULL": - case "unknown type": - default: - return gettype($var); - } - } -} - -class DUPX_Handler -{ - - const MODE_OFF = 0; // don't write in log - const MODE_LOG = 1; // write errors in log file - const MODE_VAR = 2; // put php errors in $varModeLog static var - const SHUTDOWN_TIMEOUT = 'tm'; - - public static function initErrorHandler() - { - DUPX_Boot::disableBootShutdownFunction(); - - @set_error_handler(array(__CLASS__, 'error')); - @register_shutdown_function(array(__CLASS__, 'shutdown')); - } - /** - * - * @var array - */ - private static $shutdownReturns = array( - 'tm' => 'timeout' - ); - - /** - * - * @var int - */ - private static $handlerMode = self::MODE_LOG; - - /** - * - * @var bool // print code reference and errno at end of php error line [CODE:10|FILE:test.php|LINE:100] - */ - private static $codeReference = true; - - /** - * - * @var bool // print prefix in php error line [PHP ERR][WARN] MSG: ..... - */ - private static $errPrefix = true; - - /** - * - * @var string // php errors in MODE_VAR - */ - private static $varModeLog = ''; - - /** - * 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 (self::$handlerMode) { - case self::MODE_OFF: - if ($errno == E_ERROR) { - $log_message = self::getMessage($errno, $errstr, $errfile, $errline); - DUPX_Log::error($log_message); - } - break; - case self::MODE_VAR: - self::$varModeLog .= self::getMessage($errno, $errstr, $errfile, $errline)."\n"; - break; - case self::MODE_LOG: - default: - switch ($errno) { - case E_ERROR : - $log_message = self::getMessage($errno, $errstr, $errfile, $errline); - DUPX_Log::error($log_message); - break; - case E_NOTICE : - case E_WARNING : - default : - $log_message = self::getMessage($errno, $errstr, $errfile, $errline); - DUPX_Log::info($log_message); - break; - } - } - } - - private static function getMessage($errno, $errstr, $errfile, $errline) - { - $result = ''; - - if (self::$errPrefix) { - $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; - - if (self::$codeReference) { - $result .= ' [CODE:'.$errno.'|FILE:'.$errfile.'|LINE:'.$errline.']'; - if (DUPX_Log::isLevel(DUPX_Log::LV_DEBUG)) { - ob_start(); - debug_print_backtrace(); - $result .= "\n".ob_get_clean(); - } - } - - return $result; - } - - /** - * if setMode is called without params set as default - * - * @param int $mode - * @param bool $errPrefix // print prefix in php error line [PHP ERR][WARN] MSG: ..... - * @param bool $codeReference // print code reference and errno at end of php error line [CODE:10|FILE:test.php|LINE:100] - */ - public static function setMode($mode = self::MODE_LOG, $errPrefix = true, $codeReference = true) - { - switch ($mode) { - case self::MODE_OFF: - case self::MODE_VAR: - self::$handlerMode = $mode; - break; - case self::MODE_LOG: - default: - self::$handlerMode = self::MODE_LOG; - } - - self::$varModeLog = ''; - self::$errPrefix = $errPrefix; - self::$codeReference = $codeReference; - } - - /** - * - * @return string // return var log string in MODE_VAR - */ - public static function getVarLog() - { - return self::$varModeLog; - } - - /** - * - * @return string // return var log string in MODE_VAR and clean var - */ - public static function getVarLogClean() - { - $result = self::$varModeLog; - self::$varModeLog = ''; - return $result; - } - - /** - * - * @param string $status // timeout - * @param string $string - */ - public static function setShutdownReturn($status, $str) - { - self::$shutdownReturns[$status] = $str; - } - - /** - * Shutdown handler - * - * @return void - */ - public static function shutdown() - { - if (($error = error_get_last())) { - if (preg_match('/^Maximum execution time (?:.+) exceeded$/i', $error['message'])) { - echo self::$shutdownReturns[self::SHUTDOWN_TIMEOUT]; - } - DUPX_Handler::error($error['type'], $error['message'], $error['file'], $error['line']); - } - } -} \ No newline at end of file diff --git a/installer/dup-installer/classes/class.s3.func.php b/installer/dup-installer/classes/class.s3.func.php deleted file mode 100644 index 8585ed26..00000000 --- a/installer/dup-installer/classes/class.s3.func.php +++ /dev/null @@ -1,1342 +0,0 @@ -timeStart = DUPX_U::getMicrotime(); - } - - /** - * - * @return self - */ - public static function getInstance() - { - if (is_null(self::$instance)) { - self::$instance = new self; - } - return self::$instance; - } - - /** - * inizialize 3sFunc data - */ - public function initData() - { - DUPX_Log::info('INIT S3 DATA', 2); - // else init data from $_POST - $this->setPostData(); - $this->setReplaceList(); - $this->initReport(); - $this->copyOriginalConfigFiles(); - } - - private function initReport() - { - $this->report = self::getInitReport(); - } - - public static function getInitReport() - { - return array( - 'pass' => 0, - 'chunk' => 0, - 'chunkPos' => array(), - 'progress_perc' => 0, - 'scan_tables' => 0, - 'scan_rows' => 0, - 'scan_cells' => 0, - 'updt_tables' => 0, - 'updt_rows' => 0, - 'updt_cells' => 0, - 'errsql' => array(), - 'errser' => array(), - 'errkey' => array(), - 'errsql_sum' => 0, - 'errser_sum' => 0, - 'errkey_sum' => 0, - 'profile_start' => '', - 'profile_end' => '', - 'time' => '', - 'err_all' => 0, - 'warn_all' => 0, - 'warnlist' => array() - ); - } - - public function getJsonReport() - { - $this->report['warn_all'] = empty($this->report['warnlist']) ? 0 : count($this->report['warnlist']); - - if ($this->fullReport) { - return array( - 'step1' => json_decode(urldecode($this->post['json'])), - 'step3' => $this->report - ); - } else { - return array( - 'step3' => $this->report - ); - } - } - - private static function logSectionHeader($title, $func, $line) - { - $log = "\n".'===================================='."\n". - $title; - if ($GLOBALS["LOGGING"] > 1) { - $log .= ' [FUNC: '.$func.' L:'.$line.']'; - } - $log .= "\n". - '===================================='; - DUPX_Log::info($log); - } - - private function setPostData() - { - // POST PARAMS - // SEARCH AND SEPLACE SETTINGS - $this->post = array(); - - $this->post['blogname'] = isset($_POST['blogname']) ? htmlspecialchars($_POST['blogname'], ENT_QUOTES) : 'No Blog Title Set'; - $this->post['postguid'] = filter_input(INPUT_POST, 'postguid', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false))); - $this->post['fullsearch'] = filter_input(INPUT_POST, 'fullsearch', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false))); - - $this->post['path_old'] = DUPX_U::isset_sanitize($_POST, 'path_old', array('default' => null, 'trim' => true)); - $this->post['path_new'] = DUPX_U::isset_sanitize($_POST, 'path_new', array('default' => null, 'trim' => true)); - - $this->post['siteurl'] = DUPX_U::isset_sanitize($_POST, 'siteurl', array('default' => null, 'trim' => true)); - if (!is_null($this->post['siteurl'])) { - $this->post['siteurl'] = rtrim($this->post['siteurl'], '/'); - } - - $this->post['url_old'] = DUPX_U::isset_sanitize($_POST, 'url_old', array('default' => null, 'trim' => true)); - if (!is_null($this->post['url_old'])) { - $this->post['siteurl'] = rtrim($this->post['url_old'], '/'); - } - - $this->post['url_new'] = DUPX_U::isset_sanitize($_POST, 'url_new', array('default' => null, 'trim' => true)); - if (!is_null($this->post['url_new'])) { - $this->post['siteurl'] = rtrim($this->post['url_new'], '/'); - } - - $this->post['tables'] = isset($_POST['tables']) && is_array($_POST['tables']) ? array_map('DUPX_U::sanitize_text_field', $_POST['tables']) : array(); - $this->post['maxSerializeStrlen'] = filter_input(INPUT_POST, DUPX_CTRL::NAME_MAX_SERIALIZE_STRLEN_IN_M, FILTER_VALIDATE_INT, - array("options" => array('default' => DUPX_Constants::DEFAULT_MAX_STRLEN_SERIALIZED_CHECK_IN_M, 'min_range' => 0))) * 1000000; - $this->post['replaceMail'] = filter_input(INPUT_POST, 'search_replace_email_domain', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false))); - - // DATABASE CONNECTION - $this->post['dbhost'] = trim(filter_input(INPUT_POST, 'dbhost', FILTER_DEFAULT, array('options' => array('default' => '')))); - $this->post['dbuser'] = trim(filter_input(INPUT_POST, 'dbuser', FILTER_DEFAULT, array('options' => array('default' => '')))); - $this->post['dbname'] = trim(filter_input(INPUT_POST, 'dbname', FILTER_DEFAULT, array('options' => array('default' => '')))); - $this->post['dbpass'] = trim(filter_input(INPUT_POST, 'dbpass', FILTER_DEFAULT, array('options' => array('default' => '')))); - $this->post['dbcharset'] = DUPX_U::isset_sanitize($_POST, 'dbcharset', array('default' => '')); - $this->post['dbcollate'] = DUPX_U::isset_sanitize($_POST, 'dbcollate', array('default' => '')); - - // NEW ADMIN USER - $this->post['wp_username'] = DUPX_U::isset_sanitize($_POST, 'wp_username', array('default' => '', 'trim' => true)); - $this->post['wp_password'] = DUPX_U::isset_sanitize($_POST, 'wp_password', array('default' => '', 'trim' => true)); - $this->post['wp_mail'] = DUPX_U::isset_sanitize($_POST, 'wp_mail', array('default' => '', 'trim' => true)); - $this->post['wp_nickname'] = DUPX_U::isset_sanitize($_POST, 'wp_nickname', array('default' => '', 'trim' => true)); - $this->post['wp_first_name'] = DUPX_U::isset_sanitize($_POST, 'wp_first_name', array('default' => '', 'trim' => true)); - $this->post['wp_last_name'] = DUPX_U::isset_sanitize($_POST, 'wp_last_name', array('default' => '', 'trim' => true)); - - // WP CONFIG SETTINGS - $this->post['ssl_admin'] = filter_input(INPUT_POST, 'ssl_admin', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false))); - $this->post['cache_wp'] = filter_input(INPUT_POST, 'cache_wp', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false))); - $this->post['cache_path'] = filter_input(INPUT_POST, 'cache_path', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false))); - - // OTHER - $this->post['exe_safe_mode'] = filter_input(INPUT_POST, 'exe_safe_mode', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false))); - $this->post['config_mode'] = DUPX_U::isset_sanitize($_POST, 'config_mode', array('default' => 'NEW')); - $this->post['plugins'] = filter_input(INPUT_POST, 'plugins', FILTER_UNSAFE_RAW, - array( - 'options' => array( - 'default' => array() - ), - 'flags' => FILTER_REQUIRE_ARRAY, - )); - - $this->post['json'] = filter_input(INPUT_POST, 'json', FILTER_DEFAULT, array('options' => array('default' => '{}'))); - } - - /** - * get value post if the post isn't initialized initialize it - * - * @param string $key - * @return mixed - */ - public function getPost($key = null) - { - if (is_null($this->post)) { - $this->initData(); - } - - if (is_null($key)) { - return $this->post; - } else if (isset($this->post[$key])) { - return $this->post[$key]; - } else { - return null; - } - } - - /** - * add table in tables list to scan in search and replace engine if isn't already in array - * - * @param string $table - */ - public function addTable($table) - { - if (empty($table)) { - return; - } - - // make sure post data is initialized - $this->getPost(); - if (!in_array($table, $this->post['tables'])) { - $this->post['tables'][] = $table; - } - } - - /** - * open db connection if is closed - */ - private function dbConnection() - { - if (is_null($this->dbh)) { - // make sure post data is initialized - $this->getPost(); - - //MYSQL CONNECTION - $this->dbh = DUPX_DB::connect($this->post['dbhost'], $this->post['dbuser'], $this->post['dbpass'], $this->post['dbname']); - $dbConnError = (mysqli_connect_error()) ? 'Error: '.mysqli_connect_error() : 'Unable to Connect'; - - if (!$this->dbh) { - $msg = "Unable to connect with the following parameters:
        HOST: {$post_db_host}
        DATABASE: {$post_db_name}
        "; - $msg .= "Connection Error: {$dbConnError}"; - DUPX_Log::error($msg); - } - - $db_max_time = mysqli_real_escape_string($this->dbh, $GLOBALS['DB_MAX_TIME']); - @mysqli_query($this->dbh, "SET wait_timeout = ".mysqli_real_escape_string($this->dbh, $db_max_time)); - - $post_db_charset = $this->post['dbcharset']; - $post_db_collate = $this->post['dbcollate']; - DUPX_DB::setCharset($this->dbh, $post_db_charset, $post_db_collate); - } - } - - public function getDbConnection() - { - // make sure dbConnection is initialized - $this->dbConnection(); - return $this->dbh; - } - - /** - * close db connection if is open - */ - public function closeDbConnection() - { - if (!is_null($this->dbh)) { - mysqli_close($this->dbh); - $this->dbh = null; - } - } - - public function initLog() - { - // make sure dbConnection is initialized - $this->dbConnection(); - - $charsetServer = @mysqli_character_set_name($this->dbh); - $charsetClient = @mysqli_character_set_name($this->dbh); - - //LOGGING - $date = @date('h:i:s'); - $log = "\n\n". - "********************************************************************************\n". - "DUPLICATOR PRO INSTALL-LOG\n". - "STEP-3 START @ ".$date."\n". - "NOTICE: Do NOT post to public sites or forums\n". - "********************************************************************************\n". - "CHARSET SERVER:\t".DUPX_Log::varToString($charsetServer)."\n". - "CHARSET CLIENT:\t".DUPX_Log::varToString($charsetClient)."\n". - "********************************************************************************\n". - "OPTIONS:\n"; - - $skipOpts = array('tables', 'plugins', 'dbpass', 'json', 'search', 'replace', 'mu_search', 'mu_replace', 'wp_password', 'dbhost', 'dbuser', 'dbname', 'wp_username'); - foreach ($this->post as $key => $val) { - if (in_array($key, $skipOpts)) { - continue; - } - $log .= str_pad($key, 22, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($val)."\n"; - } - $log .= "********************************************************************************\n"; - - DUPX_Log::info($log); - - $POST_LOG = $this->post; - unset($POST_LOG['tables']); - unset($POST_LOG['plugins']); - unset($POST_LOG['dbpass']); - ksort($POST_LOG); - - //Detailed logging - $log = "--------------------------------------\n"; - $log .= "POST DATA\n"; - $log .= "--------------------------------------\n"; - $log .= print_r($POST_LOG, true); - DUPX_Log::info($log, DUPX_Log::LV_DEBUG); - - $log = "--------------------------------------\n"; - $log .= "TABLES TO SCAN\n"; - $log .= "--------------------------------------\n"; - $log .= (isset($this->post['tables']) && count($this->post['tables']) > 0) ? DUPX_Log::varToString($this->post['tables']) : 'No tables selected to update'; - $log .= "--------------------------------------\n"; - $log .= "KEEP PLUGINS ACTIVE\n"; - $log .= "--------------------------------------\n"; - $log .= (isset($this->post['plugins']) && count($this->post['plugins']) > 0) ? DUPX_Log::varToString($this->post['plugins']) : 'No plugins selected for activation'; - DUPX_Log::info($log, 2); - DUPX_Log::flush(); - } - - /** - * - * @staticvar type $configTransformer - * - * @return DupLiteWPConfigTransformer - */ - public function getWpConfigTransformer() - { - static $configTransformer = null; - - if (is_null($configTransformer)) { - //@todo: integrate all logic into DUPX_WPConfig::updateVars - if (!is_writable(DUPX_Package::getWpconfigArkPath())) { - if (DupLiteSnapLibIOU::chmod(DUPX_Package::getWpconfigArkPath(), 0644)) { - DUPX_Log::info("File Permission Update: dup-wp-config-arc__[HASH].txt set to 0644"); - } else { - $err_log = "\nWARNING: Unable to update file permissions and write to dup-wp-config-arc__[HASH].txt. "; - $err_log .= "Check that the wp-config.php is in the archive.zip and check with your host or administrator to enable PHP to write to the wp-config.php file. "; - $err_log .= "If performing a 'Manual Extraction' please be sure to select the 'Manual Archive Extraction' option on step 1 under options."; - DUPX_Log::error($err_log); - } - } - $configTransformer = new DupLiteWPConfigTransformer(DUPX_Package::getWpconfigArkPath()); - } - - return $configTransformer; - } - - /** - * - * @return string - */ - public function copyOriginalConfigFiles() - { - $wpOrigPath = DUPX_Package::getOrigWpConfigPath(); - $wpArkPath = DUPX_Package::getWpconfigArkPath(); - - if (file_exists($wpOrigPath)) { - if (!@unlink($wpOrigPath)) { - DUPX_Log::info('Can\'t delete copy of WP Config orig file'); - } - } - - if (!file_exists($wpArkPath)) { - DUPX_Log::info('WP Config ark file don\' exists'); - } else { - if (!@copy($wpArkPath, $wpOrigPath)) { - $errors = error_get_last(); - DUPX_Log::info("COPY ERROR: ".$errors['type']."\n".$errors['message']); - } else { - echo DUPX_Log::info("Original WP Config file copied", 2); - } - } - - $htOrigPath = DUPX_Package::getOrigHtaccessPath(); - $htArkPath = DUPX_Package::getHtaccessArkPath(); - - if (file_exists($htOrigPath)) { - if (!@unlink($htOrigPath)) { - DUPX_Log::info('Can\'t delete copy of htaccess orig file'); - } - } - - if (!file_exists($htArkPath)) { - DUPX_Log::info('htaccess ark file don\' exists'); - } else { - if (!@copy($htArkPath, $htOrigPath)) { - $errors = error_get_last(); - DUPX_Log::info("COPY ERROR: ".$errors['type']."\n".$errors['message']); - } else { - echo DUPX_Log::info("htaccess file copied", 2); - } - } - } - - /** - * set replace list - * - * Auto inizialize function - */ - public function setReplaceList() - { - self::logSectionHeader('SET SEARCH AND REPLACE LIST', __FUNCTION__, __LINE__); - $this->setGlobalSearchAndReplaceList(); - } - - /** - * - * @return int MODE_NORAML - */ - public function getEngineMode() - { - return self::MODE_NORMAL; - } - - private function setGlobalSearchAndReplaceList() - { - $s_r_manager = DUPX_S_R_MANAGER::getInstance(); - - // make sure dbConnection is initialized - $this->dbConnection(); - - // DIRS PATHS - $post_path_old = $this->post['path_old']; - $post_path_new = $this->post['path_new']; - $s_r_manager->addItem($post_path_old, $post_path_new, DUPX_S_R_ITEM::TYPE_PATH, 10); - - // URLS - // url from _POST - $old_urls_list = array($this->post['url_old']); - $post_url_new = $this->post['url_new']; - $at_new_domain = '@'.DUPX_U::getDomain($post_url_new); - - try { - $confTransformer = $this->getWpConfigTransformer(); - - // urls from wp-config - if (!is_null($confTransformer)) { - if ($confTransformer->exists('constant', 'WP_HOME')) { - $old_urls_list[] = $confTransformer->get_value('constant', 'WP_HOME'); - } - - if ($confTransformer->exists('constant', 'WP_SITEURL')) { - $old_urls_list[] = $confTransformer->get_value('constant', 'WP_SITEURL'); - } - } - - // urls from db - $dbUrls = mysqli_query($this->dbh, 'SELECT * FROM `'.mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix).'options` where option_name IN (\'siteurl\',\'home\')'); - if ($dbUrls instanceof mysqli_result) { - while ($row = $dbUrls->fetch_object()) { - $old_urls_list[] = $row->option_value; - } - } else { - DUPX_Log::info('DB ERROR: '.mysqli_error($this->dbh)); - } - } catch (Exception $e) { - DUPX_Log::info('CONTINUE EXCEPTION: '.$e->getMessage()); - DUPX_Log::info('TRACE:'); - DUPX_Log::info($e->getTraceAsString()); - } - - foreach (array_unique($old_urls_list) as $old_url) { - $s_r_manager->addItem($old_url, $post_url_new, DUPX_S_R_ITEM::TYPE_URL_NORMALIZE_DOMAIN, 10); - - // Replace email address (xyz@oldomain.com to xyz@newdomain.com). - if ($this->post['replaceMail']) { - $at_old_domain = '@'.DUPX_U::getDomain($old_url); - $s_r_manager->addItem($at_old_domain, $at_new_domain, DUPX_S_R_ITEM::TYPE_STRING, 20); - } - } - } - - public function runSearchAndReplace() - { - self::logSectionHeader('RUN SEARCH AND REPLACE', __FUNCTION__, __LINE__); - - // make sure post data is initialized - $this->getPost(); - - DUPX_UpdateEngine::load($this->post['tables']); - DUPX_UpdateEngine::logStats(); - DUPX_UpdateEngine::logErrors(); - } - - public function removeLicenseKey() - { - self::logSectionHeader('REMOVE LICENSE KEY', __FUNCTION__, __LINE__); - // make sure dbConnection is initialized - $this->dbConnection(); - - if (isset($GLOBALS['DUPX_AC']->brand) && isset($GLOBALS['DUPX_AC']->brand->enabled) && $GLOBALS['DUPX_AC']->brand->enabled) { - $license_check = mysqli_query($this->dbh, - "SELECT COUNT(1) AS count FROM `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` WHERE `option_name` LIKE 'duplicator_pro_license_key' "); - $license_row = mysqli_fetch_row($license_check); - $license_count = is_null($license_row) ? 0 : $license_row[0]; - if ($license_count > 0) { - mysqli_query($this->dbh, - "UPDATE `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` SET `option_value` = '' WHERE `option_name` LIKE 'duplicator_pro_license_key'"); - } - } - } - - public function createNewAdminUser() - { - self::logSectionHeader('CREATE NEW ADMIN USER', __FUNCTION__, __LINE__); - // make sure dbConnection is initialized - $this->dbConnection(); - - $nManager = DUPX_NOTICE_MANAGER::getInstance(); - - if (strlen($this->post['wp_username']) >= 4 && strlen($this->post['wp_password']) >= 6) { - $wp_username = mysqli_real_escape_string($this->dbh, $this->post['wp_username']); - $newuser_check = mysqli_query($this->dbh, - "SELECT COUNT(*) AS count FROM `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."users` WHERE user_login = '{$wp_username}' "); - $newuser_row = mysqli_fetch_row($newuser_check); - $newuser_count = is_null($newuser_row) ? 0 : $newuser_row[0]; - - if ($newuser_count == 0) { - - $newuser_datetime = @date("Y-m-d H:i:s"); - $newuser_datetime = mysqli_real_escape_string($this->dbh, $newuser_datetime); - $newuser_security = mysqli_real_escape_string($this->dbh, 'a:1:{s:13:"administrator";b:1;}'); - - $post_wp_username = $this->post['wp_username']; - $post_wp_password = $this->post['wp_password']; - - $post_wp_mail = $this->post['wp_mail']; - $post_wp_nickname = $this->post['wp_nickname']; - if (empty($post_wp_nickname)) { - $post_wp_nickname = $post_wp_username; - } - $post_wp_first_name = $this->post['wp_first_name']; - $post_wp_last_name = $this->post['wp_last_name']; - - $wp_username = mysqli_real_escape_string($this->dbh, $post_wp_username); - $wp_password = mysqli_real_escape_string($this->dbh, $post_wp_password); - $wp_mail = mysqli_real_escape_string($this->dbh, $post_wp_mail); - $wp_nickname = mysqli_real_escape_string($this->dbh, $post_wp_nickname); - $wp_first_name = mysqli_real_escape_string($this->dbh, $post_wp_first_name); - $wp_last_name = mysqli_real_escape_string($this->dbh, $post_wp_last_name); - - $newuser1 = @mysqli_query($this->dbh, - "INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."users` - (`user_login`, `user_pass`, `user_nicename`, `user_email`, `user_registered`, `user_activation_key`, `user_status`, `display_name`) - VALUES ('{$wp_username}', MD5('{$wp_password}'), '{$wp_username}', '{$wp_mail}', '{$newuser_datetime}', '', '0', '{$wp_username}')"); - - $newuser1_insert_id = intval(mysqli_insert_id($this->dbh)); - - $newuser2 = @mysqli_query($this->dbh, - "INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` - (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', '".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."capabilities', '{$newuser_security}')"); - - $newuser3 = @mysqli_query($this->dbh, - "INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` - (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', '".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."user_level', '10')"); - - //Misc Meta-Data Settings: - @mysqli_query($this->dbh, - "INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'rich_editing', 'true')"); - @mysqli_query($this->dbh, - "INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'admin_color', 'fresh')"); - @mysqli_query($this->dbh, - "INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'nickname', '{$wp_nickname}')"); - @mysqli_query($this->dbh, - "INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'first_name', '{$wp_first_name}')"); - @mysqli_query($this->dbh, - "INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'last_name', '{$wp_last_name}')"); - - DUPX_Log::info("\nNEW WP-ADMIN USER:"); - if ($newuser1 && $newuser2 && $newuser3) { - DUPX_Log::info("- New username '{$this->post['wp_username']}' was created successfully allong with MU usermeta."); - } elseif ($newuser1) { - DUPX_Log::info("- New username '{$this->post['wp_username']}' was created successfully."); - } else { - $newuser_warnmsg = "- Failed to create the user '{$this->post['wp_username']}' \n "; - $this->report['warnlist'][] = $newuser_warnmsg; - - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'New admin user create error', - 'level' => DUPX_NOTICE_ITEM::HARD_WARNING, - 'longMsg' => $newuser_warnmsg, - 'sections' => 'general' - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE, 'new-user-create-error'); - - DUPX_Log::info($newuser_warnmsg); - } - } else { - $newuser_warnmsg = "\nNEW WP-ADMIN USER:\n - Username '{$this->post['wp_username']}' already exists in the database. Unable to create new account.\n"; - $this->report['warnlist'][] = $newuser_warnmsg; - - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'New admin user create error', - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => $newuser_warnmsg, - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_PRE, - 'sections' => 'general' - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE, 'new-user-create-error'); - - DUPX_Log::info($newuser_warnmsg); - } - } - } - - public function configurationFileUpdate() - { - self::logSectionHeader('CONFIGURATION FILE UPDATES', __FUNCTION__, __LINE__); - DUPX_Log::incIndent(); - // make sure post data is initialized - $this->getPost(); - $strReplaced = 0; - - $nManager = DUPX_NOTICE_MANAGER::getInstance(); - try { - if (file_exists(DUPX_Package::getWpconfigArkPath())) { - $confTransformer = $this->getWpConfigTransformer(); - - $mu_newDomain = parse_url($this->getPost('url_new')); - $mu_oldDomain = parse_url($this->getPost('url_old')); - $mu_newDomainHost = $mu_newDomain['host']; - $mu_oldDomainHost = $mu_oldDomain['host']; - $mu_newUrlPath = parse_url($this->getPost('url_new'), PHP_URL_PATH); - $mu_oldUrlPath = parse_url($this->getPost('url_old'), PHP_URL_PATH); - - if (empty($mu_newUrlPath) || ($mu_newUrlPath == '/')) { - $mu_newUrlPath = '/'; - } else { - $mu_newUrlPath = rtrim($mu_newUrlPath, '/').'/'; - } - - if (empty($mu_oldUrlPath) || ($mu_oldUrlPath == '/')) { - $mu_oldUrlPath = '/'; - } else { - $mu_oldUrlPath = rtrim($mu_oldUrlPath, '/').'/'; - } - - if ($confTransformer->exists('constant', 'WP_HOME')) { - $confTransformer->update('constant', 'WP_HOME', $this->post['url_new'], array('normalize' => true, 'add' => false)); - DUPX_Log::info('UPDATE WP_HOME '.DUPX_Log::varToString($this->post['url_new'])); - } - if ($confTransformer->exists('constant', 'WP_SITEURL')) { - $confTransformer->update('constant', 'WP_SITEURL', $this->post['url_new'], array('normalize' => true, 'add' => false)); - DUPX_Log::info('UPDATE WP_SITEURL '.DUPX_Log::varToString($this->post['url_new'])); - } - if ($confTransformer->exists('constant', 'DOMAIN_CURRENT_SITE')) { - $confTransformer->update('constant', 'DOMAIN_CURRENT_SITE', $mu_newDomainHost, array('normalize' => true, 'add' => false)); - DUPX_Log::info('UPDATE DOMAIN_CURRENT_SITE '.DUPX_Log::varToString($mu_newDomainHost)); - } - if ($confTransformer->exists('constant', 'PATH_CURRENT_SITE')) { - $confTransformer->update('constant', 'PATH_CURRENT_SITE', $mu_newUrlPath, array('normalize' => true, 'add' => false)); - DUPX_Log::info('UPDATE PATH_CURRENT_SITE '.DUPX_Log::varToString($mu_newUrlPath)); - } - - /** - * clean multisite settings for security reasons. - */ - if ($confTransformer->exists('constant', 'WP_ALLOW_MULTISITE')) { - $confTransformer->remove('constant', 'WP_ALLOW_MULTISITE'); - DUPX_Log::info('REMOVED WP_ALLOW_MULTISITE'); - } - if ($confTransformer->exists('constant', 'ALLOW_MULTISITE')) { - $confTransformer->update('constant', 'ALLOW_MULTISITE', 'false', array('add' => false, 'raw' => true, 'normalize' => true)); - DUPX_Log::info('TRANSFORMER: ALLOW_MULTISITE constant value set to false in WP config file'); - } - if ($confTransformer->exists('constant', 'MULTISITE')) { - $confTransformer->update('constant', 'MULTISITE', 'false', array('add' => false, 'raw' => true, 'normalize' => true)); - DUPX_Log::info('TRANSFORMER: MULTISITE constant value set to false in WP config file'); - } - if ($confTransformer->exists('constant', 'NOBLOGREDIRECT')) { - $confTransformer->update('constant', 'NOBLOGREDIRECT', 'false', array('add' => false, 'raw' => true, 'normalize' => true)); - DUPX_Log::info('TRANSFORMER: NOBLOGREDIRECT constant value set to false in WP config file'); - } - if ($confTransformer->exists('constant', 'SUBDOMAIN_INSTALL')) { - $confTransformer->remove('constant', 'SUBDOMAIN_INSTALL'); - DUPX_Log::info('TRANSFORMER: SUBDOMAIN_INSTALL constant removed from WP config file'); - } - if ($confTransformer->exists('constant', 'VHOST')) { - $confTransformer->remove('constant', 'VHOST'); - DUPX_Log::info('TRANSFORMER: VHOST constant removed from WP config file'); - } - if ($confTransformer->exists('constant', 'SUNRISE')) { - $confTransformer->remove('constant', 'SUNRISE'); - DUPX_Log::info('TRANSFORMER: SUNRISE constant removed from WP config file'); - } - - - $dbname = DUPX_U::getEscapedGenericString($this->post['dbname']); - $dbuser = DUPX_U::getEscapedGenericString($this->post['dbuser']); - $dbpass = DUPX_U::getEscapedGenericString($this->post['dbpass']); - $dbhost = DUPX_U::getEscapedGenericString($this->post['dbhost']); - - $confTransformer->update('constant', 'DB_NAME', $dbname, array('raw' => true)); - DUPX_Log::info('UPDATE DB_NAME '. DUPX_Log::varToString('** OBSCURED **')); - - $confTransformer->update('constant', 'DB_USER', $dbuser, array('raw' => true)); - DUPX_Log::info('UPDATE DB_USER '. DUPX_Log::varToString('** OBSCURED **')); - - $confTransformer->update('constant', 'DB_PASSWORD', $dbpass, array('raw' => true)); - DUPX_Log::info('UPDATE DB_PASSWORD '.DUPX_Log::varToString('** OBSCURED **')); - - $confTransformer->update('constant', 'DB_HOST', $dbhost, array('raw' => true)); - DUPX_Log::info('UPDATE DB_HOST '.DUPX_Log::varToString($dbhost)); - - //SSL CHECKS - if ($this->post['ssl_admin']) { - $confTransformer->update('constant', 'FORCE_SSL_ADMIN', 'true', array('raw' => true, 'normalize' => true)); - DUPX_Log::info('UPDATE FORCE_SSL_ADMIN '.DUPX_Log::varToString(true)); - } else { - if ($confTransformer->exists('constant', 'FORCE_SSL_ADMIN')) { - $confTransformer->update('constant', 'FORCE_SSL_ADMIN', 'false', array('raw' => true, 'add' => false, 'normalize' => true)); - DUPX_Log::info('UPDATE FORCE_SSL_ADMIN '.DUPX_Log::varToString(false)); - } - } - - // COOKIE_DOMAIN - if ($confTransformer->exists('constant', 'COOKIE_DOMAIN')) { - $const_val = $confTransformer->get_value('constant', 'COOKIE_DOMAIN'); - $const_new_val = str_replace($mu_oldDomainHost, $mu_newDomainHost, $const_val, $strReplaced); - if ($strReplaced > 0) { - $confTransformer->update('constant', 'COOKIE_DOMAIN', $const_new_val, array('normalize' => true)); - } - } - - if ($this->post['cache_wp']) { - $confTransformer->update('constant', 'WP_CACHE', 'true', array('raw' => true, 'normalize' => true)); - DUPX_Log::info('UPDATE WP_CACHE '.DUPX_Log::varToString(true)); - } else { - if ($confTransformer->exists('constant', 'WP_CACHE')) { - $confTransformer->update('constant', 'WP_CACHE', 'false', array('raw' => true, 'add' => false, 'normalize' => true)); - DUPX_Log::info('UPDATE WP_CACHE '.DUPX_Log::varToString(false)); - } - } - - // Cache: [ ] Keep Home Path - if ($this->post['cache_path']) { - if ($confTransformer->exists('constant', 'WPCACHEHOME')) { - $wpcachehome_const_val = $confTransformer->get_value('constant', 'WPCACHEHOME'); - $wpcachehome_const_val = DUPX_U::wp_normalize_path($wpcachehome_const_val); - $wpcachehome_new_const_val = str_replace($this->post['path_old'], $this->post['path_new'], $wpcachehome_const_val, $strReplaced); - if ($strReplaced > 0) { - $confTransformer->update('constant', 'WPCACHEHOME', $wpcachehome_new_const_val, array('normalize' => true)); - DUPX_Log::info('UPDATE WPCACHEHOME '.DUPX_Log::varToString($wpcachehome_new_const_val)); - } - } - } else { - $confTransformer->remove('constant', 'WPCACHEHOME'); - DUPX_Log::info('REMOVE WPCACHEHOME'); - } - - if ($GLOBALS['DUPX_AC']->is_outer_root_wp_content_dir) { - if (empty($GLOBALS['DUPX_AC']->wp_content_dir_base_name)) { - $ret = $confTransformer->remove('constant', 'WP_CONTENT_DIR'); - DUPX_Log::info('REMOVE WP_CONTENT_DIR'); - // sometimes WP_CONTENT_DIR const removal failed, so we need to update them - if (false === $ret) { - $wpContentDir = "dirname(__FILE__).'/wp-content'"; - $confTransformer->update('constant', 'WP_CONTENT_DIR', $wpContentDir, array('raw' => true, 'normalize' => true)); - DUPX_Log::info('UPDATE WP_CONTENT_DIR '.DUPX_Log::varToString($wpContentDir)); - } - } else { - $wpContentDir = "dirname(__FILE__).'/".$GLOBALS['DUPX_AC']->wp_content_dir_base_name."'"; - $confTransformer->update('constant', 'WP_CONTENT_DIR', $wpContentDir, array('raw' => true, 'normalize' => true)); - DUPX_Log::info('UPDATE WP_CONTENT_DIR '.DUPX_Log::varToString($wpContentDir)); - } - } elseif ($confTransformer->exists('constant', 'WP_CONTENT_DIR')) { - $wp_content_dir_const_val = $confTransformer->get_value('constant', 'WP_CONTENT_DIR'); - $wp_content_dir_const_val = DUPX_U::wp_normalize_path($wp_content_dir_const_val); - $new_path = str_replace($this->post['path_old'], $this->post['path_new'], $wp_content_dir_const_val, $strReplaced); - if ($strReplaced > 0) { - $confTransformer->update('constant', 'WP_CONTENT_DIR', $new_path, array('normalize' => true)); - DUPX_Log::info('UPDATE WP_CONTENT_DIR '.DUPX_Log::varToString($new_path)); - } - } - - //WP_CONTENT_URL - // '/' added to prevent word boundary with domains that have the same root path - if ($GLOBALS['DUPX_AC']->is_outer_root_wp_content_dir) { - if (empty($GLOBALS['DUPX_AC']->wp_content_dir_base_name)) { - $ret = $confTransformer->remove('constant', 'WP_CONTENT_URL'); - DUPX_Log::info('REMOVE WP_CONTENT_URL'); - // sometimes WP_CONTENT_DIR const removal failed, so we need to update them - if (false === $ret) { - $new_url = $this->post['url_new'].'/wp-content'; - $confTransformer->update('constant', 'WP_CONTENT_URL', $new_url, array('raw' => true, 'normalize' => true)); - DUPX_Log::info('UPDATE WP_CONTENT_URL '.DUPX_Log::varToString($new_url)); - } - } else { - $new_url = $this->post['url_new'].'/'.$GLOBALS['DUPX_AC']->wp_content_dir_base_name; - $confTransformer->update('constant', 'WP_CONTENT_URL', $new_url, array('normalize' => true)); - DUPX_Log::info('UPDATE WP_CONTENT_URL '.DUPX_Log::varToString($new_url)); - } - } elseif ($confTransformer->exists('constant', 'WP_CONTENT_URL')) { - $wp_content_url_const_val = $confTransformer->get_value('constant', 'WP_CONTENT_URL'); - $new_path = str_replace($this->post['url_old'].'/', $this->post['url_new'].'/', $wp_content_url_const_val, $strReplaced); - if ($strReplaced > 0) { - $confTransformer->update('constant', 'WP_CONTENT_URL', $new_path, array('normalize' => true)); - DUPX_Log::info('UPDATE WP_CONTENT_URL '.DUPX_Log::varToString($new_path)); - } - } - - //WP_TEMP_DIR - if ($confTransformer->exists('constant', 'WP_TEMP_DIR')) { - $wp_temp_dir_const_val = $confTransformer->get_value('constant', 'WP_TEMP_DIR'); - $wp_temp_dir_const_val = DUPX_U::wp_normalize_path($wp_temp_dir_const_val); - $new_path = str_replace($this->post['path_old'], $this->post['path_new'], $wp_temp_dir_const_val, $strReplaced); - if ($strReplaced > 0) { - $confTransformer->update('constant', 'WP_TEMP_DIR', $new_path, array('normalize' => true)); - DUPX_Log::info('UPDATE WP_TEMP_DIR '.DUPX_Log::varToString($new_path)); - } - } - - // WP_PLUGIN_DIR - if ($confTransformer->exists('constant', 'WP_PLUGIN_DIR')) { - $wp_plugin_dir_const_val = $confTransformer->get_value('constant', 'WP_PLUGIN_DIR'); - $wp_plugin_dir_const_val = DUPX_U::wp_normalize_path($wp_plugin_dir_const_val); - $new_path = str_replace($this->post['path_old'], $this->post['path_new'], $wp_plugin_dir_const_val, $strReplaced); - if ($strReplaced > 0) { - $confTransformer->update('constant', 'WP_PLUGIN_DIR', $new_path, array('normalize' => true)); - DUPX_Log::info('UPDATE WP_PLUGIN_DIR '.DUPX_Log::varToString($new_path)); - } - } - - // WP_PLUGIN_URL - if ($confTransformer->exists('constant', 'WP_PLUGIN_URL')) { - $wp_plugin_url_const_val = $confTransformer->get_value('constant', 'WP_PLUGIN_URL'); - $new_path = str_replace($this->post['url_old'].'/', $this->post['url_new'].'/', $wp_plugin_url_const_val, $strReplaced); - if ($strReplaced > 0) { - $confTransformer->update('constant', 'WP_PLUGIN_URL', $new_path, array('normalize' => true)); - DUPX_Log::info('UPDATE WP_PLUGIN_URL '.DUPX_Log::varToString($new_path)); - } - } - - // WPMU_PLUGIN_DIR - if ($confTransformer->exists('constant', 'WPMU_PLUGIN_DIR')) { - $wpmu_plugin_dir_const_val = $confTransformer->get_value('constant', 'WPMU_PLUGIN_DIR'); - $wpmu_plugin_dir_const_val = DUPX_U::wp_normalize_path($wpmu_plugin_dir_const_val); - $new_path = str_replace($this->post['path_old'], $this->post['path_new'], $wpmu_plugin_dir_const_val, $strReplaced); - if ($strReplaced > 0) { - $confTransformer->update('constant', 'WPMU_PLUGIN_DIR', $new_path, array('normalize' => true)); - DUPX_Log::info('UPDATE WPMU_PLUGIN_DIR '.DUPX_Log::varToString($new_path)); - } - } - - // WPMU_PLUGIN_URL - if ($confTransformer->exists('constant', 'WPMU_PLUGIN_URL')) { - $wpmu_plugin_url_const_val = $confTransformer->get_value('constant', 'WPMU_PLUGIN_URL'); - $new_path = str_replace($this->post['url_old'].'/', $this->post['url_new'].'/', $wpmu_plugin_url_const_val, $strReplaced); - if ($strReplaced > 0) { - $confTransformer->update('constant', 'WPMU_PLUGIN_URL', $new_path, array('normalize' => true)); - DUPX_Log::info('UPDATE WPMU_PLUGIN_URL '.DUPX_Log::varToString($new_path)); - } - } - DUPX_Log::info("\n*** UPDATED WP CONFIG FILE ***"); - } else { - DUPX_Log::info("WP-CONFIG ARK FILE NOT FOUND"); - DUPX_Log::info("WP-CONFIG ARK FILE:\n - 'dup-wp-config-arc__[HASH].txt'"); - DUPX_Log::info("SKIP FILE UPDATES\n"); - - $shortMsg = 'wp-config.php not found'; - $longMsg = << -The installation is finished but check the wp-config.php file and manually update the incorrect values. -LONGMSG; - /* $nManager->addNextStepNotice(array( - 'shortMsg' => $shortMsg, - 'level' => DUPX_NOTICE_ITEM::CRITICAL, - - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE , 'wp-config-transformer-exception'); */ - $nManager->addFinalReportNotice(array( - 'shortMsg' => $shortMsg, - 'level' => DUPX_NOTICE_ITEM::HARD_WARNING, - 'longMsg' => $longMsg, - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, - 'sections' => 'general' - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'wp-config-transformer-exception'); - } - } catch (Exception $e) { - $shortMsg = 'wp-config.php transformer:'.$e->getMessage(); - $longMsg = << -The installation is finished but check the wp-config.php file and manually update the incorrect values. -LONGMSG; - /* $nManager->addNextStepNotice(array( - 'shortMsg' => $shortMsg, - 'level' => DUPX_NOTICE_ITEM::CRITICAL, - - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE , 'wp-config-transformer-exception'); */ - $nManager->addFinalReportNotice(array( - 'shortMsg' => $shortMsg, - 'level' => DUPX_NOTICE_ITEM::CRITICAL, - 'longMsg' => $longMsg, - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, - 'sections' => 'general' - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'wp-config-transformer-exception'); - - DUPX_Log::info("WP-CONFIG TRANSFORMER EXCEPTION\n".$e->getTraceAsString()); - } - DUPX_Log::resetIndent(); - } - - public function htaccessUpdate() - { - $this->getPost(); - self::logSectionHeader('HTACCESS UPDATE MODE: '.DUPX_LOG::varToString($this->post['config_mode']), __FUNCTION__, __LINE__); - - - switch ($this->post['config_mode']) { - case 'NEW': - DUPX_ServerConfig::createNewConfigs(); - break; - case 'RESTORE': - DUPX_ServerConfig::renameOrigConfigs(); - DUPX_Log::info("\nWARNING: Retaining the original .htaccess or web.config files may cause"); - DUPX_Log::info("issues with the initial setup of your site. If you run into issues with the install"); - DUPX_Log::info("process choose 'Create New' for the 'Config Files' options"); - break; - case 'IGNORE': - DUPX_Log::info("\nWARNING: Choosing the option to ignore the .htaccess, web.config and .user.ini files"); - DUPX_Log::info("can lead to install issues. The 'Ignore All' option is designed for advanced users."); - break; - } - } - - public function generalUpdateAndCleanup() - { - self::logSectionHeader('GENERAL UPDATES & CLEANUP', __FUNCTION__, __LINE__); - // make sure dbConnection is initialized - $this->dbConnection(); - $this->deactivateIncompatiblePlugins(); - $blog_name = mysqli_real_escape_string($this->dbh, $this->post['blogname']); - - /** FINAL UPDATES: Must happen after the global replace to prevent double pathing - http://xyz.com/abc01 will become http://xyz.com/abc0101 with trailing data */ - mysqli_query($this->dbh, - "UPDATE `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` SET option_value = '".mysqli_real_escape_string($this->dbh, $blog_name)."' WHERE option_name = 'blogname' "); - mysqli_query($this->dbh, - "UPDATE `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` SET option_value = '".mysqli_real_escape_string($this->dbh, $this->post['url_new'])."' WHERE option_name = 'home' "); - mysqli_query($this->dbh, - "UPDATE `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` SET option_value = '".mysqli_real_escape_string($this->dbh, $this->post['siteurl'])."' WHERE option_name = 'siteurl' "); - mysqli_query($this->dbh, - "REPLACE INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` (option_value, option_name) VALUES('".mysqli_real_escape_string($this->dbh, - $this->post['exe_safe_mode'])."','duplicator_exe_safe_mode')"); - //Reset the postguid data - if ($this->post['postguid']) { - mysqli_query($this->dbh, - "UPDATE `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."posts` SET guid = REPLACE(guid, '".mysqli_real_escape_string($this->dbh, $this->post['url_new'])."', '".mysqli_real_escape_string($this->dbh, - $this->post['url_old'])."')"); - $update_guid = @mysqli_affected_rows($this->dbh) or 0; - DUPX_Log::info("Reverted '{$update_guid}' post guid columns back to '{$this->post['url_old']}'"); - } - - DUPX_U::maintenanceMode(false); - } - - /** - * Deactivate incompatible plugins - * - * @return void - */ - private function deactivateIncompatiblePlugins() { - self::logSectionHeader("DEACTIVATE PLUGINS CHECK", __FUNCTION__, __LINE__); - // make sure post data is initialized - $this->getPost(); - $nManager = DUPX_NOTICE_MANAGER::getInstance(); - $plugin_list = array(); - $auto_deactivate_plugins = $this->getAutoDeactivatePlugins(); - $deactivated_plugins = array(); - $reactivate_plugins_after_installation = array(); - foreach ($this->post['plugins'] as $plugin_slug) { - if (isset($auto_deactivate_plugins[$plugin_slug])) { - DUPX_Log::info("deactivate ".$plugin_slug); - $deactivated_plugins[] = $plugin_slug; - $nManager->addFinalReportNotice(array( - 'shortMsg' => $auto_deactivate_plugins[$plugin_slug]['shortMsg'], - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => $auto_deactivate_plugins[$plugin_slug]['longMsg'], - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, - 'sections' => 'general' - )); - if ($auto_deactivate_plugins[$plugin_slug]['reactivate']) { - $reactivate_plugins_after_installation[$plugin_slug] = $auto_deactivate_plugins[$plugin_slug]['title']; - } - } else { - $plugin_list[] = $plugin_slug; - } - } - - if (!empty($deactivated_plugins)) { - DUPX_Log::info('Plugin(s) listed here are deactivated: '. implode(', ', $deactivated_plugins)); - } - - if (!empty($reactivate_plugins_after_installation)) { - DUPX_Log::info('Plugin(s) reactivated after installation: '. implode(', ', $deactivated_plugins)); - $reactivate_plugins_after_installation_str = serialize($reactivate_plugins_after_installation); - mysqli_query($this->dbh, "INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` (option_value, option_name) VALUES('".mysqli_real_escape_string($this->dbh, - $reactivate_plugins_after_installation_str)."','duplicator_reactivate_plugins_after_installation')"); - } - - // Force Duplicator active so the security cleanup will be available - if (!in_array('duplicator/duplicator.php', $plugin_list)) { - $plugin_list[] = 'duplicator/duplicator.php'; - } - $serial_plugin_list = @serialize($plugin_list); - - mysqli_query($this->dbh, - "UPDATE `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` " - . "SET option_value = '".mysqli_real_escape_string($this->dbh, $serial_plugin_list)."' WHERE option_name = 'active_plugins' "); - } - - /** - * Get Automatic deactivation plugins lists - * - * @return array key as plugin slug and val as plugin title - */ - private function getAutoDeactivatePlugins() { - $excludePlugins = array(); - - if (!DUPX_U::is_ssl()) { - DUPX_Log::info('Really Simple SSL [as Non-SSL installation] will be Deactivated, If It is activated', DUPX_Log::LV_HARD_DEBUG); - $excludePlugins['really-simple-ssl/rlrsssl-really-simple-ssl.php'] = array( - 'title' => "Really Simple SSL", - 'shortMsg' => "Deactivated Plugin: Really Simple SSL", - 'longMsg' => "This plugin has been deactivated since this migration is going from SSL (HTTPS) to Non-SSL (HTTP). This will allow you to login to your WordPress Admin. " - . " To reactivate the plugin please go to the admin plugin page.", - 'reactivate' => false - - ); - } - - if ($GLOBALS['DUPX_AC']->url_old != $this->post['siteurl']) { - DUPX_Log::info('Simple Google reCAPTCHA [as Package creation site URL and installation site URL are different] will be deactivated, If It is activated', DUPX_Log::LV_HARD_DEBUG); - $excludePlugins['simple-google-recaptcha/simple-google-recaptcha.php'] = array( - 'title' => "Simple Google reCAPTCHA", - 'shortMsg' => "Deactivated Plugin: Simple Google reCAPTCHA", - 'longMsg' => "It is deactivated because the Google Recaptcha required reCaptcha site key which is bound to the site's address. Your package site's address and installed site's address doesn't match. You can reactivate it from the installed site login panel after completion of the installation.
        - Please do not forget to change the reCaptcha site key after activating it.", - 'reactivate' => false - ); - } - - DUPX_Log::info('WPBakery Page Builder will be Deactivated, If It is activated', DUPX_Log::LV_HARD_DEBUG); - $excludePlugins['js_composer/js_composer.php'] = array( - 'title' => 'WPBakery Page Builder', - 'shortMsg' => "Deactivated Plugin: WPBakery Page Builder", - 'longMsg' => "This plugin is deactivated automatically, because it requires a reacivation to work properly. " - . "Please reactivate from the WordPress admin panel after logging in. This will re-enable your site's frontend.", - 'reactivate' => true - ); - - DUPX_Log::info('Auto Deactivated plugins list here: '.DUPX_Log::varToString(array_keys($excludePlugins))); - return $excludePlugins; - } - - public function noticeTest() - { - self::logSectionHeader('NOTICES TEST', __FUNCTION__, __LINE__); - // make sure dbConnection is initialized - $this->dbConnection(); - - $nManager = DUPX_NOTICE_MANAGER::getInstance(); - if (file_exists(DUPX_Package::getWpconfigArkPath())) { - $wpconfig_ark_contents = file_get_contents(DUPX_Package::getWpconfigArkPath()); - $config_vars = array('WPCACHEHOME', 'COOKIE_DOMAIN', 'WP_SITEURL', 'WP_HOME', 'WP_TEMP_DIR'); - $config_found = DUPX_U::getListValues($config_vars, $wpconfig_ark_contents); - - //Files - if (!empty($config_found)) { - $msg = "WP-CONFIG NOTICE: The wp-config.php has following values set [".implode(", ", $config_found)."]. \n"; - $msg .= "Please validate these values are correct by opening the file and checking the values.\n"; - $msg .= "See the codex link for more details: https://codex.wordpress.org/Editing_wp-config.php"; - // old system - $this->report['warnlist'][] = $msg; - DUPX_Log::info($msg); - - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'wp-config notice', - 'level' => DUPX_NOTICE_ITEM::NOTICE, - 'longMsg' => $msg, - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_PRE, - 'sections' => 'general' - )); - } - - //-- Finally, back up the old wp-config and rename the new one - $wpconfig_path = "{$GLOBALS['DUPX_ROOT']}/wp-config.php"; - if (DUPX_Package::getWpconfigArkPath() !== $wpconfig_path) { - if (copy(DUPX_Package::getWpconfigArkPath(), $wpconfig_path) === false) { - DUPX_LOG::info( - 'COPY SOURCE: '.DUPX_LOG::varToString(DUPX_Package::getWpconfigArkPath())."\n". - "COPY DEST:".DUPX_LOG::varToString($wpconfig_path), DUPX_Log::LV_DEBUG); - DUPX_Log::error("ERROR: Unable to copy 'dup-wp-config-arc__[HASH].txt' to 'wp-config.php'.\n". - "Check server permissions for more details see FAQ: https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-055-q"); - } - } - } else { - $msg = "WP-CONFIG NOTICE: wp-config.php not found.

        "; - $msg .= "No action on the wp-config was possible.
        "; - $msg .= "Be sure to insert a properly modified wp-config for correct wordpress operation."; - $this->report['warnlist'][] = $msg; - - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'wp-config not found', - 'level' => DUPX_NOTICE_ITEM::HARD_WARNING, - 'longMsg' => $msg, - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, - 'sections' => 'general' - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE, 'wp-config-not-found'); - - DUPX_Log::info($msg); - } - - //Database - $result = @mysqli_query($this->dbh, - "SELECT option_value FROM `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` WHERE option_name IN ('upload_url_path','upload_path')"); - if ($result) { - while ($row = mysqli_fetch_row($result)) { - if (strlen($row[0])) { - $msg = "MEDIA SETTINGS NOTICE: The table '".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options' has at least one the following values ['upload_url_path','upload_path'] \n"; - $msg .= "set please validate settings. These settings can be changed in the wp-admin by going to /wp-admin/options.php'"; - - $this->report['warnlist'][] = $msg; - DUPX_Log::info($msg); - - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'Media settings notice', - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => $msg, - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_PRE, - 'sections' => 'general' - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE, 'media-settings-notice'); - - break; - } - } - } - - if (empty($this->report['warnlist'])) { - DUPX_Log::info("No General Notices Found\n"); - } - } - - public function cleanupTmpFiles() - { - self::logSectionHeader('CLEANUP TMP FILES', __FUNCTION__, __LINE__); - // make sure post data is initialized - $this->getPost(); - - //Cleanup any tmp files a developer may have forgotten about - //Lets be proactive for the developer just in case - $wpconfig_path_bak = "{$GLOBALS['DUPX_ROOT']}/wp-config.bak"; - $wpconfig_path_old = "{$GLOBALS['DUPX_ROOT']}/wp-config.old"; - $wpconfig_path_org = "{$GLOBALS['DUPX_ROOT']}/wp-config.org"; - $wpconfig_path_orig = "{$GLOBALS['DUPX_ROOT']}/wp-config.orig"; - $wpconfig_safe_check = array($wpconfig_path_bak, $wpconfig_path_old, $wpconfig_path_org, $wpconfig_path_orig); - foreach ($wpconfig_safe_check as $file) { - if (file_exists($file)) { - $tmp_newfile = $file.uniqid('_'); - if (rename($file, $tmp_newfile) === false) { - DUPX_Log::info("WARNING: Unable to rename '{$file}' to '{$tmp_newfile}'"); - } - } - } - } - - public function finalReportNotices() - { - self::logSectionHeader('FINAL REPORT NOTICES', __FUNCTION__, __LINE__); - - $this->wpConfigFinalReport(); - $this->htaccessFinalReport(); - } - - private function htaccessFinalReport() - { - $nManager = DUPX_NOTICE_MANAGER::getInstance(); - - $orig = file_get_contents(DUPX_Package::getOrigHtaccessPath()); - $new = file_get_contents($GLOBALS['DUPX_ROOT'].'/.htaccess'); - - $lightBoxContent = '
        '. - '
        Original .htaccess
        '.htmlspecialchars($orig).'
        '. - '
        New .htaccess
        '.htmlspecialchars($new).'
        '. - '
        '; - $longMsg = DUPX_U_Html::getLigthBox('.htaccess changes', 'HTACCESS COMPARE', $lightBoxContent, false); - - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'htaccess changes', - 'level' => DUPX_NOTICE_ITEM::INFO, - 'longMsg' => $longMsg, - 'sections' => 'changes', - 'open' => true, - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'htaccess-changes'); - } - - private function wpConfigFinalReport() - { - $nManager = DUPX_NOTICE_MANAGER::getInstance(); - - if (($orig = file_get_contents(DUPX_Package::getOrigWpConfigPath())) === false) { - $orig = 'Can read origin wp-config.php file'; - } else { - $orig = $this->obscureWpConfig($orig); - } - - if (($new = file_get_contents($GLOBALS['DUPX_ROOT'].'/wp-config.php')) === false) { - $new = 'Can read wp-config.php file'; - } else { - $new = $this->obscureWpConfig($new); - } - - $lightBoxContent = '
        '. - '
        Original wp-config.php
        '.htmlspecialchars($orig).'
        '. - '
        New wp-config.php
        '.htmlspecialchars($new).'
        '. - '
        '; - $longMsg = DUPX_U_Html::getLigthBox('wp-config.php changes', 'WP-CONFIG.PHP COMPARE', $lightBoxContent, false); - - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'wp-config.php changes', - 'level' => DUPX_NOTICE_ITEM::INFO, - 'longMsg' => $longMsg, - 'sections' => 'changes', - 'open' => true, - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'wp-config-changes'); - } - - private function obscureWpConfig($src) - { - $transformer = new DupLiteWPConfigTransformerSrc($src); - $obsKeys = array( - 'DB_NAME', - 'DB_USER', - 'DB_HOST', - 'DB_PASSWORD', - 'AUTH_KEY', - 'SECURE_AUTH_KEY', - 'LOGGED_IN_KEY', - 'NONCE_KEY', - 'AUTH_SALT', - 'SECURE_AUTH_SALT', - 'LOGGED_IN_SALT', - 'NONCE_SALT'); - - foreach ($obsKeys as $key) { - if ($transformer->exists('constant', $key)) { - $transformer->update('constant', $key, '**OBSCURED**'); - } - } - - return $transformer->getSrc(); - } - - public function complete() - { - // make sure post data is initialized - $this->getPost(); - $this->closeDbConnection(); - - $ajax3_sum = DUPX_U::elapsedTime(DUPX_U::getMicrotime(), $this->timeStart); - DUPX_Log::info("\nSTEP-3 COMPLETE @ ".@date('h:i:s')." - RUNTIME: {$ajax3_sum} \n\n"); - - $this->fullReport = true; - $this->report['pass'] = 1; - $this->report['chunk'] = 0; - $this->report['chunkPos'] = null; - $this->report['progress_perc'] = 100; - // error_reporting($ajax3_error_level); - } - - public function error($message) - { - // make sure post data is initialized - $this->getPost(); - - $this->closeDbConnection(); - - $ajax3_sum = DUPX_U::elapsedTime(DUPX_U::getMicrotime(), $this->timeStart); - DUPX_Log::info("\nSTEP-3 ERROR @ ".@date('h:i:s')." - RUNTIME: {$ajax3_sum} \n\n"); - - $this->report['pass'] = -1; - $this->report['chunk'] = 0; - $this->report['chunkPos'] = null; - $this->report['error_message'] = $message; - } - - protected function __clone() - { - - } - - public function __wakeup() - { - throw new Exception("Cannot unserialize singleton"); - } -} \ No newline at end of file diff --git a/installer/dup-installer/classes/class.view.php b/installer/dup-installer/classes/class.view.php deleted file mode 100644 index 97c82ef9..00000000 --- a/installer/dup-installer/classes/class.view.php +++ /dev/null @@ -1,92 +0,0 @@ -secure_on) { - self::helpLink('secure', ''); - } else { - self::helpLink('secure', ''); - } - } - - public static function helpIconLink($section) - { - self::helpLink($section, ''); - } - - /** - * Get badge class attr val from status - * - * @param string $status - * @return string html class attribute - */ - public static function getBadgeClassFromCheckStatus($status) - { - switch ($status) { - case 'Pass': - return 'status-badge-pass'; - case 'Fail': - return 'status-badge-fail'; - case 'Warn': - return 'status-badge-warn'; - default: - DUPX_Log::error(sprintf("The arcCheck var has the illegal value %s in switch case", DUPX_Log::varToString($status))); - } - } -} \ No newline at end of file diff --git a/installer/dup-installer/classes/config/class.boot.php b/installer/dup-installer/classes/config/class.boot.php deleted file mode 100644 index 89d90eee..00000000 --- a/installer/dup-installer/classes/config/class.boot.php +++ /dev/null @@ -1,318 +0,0 @@ -init(); - - // init ERR defines - DUPX_Constants::initErrDefines(); - // init error handler after constant - DUPX_Handler::initErrorHandler(); - - self::initArchive(); - - $pathInfo = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : ''; - DUPX_Log::info("\n\n" - ."==============================================\n" - ."= BOOT INIT OK [".$pathInfo."]\n" - ."==============================================\n", DUPX_Log::LV_DETAILED); - } - - /** - * init ini_set and default constants - * - * @throws Exception - */ - public static function phpIni() - { - /** Absolute path to the Installer directory. - necessary for php protection */ - if (!defined('KB_IN_BYTES')) { - define('KB_IN_BYTES', 1024); - } - if (!defined('MB_IN_BYTES')) { - define('MB_IN_BYTES', 1024 * KB_IN_BYTES); - } - if (!defined('GB_IN_BYTES')) { - define('GB_IN_BYTES', 1024 * MB_IN_BYTES); - } - if (!defined('DUPLICATOR_PHP_MAX_MEMORY')) { - 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); - - @set_time_limit(3600); - - $defaultCharset = ini_get("default_charset"); - if (empty($defaultCharset) && DupLiteSnapLibUtil::wp_is_ini_value_changeable('default_charset')) { - @ini_set("default_charset", 'utf-8'); - } - if (DupLiteSnapLibUtil::wp_is_ini_value_changeable('memory_limit')) { - @ini_set('memory_limit', DUPLICATOR_PHP_MAX_MEMORY); - } - if (DupLiteSnapLibUtil::wp_is_ini_value_changeable('max_input_time')) { - @ini_set('max_input_time', '-1'); - } - if (DupLiteSnapLibUtil::wp_is_ini_value_changeable('pcre.backtrack_limit')) { - @ini_set('pcre.backtrack_limit', PHP_INT_MAX); - } - - //PHP INI SETUP: all time in seconds - if (!isset($GLOBALS['DUPX_ENFORCE_PHP_INI']) || !$GLOBALS['DUPX_ENFORCE_PHP_INI']) { - if (DupLiteSnapLibUtil::wp_is_ini_value_changeable('mysql.connect_timeout')) { - @ini_set('mysql.connect_timeout', '5000'); - } - if (DupLiteSnapLibUtil::wp_is_ini_value_changeable('max_execution_time')) { - @ini_set("max_execution_time", '5000'); - } - if (DupLiteSnapLibUtil::wp_is_ini_value_changeable('max_input_time')) { - @ini_set("max_input_time", '5000'); - } - if (DupLiteSnapLibUtil::wp_is_ini_value_changeable('default_socket_timeout')) { - @ini_set('default_socket_timeout', '5000'); - } - @set_time_limit(0); - } - } - - /** - * include default utils files and constants - * - * @throws Exception - */ - public static function includes() - { - require_once($GLOBALS['DUPX_INIT'].'/lib/snaplib/snaplib.all.php'); - require_once($GLOBALS['DUPX_INIT'].'/classes/utilities/class.u.exceptions.php'); - require_once($GLOBALS['DUPX_INIT'].'/classes/utilities/class.u.php'); - require_once($GLOBALS['DUPX_INIT'].'/classes/utilities/class.u.notices.manager.php'); - require_once($GLOBALS['DUPX_INIT'].'/classes/utilities/class.u.html.php'); - require_once($GLOBALS['DUPX_INIT'].'/classes/config/class.constants.php'); - require_once($GLOBALS['DUPX_INIT'].'/classes/class.package.php'); - require_once($GLOBALS['DUPX_INIT'].'/ctrls/ctrl.base.php'); - require_once($GLOBALS['DUPX_INIT'].'/classes/config/class.archive.config.php'); - require_once($GLOBALS['DUPX_INIT'].'/classes/config/class.security.php'); - require_once($GLOBALS['DUPX_INIT'].'/classes/class.logging.php'); - require_once($GLOBALS['DUPX_INIT'].'/classes/host/class.custom.host.manager.php'); - } - - /** - * init archive config - * - * @throws Exception - */ - public static function initArchive() - { - $GLOBALS['DUPX_AC'] = DUPX_ArchiveConfig::getInstance(); - if (empty($GLOBALS['DUPX_AC'])) { - throw new Exception("Can't initialize config globals"); - } - } - - /** - * This function moves the error_log.php into the dup-installer directory. - * It is called before including any other file so it uses only native PHP functions. - * - * !!! Don't use any Duplicator function within this function. !!! - * - * @param bool $reset - * @return boolean - */ - public static function initPhpErrorLog($reset = false) - { - if (!function_exists('ini_set')) { - return false; - } - - $logFile = $GLOBALS['DUPX_INIT'].'/php_error__'.self::getPackageHash().'.log'; - - if (file_exists($logFile) && !is_writable($logFile)) { - if (!is_writable($logFile)) { - return false; - } else if ($reset && function_exists('unlink')) { - @unlink($logFile); - } - } - - if (function_exists('error_reporting')) { - error_reporting(E_ALL | E_STRICT); // E_STRICT for PHP 5.3 - } - - @ini_set("log_errors", 1); - if (@ini_set("error_log", $logFile) === false) { - return false; - } - - if (!file_exists($logFile)) { - error_log("PHP ERROR LOG INIT"); - } - - return true; - } - - /** - * It is called before including any other file so it uses only native PHP functions. - * - * !!! Don't use any Duplicator function within this function. !!! - * - * @staticvar bool|string $packageHash - * @return bool|string // package hash or false if fail - */ - public static function getPackageHash() - { - static $packageHash = null; - if (is_null($packageHash)) { - $searchStr = $GLOBALS['DUPX_INIT'].'/'.self::ARCHIVE_PREFIX.'*'.self::ARCHIVE_EXTENSION; - $config_files = glob($searchStr); - if (empty($config_files)) { - $packageHash = false; - } else { - $config_file_absolute_path = array_pop($config_files); - $config_file_name = basename($config_file_absolute_path, self::ARCHIVE_EXTENSION); - $packageHash = substr($config_file_name, strlen(self::ARCHIVE_PREFIX)); - } - } - return $packageHash; - } - - /** - * This function init all params before read from request - * - */ - protected static function initParamsBase() - { - DUPX_Log::setLogLevel(); - $GLOBALS['DUPX_DEBUG'] = isset($_POST['logging']) ? $_POST['logging'] : DUPX_Log::LV_DEFAULT; - } - - /** - * this function disables the shutdown function defined in the boot class - */ - public static function disableBootShutdownFunction() - { - self::$shutdownFunctionEnabled = false; - } - - /** - * This function sets the shutdown function before the installer is initialized. - * Prevents blank pages. - * - * After the plugin is initialized it will be set as a shudwon ​​function DUPX_Handler::shutdown - * - * !!! Don't use any Duplicator function within this function. !!! - * - */ - public static function bootShutdown() - { - if (!self::$shutdownFunctionEnabled) { - return; - } - - if (($error = error_get_last())) { - ?> -

        BOOT SHUTDOWN FATAL ERROR

        -
        
        -            
        - =')) { - return true; - } - $match = null; - if (preg_match("#^\d+(\.\d+)*#", PHP_VERSION, $match)) { - $phpVersion = $match[0]; - } else { - $phpVersion = PHP_VERSION; - } - $minPHPVersion = self::MINIMUM_PHP_VERSION; - - echo '
        '; - - die(); - } -} \ No newline at end of file diff --git a/installer/dup-installer/classes/utilities/class.u.html.php b/installer/dup-installer/classes/utilities/class.u.html.php deleted file mode 100644 index 1fad4427..00000000 --- a/installer/dup-installer/classes/utilities/class.u.html.php +++ /dev/null @@ -1,551 +0,0 @@ - - -
        -
        -

        -
        - -
        -
        - '; - if ($autoUpdate) { - //$classes[] = 'auto-update'; - $afterContent .= ''; - } - if ($enableTargetDownload) { - $path = parse_url($url, PHP_URL_PATH); - if (!empty($path)) { - $urlPath = parse_url($url, PHP_URL_PATH); - $fileName = basename($urlPath); - } else { - $fileName = parse_url($url, PHP_URL_HOST); - } - $afterContent .= ''; - } - $afterContent .= '
        '; - - $lightBoxContent = ' '; - return DUPX_U_Html::getLigthBox($linkLabelHtml, $titleContent, $lightBoxContent, $echo, $afterContent); - } - - protected static function lightBoxCss() - { - ?> - - - - -
        class="" data-more-step="" style="max-height: px"> -
        - - -
        - - - - - $atValue) { - $attrsHtml[] = $atName.'="'.DUPX_U::esc_attr($atValue).'"'; - } - ?> - - /> - - - - - - - runExtraction(); -die(DupLiteSnapJsonU::wp_json_encode($data)); diff --git a/installer/dup-installer/ctrls/ctrl.s2.base.php b/installer/dup-installer/ctrls/ctrl.s2.base.php deleted file mode 100644 index 1aea133b..00000000 --- a/installer/dup-installer/ctrls/ctrl.s2.base.php +++ /dev/null @@ -1,198 +0,0 @@ -mode = DUPX_U::sanitize_text_field($_POST['view_mode']); -$dbTestIn->dbaction = DUPX_U::sanitize_text_field($_POST['dbaction']); -$dbTestIn->dbhost = DUPX_U::sanitize_text_field($_POST['dbhost']); -$dbTestIn->dbuser = DUPX_U::sanitize_text_field($_POST['dbuser']); -$dbTestIn->dbpass = trim($_POST['dbpass']); -$dbTestIn->dbname = DUPX_U::sanitize_text_field($_POST['dbname']); -$dbTestIn->dbport = DUPX_U::sanitize_text_field($_POST['dbport']); -$dbTestIn->dbcollatefb = DUPX_U::sanitize_text_field($_POST['dbcollatefb']); - -$dbTest = new DUPX_DBTest($dbTestIn); - -//CLICKS 'Test Database' -if (isset($_GET['dbtest'])) { - - $dbTest->runMode = 'TEST'; - $dbTest->responseMode = 'JSON'; - if (!headers_sent()) { - header('Content-Type: application/json'); - } - die($dbTest->run()); -} - -$not_yet_logged = (isset($_POST['first_chunk']) && $_POST['first_chunk']) || (!isset($_POST['continue_chunking'])); - -if($not_yet_logged){ - DUPX_Log::info("\n\n\n********************************************************************************"); - DUPX_Log::info('* DUPLICATOR-LITE INSTALL-LOG'); - DUPX_Log::info('* STEP-2 START @ '.@date('h:i:s')); - DUPX_Log::info('* NOTICE: Do NOT post to public sites or forums!!'); - DUPX_Log::info("********************************************************************************"); - - $labelPadSize = 20; - DUPX_Log::info("USER INPUTS"); - DUPX_Log::info(str_pad('VIEW MODE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['view_mode'])); - DUPX_Log::info(str_pad('DB ACTION', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbaction'])); - DUPX_Log::info(str_pad('DB HOST', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString('**OBSCURED**')); - DUPX_Log::info(str_pad('DB NAME', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString('**OBSCURED**')); - DUPX_Log::info(str_pad('DB PASS', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString('**OBSCURED**')); - DUPX_Log::info(str_pad('DB PORT', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString('**OBSCURED**')); - DUPX_Log::info(str_pad('NON-BREAKING SPACES', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbnbsp'])); - DUPX_Log::info(str_pad('MYSQL MODE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbmysqlmode'])); - DUPX_Log::info(str_pad('MYSQL MODE OPTS', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbmysqlmode_opts'])); - DUPX_Log::info(str_pad('CHARSET', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbcharset'])); - DUPX_Log::info(str_pad('COLLATE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbcollate'])); - DUPX_Log::info(str_pad('COLLATE FB', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbcollatefb'])); - DUPX_Log::info(str_pad('VIEW CREATION', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbobj_views'])); - DUPX_Log::info(str_pad('STORED PROCEDURE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbobj_procs'])); - DUPX_Log::info(str_pad('FUNCTION CREATION', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbobj_funcs'])); - DUPX_Log::info("********************************************************************************\n"); - - $POST_LOG = $_POST; - unset($POST_LOG['dbpass']); - ksort($POST_LOG); - $log = "--------------------------------------\n"; - $log .= "POST DATA\n"; - $log .= "--------------------------------------\n"; - $log .= print_r($POST_LOG, true); - DUPX_Log::info($log, DUPX_Log::LV_DEBUG, true); - -} - - -//=============================================== -//DATABASE ROUTINES -//=============================================== -$dbinstall = new DUPX_DBInstall($_POST, $ajax2_start); -if ($_POST['dbaction'] != 'manual') { - if(!isset($_POST['continue_chunking'])){ - $dbinstall->prepareDB(); - } else if($_POST['first_chunk'] == 1) { - $dbinstall->prepareDB(); - } -} - -if($not_yet_logged) { - - //Fatal Memory errors from file_get_contents is not catchable. - //Try to warn ahead of time with a check on buffer in memory difference - $current_php_mem = DUPX_U::returnBytes($GLOBALS['PHP_MEMORY_LIMIT']); - $current_php_mem = is_numeric($current_php_mem) ? $current_php_mem : null; - - if ($current_php_mem != null && $dbinstall->dbFileSize > $current_php_mem) { - $readable_size = DUPX_U::readableByteSize($dbinstall->dbFileSize); - $msg = "\nWARNING: The database script is '".DUPX_U::sanitize_text_field($readable_size)."' in size. The PHP memory allocation is set\n"; - $msg .= "at '".DUPX_U::sanitize_text_field($GLOBALS['PHP_MEMORY_LIMIT'])."'. There is a high possibility that the installer script will fail with\n"; - $msg .= "a memory allocation error when trying to load the database.sql file. It is\n"; - $msg .= "recommended to increase the 'memory_limit' setting in the php.ini config file.\n"; - $msg .= "see: ".DUPX_U::esc_url($faq_url.'#faq-trouble-056-q')." \n"; - DUPX_Log::info($msg); - unset($msg); - } - - DUPX_Log::info("--------------------------------------"); - DUPX_Log::info("DATABASE RESULTS"); - DUPX_Log::info("--------------------------------------"); -} - -if ($_POST['dbaction'] == 'manual') { - DUPX_Log::info("\n** SQL EXECUTION IS IN MANUAL MODE **"); - DUPX_Log::info("- No SQL script has been executed -"); - $JSON['pass'] = 1; -} elseif(!isset($_POST['continue_chunking'])) { - $dbinstall->writeInDB(); - $rowCountMisMatchTables = $dbinstall->getRowCountMisMatchTables(); - $JSON['pass'] = 1; - if (!empty($rowCountMisMatchTables)) { - $errMsg = 'ERROR: Database Table row count verification was failed for table(s): '.implode(', ', $rowCountMisMatchTables); - DUPX_Log::info($errMsg); - } -} - -$dbinstall->profile_end = DUPX_U::getMicrotime(); -$dbinstall->writeLog(); -$JSON = $dbinstall->getJSON($JSON); -$nManager->saveNotices(); - -//FINAL RESULTS -$ajax1_sum = DUPX_U::elapsedTime(DUPX_U::getMicrotime(), $dbinstall->start_microtime); -DUPX_Log::info("\nINSERT DATA RUNTIME: " . DUPX_U::elapsedTime($dbinstall->profile_end, $dbinstall->profile_start)); -DUPX_Log::info('STEP-2 COMPLETE @ '.@date('h:i:s')." - RUNTIME: {$ajax1_sum}"); - -error_reporting($ajax2_error_level); -die(DupLiteSnapJsonU::wp_json_encode($JSON)); \ No newline at end of file diff --git a/installer/dup-installer/ctrls/ctrl.s2.dbinstall.php b/installer/dup-installer/ctrls/ctrl.s2.dbinstall.php deleted file mode 100644 index 496a3dd6..00000000 --- a/installer/dup-installer/ctrls/ctrl.s2.dbinstall.php +++ /dev/null @@ -1,732 +0,0 @@ -post = $post; - $this->php_mem = $GLOBALS['PHP_MEMORY_LIMIT']; - $this->php_used_mem = memory_get_usage(); - $this->php_mem_range = 1024 * 1024; - $this->root_path = $GLOBALS['DUPX_ROOT']; - $this->sql_file_path = "{$GLOBALS['DUPX_INIT']}/dup-database__{$GLOBALS['DUPX_AC']->package_hash}.sql"; - $this->sql_result_file_path = "{$GLOBALS['DUPX_INIT']}/{$GLOBALS['SQL_FILE_NAME']}"; - $this->dbFileSize = @filesize($this->sql_file_path); - - //ESTABLISH CONNECTION - $this->dbh = DUPX_DB::connect($post['dbhost'], $post['dbuser'], $post['dbpass']); - ($this->dbh) or DUPX_Log::error(ERR_DBCONNECT.mysqli_connect_error()); - if ($_POST['dbaction'] == 'empty' || $post['dbaction'] == 'rename') { - mysqli_select_db($this->dbh, $post['dbname']) - or DUPX_Log::error(sprintf(ERR_DBCREATE, $post['dbname'])); - } - - //PHP 8.1 throws exceptions vs pre 8.1 which silently fails - try { - @mysqli_query($this->dbh, "SET wait_timeout = ".mysqli_real_escape_string($this->dbh, $GLOBALS['DB_MAX_TIME'])); - $qryResult = @mysqli_query($this->dbh, "SET GLOBAL max_allowed_packet = ".mysqli_real_escape_string($this->dbh, $GLOBALS['DB_MAX_PACKETS'])); - if ($qryResult === false) { - @mysqli_query($this->dbh, "SET max_allowed_packet = ".mysqli_real_escape_string($this->dbh, $GLOBALS['DB_MAX_PACKETS'])); - } - } - catch (Exception $ex) { - DUPX_Log::info("SQL ERROR:" . $ex->getMessage() . "\n" . $ex->getTraceAsString()); - } - - $this->profile_start = isset($post['profile_start']) ? DUPX_U::sanitize_text_field($post['profile_start']) : DUPX_U::getMicrotime(); - $this->start_microtime = isset($post['start_microtime']) ? DUPX_U::sanitize_text_field($post['start_microtime']) : $start_microtime; - $this->dbvar_maxtime = DUPX_DB::getVariable($this->dbh, 'wait_timeout'); - $this->dbvar_maxpacks = DUPX_DB::getVariable($this->dbh, 'max_allowed_packet'); - $this->dbvar_sqlmode = DUPX_DB::getVariable($this->dbh, 'sql_mode'); - $this->dbvar_version = DUPX_DB::getVersion($this->dbh); - $this->dbvar_maxtime = is_null($this->dbvar_maxtime) ? 300 : $this->dbvar_maxtime; - $this->dbvar_maxpacks = is_null($this->dbvar_maxpacks) ? 1048576 : $this->dbvar_maxpacks; - $this->dbvar_sqlmode = empty($this->dbvar_sqlmode) ? 'NOT_SET' : $this->dbvar_sqlmode; - $definerHost = $this->post["dbhost"] == "localhost" || $this->post["dbhost"] == "127.0.0.1" ? $this->post["dbhost"] : '%'; - $this->dbDefinerReplace = '$1' . addcslashes("`" . $this->post["dbuser"] . "`@`" . $definerHost . "`", '\\$') . '$3'; - $this->dbquery_errs = isset($post['dbquery_errs']) ? DUPX_U::sanitize_text_field($post['dbquery_errs']) : 0; - $this->drop_tbl_log = isset($post['drop_tbl_log']) ? DUPX_U::sanitize_text_field($post['drop_tbl_log']) : 0; - $this->rename_tbl_log = isset($post['rename_tbl_log']) ? DUPX_U::sanitize_text_field($post['rename_tbl_log']) : 0; - $this->dbquery_rows = isset($post['dbquery_rows']) ? DUPX_U::sanitize_text_field($post['dbquery_rows']) : 0; - $this->dbdelete_count = isset($post['dbdelete_count']) ? DUPX_U::sanitize_text_field($post['dbdelete_count']) : 0; - $this->dbcollatefb = isset($post['dbcollatefb']) ? DUPX_U::sanitize_text_field($post['dbcollatefb']) : 0; - $this->dbobj_views = isset($post['dbobj_views']) ? DUPX_U::sanitize_text_field($post['dbobj_views']) : 0; - $this->dbobj_procs = isset($post['dbobj_procs']) ? DUPX_U::sanitize_text_field($post['dbobj_procs']) : 0; - $this->dbobj_funcs = isset($post['dbobj_funcs']) ? DUPX_U::sanitize_text_field($post['dbobj_funcs']) : 0; - $this->dbRemoveDefiner = isset($post['db_remove_definer']) ? DUPX_U::sanitize_text_field($post['db_remove_definer']) : 0; - } - - public function prepareDB() - { - //RUN DATABASE SCRIPT - //PHP 8.1 throws exceptions vs pre-8.1 which silently fails - try { - @mysqli_query($this->dbh, "SET wait_timeout = ".mysqli_real_escape_string($this->dbh, $GLOBALS['DB_MAX_TIME'])); - $qryResult = @mysqli_query($this->dbh, "SET GLOBAL max_allowed_packet = ".mysqli_real_escape_string($this->dbh, $GLOBALS['DB_MAX_PACKETS'])); - if ($qryResult === false) { - @mysqli_query($this->dbh, "SET max_allowed_packet = ".mysqli_real_escape_string($this->dbh, $GLOBALS['DB_MAX_PACKETS'])); - } - } - catch (Exception $ex) { - DUPX_Log::info("SQL ERROR:" . $ex->getMessage() . "\n" . $ex->getTraceAsString()); - } - - DUPX_DB::setCharset($this->dbh, $this->post['dbcharset'], $this->post['dbcollate']); - - //Will set mode to null only for this db handle session - //sql_mode can cause db create issues on some systems - switch ($this->post['dbmysqlmode']) { - case 'DISABLE': - @mysqli_query($this->dbh, "SET SESSION sql_mode = ''"); - break; - case 'CUSTOM': - $dbmysqlmode_opts = $this->post['dbmysqlmode_opts']; - - $qry_session_custom = @mysqli_query($this->dbh, "SET SESSION sql_mode = '".mysqli_real_escape_string($this->dbh, $dbmysqlmode_opts)."'"); - if ($qry_session_custom == false) { - $sql_error = mysqli_error($this->dbh); - $log = "WARNING: A custom sql_mode setting issue has been detected:\n{$sql_error}.\n"; - $log .= "For more details visit: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html\n"; - } - break; - } - - //Set defaults incase the variable could not be read - $this->drop_tbl_log = 0; - $this->rename_tbl_log = 0; - $sql_file_size = DUPX_U::readableByteSize(@filesize("{$GLOBALS['DUPX_INIT']}/dup-database__{$GLOBALS['DUPX_AC']->package_hash}.sql")); - $collate_fb = $this->dbcollatefb ? 'On' : 'Off'; - - DUPX_Log::info("--------------------------------------"); - DUPX_Log::info('DATABASE-ENVIRONMENT'); - DUPX_Log::info("--------------------------------------"); - DUPX_Log::info("MYSQL VERSION:\tThis Server: {$this->dbvar_version} -- Build Server: {$GLOBALS['DUPX_AC']->version_db}"); - DUPX_Log::info("FILE SIZE:\tdup-database__{$GLOBALS['DUPX_AC']->package_hash}.sql ({$sql_file_size})"); - DUPX_Log::info("TIMEOUT:\t{$this->dbvar_maxtime}"); - DUPX_Log::info("MAXPACK:\t{$this->dbvar_maxpacks}"); - DUPX_Log::info("SQLMODE:\t{$this->dbvar_sqlmode}"); - DUPX_Log::info("NEW SQL FILE:\t[{$this->sql_result_file_path}]"); - DUPX_Log::info("COLLATE FB:\t{$collate_fb}"); - - if (version_compare($this->dbvar_version, $GLOBALS['DUPX_AC']->version_db) < 0) { - DUPX_Log::info("\nNOTICE: This servers version [{$this->dbvar_version}] is less than the build version [{$GLOBALS['DUPX_AC']->version_db}]. \n" - ."If you find issues after testing your site please referr to this FAQ item.\n" - ."https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-260-q"); - } - - //CREATE DB - switch ($this->post['dbaction']) { - case "create": - if ($this->post['view_mode'] == 'basic') { - mysqli_query($this->dbh, "CREATE DATABASE IF NOT EXISTS `".mysqli_real_escape_string($this->dbh, $this->post['dbname'])."`"); - } - mysqli_select_db($this->dbh, mysqli_real_escape_string($this->dbh, $this->post['dbname'])) - or DUPX_Log::error(sprintf(ERR_DBCONNECT_CREATE, $this->post['dbname'])); - break; - - //DROP DB TABLES: DROP TABLE statement does not support views - case "empty": - //Drop all tables, views, funcs and procs - $this->dropTables(); - $this->dropViews(); - $this->dropProcs(); - $this->dropFuncs(); - break; - - //RENAME DB TABLES - case "rename" : - $sql = "SHOW TABLES FROM `".mysqli_real_escape_string($this->dbh, $this->post['dbname'])."` WHERE `Tables_in_".mysqli_real_escape_string($this->dbh, $this->post['dbname'])."` NOT LIKE '".mysqli_real_escape_string($this->dbh, $GLOBALS['DB_RENAME_PREFIX'])."%'"; - $found_tables = null; - if ($result = mysqli_query($this->dbh, $sql)) { - while ($row = mysqli_fetch_row($result)) { - $found_tables[] = $row[0]; - } - if (count($found_tables) > 0) { - foreach ($found_tables as $table_name) { - $sql = "RENAME TABLE `".mysqli_real_escape_string($this->dbh, $this->post['dbname'])."`.`".mysqli_real_escape_string($this->dbh, $table_name)."` TO `".mysqli_real_escape_string($this->dbh, $this->post['dbname'])."`.`".mysqli_real_escape_string($this->dbh, $GLOBALS['DB_RENAME_PREFIX']).mysqli_real_escape_string($this->dbh, $table_name)."`"; - if (!$result = mysqli_query($this->dbh, $sql)) { - DUPX_Log::error(sprintf(ERR_DBTRYRENAME, "{$this->post['dbname']}.{$table_name}")); - } - } - $this->rename_tbl_log = count($found_tables); - } - } - break; - } - - } - - public function getRowCountMisMatchTables() - { - $nManager = DUPX_NOTICE_MANAGER::getInstance(); - - $tableWiseRowCounts = $GLOBALS['DUPX_AC']->dbInfo->tableWiseRowCounts; - $skipTables = array( - $GLOBALS['DUPX_AC']->wp_tableprefix."duplicator_packages", - $GLOBALS['DUPX_AC']->wp_tableprefix."options", - $GLOBALS['DUPX_AC']->wp_tableprefix."duplicator_pro_packages", - $GLOBALS['DUPX_AC']->wp_tableprefix."duplicator_pro_entities", - ); - $misMatchTables = array(); - foreach ($tableWiseRowCounts as $table => $rowCount) { - if (in_array($table, $skipTables)) { - continue; - } - $sql = "SELECT count(*) as cnt FROM `".mysqli_real_escape_string($this->dbh, $table)."`"; - $result = mysqli_query($this->dbh, $sql); - if (false !== $result) { - $row = mysqli_fetch_assoc($result); - if ($rowCount != ($row['cnt'])) { - $errMsg = 'DATABASE: table '.DUPX_Log::varToString($table).' row count mismatch; expected '.DUPX_Log::varToString($rowCount).' in database'.DUPX_Log::varToString($row['cnt']); - DUPX_Log::info($errMsg); - $nManager->addBothNextAndFinalReportNotice(array( - 'shortMsg' => 'Database Table row count validation was failed', - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => $errMsg."\n", - 'sections' => 'database' - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, 'row-count-mismatch'); - - $misMatchTables[] = $table; - } - } - } - return $misMatchTables; - } - - public function writeInDB() - { - //WRITE DATA - $fcgi_buffer_pool = 5000; - $fcgi_buffer_count = 0; - $counter = 0; - if (!empty($sql_data)) { - $this->sql_result_data = $sql_data; - } - - $handle = fopen($this->sql_file_path, 'rb'); - if ($handle === false) { - return false; - } - - $nManager = DUPX_NOTICE_MANAGER::getInstance(); - - @mysqli_autocommit($this->dbh, false); - - $query = ''; - $delimiter = ';'; - - while (($line = fgets($handle)) !== false) { - if ('DELIMITER ;' == trim($query)) { - $delimiter = ';'; - $query = ''; - continue; - } - $query .= $line; - if (preg_match('/'.$delimiter.'\s*$/S', $query)) { - $query_strlen = strlen(trim($query)); - if ($this->dbvar_maxpacks < $query_strlen) { - $errorMsg = "**ERROR** Query size limit [length={$this->dbvar_maxpacks}] [sql=".substr($this->sql_result_data[$counter], 0, 75)."...]"; - $this->dbquery_errs++; - $nManager->addNextStepNoticeMessage('QUERY ERROR: size limit' , DUPX_NOTICE_ITEM::SOFT_WARNING , DUPX_NOTICE_MANAGER::ADD_UNIQUE , 'query-size-limit-msg'); - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'QUERY ERROR: size limit', - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => $errorMsg, - 'sections' => 'database' - )); - DUPX_Log::info($errorMsg); - } elseif ($query_strlen > 0) { - $query = $this->nbspFix($query); - $query = $this->applyQueryCollationFallback($query); - $query = $this->applyQueryProcAndViewFix($query); - - // $query = $this->queryDelimiterFix($query); - $query = trim($query); - if (0 === strpos($query, "DELIMITER")) { - // Ending delimiter - // control never comes in this if condition, but written - if ('DELIMITER ;' == $query) { - $delimiter = ';'; - } else { // starting delimiter - $delimiter = substr($query, 10); - $delimiter = trim($delimiter); - } - - DUPX_Log::info("Skipping delimiter query"); - $query = ''; - continue; - } - - $result = @mysqli_query($this->dbh, $query); - if ($result instanceof mysqli_result){ - @mysqli_free_result($result); - } - - $err = mysqli_error($this->dbh); - //Check to make sure the connection is alive - if (!empty($err)) { - if (!mysqli_ping($this->dbh)) { - mysqli_close($this->dbh); - $this->dbh = DUPX_DB::connect($this->post['dbhost'], $this->post['dbuser'], $this->post['dbpass'], $this->post['dbname']); - // Reset session setup - @mysqli_query($this->dbh, "SET wait_timeout = ".mysqli_real_escape_string($this->dbh, $GLOBALS['DB_MAX_TIME'])); - DUPX_DB::setCharset($this->dbh, $this->post['dbcharset'], $this->post['dbcollate']); - } - $errMsg = "**ERROR** database error write '{$err}' - [sql=".substr($query, 0, 75)."...]"; - DUPX_Log::info($errMsg); - - if (DUPX_U::contains($err, 'Unknown collation')) { - $nManager->addNextStepNotice(array( - 'shortMsg' => 'DATABASE ERROR: database error write', - 'level' => DUPX_NOTICE_ITEM::HARD_WARNING, - 'longMsg' => 'Unknown collation
        RECOMMENDATION: Try resolutions found at https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-110-q', - 'faqLink' => array( - 'url' => 'https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-110-q', - 'label' => 'FAQ Link' - ) - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE , 'query-collation-write-msg'); - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'DATABASE ERROR: database error write', - 'level' => DUPX_NOTICE_ITEM::HARD_WARNING, - 'longMsg' => 'Unknown collation
        RECOMMENDATION: Try resolutions found at https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-110-q'.'
        '.$errMsg, - 'sections' => 'database', - 'faqLink' => array( - 'url' => 'https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-110-q', - 'label' => 'FAQ Link' - ) - )); - DUPX_Log::info('RECOMMENDATION: Try resolutions found at https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-110-q'); - } else { - $nManager->addNextStepNoticeMessage('DATABASE ERROR: database error write' , DUPX_NOTICE_ITEM::SOFT_WARNING , DUPX_NOTICE_MANAGER::ADD_UNIQUE , 'query-write-msg'); - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'DATABASE ERROR: database error write', - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => $errMsg, - 'sections' => 'database' - )); - } - - $this->dbquery_errs++; - - //Buffer data to browser to keep connection open - } else { - if ($fcgi_buffer_count++ > $fcgi_buffer_pool) { - $fcgi_buffer_count = 0; - } - $this->dbquery_rows++; - } - } - $query = ''; - $counter++; - } - } - @mysqli_commit($this->dbh); - @mysqli_autocommit($this->dbh, true); - - $nManager ->saveNotices(); - - //DATA CLEANUP: Perform Transient Cache Cleanup - //Remove all duplicator entries and record this one since this is a new install. - $dbdelete_count1 = 0; - $dbdelete_count2 = 0; - - @mysqli_query($this->dbh, "DELETE FROM `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."duplicator_packages`"); - $dbdelete_count1 = @mysqli_affected_rows($this->dbh); - - @mysqli_query($this->dbh, - "DELETE FROM `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` WHERE `option_name` LIKE ('_transient%') OR `option_name` LIKE ('_site_transient%')"); - $dbdelete_count2 = @mysqli_affected_rows($this->dbh); - - mysqli_query($this->dbh, "DELETE FROM `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` WHERE `option_name` = 'duplicator_usage_id'"); - $dbdelete_count3 = @mysqli_affected_rows($this->dbh); - $this->dbdelete_count += (abs($dbdelete_count1) + abs($dbdelete_count2) + abs($dbdelete_count3)); - - //Reset Duplicator Options - if (DUPX_U::isTraversable($GLOBALS['DUPX_AC']->opts_delete)) { - foreach ($GLOBALS['DUPX_AC']->opts_delete as $value) { - mysqli_query($this->dbh, "DELETE FROM `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` WHERE `option_name` = '".mysqli_real_escape_string($this->dbh, $value)."'"); - } - } - - //Remove views from DB - if (!$this->dbobj_views) { - $this->dropViews(); - DUPX_Log::info("DB VIEWS:\tdisabled"); - } else { - DUPX_Log::info("DB VIEWS:\tenabled"); - } - - //Remove procedures from DB - if (!$this->dbobj_procs) { - $this->dropProcs(); - DUPX_Log::info("DB PROCEDURES:\tdisabled"); - } else { - DUPX_Log::info("DB PROCEDURES:\tenabled"); - } - - //Remove FUNCTIONS from DB - if (!$this->dbobj_funcs) { - $this->dropFuncs(); - DUPX_Log::info("DB FUNCTIONS:\tdisabled"); - } else { - DUPX_Log::info("DB FUNCTIONS:\tenabled"); - } - } - - private function dropTables() - { - $sql = "SHOW FULL TABLES WHERE Table_Type != 'VIEW'"; - $found_tables = null; - if ($result = mysqli_query($this->dbh, $sql)) { - while ($row = mysqli_fetch_row($result)) { - $found_tables[] = $row[0]; - } - if ($found_tables != null && count($found_tables) > 0) { - mysqli_query($this->dbh, "SET FOREIGN_KEY_CHECKS = 0;"); - foreach ($found_tables as $table_name) { - $sql = "DROP TABLE `".mysqli_real_escape_string($this->dbh, $this->post['dbname'])."`.`".mysqli_real_escape_string($this->dbh, $table_name)."`"; - if (!$result = mysqli_query($this->dbh, $sql)) { - DUPX_Log::error(sprintf(ERR_DROP_TABLE_TRYCLEAN, $table_name, $this->post['dbname'], mysqli_error($this->dbh))); - } - } - $this->drop_tbl_log = count($found_tables); - mysqli_query($this->dbh, "SET FOREIGN_KEY_CHECKS = 1;"); - } - } - } - - private function dropProcs() - { - $sql = "SHOW PROCEDURE STATUS WHERE db='{$this->post['dbname']}'"; - $found = array(); - if ($result = mysqli_query($this->dbh, $sql)) { - while ($row = mysqli_fetch_row($result)) { - $found[] = $row[1]; - } - if (count($found) > 0) { - $nManager = DUPX_NOTICE_MANAGER::getInstance(); - - foreach ($found as $proc_name) { - $sql = "DROP PROCEDURE IF EXISTS `".mysqli_real_escape_string($this->dbh, $this->post['dbname'])."`.`".mysqli_real_escape_string($this->dbh, $proc_name)."`"; - if (!$result = mysqli_query($this->dbh, $sql)) { - $err = mysqli_error($this->dbh); - - $nManager->addNextStepNotice(array( - 'shortMsg' => 'PROCEDURE CLEAN ERROR', - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => sprintf('Unable to remove PROCEDURE "%s" from database "%s".
        ', $proc_name, $this->post['dbname']), - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, 'drop-proc-fail-msg'); - - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'PROCEDURE CLEAN ERROR: '.$err, - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => sprintf('Unable to remove PROCEDURE "%s" from database "%s".', $proc_name, $this->post['dbname']), - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, - 'sections' => 'database', - )); - - DUPX_Log::info("PROCEDURE CLEAN ERROR: '{$err}'\n\t[SQL=".substr($sql, 0, self::QUERY_ERROR_LOG_LEN)."...]\n\n"); - } - } - - $nManager->addNextStepNotice(array( - 'shortMsg' => 'PROCEDURE CLEAN ERROR', - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => sprintf(ERR_DROP_PROCEDURE_TRYCLEAN, mysqli_error($this->dbh)), - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_PREPEND_IF_EXISTS, 'drop-proc-fail-msg'); - } - } - } - - private function dropFuncs() - { - $sql = "SHOW FUNCTION STATUS WHERE db='{$this->post['dbname']}'"; - if (($result = mysqli_query($this->dbh, $sql)) === false || mysqli_num_rows($result) === 0) { - return; - } - - DUPX_Log::info("MYSQL RESULT: ".DUPX_Log::varToString($result)); - DUPX_Log::info("NUMBER OF FUNCS: ".DUPX_Log::varToString(mysqli_num_rows($result))); - - $nManager = DUPX_NOTICE_MANAGER::getInstance(); - while ($row = mysqli_fetch_row($result)) { - $func_name = $row[1]; - $sql = "DROP FUNCTION IF EXISTS `".mysqli_real_escape_string($this->dbh, $this->post['dbname'])."`.`".mysqli_real_escape_string($this->dbh, $func_name)."`"; - if (!mysqli_query($this->dbh, $sql)) { - $err = mysqli_error($this->dbh); - - $nManager->addNextStepNotice(array( - 'shortMsg' => 'FUNCTION CLEAN ERROR', - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => sprintf('Unable to remove FUNCTION "%s" from database "%s".
        ', $func_name, $this->post['dbname']), - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, 'drop-func-fail-msg'); - - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'PROCEDURE CLEAN ERROR: '.$err, - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => sprintf('Unable to remove FUNCTION "%s" from database "%s".', $func_name, $this->post['dbname']), - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, - 'sections' => 'database', - )); - - DUPX_Log::info("FUNCTION CLEAN ERROR: '{$err}'\n\t[SQL=".substr($sql, 0, self::QUERY_ERROR_LOG_LEN)."...]\n\n"); - } - } - - $nManager->addNextStepNotice(array( - 'shortMsg' => 'PROCEDURE CLEAN ERROR', - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => sprintf(ERR_DROP_FUNCTION_TRYCLEAN, mysqli_error($this->dbh)), - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_PREPEND_IF_EXISTS, 'drop-func-fail-msg'); - } - - private function dropViews() - { - $sql = "SHOW FULL TABLES WHERE Table_Type = 'VIEW'"; - $found_views = null; - if ($result = mysqli_query($this->dbh, $sql)) { - while ($row = mysqli_fetch_row($result)) { - $found_views[] = $row[0]; - } - if (!is_null($found_views) && count($found_views) > 0) { - $nManager = DUPX_NOTICE_MANAGER::getInstance(); - - foreach ($found_views as $view_name) { - $sql = "DROP VIEW `".mysqli_real_escape_string($this->dbh, $this->post['dbname'])."`.`".mysqli_real_escape_string($this->dbh, $view_name)."`"; - if (!$result = mysqli_query($this->dbh, $sql)) { - $err = mysqli_error($this->dbh); - - $nManager->addNextStepNotice(array( - 'shortMsg' => 'VIEW CLEAN ERROR', - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => sprintf('Unable to remove VIEW "%s" from database "%s".
        ', $view_name, $this->post['dbname']), - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, 'drop-view-fail-msg'); - - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'VIEW CLEAN ERROR: '.$err, - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => sprintf('Unable to remove VIEW "%s" from database "%s"', $view_name, $this->post['dbname']), - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, - 'sections' => 'database', - )); - - DUPX_Log::info("VIEW CLEAN ERROR: '{$err}'\n\t[SQL=".substr($sql, 0, self::QUERY_ERROR_LOG_LEN)."...]\n\n"); - } - } - - $nManager->addNextStepNotice(array( - 'shortMsg' => 'VIEW CLEAN ERROR', - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => sprintf(ERR_DROP_VIEW_TRYCLEAN, mysqli_error($this->dbh)), - 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_PREPEND_IF_EXISTS, 'drop-view-fail-msg'); - - } - } - } - - public function writeLog() - { - $nManager = DUPX_NOTICE_MANAGER::getInstance(); - $nManager->saveNotices(); - - DUPX_Log::info("ERRORS FOUND:\t{$this->dbquery_errs}"); - DUPX_Log::info("DROPPED TABLES:\t{$this->drop_tbl_log}"); - DUPX_Log::info("RENAMED TABLES:\t{$this->rename_tbl_log}"); - DUPX_Log::info("QUERIES RAN:\t{$this->dbquery_rows}\n"); - - $this->dbtable_rows = 1; - $this->dbtable_count = 0; - - if ($result = mysqli_query($this->dbh, "SHOW TABLES")) { - while ($row = mysqli_fetch_array($result, MYSQLI_NUM)) { - $table_rows = DUPX_DB::countTableRows($this->dbh, $row[0]); - $this->dbtable_rows += $table_rows; - DUPX_Log::info("{$row[0]}: ({$table_rows})"); - $this->dbtable_count++; - } - @mysqli_free_result($result); - } - - DUPX_Log::info("Removed '{$this->dbdelete_count}' cache/transient rows"); - - if ($this->dbtable_count == 0) { - DUPX_Log::info("NOTICE: You may have to manually run the installer-data.sql to validate data input. - Also check to make sure your installer file is correct and the table prefix - '{$GLOBALS['DUPX_AC']->wp_tableprefix}' is correct for this particular version of WordPress. \n"); - } - } - - public function getJSON($json) - { - $json['table_count'] = $this->dbtable_count; - $json['table_rows'] = $this->dbtable_rows; - $json['query_errs'] = $this->dbquery_errs; - - return $json; - } - - private function applyQueryCollationFallback($query) { - if (!empty($this->post['dbcolsearchreplace']) && $this->post['dbcollatefb']) { - $collation_replace_list = json_decode(stripslashes($this->post['dbcolsearchreplace']), true); - - if ($collation_replace_list === null) { - DUPX_Log::info("WARNING: Cannot decode collation replace list JSON.\n", 1); - return; - } - - if (!empty($collation_replace_list)) { - - if ($this->firstOrNotChunking()) { - DUPX_Log::info("LEGACY COLLATION FALLBACK:\n\tRunning the following replacements:\n\t".stripslashes($this->post['dbcolsearchreplace'])); - } - - foreach ($collation_replace_list as $val) { - $replace_charset = false; - if (strpos($val['search'], 'utf8mb4') !== false && strpos($val['replace'], 'utf8mb4') === false) { - $replace_charset = true; - } - /* - foreach ($this->sql_result_data as $key => $query) { - */ - if (strpos($query, $val['search'])) { - $query = str_replace($val['search'], $val['replace'], $query); - $sub_query = str_replace("\n", '', substr($query, 0, 80)); - DUPX_Log::info("\tNOTICE: {$val['search']} replaced by {$val['replace']} in query [{$sub_query}...]"); - } - if ($replace_charset && strpos($query, 'utf8mb4')) { - $query = str_replace('utf8mb4', 'utf8', $query); - $sub_query = str_replace("\n", '', substr($query, 0, 80)); - DUPX_Log::info("\tNOTICE: utf8mb4 replaced by utf8 in query [{$sub_query}...]"); - } - /* - } - */ - } - } - } - - return $query; - } - - private function applyQueryProcAndViewFix($query) - { - static $replaceRules = null; - if (is_null($replaceRules)) { - $replaceRules['patterns'] = array( - self::USER_DEFINER_REPLACE_PATTERN, - self::SQL_SECURITY_INVOKER_PATTERN - ); - - $replaceRules['replaces'] = array( - $this->dbDefinerReplace, - self::SQL_SECURITY_INVOKER_REPLACE - ); - - if ($this->dbRemoveDefiner) { - //No need to run the definer replace if we are removing them - $replaceRules['patterns'][0] = self::USER_DEFINER_REMOVE_PATTERN; - $replaceRules['replaces'][0] = "$1 $3"; - } - } - - $fixedQuery = preg_replace($replaceRules['patterns'], $replaceRules['replaces'], $query); - - if ($fixedQuery !== $query) { - DUPX_Log::info("REPLACED DEFINER/INVOKER IN QUERY: [sql=".$fixedQuery."]", DUPX_Log::LV_DEBUG); - } - - return $fixedQuery; - } - - private function delimiterFix($counter) - { - $firstQuery = trim(preg_replace('/\s\s+/', ' ', $this->sql_result_data[$counter])); - $start = $counter; - $end = 0; - if (strpos($firstQuery, "DELIMITER") === 0) { - $this->sql_result_data[$start] = ""; - $continueSearch = true; - while ($continueSearch) { - $counter++; - if (strpos($this->sql_result_data[$counter], 'DELIMITER') === 0) { - $continueSearch = false; - unset($this->sql_result_data[$counter]); - $this->sql_result_data = array_values($this->sql_result_data); - } else { - $this->sql_result_data[$start] .= $this->sql_result_data[$counter].";\n"; - unset($this->sql_result_data[$counter]); - } - } - } - } - - public function nbspFix($sql) - { - if ($this->post['dbnbsp']) { - if ($this->firstOrNotChunking()) { - DUPX_Log::info("ran fix non-breaking space characters\n"); - } - $sql = preg_replace('/\xC2\xA0/', ' ', $sql); - } - return $sql; - } - - public function firstOrNotChunking() - { - return (!isset($this->post['continue_chunking']) || $this->post['first_chunk']); - } - - public function __destruct() - { - @mysqli_close($this->dbh); - } -} \ No newline at end of file diff --git a/installer/dup-installer/ctrls/ctrl.s2.dbtest.php b/installer/dup-installer/ctrls/ctrl.s2.dbtest.php deleted file mode 100644 index cbf034a2..00000000 --- a/installer/dup-installer/ctrls/ctrl.s2.dbtest.php +++ /dev/null @@ -1,810 +0,0 @@ -in = $input; - $this->out = new DUPX_DBTestOut(); - $this->tblPerms = array('all' => -1, 'create' => -1, 'insert' => -1, 'update' => -1, 'delete' => -1, 'select' => -1, 'drop' => -1); - $this->ac = DUPX_ArchiveConfig::getInstance(); - - //REQUIRMENTS - //Pass States: skipped = -1 failed = 0 passed = 1 warned = 2 - $this->reqs[5] = array('title' => "Create Database User", 'info' => "{$default_msg}", 'pass' => -1); - $this->reqs[10] = array('title' => "Host Connection", 'info' => "{$default_msg}", 'pass' => -1); - $this->reqs[20] = array('title' => "Database Version", 'info' => "{$default_msg}", 'pass' => -1); - $this->reqs[30] = array('title' => "Database Create New Tests", 'info' => "{$default_msg}", 'pass' => -1); - $this->reqs[40] = array('title' => "Privileges: User Visibility", 'info' => "{$default_msg}", 'pass' => -1); - $this->reqs[50] = array('title' => "Manual Table Check", 'info' => "{$default_msg}", 'pass' => -1); - $this->reqs[60] = array('title' => "Privileges: User Resources", 'info' => "{$default_msg}", 'pass' => -1); - $this->reqs[70] = array('title' => "Check Collation Capability", 'info' => "{$default_msg}", 'pass' => -1); - $this->reqs[80] = array('title' => "Database GTID mode", 'info' => "{$default_msg}", 'pass' => -1); - //NOTICES - $this->notices[10] = array('title' => "Table Case Sensitivity", 'info' => "{$default_msg}", 'pass' => -1); - $this->notices[20] = array('title' => "Source Database Triggers", 'info' => "{$default_msg}", 'pass' => -1); - } - - public function run() - { - //Requirments - $this->runBasic(); - - $this->buildStateSummary(); - $this->buildDisplaySummary(); - $this->out->payload = $this; - foreach ($this->out->payload->in as $key=>$val) { - $this->out->payload->in->$key = htmlentities($val); - } - $this->out->getProcessTime(); - - //Return PHP or JSON result - if ($this->responseMode == 'PHP') { - $result = $this->out; - return $result; - } elseif ($this->responseMode == 'JSON') { - $result = DupLiteSnapJsonU::wp_json_encode($this->out); - return $result; - } else { - die('Please specific the responseMode property'); - } - - } - - private function runBasic() - { - //REQUIRMENTS: - //[10] = "Verify Host Connection" - //[20] = "Check Server Version" - //[30] = "Create New Database Tests" - //[40] = "Confirm Database Visibility" - //[50] = "Manual Table Check" - //[60] = "Test User Table Privileges" - - - $this->r10All($this->reqs[10]); - $this->r20All($this->reqs[20]); - - switch ($this->in->dbaction) { - case "create" : - $this->r30Basic($this->reqs[30]); - $this->r40Basic($this->reqs[40]); - break; - case "empty" : - $this->r40Basic($this->reqs[40]); - break; - case "rename": - $this->r40Basic($this->reqs[40]); - break; - case "manual": - $this->r40Basic($this->reqs[40]); - $this->r50All($this->reqs[50]); - break; - } - - $this->r60All($this->reqs[60]); - - //NOTICES - $this->n10All($this->notices[10]); - $this->n20All($this->notices[20]); - $this->r70All($this->reqs[70]); - $this->r80All($this->reqs[80]); - $this->basicCleanup(); - } - - /** - * Verify Host Connection - * - * @return null - */ - private function r10All(&$test) - { - try { - - if ($this->isFailedState($test)) { - return; - } - - //Host check - $parsed_host_info = DUPX_DB::parseDBHost($this->in->dbhost); - $parsed_host = $parsed_host_info[0]; - $isInvalidHost = $parsed_host == 'http' || $parsed_host == "https"; - - if ($isInvalidHost) { - $fixed_host = DupLiteSnapLibIOU::untrailingslashit(str_replace($parsed_host."://","",$this->in->dbhost)); - $test['pass'] = 0; - $test['info'] = "[".htmlentities($this->in->dbhost)."] is not a valid input. Try using [$fixed_host] instead."; - return; - } - - $this->dbh = DUPX_DB::connect($this->in->dbhost, $this->in->dbuser, $this->in->dbpass, null); - if ($this->dbh) { - $test['pass'] = 1; - $test['info'] = "The user [".htmlentities($this->in->dbuser)."] successfully connected to the database server on host [".htmlentities($this->in->dbhost)."]."; - } else { - $msg = "Unable to connect the user [".htmlentities($this->in->dbuser)."] to the host [".htmlentities($this->in->dbhost)."]"; - $test['pass'] = 0; - $test['info'] = (mysqli_connect_error()) ? "{$msg}. The server error response was: ".htmlentities(mysqli_connect_error()).'' : "{$msg}. Please contact your hosting provider or server administrator."; - } - } - catch (Exception $ex) { - $test['pass'] = 0; - $test['info'] = "Unable to connect the user [".htmlentities($this->in->dbuser)."] to the host [".htmlentities($this->in->dbhost)."].
        ".$this->formatError($ex); - } - } - - /** - * Check Server Version - * - * @return null - */ - private function r20All(&$test) - { - try { - - if ($this->isFailedState($test)) { - return; - } - - $db_version = DUPX_DB::getVersion($this->dbh); - $db_version_pass = version_compare('5.0.0', $db_version) <= 0; - - if ($db_version_pass) { - $test['pass'] = 1; - $test['info'] = "This test passes with a current database version of [".htmlentities($db_version)."]"; - } else { - $test['pass'] = 0; - $test['info'] = "The current database version is [".htmlentities($db_version)."] which is below the required version of 5.0.0 " - ."Please work with your server admin or hosting provider to update the database server."; - } - - } catch (Exception $ex) { - $test['pass'] = 0; - $test['info'] = "Unable to properly check the database server version number.
        " . $this->formatError($ex); - } - } - - /** - * Create New Database Basic Test - * Use selects: 'Create New Database for basic - * - * @return null - */ - private function r30Basic(&$test) - { - try { - - if ($this->isFailedState($test)) { - return; - } - - //DATABASE EXISTS - $db_found = mysqli_select_db($this->dbh, $this->in->dbname); - if ($db_found) { - $test['pass'] = 0; - $test['info'] = "DATABASE CREATION FAILURE: A database named [".htmlentities($this->in->dbname)."] already exists.

        " - ."Please continue with the following options:
        " - ."- Choose a different database name or remove this one.
        " - ."- Change the action drop-down to an option like \"Connect and Remove All Data\".
        "; - return; - } - - //CREATE & DROP DB - $result = mysqli_query($this->dbh, "CREATE DATABASE IF NOT EXISTS `".mysqli_real_escape_string($this->dbh, $this->in->dbname)."`"); - $db_found = mysqli_select_db($this->dbh, mysqli_real_escape_string($this->dbh, $this->in->dbname)); - - if (!$db_found) { - $test['pass'] = 0; - $test['info'] = sprintf(ERR_DBCONNECT_CREATE, htmlentities($this->in->dbname)); - $test['info'] .= "\nError Message: ".mysqli_error($this->dbh); - } else { - $this->newDBMade = true; - $test['pass'] = 1; - $test['info'] = "Database [".htmlentities($this->in->dbname)."] was successfully created and dropped. The user has enough privileges to create a new database with the " - . "'Basic' option enabled."; - } - } catch (Exception $ex) { - $test['pass'] = 0; - $test['info'] = "Error creating database [".htmlentities($this->in->dbname)."].
        " . $this->formatError($ex); - } - } - - /** - * Confirm Database Visibility for Basic - * - * @return null - */ - private function r40Basic(&$test) - { - try { - - if ($this->isFailedState($test)) { - return; - } - - //Show Databases by the host account, otherwise a timeout - //to issue the 'Show Databases' query may occur on some hosts - $host_user = substr_replace($this->in->dbuser, '', strpos($this->in->dbuser, '_')); - $this->databases = DUPX_DB::getDatabases($this->dbh, $host_user); - - $db_found = mysqli_select_db($this->dbh, $this->in->dbname); - if (!$db_found) { - $test['pass'] = 0; - $test['info'] = "The user '[".htmlentities($this->in->dbuser)."]' is unable to see the database named '[".htmlentities($this->in->dbname)."]'. " - . "Be sure the database name already exists and check that the database user has access to the database. " - . "If you want to create a new database choose the action 'Create New Database'."; - } else { - $test['pass'] = 1; - $test['info'] = "The database user [".htmlentities($this->in->dbuser)."] has visible access to see the database named [".htmlentities($this->in->dbname)."]"; - } - - } catch (Exception $ex) { - $test['pass'] = 0; - $test['info'] = "The user '[".htmlentities($this->in->dbuser)."]' is unable to see the database named '[".htmlentities($this->in->dbname)."]'. " - . "Be sure the database name already exists and check that the database user has access to the database. " - . "If you want to create a new database choose the action 'Create New Database'
        " . $this->formatError($ex); - } - } - - /** - * Manual Table Check - * - * User chooses "Manual SQL Execution" - * Core WP has 12 tables. Check to make sure at least 10 are present - * otherwise present an error message - * - * @return null - */ - private function r50All(&$test) - { - try { - - if ($this->isFailedState($test)) { - return; - } - - $tblcount = DUPX_DB::countTables($this->dbh, htmlentities($this->in->dbname)); - - if ($tblcount < 10) { - $test['pass'] = 0; - $test['info'] = sprintf(ERR_DBMANUAL, htmlentities($this->in->dbname), htmlentities($tblcount)); - } else { - $test['pass'] = 1; - $test['info'] = "This test passes. A WordPress database looks to be setup."; - } - - } catch (Exception $ex) { - $test['pass'] = 0; - $test['info'] = "The database user [".htmlentities($this->in->dbuser)."] has visible access to see the database named [".htmlentities($this->in->dbname)."] .
        " . $this->formatError($ex); - } - } - - /** - * Test User Table privileges - * - * @return null - */ - private function r60All(&$test) - { - try { - - if ($this->isFailedState($test)) { - return; - } - - $this->checkTablePerms(); - - if ($this->tblPerms['all']) { - $test['pass'] = 1; - $test['info'] = "The user [".htmlentities($this->in->dbuser)."] has the correct privileges on the database [".htmlentities($this->in->dbname)."]"; - } else { - $list = array(); - $test['pass'] = 0; - foreach ($this->tblPerms as $key => $val) { - if ($key != 'all') { - if ($val == false) array_push($list, $key); - } - } - $list = implode(',', $list); - $test['info'] = "The user [".htmlentities($this->in->dbuser)."] is missing the privileges [".htmlentities($list)."] on the database [".htmlentities($this->in->dbname)."]"; - } - - } catch (Exception $ex) { - $test['pass'] = 0; - $test['info'] = "Failure in attempt to read the users table priveleges.
        " . $this->formatError($ex); - } - } - - /** - * Check Collation Capability - * - * @return null - */ - private function r70All(&$test) - { - try { - if ($this->isFailedState($test)) { - return; - } - - $this->collationStatus = DUPX_DB::getCollationStatus($this->dbh, $this->ac->dbInfo->collationList); - - $collation_arr = array( - 'utf8mb4_unicode_520_ci', - 'utf8mb4_unicode_520', - 'utf8mb4_unicode_ci', - 'utf8mb4', - 'utf8_unicode_520_ci', - 'utf8_unicode_520', - 'utf8_unicode_ci', - 'utf8', - ); - $invalid = 0; - $collation_arr_max = count($collation_arr); - $invalid_match = 0; - - foreach($this->collationStatus as $key => $val) { - if ($this->collationStatus[$key]['found'] == 0) { - if($this->in->dbcollatefb){ - $not_supported_col = $this->collationStatus[$key]['name']; - for($i = 0; $i < $collation_arr_max; $i++) { - $col_status = DUPX_DB::getCollationStatus($this->dbh, array($collation_arr[$i])); - $cur_col_is_supported = $col_status[0]['found']; - if($cur_col_is_supported){ - $this->collationReplaceList[] = array( - 'search' => $not_supported_col, - 'replace' => $collation_arr[$i] - ); - ++$invalid_match; - break; - } - } - $invalid = 1; - break; - } else { - $invalid = 1; - break; - } - } - } - - if($invalid_match > 0) { - $invalid = -1; - } - - if ($invalid === 1) { - $test['pass'] = 0; - $test['info'] = "Please check the 'Legacy' checkbox in the options section and then click the 'Retry Test' link.
        " - . "Details: The database where the package was created has a collation that is not supported on this server. This issue happens " - . "when a site is moved from an older version of MySQL to a newer version of MySQL. The recommended fix is to update MySQL on this server to support " - . "the collation that is failing below. If that is not an option for your host then continue by clicking the 'Legacy' checkbox above. For more " - . "details about this issue and other details regarding this issue see the FAQ link below. "; - } else if($invalid === -1) { - $test['pass'] = 1; - $test['info'] = "There is at least one collation that is not supported, however a replacement collation is possible. Please continue by clicking the next button and the " - . "installer will attempt to use a legacy/fallback collation type to create the database table. For more details about this issue see the FAQ link below."; - } else { - $test['pass'] = 1; - $test['info'] = "Collation test passed! This database supports the required table collations."; - } - - } catch (Exception $ex) { - //Return '1' to allow user to continue - $test['pass'] = 1; - $test['info'] = "Failure in attempt to check collation capability status.
        " . $this->formatError($ex); - } - - } - - /** - * Check GTID mode - * - * @return null - */ - private function r80All(&$test) - { - try { - if ($this->isFailedState($test)) { - return; - } - - $gtid_mode_enabled = false; - $query = "SELECT @@GLOBAL.GTID_MODE"; - $result = mysqli_query($this->dbh, $query); - - if ($result = mysqli_query($this->dbh, $query)) { - if ($row = mysqli_fetch_array($result, MYSQLI_NUM)) { - if ('ON' == $row[0] || 'on' == $row[0]) - $gtid_mode_enabled = true; - } - } - - // $gtid_mode_enabled = true; - if ($gtid_mode_enabled) { - $test['pass'] = 2; - $test['info'] = "Your database server have GTID mode is on, It might make a trouble in Database installation.
        " - . "Details: You might face the error something like Statement violates GTID consistency. " - . "You should ask hosting provider to make off GTID off. " - . "You can make off GTID mode as decribed in the https://dev.mysql.com/doc/refman/5.7/en/replication-mode-change-online-disable-gtids.html" - . ""; - } else { - $test['pass'] = 1; - $test['info'] = "The installer has not detected GTID mode."; - } - } catch (Exception $ex) { - //Return '1' to allow user to continue - $test['pass'] = 1; - $test['info'] = "Failure in attempt to check GTID mode status.
        " . $this->formatError($ex); - } - } - - /** - * Table Case Compatibility - * - * Failure occurs when: - * BuildServer = lower_case_table_names=1 && - * BuildServer = HasATableUpperCase && - * InstallServer = lower_case_table_names=0 - * - * @return null - */ - private function n10All(&$test) - { - try { - - if ($this->isFailedState($test)) { - return; - } - - $localhostLowerCaseTables = DUPX_DB::getVariable($this->dbh, 'lower_case_table_names'); - $localhostLowerCaseTables = (empty($localhostLowerCaseTables) && DUPX_U::isWindows()) ? 0 : $localhostLowerCaseTables; - - if (isset($this->ac->dbInfo->isTablesUpperCase) && $this->ac->dbInfo->isTablesUpperCase && $this->ac->dbInfo->varLowerCaseTables == 1 && $localhostLowerCaseTables == 0) { - $test['pass'] = 0; - $test['info'] = "An upper case table name was found in the database SQL script and the server variable lower_case_table_names is set " - . "to [".htmlentities($localhostLowerCaseTables)."]. When both of these conditions are met it can lead to issues with creating tables with upper case characters. " - . "
        Options:
        " - . " - On this server have the host company set the lower_case_table_names value to 1 or 2 in the my.cnf file.
        " - . " - On the build server set the lower_case_table_names value to 2 restart server and build package.
        " - . " - Optionally continue the install with data creation issues on upper case tables names.
        "; - } else { - $test['pass'] = 1; - $test['info'] = "No table casing issues detected. This servers variable setting for lower_case_table_names is [{$localhostLowerCaseTables}]"; - } - - } catch (Exception $ex) { - //Return '1' to allow user to continue - $test['pass'] = 1; - $test['info'] = "Failure in attempt to read the upper case table status.
        " . $this->formatError($ex); - } - } - - /** - * Show source site trigger creates - * - * @return null - */ - private function n20All(&$test) - { - if ($this->isFailedState($test)) { - return; - } - - $triggers = (array)$this->ac->dbInfo->triggerList; - if (count($triggers) > 0) { - $test['pass'] = 0; - $test['info'] = ""; - - foreach ($triggers as $trigger) { - $test['info'] .= $trigger->create."\n\n";; - } - - } else { - $test['pass'] = 1; - $test['info'] = "Source site did not contain triggers."; - } - } - - /** - * Input has UTF8 data - * - * @return null - */ - private function n30All(&$test) - { - try { - - if ($this->isFailedState($test)) { - return; - } - - //WARNNG: Input has utf8 data - $dbConnItems = array($this->in->dbhost, $this->in->dbuser, $this->in->dbname, $this->in->dbpass); - $dbUTF8_tst = false; - foreach ($dbConnItems as $value) { - if (DUPX_U::isNonASCII($value)) { - $dbUTF8_tst = true; - break; - } - } - - if (!$dbConn && $dbUTF8_tst) { - $test['pass'] = 0; - $test['info'] = ERR_TESTDB_UTF8; - - } else { - $test['pass'] = 1; - $test['info'] = "Connection string is using all non-UTF8 characters and should be safe."; - } - - } catch (Exception $ex) { - //Return '1' to allow user to continue - $test['pass'] = 1; - $test['info'] = "Failure in attempt to read input has utf8 data status.
        " . $this->formatError($ex); - } - } - - /** - * Runs a series of CREATE, INSERT, SELECT, UPDATE, DELETE and DROP statements - * on a temporary test table to find out the state of the users privileges - * - * @return null - */ - private function checkTablePerms() - { - - if ($this->permsChecked) { - return; - } - - mysqli_select_db($this->dbh, mysqli_real_escape_string($this->dbh, $this->in->dbname)); - $tmp_table = '__dpro_temp_'.rand(1000, 9999).'_'.date("ymdHis"); - $qry_create = @mysqli_query($this->dbh, "CREATE TABLE `".mysqli_real_escape_string($this->dbh, $tmp_table)."` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `text` text NOT NULL, - PRIMARY KEY (`id`))"); - - $this->tblPerms['create'] = ($qry_create) ? 1 : 0; - - if ($qry_create) { - $qry_insert = @mysqli_query($this->dbh, "INSERT INTO `".mysqli_real_escape_string($this->dbh, $tmp_table)."` (`text`) VALUES ('Duplicator Test: Please Remove this Table')"); - $qry_insert = @mysqli_query($this->dbh, "INSERT INTO `".mysqli_real_escape_string($this->dbh, $tmp_table)."` (`text`) VALUES ('TEXT-1')"); - $qry_select = @mysqli_query($this->dbh, "SELECT COUNT(*) FROM `".mysqli_real_escape_string($this->dbh, $tmp_table)."`"); - $qry_update = @mysqli_query($this->dbh, "UPDATE `".mysqli_real_escape_string($this->dbh, $tmp_table)."` SET text = 'TEXT-2' WHERE text = 'TEXT-1'"); - $qry_delete = @mysqli_query($this->dbh, "DELETE FROM `".mysqli_real_escape_string($this->dbh, $tmp_table)."` WHERE text = 'TEXT-2'"); - $qry_drop = @mysqli_query($this->dbh, "DROP TABLE IF EXISTS `".mysqli_real_escape_string($this->dbh, $tmp_table)."`;"); - - $this->tblPerms['insert'] = ($qry_insert) ? 1 : 0; - $this->tblPerms['select'] = ($qry_select) ? 1 : 0; - $this->tblPerms['update'] = ($qry_update) ? 1 : 0; - $this->tblPerms['delete'] = ($qry_delete) ? 1 : 0; - $this->tblPerms['drop'] = ($qry_drop) ? 1 : 0; - } - - $this->tblPerms['all'] = $this->tblPerms['create'] && $this->tblPerms['insert'] && $this->tblPerms['select'] && - $this->tblPerms['update'] && $this->tblPerms['delete'] && $this->tblPerms['drop']; - - $this->permsChecked = true; - } - - /** - * Return the sql_mode set for the database - * - * @return null - */ - private function checkSQLMode() - { - if ($this->sqlmodeChecked) { - return; - } - - $qry_sqlmode = @mysqli_query($this->dbh, "SELECT @@GLOBAL.sql_mode as mode"); - if($qry_sqlmode){ - $sql_mode_array = mysqli_fetch_assoc($qry_sqlmode); - - if($sql_mode_array !== false) { - $this->sql_modes = $sql_mode_array['mode']; - } else { - $this->sql_modes ="query failed
        ".htmlentities(@mysqli_error($this->dbh)); - } - - }else{ - $this->sql_modes ="query failed
        ".htmlentities(@mysqli_error($this->dbh)); - } - - $this->sqlmodeChecked = true; - return $this->sql_modes; - } - - /** - * Test if '0000-00-00' date query fails or not - * - * @return null - */ - private function testDateInsert() - { - if ($this->dateInsertChecked) { - return; - } - - mysqli_select_db($this->dbh, $this->in->dbname); - - $tmp_table = '__dpro_temp_'.rand(1000, 9999).'_'.date("ymdHis"); - $tmp_table = mysqli_real_escape_string($dbh, $tmp_table); - - $qry_create = @mysqli_query($this->dbh, "CREATE TABLE `{$tmp_table}` ( - `datetimefield` datetime NOT NULL, - `datefield` date NOT NULL)"); - - if ($qry_create) { - $qry_date = @mysqli_query($this->dbh, "INSERT INTO `".$tmp_table."` (`datetimefield`,`datefield`) VALUES ('0000-00-00 00:00:00','0000-00-00')"); - - if($qry_date) { - $this->queryDateInserted = true; - } - } - - $this->dateInsertChecked = true; - - return $this->queryDateInserted; - } - - /** - * Cleans up basic setup items when test mode is enabled - * - * @return null - */ - private function basicCleanup() - { - //TEST MODE ONLY - if ($this->runMode == 'TEST') { - - //DELETE DB - if ($this->newDBMade && $this->in->dbaction == 'create') { - $result = mysqli_query($this->dbh, "DROP DATABASE IF EXISTS `".mysqli_real_escape_string($this->dbh, $this->in->dbname)."`"); - if (!$result) { - $this->reqs[30][pass] = 0; - $this->reqs[30][info] = "The database [".htmlentities($this->in->dbname)."] was successfully created. However removing the database was not successful with the following response.
        " - ."Response Message: ".htmlentities(mysqli_error($this->dbh)).". This database may need to be removed manually."; - } - } - } - } - - /** - * Checks if any previous test has failed. If so then prevent the current test - * from running - * - * @return null - */ - private function isFailedState(&$test) - { - foreach ($this->reqs as $key => $value) { - if ($this->reqs[$key]['pass'] == 0) { - $test['pass'] = -1; - $test['info'] = 'This test has been skipped because a higher-level requirement failed. Please resolve previous failed tests.'; - return true; - } - } - return false; - } - - /** - * Gathers all the test data and builds a summary result - * - * @return null - */ - private function buildStateSummary() - { - $req_status = 1; - $notice_status = -1; - $last_error = 'Unable to determine error response'; - foreach ($this->reqs as $key => $value) { - if ($this->reqs[$key]['pass'] == 0) { - $req_status = 0; - $last_error = $this->reqs[$key]['info']; - break; - } - } - - if (1 == $req_status) { - foreach ($this->reqs as $key => $value) { - if ($this->reqs[$key]['pass'] == 2) { - $req_status = 2; - break; - } - } - } - - //Only show notice summary if a test was ran - foreach ($this->notices as $key => $value) { - if ($this->notices[$key]['pass'] == 0) { - $notice_status = 0; - break; - } elseif ($this->notices[$key]['pass'] == 1) { - $notice_status = 1; - } - } - - $this->lastError = $last_error; - $this->reqsPass = $req_status; - $this->noticesPass = $notice_status; - } - - /** - * Converts all test info messages to either TEXT or HTML format - * - * @return null - */ - private function buildDisplaySummary() - { - if ($this->displayMode == 'TEXT') { - //TODO: Format for text - } else { - //TODO: Format for html - } - } - - private function formatError(Exception $ex) - { - return "Message: " . htmlentities($ex->getMessage()) . "
        Line: " . htmlentities($ex->getFile()) . ':' . htmlentities($ex->getLine()); - } -} diff --git a/installer/dup-installer/ctrls/ctrl.s3.php b/installer/dup-installer/ctrls/ctrl.s3.php deleted file mode 100644 index 52361967..00000000 --- a/installer/dup-installer/ctrls/ctrl.s3.php +++ /dev/null @@ -1,50 +0,0 @@ -getEngineMode()) { - case DUPX_S3_Funcs::MODE_NORMAL: - default: - $s3Func->initLog(); - $s3Func->runSearchAndReplace(); - - $s3Func->removeLicenseKey(); - $s3Func->createNewAdminUser(); - $s3Func->configurationFileUpdate(); - $s3Func->htaccessUpdate(); - $s3Func->generalUpdateAndCleanup(); - - $s3Func->noticeTest(); - $s3Func->cleanupTmpFiles(); - $s3Func->finalReportNotices(); - $s3Func->complete(); - } - - $nManager->saveNotices(); -} catch (Exception $e) { - $s3Func->error($e->getMessage()); -} - -$json = $s3Func->getJsonReport(); -DUPX_Log::close(); -die(DupLiteSnapJsonU::wp_json_encode($json)); diff --git a/installer/dup-installer/favicon/android-chrome-192x192.png b/installer/dup-installer/favicon/android-chrome-192x192.png deleted file mode 100644 index 1807bf9e0b549d5baffb07d6678434ce25c7cf64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28559 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 diff --git a/installer/dup-installer/favicon/android-chrome-384x384.png b/installer/dup-installer/favicon/android-chrome-384x384.png deleted file mode 100644 index b67d909a7b8a25db385770b933dc46e293470747..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69783 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

        G1?6xzL@*XVn}e&WH_AipBe+ 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 H)qMFkZ8-@m diff --git a/installer/dup-installer/favicon/favicon-32x32.png b/installer/dup-installer/favicon/favicon-32x32.png deleted file mode 100644 index cb3c86110ed78d47dad62be9e8f8e0285e322198..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2958 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 diff --git a/installer/dup-installer/views/index.php b/installer/dup-installer/views/index.php deleted file mode 100644 index 17a71fa7..00000000 --- a/installer/dup-installer/views/index.php +++ /dev/null @@ -1,2 +0,0 @@ - -

        -
        - Exception error -

        -
        - INSTALL ERROR! -

        - Message: getMessage()); ?>
        - Please see the file for more details. - haveFaqLink()) { - ?> -
        - See FAQ: getFaqLinkLabel(); ?> - - getLongMsg())) { - echo '

        '.$longMsg; - } - } - ?> -

        -
        - Trace: -
        getTraceAsString();
        -    ?>
        -
        -
        - - See online help for more details at snapcreek.com -
        diff --git a/installer/dup-installer/views/view.help.php b/installer/dup-installer/views/view.help.php deleted file mode 100644 index e14156ab..00000000 --- a/installer/dup-installer/views/view.help.php +++ /dev/null @@ -1,714 +0,0 @@ - array('default' => ''))); - -?> -
        - HELP -
        - -
        -

        - For complete help visit - Duplicator Migration and Backup Online Help
        - Features available only in Duplicator Pro are flagged with a pro tag. -
        - - - - - - - - - - - - - - - - - - - - - - - -
        For additional help please visit Duplicator Migration and Backup Online Help
        - - -
        - - - diff --git a/installer/dup-installer/views/view.init1.php b/installer/dup-installer/views/view.init1.php deleted file mode 100644 index 024a2422..00000000 --- a/installer/dup-installer/views/view.init1.php +++ /dev/null @@ -1,159 +0,0 @@ -getSecurityType() == DUPX_Security::SECURITY_NONE) { - DUPX_HTTP::post_with_html($page_url, array( - 'action_step' => '1', - 'csrf_token' => DUPX_CSRF::generate('step1') - )); - exit; -} - -//POSTBACK: valid security -if ($security->securityCheck()) { - DUPX_HTTP::post_with_html($page_url, - array( - 'action_step' => '1', - 'csrf_token' => DUPX_CSRF::generate('step1'), - 'secure-pass' => $_POST['secure-pass'], - 'secure-archive' => $_POST['secure-archive'] - ) - ); - exit; -} -$page_err = isset($_POST['secure-try']) ? 1 : 0; - -switch (DUPX_Security::getInstance()->getSecurityType()) { - case DUPX_Security::SECURITY_PASSWORD: - $errorMsg = 'Invalid Password! Please try again...'; - break; - case DUPX_Security::SECURITY_ARCHIVE: - $errorMsg = 'Invalid Archive name! Please try again...'; - break; - case DUPX_Security::SECURITY_NONE: - default: - $errorMsg = ''; - break; -} - -$css_why_display = ($GLOBALS['DUPX_STATE']->mode === DUPX_InstallerMode::OverwriteInstall) ? "" : "no-display"; -$archive_name = isset($_POST['secure-archive']) ? $_POST['secure-archive'] : ''; - -?> - - - - -
        - - - - -
        - Installer Security -
        - - -
        -

        -
        - - -
        - -
        - This screen will show under the following conditions: -
          -
        • - Password Protection: If the file was password protected when it was created then the password input below should - be enabled. If the input is disabled then no password was set. -
        • -
        • - Simple Installer Name: If no password is set and you are performing an "Overwrite Install" on a public server - (non localhost) without a secure installer.php file name (i.e. [hash]_installer.php). Then users will need to enter the archive file for - a valid security check. If the Archive File Name input is disabled then it can be ignored. -
        • -
        -
        -
        - -
        - - getSecurityType() == $security::SECURITY_PASSWORD) { - $attrs['required'] = 'required'; - } else { - $attrs['placeholder'] = 'Password not enabled'; - $attrs['disabled'] = 'disabled'; - } - DUPX_U_Html::inputPasswordToggle('secure-pass', 'secure-pass', array(), $attrs); - ?> -
        - - mode === DUPX_InstallerMode::OverwriteInstall) : ?> -
        - -
        - getSecurityType() == $security::SECURITY_ARCHIVE ? '' : 'disabled'); ?>> -
        - -
        -
        -
        - - - -
        - - - \ No newline at end of file diff --git a/installer/dup-installer/views/view.s1.base.php b/installer/dup-installer/views/view.s1.base.php deleted file mode 100644 index f6a89896..00000000 --- a/installer/dup-installer/views/view.s1.base.php +++ /dev/null @@ -1,1544 +0,0 @@ -mode === DUPX_InstallerMode::OverwriteInstall); -$is_wordpress = DUPX_Server::isWordPress(); -$is_dbonly = $GLOBALS['DUPX_AC']->exportOnlyDB; -$managed_host = $mh_manager->isManaged(); - -//REQUIRMENTS -$req = array(); -$req['05'] = $arcCheck; -$req['10'] = DUPX_Server::is_dir_writable($GLOBALS['DUPX_ROOT']) ? 'Pass' : 'Fail'; -$req['20'] = function_exists('mysqli_connect') ? 'Pass' : 'Fail'; -$req['30'] = DUPX_Server::$php_version_safe ? 'Pass' : 'Fail'; -$req['40'] = $managed_host === false ? 'Pass' : 'Fail'; -$all_req = in_array('Fail', $req) ? 'Fail' : 'Pass'; - -//NOTICES -$openbase = ini_get("open_basedir"); -$datetime1 = $GLOBALS['DUPX_AC']->created; -$datetime2 = date("Y-m-d H:i:s"); -$fulldays = round(abs(strtotime($datetime1) - strtotime($datetime2)) / 86400); -$root_path = DupLiteSnapLibIOU::safePath($GLOBALS['DUPX_ROOT'], true); -$wpconf_path = "{$root_path}/wp-config.php"; -$max_time_zero = ($GLOBALS['DUPX_ENFORCE_PHP_INI']) ? false : @set_time_limit(0); -$max_time_size = 314572800; //300MB -$max_time_ini = ini_get('max_execution_time'); -$max_time_warn = (is_numeric($max_time_ini) && $max_time_ini < 31 && $max_time_ini > 0) && $arcSize > $max_time_size; -$parentWordFencePath = DUPX_Server::parentWordfencePath(); - -$notice = array(); -$notice['10'] = !$is_overwrite_mode ? 'Good' : 'Warn'; -$notice['20'] = !$is_wpconfarc_present ? 'Good' : 'Warn'; -if ($is_dbonly) { - $notice['25'] = $is_wordpress ? 'Good' : 'Warn'; -} -$notice['30'] = $fulldays <= 180 ? 'Good' : 'Warn'; - -$packagePHP = $GLOBALS['DUPX_AC']->version_php; -$currentPHP = DUPX_Server::$php_version; -$packagePHPMajor = intval($packagePHP); -$currentPHPMajor = intval($currentPHP); -$notice['45'] = ($packagePHPMajor === $currentPHPMajor || $GLOBALS['DUPX_AC']->exportOnlyDB) ? 'Good' : 'Warn'; - -$notice['50'] = empty($openbase) ? 'Good' : 'Warn'; -$notice['60'] = !$max_time_warn ? 'Good' : 'Warn'; -$notice['70'] = $GLOBALS['DUPX_AC']->mu_mode == 0 ? 'Good' : 'Warn'; -$notice['80'] = !$GLOBALS['DUPX_AC']->is_outer_root_wp_config_file ? 'Good' : 'Warn'; -if ($GLOBALS['DUPX_AC']->exportOnlyDB) { - $notice['90'] = 'Good'; -} else { - $notice['90'] = (!$GLOBALS['DUPX_AC']->is_outer_root_wp_content_dir) ? 'Good' : 'Warn'; -} - -$space_free = @disk_free_space($GLOBALS['DUPX_ROOT']); -$archive_size = file_exists($GLOBALS['FW_PACKAGE_PATH']) ? filesize($GLOBALS['FW_PACKAGE_PATH']) : 0; -$notice['100'] = ($space_free && $archive_size > $space_free) ? 'Warn' : 'Good'; -$notice['110'] = $parentWordFencePath === false ? 'Good' : 'Warn'; - -$all_notice = in_array('Warn', $notice) ? 'Warn' : 'Good'; - -//SUMMATION -$req_success = ($all_req == 'Pass'); -$req_notice = ($all_notice == 'Good'); -$all_success = ($req_success && $req_notice); -$agree_msg = "To enable this button the checkbox above under the 'Terms & Notices' must be checked."; - -$shell_exec_unzip_path = DUPX_Server::get_unzip_filepath(); -$shell_exec_zip_enabled = ($shell_exec_unzip_path != null); -$zip_archive_enabled = class_exists('ZipArchive') ? 'Enabled' : 'Not Enabled'; -$archive_config = DUPX_ArchiveConfig::getInstance(); -?> - -
        - - - - - - - - -
        - Step 1 of 4: Deployment -
        This step will extract the archive file contents.
        -
        - - - - - - - - -
        - - - -
        - Options -
        -
        - - - -
        - Validation -
        - -
        -
        -
        -

        - - - -
        - - -
        - - -
        -
        - -

        -

        - - - - -
        - - This installation will not be able to proceed until the setup and validation sections above both pass. Please adjust your servers settings or contact your - server administrator, hosting provider or visit the resources below for additional help. - - -
        - - - - -
        - - -
        - - - - - -
        - - - - - - diff --git a/installer/dup-installer/views/view.s1.terms.php b/installer/dup-installer/views/view.s1.terms.php deleted file mode 100644 index fa238c64..00000000 --- a/installer/dup-installer/views/view.s1.terms.php +++ /dev/null @@ -1,83 +0,0 @@ - - - - - \ No newline at end of file diff --git a/installer/dup-installer/views/view.s2.base.php b/installer/dup-installer/views/view.s2.base.php deleted file mode 100644 index 2b9679fa..00000000 --- a/installer/dup-installer/views/view.s2.base.php +++ /dev/null @@ -1,366 +0,0 @@ -dbcharset) - ? $GLOBALS['DBCHARSET_DEFAULT'] - : $archive_config->dbcharset; -$_POST['dbcharset'] = isset($_POST['dbcharset']) ? trim($_POST['dbcharset']) : $dbcharset; - -$dbcollate = empty($archive_config->dbcollation) - ? $GLOBALS['DBCOLLATE_DEFAULT'] - : $archive_config->dbcollation; -$_POST['dbcollate'] = isset($_POST['dbcollate']) ? trim($_POST['dbcollate']) : $dbcollate; - -$_POST['exe_safe_mode'] = (isset($_POST['exe_safe_mode'])) ? DUPX_U::sanitize_text_field($_POST['exe_safe_mode']) : 0; -$is_dbtest_mode = isset($_POST['dbonlytest']) ? 1 : 0; - -if (isset($_POST['logging'])) { - $post_logging = DUPX_U::sanitize_text_field($_POST['logging']); - $_POST['logging'] = trim($post_logging); -} else { - $_POST['logging'] = 1; -} - -$cpnl_supported = DUPX_U::$on_php_53_plus ? true : false; -?> - -
        - - -
        Database Validation
        - - -
        - Step 2 of 4: Install Database -
        This step will install the database from the archive.
        -
        -
        - - -
        - - - -
        - Step 2 - Page Load - - - - - - - - - - - -
        - - -
        - -
        - - - - - - -
        - - - - - - - - - - \ No newline at end of file diff --git a/installer/dup-installer/views/view.s2.basic.php b/installer/dup-installer/views/view.s2.basic.php deleted file mode 100644 index d97abe02..00000000 --- a/installer/dup-installer/views/view.s2.basic.php +++ /dev/null @@ -1,342 +0,0 @@ -mode == DUPX_InstallerMode::StandardInstall; -$is_overwrite_mode = ($state->mode == DUPX_InstallerMode::OverwriteInstall && $GLOBALS['DUPX_AC']->installSiteOverwriteOn); - -if ($is_standard_mode) { - - $ovr_dbhost = NULL; - $ovr_dbname = NULL; - $ovr_dbuser = NULL; - $ovr_dbpass = NULL; - - $dbhost = $GLOBALS['DUPX_AC']->dbhost; - $dbname = $GLOBALS['DUPX_AC']->dbname; - $dbuser = $GLOBALS['DUPX_AC']->dbuser; - $dbpass = $GLOBALS['DUPX_AC']->dbpass; - - $dbFormDisabledString = ''; -} else { - $wpConfigPath = "{$GLOBALS['DUPX_ROOT']}/wp-config.php"; - $outerWPConfigPath = dirname($GLOBALS['DUPX_ROOT'])."/wp-config.php"; - require_once($GLOBALS['DUPX_INIT'].'/lib/config/class.wp.config.tranformer.php'); - $config_transformer = file_exists($wpConfigPath) ? new DupLiteWPConfigTransformer($wpConfigPath) : new DupLiteWPConfigTransformer($outerWPConfigPath); - - function dupxGetDbConstVal($constName) - { - if ($GLOBALS['config_transformer']->exists('constant', $constName)) { - $configVal = $GLOBALS['config_transformer']->get_value('constant', $constName); - $constVal = htmlspecialchars($configVal); - } else { - $constVal = ''; - } - return $constVal; - } - $ovr_dbhost = dupxGetDbConstVal('DB_HOST'); - $ovr_dbname = dupxGetDbConstVal('DB_NAME'); - $ovr_dbuser = dupxGetDbConstVal('DB_USER'); - $ovr_dbpass = dupxGetDbConstVal('DB_PASSWORD'); - - $dbhost = ''; - $dbname = ''; - $dbuser = ''; - $dbpass = ''; -} -?> - - -
        - Setup -
        -
        -
        Database Connection
        - - -
        - Ready to connect to existing sites database?
        -
        - The existing sites database settings should have been applied below. If you want to connect to this database and replace all its data then keep these values. - To use different database settings click the 'Reset button' to clear the values. To apply the current sites database use the 'Apply Button'. -

        - - Warning: Please note that reusing an existing site's database will overwrite all of its data. If you're not 100% sure about - using these database settings, then create a new database and use the new credentials instead. -
        - -
        - - -
        -
        - - - - - - - - - - - - - - - - - - - -
        Action: - -
        Host:
        Database: - -
        - Warning: The selected 'Action' above will remove all data from this database! -
        -
        - Notice: The selected 'Action' will rename all existing tables from the database name above with a prefix ''. - The prefix is only applied to existing tables and not the new tables that will be installed. -
        -
        - Notice: The 'Manual SQL execution' action will prevent the SQL script in the archive from running. The database above should already be - pre-populated with data which will be updated in the next step. No data in the database will be modified until after Step 3 runs. -
        -
        User:
        Password: - 'valid database user password', - 'value' => $dbpass - )); - ?> -
        -
        -
        - - - - -
        - Options -
        -
        - - - - - - - -
        - -
        -
        -
        - Please validate database setup by clicking the 'Test Database' button.
        - This test checks to make sure the database is ready for install. -
        -
        -
        - -


        -


        - - - - diff --git a/installer/dup-installer/views/view.s2.cpnl.lite.php b/installer/dup-installer/views/view.s2.cpnl.lite.php deleted file mode 100644 index 3df60800..00000000 --- a/installer/dup-installer/views/view.s2.cpnl.lite.php +++ /dev/null @@ -1,39 +0,0 @@ - - -
        -

        cPanel Connectivity

        - - - - -
        - This server does not appear to support cPanel!
        - Consider upgrading to a host that does.
        -
        - - - -
        - Want even easier installs? - Duplicator Pro - allows the following right from the installer: -
        -
          -
        • Directly login to cPanel
        • -
        • Instantly create new databases & users
        • -
        • Preview and select existing databases & users
        • -
        - - Note: Hosts that support cPanel provide remote access to server resources, allowing operations such as direct database and user creation. - Since the Duplicator Pro - installer can directly access cPanel, it dramatically speeds up your workflow. - -
        \ No newline at end of file diff --git a/installer/dup-installer/views/view.s2.dbtest.php b/installer/dup-installer/views/view.s2.dbtest.php deleted file mode 100644 index a760f3d4..00000000 --- a/installer/dup-installer/views/view.s2.dbtest.php +++ /dev/null @@ -1,566 +0,0 @@ - - - - - - diff --git a/installer/dup-installer/views/view.s3.php b/installer/dup-installer/views/view.s3.php deleted file mode 100644 index 95c10c46..00000000 --- a/installer/dup-installer/views/view.s3.php +++ /dev/null @@ -1,638 +0,0 @@ -wproot; - - // RSR TODO: need to do the path too? - $new_path = $GLOBALS['DUPX_ROOT']; - $new_path = ((strrpos($old_path, '/') + 1) == strlen($old_path)) ? DUPX_U::addSlash($new_path) : $new_path; - $empty_schedule_display = (DUPX_U::$on_php_53_plus) ? 'table-row' : 'none'; -?> - - -
        - - -
        - Step 3 of 4: Update Data -
        This step will update the database and config files to match your new sites values.
        -
        - - Manual SQL execution is enabled'; - } - ?> - - -
        - Step 3 - Page Load - - - - - - - - - - - - - - - - -
        - -
        - Setup -
        -
        - - - - - - - - - - - - - -
        Title:
        URL: - - get -
        Path:
        -
        -
        - - -
        - Replace -
        - - -
        - - -
        - Options -
        - -



        - - - -
        - - - - - diff --git a/installer/dup-installer/views/view.s4.php b/installer/dup-installer/views/view.s4.php deleted file mode 100644 index da1eff32..00000000 --- a/installer/dup-installer/views/view.s4.php +++ /dev/null @@ -1,430 +0,0 @@ -wplogin_url); -$admin_redirect ="{$url_new_rtrim}/wp-admin/admin.php?page=duplicator-tools&tab=diagnostics"; - -$safe_mode = DUPX_U::sanitize_text_field($_POST['exe_safe_mode']); -$admin_redirect = "{$admin_redirect}&sm={$safe_mode}" ; -$admin_redirect = urlencode($admin_redirect); -$admin_url_qry = (strpos($admin_base, '?') === false) ? '?' : '&'; -$admin_login = "{$url_new_rtrim}/{$admin_base}{$admin_url_qry}redirect_to={$admin_redirect}"; - -// Few machines doen's have utf8_decode -if (!function_exists('utf8_decode')) { - function utf8_decode($s) { - $s = (string) $s; - $len = strlen($s); - for ($i = 0, $j = 0; $i < $len; ++$i, ++$j) { - switch ($s[$i] & "\xF0") { - case "\xC0": - case "\xD0": - $c = (\ord($s[$i] & "\x1F") << 6) | \ord($s[++$i] & "\x3F"); - $s[$j] = $c < 256 ? \chr($c) : '?'; - break; - case "\xF0": - ++$i; - // no break - case "\xE0": - $s[$j] = '?'; - $i += 2; - break; - default: - $s[$j] = $s[$i]; - } - } - return substr($s, 0, $j); - } -} -//Sanitize -$json_result = true; -$_POST['json'] = isset($_POST['json']) ? DUPX_U::esc_attr($_POST['json']) : 'json data not set'; -$json_data = utf8_decode(urldecode($_POST['json'])); -$json_decode = json_decode($json_data); -if ($json_decode == NULL || $json_decode == FALSE) { - $json_data = "{'json reset invalid form value sent. Possible site script attempt'}"; - $json_result = false; -} - -?> - - - - -
        - - - -
        - Step 4 of 4: Test Site -

        - - -
        - Step 4 - Page Load - - - -
        - - - - - - -
        - - - Login to the WordPress Admin to finalize this install.
        - - -
        - - -
        - SAFE MODE: - Safe mode has deactivated all plugins except for Duplicator. Please be sure to enable your plugins after logging in. If you notice that problems - arise when activating more than one plugin at a time, then it is recommended to active them one-by-one to isolate the plugin that could be causing the issue. -
        - - -
        - IMPORTANT FINAL STEPS: Login into the WordPress Admin to remove all and finalize the install process. This install is NOT complete until all installer - files have been completely removed. Leaving any of the installer files on this server can lead to security issues. -

        - - step1->query_errs > 0) { - $linkAttr = './'.DUPX_U::esc_attr($GLOBALS["LOG_FILE_NAME"]); - $longMsg = <<install-log.txt file and -and marked with an **ERROR** status. If you experience a few errors (under 5), in many cases they can be ignored as long as your site is working correctly. -However if you see a large amount of errors or you experience an issue with your site then the error messages in the log file will need to be investigated. -

        - -COMMON FIXES: - -LONGMSG; - - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'STEP 2 - INSTALL NOTICES ('.$json_decode->step1->query_errs.')', - 'level' => DUPX_NOTICE_ITEM::HARD_WARNING, - 'longMsg' => $longMsg, - 'longMsgMode'=> DUPX_NOTICE_ITEM::MSG_MODE_HTML, - 'sections' => array('database'), - 'priority' => 5, - 'open' => true - )); - } - - if ($json_decode && $json_decode->step3->errsql_sum > 0) { - $longMsg = <<addFinalReportNotice(array( - 'shortMsg' => 'STEP 3 - UPDATE NOTICES ('.$json_decode->step3->errsql_sum.')', - 'level' => DUPX_NOTICE_ITEM::HARD_WARNING, - 'longMsg' => $longMsg, - 'sections' => array('database'), - 'priority' => 5, - 'open' => true - )); - } - - if ($json_decode && $json_decode->step3->errkey_sum > 0) { - $longMsg = <<
        - - Advanced Searching:
        - Use the following query to locate the table that was not updated:
        - SELECT @row := @row + 1 as row, t.* FROM some_table t, (SELECT @row := 0) r -
        -LONGMSG; - - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'TABLE KEY NOTICES ('.$json_decode->step3->errkey_sum.')', - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => $longMsg, - 'longMsgMode'=> DUPX_NOTICE_ITEM::MSG_MODE_HTML, - 'sections' => array('database'), - 'priority' => 5, - 'open' => true - )); - } - - if ($json_decode && $json_decode->step3->errser_sum > 0) { - $longMsg = <<addFinalReportNotice(array( - 'shortMsg' => 'SERIALIZATION NOTICES ('.$json_decode->step3->errser_sum.')', - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => $longMsg, - 'sections' => array('search_replace'), - 'priority' => 5, - 'open' => true - )); - } - - $numGeneralNotices = $nManager->countFinalReportNotices('general', DUPX_NOTICE_ITEM::NOTICE, '>='); - if ($numGeneralNotices == 0) { - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'No general notices', - 'level' => DUPX_NOTICE_ITEM::INFO, - 'sections' => array('general'), - 'priority' => 5 - )); - } else { - $longMsg = <<WordPress Codex. -LONGMSG; - - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'Info', - 'level' => DUPX_NOTICE_ITEM::INFO, - 'longMsg' => $longMsg, - 'longMsgMode'=> DUPX_NOTICE_ITEM::MSG_MODE_HTML, - 'sections' => array('general'), - 'priority' => 5, - 'open' => true - )); - } - - $numDbNotices = $nManager->countFinalReportNotices('database', DUPX_NOTICE_ITEM::NOTICE, '>='); - if ($numDbNotices == 0) { - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'No errors in database', - 'level' => DUPX_NOTICE_ITEM::INFO, - 'longMsg' => '', - 'sections' => 'database', - 'priority' => 5 - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE, 'query_err_counts'); - } else if ($numDbNotices <= 10) { - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'Some errors in the database ('.$numDbNotices.')', - 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, - 'longMsg' => '', - 'sections' => 'database', - 'priority' => 5 - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE, 'query_err_counts'); - } else if ($numDbNotices <= 100) { - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'Errors in the database ('.$numDbNotices.')', - 'level' => DUPX_NOTICE_ITEM::HARD_WARNING, - 'longMsg' => '', - 'sections' => 'database', - 'priority' => 5 - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE, 'query_err_counts'); - } else { - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'Many errors in the database ('.$numDbNotices.')', - 'level' => DUPX_NOTICE_ITEM::CRITICAL, - 'longMsg' => '', - 'sections' => 'database', - 'priority' => 5 - ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE, 'query_err_counts'); - } - - - $numSerNotices = $nManager->countFinalReportNotices('search_replace', DUPX_NOTICE_ITEM::NOTICE, '>='); - if ($numSerNotices == 0) { - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'No search and replace data errors', - 'level' => DUPX_NOTICE_ITEM::INFO, - 'longMsg' => '', - 'sections' => 'search_replace', - 'priority' => 5 - )); - } - - $numFilesNotices = $nManager->countFinalReportNotices('files', DUPX_NOTICE_ITEM::NOTICE, '>='); - - if ($numFilesNotices == 0) { - $nManager->addFinalReportNotice(array( - 'shortMsg' => 'No files extraction errors', - 'level' => DUPX_NOTICE_ITEM::INFO, - 'longMsg' => '', - 'sections' => 'files', - 'priority' => 5 - )); - } - - $nManager->sortFinalReport(); - $nManager->finalReportLog(array('general','files','database','search_replace')); - ?> - -
        - Additional Details: -
          -
        • - Review Migration Report

          - - - - - - - - - - - - - - - - - - - - - - - -
          Files notices() getSectionErrLevelHtml('files'); ?>
          Database Notices()getSectionErrLevelHtml('database'); ?>
          Search & Replace Notices() getSectionErrLevelHtml('search_replace'); ?>
          General Notices()getSectionErrLevelHtml('general'); ?>

          -
        • -
        • - Review this sites front-end or - re-run the installer and ">go back to step 1 -
        • - getFinalReporNoticeById('wp-config-changes'); - $htaccessNotice = $nManager->getFinalReporNoticeById('htaccess-changes'); - if ($wpconfigNotice) { - print("
        • Please validate ".$wpconfigNotice->longMsg."
        • "); - } - if ($htaccessNotice) { - print("
        • Please validate ".$htaccessNotice->longMsg."
        • "); - } - ?> -
        • For additional help and questions visit the online FAQs
        • -
        -
        - - -

        - -
        - - - - - -
        - - - -
        -


        - - - - - - diff --git a/installer/dup-installer/views/view.security.error.php b/installer/dup-installer/views/view.security.error.php deleted file mode 100644 index e017d840..00000000 --- a/installer/dup-installer/views/view.security.error.php +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - Duplicator - - - - - - - - - - - -
        -

        DUPLICATOR: SECURITY CHECK

        - An invalid request was made.
        - Message: Invalid token validation

        - In order to protect this request from unauthorized access please restart this install process by browsing to the installer.php file or hashed file. -
        - - \ No newline at end of file diff --git a/lib/config/class.wp.config.tranformer.php b/lib/config/class.wp.config.tranformer.php deleted file mode 100644 index deeca0b8..00000000 --- a/lib/config/class.wp.config.tranformer.php +++ /dev/null @@ -1,459 +0,0 @@ -wp_config_path = $wp_config_path; - } - - /** - * Checks if a config exists in the wp-config.php file. - * - * @throws Exception If the wp-config.php file is empty. - * @throws Exception If the requested config type is invalid. - * - * @param string $type Config type (constant or variable). - * @param string $name Config name. - * - * @return bool - */ - public function exists( $type, $name ) { - $wp_config_src = file_get_contents( $this->wp_config_path ); - - if ( ! trim( $wp_config_src ) ) { - throw new Exception( 'wp-config.php file is empty.' ); - } - - // SnapCreek custom change - // Normalize the newline to prevent an issue coming from OSX - $wp_config_src = str_replace(array("\n\r", "\r"), array("\n", "\n"), $wp_config_src); - - $this->wp_config_src = $wp_config_src; - $this->wp_configs = $this->parse_wp_config( $this->wp_config_src ); - - if ( ! isset( $this->wp_configs[ $type ] ) ) { - throw new Exception( "Config type '{$type}' does not exist." ); - } - - return isset( $this->wp_configs[ $type ][ $name ] ); - } - - /** - * Get the value of a config in the wp-config.php file. - * - * @throws Exception If the wp-config.php file is empty. - * @throws Exception If the requested config type is invalid. - * - * @param string $type Config type (constant or variable). - * @param string $name Config name. - * - * @return array - */ - public function get_value( $type, $name, $get_real_value = true) { - $wp_config_src = file_get_contents( $this->wp_config_path ); - if ( ! trim( $wp_config_src ) ) { - throw new Exception( 'wp-config.php file is empty.' ); - } - - // SnapCreek custom change - // Normalize the newline to prevent an issue coming from OSX - $wp_config_src = str_replace(array("\n\r", "\r"), array("\n", "\n"), $wp_config_src); - - - $this->wp_config_src = $wp_config_src; - $this->wp_configs = $this->parse_wp_config( $this->wp_config_src ); - - if ( ! isset( $this->wp_configs[ $type ] ) ) { - throw new Exception( "Config type '{$type}' does not exist." ); - } - - // Duplicator Extra - $val = $this->wp_configs[ $type ][ $name ]['value']; - if ($get_real_value) { - return self::getRealValFromVal($val); - } else { - return $val; - } - - return $val; - } - - public static function getRealValFromVal($val) - { - if ($val[0] === '\'') { - // string with ' - $result = substr($val, 1, strlen($val) - 2); - return str_replace(array('\\\'', '\\\\'), array('\'', '\\'), $result); - } else if ($val[0] === '"') { - // string with " - return json_decode(str_replace('\\$', '$', $val)); - } else if (strcasecmp($val, 'true') === 0) { - return true; - } else if (strcasecmp($val, 'false') === 0) { - return false; - } else if (strcasecmp($val, 'null') === 0) { - return null; - } else if (preg_match('/^[-+]?[0-9]+$/', $val)) { - return (int) $val; - } else if (preg_match('/^[-+]?[0-9]+\.[0-9]+$/', $val)) { - return (float) $val; - } else { - return $val; - } - } - - /** - * Adds a config to the wp-config.php file. - * - * @throws Exception If the config value provided is not a string. - * @throws Exception If the config placement anchor could not be located. - * - * @param string $type Config type (constant or variable). - * @param string $name Config name. - * @param string $value Config value. - * @param array $options (optional) Array of special behavior options. - * - * @return bool - */ - public function add( $type, $name, $value, array $options = array() ) { - if ( ! is_string( $value ) ) { - throw new Exception( 'Config value must be a string.' ); - } - - if ( $this->exists( $type, $name ) ) { - return false; - } - - $defaults = array( - 'raw' => false, // Display value in raw format without quotes. - 'anchor' => "/* That's all, stop editing!", // Config placement anchor string. - 'separator' => PHP_EOL, // Separator between config definition and anchor string. - 'placement' => 'before', // Config placement direction (insert before or after). - ); - - list( $raw, $anchor, $separator, $placement ) = array_values( array_merge( $defaults, $options ) ); - - $raw = (bool) $raw; - $anchor = (string) $anchor; - $separator = (string) $separator; - $placement = (string) $placement; - - // Custom code by the SnapCreek Team - if ( false === strpos( $this->wp_config_src, $anchor ) ) { - $other_anchor_points = array( - '/** Absolute path to the WordPress directory', - // ABSPATH defined check with single quote - "if ( !defined('ABSPATH') )", - "if ( ! defined( 'ABSPATH' ) )", - "if (!defined('ABSPATH') )", - "if(!defined('ABSPATH') )", - "if(!defined('ABSPATH'))", - "if ( ! defined( 'ABSPATH' ))", - "if ( ! defined( 'ABSPATH') )", - "if ( ! defined('ABSPATH' ) )", - "if (! defined( 'ABSPATH' ))", - "if (! defined( 'ABSPATH') )", - "if (! defined('ABSPATH' ) )", - "if ( !defined( 'ABSPATH' ))", - "if ( !defined( 'ABSPATH') )", - "if ( !defined('ABSPATH' ) )", - "if( !defined( 'ABSPATH' ))", - "if( !defined( 'ABSPATH') )", - "if( !defined('ABSPATH' ) )", - // ABSPATH defined check with double quote - 'if ( !defined("ABSPATH") )', - 'if ( ! defined( "ABSPATH" ) )', - 'if (!defined("ABSPATH") )', - 'if(!defined("ABSPATH") )', - 'if(!defined("ABSPATH"))', - 'if ( ! defined( "ABSPATH" ))', - 'if ( ! defined( "ABSPATH") )', - 'if ( ! defined("ABSPATH" ) )', - 'if (! defined( "ABSPATH" ))', - 'if (! defined( "ABSPATH") )', - 'if (! defined("ABSPATH" ) )', - 'if ( !defined( "ABSPATH" ))', - 'if ( !defined( "ABSPATH") )', - 'if ( !defined("ABSPATH" ) )', - 'if( !defined( "ABSPATH" ))', - 'if( !defined( "ABSPATH") )', - 'if( !defined("ABSPATH" ) )', - - '/** Sets up WordPress vars and included files', - 'require_once(ABSPATH', - 'require_once ABSPATH', - 'require_once( ABSPATH', - 'require_once', - "define( 'DB_NAME'", - 'define( "DB_NAME"', - "define('DB_NAME'", - 'define("DB_NAME"', - 'require', - 'include_once', - ); - foreach ($other_anchor_points as $anchor_point) { - $anchor_point = (string) $anchor_point; - if ( false !== strpos( $this->wp_config_src, $anchor_point ) ) { - $anchor = $anchor_point; - break; - } - } - } - - if ( false === strpos( $this->wp_config_src, $anchor ) ) { - throw new Exception( 'Unable to locate placement anchor.' ); - } - - $new_src = $this->normalize( $type, $name, $this->format_value( $value, $raw ) ); - $new_src = ( 'after' === $placement ) ? $anchor . $separator . $new_src : $new_src . $separator . $anchor; - $contents = str_replace( $anchor, $new_src, $this->wp_config_src ); - - return $this->save( $contents ); - } - - /** - * Updates an existing config in the wp-config.php file. - * - * @throws Exception If the config value provided is not a string. - * - * @param string $type Config type (constant or variable). - * @param string $name Config name. - * @param string $value Config value. - * @param array $options (optional) Array of special behavior options. - * - * @return bool - */ - public function update( $type, $name, $value, array $options = array() ) { - if ( ! is_string( $value ) ) { - throw new Exception( 'Config value must be a string.' ); - } - - $defaults = array( - 'add' => true, // Add the config if missing. - 'raw' => false, // Display value in raw format without quotes. - 'normalize' => false, // Normalize config output using WP Coding Standards. - ); - - list( $add, $raw, $normalize ) = array_values( array_merge( $defaults, $options ) ); - - $add = (bool) $add; - $raw = (bool) $raw; - $normalize = (bool) $normalize; - - if ( ! $this->exists( $type, $name ) ) { - return ( $add ) ? $this->add( $type, $name, $value, $options ) : false; - } - - $old_src = $this->wp_configs[ $type ][ $name ]['src']; - $old_value = $this->wp_configs[ $type ][ $name ]['value']; - $new_value = $this->format_value( $value, $raw ); - - if ( $normalize ) { - $new_src = $this->normalize( $type, $name, $new_value ); - } else { - $new_parts = $this->wp_configs[ $type ][ $name ]['parts']; - $new_parts[1] = str_replace( $old_value, $new_value, $new_parts[1] ); // Only edit the value part. - $new_src = implode( '', $new_parts ); - } - - $contents = preg_replace( - sprintf( '/(?<=^|;|<\?php\s|<\?\s)(\s*?)%s/m', preg_quote( trim( $old_src ), '/' ) ), - '$1' . self::REPLACE_TEMP_STIRNG , - $this->wp_config_src - ); - $contents = str_replace(self::REPLACE_TEMP_STIRNG, trim($new_src), $contents); - return $this->save( $contents ); - } - - /** - * Removes a config from the wp-config.php file. - * - * @param string $type Config type (constant or variable). - * @param string $name Config name. - * - * @return bool - */ - public function remove( $type, $name ) { - if ( ! $this->exists( $type, $name ) ) { - return false; - } - - $pattern = sprintf( '/(?<=^|;|<\?php\s|<\?\s)%s\s*(\S|$)/m', preg_quote( $this->wp_configs[ $type ][ $name ]['src'], '/' ) ); - $contents = preg_replace( $pattern, '$1', $this->wp_config_src ); - - return $this->save( $contents ); - } - - /** - * Applies formatting to a config value. - * - * @throws Exception When a raw value is requested for an empty string. - * - * @param string $value Config value. - * @param bool $raw Display value in raw format without quotes. - * - * @return mixed - */ - protected function format_value( $value, $raw ) { - if ( $raw && '' === trim( $value ) ) { - throw new Exception( 'Raw value for empty string not supported.' ); - } - - return ( $raw ) ? $value : var_export( $value, true ); - } - - /** - * Normalizes the source output for a name/value pair. - * - * @throws Exception If the requested config type does not support normalization. - * - * @param string $type Config type (constant or variable). - * @param string $name Config name. - * @param mixed $value Config value. - * - * @return string - */ - protected function normalize( $type, $name, $value ) { - if ( 'constant' === $type ) { - $placeholder = "define( '%s', %s );"; - } elseif ( 'variable' === $type ) { - $placeholder = '$%s = %s;'; - } else { - throw new Exception( "Unable to normalize config type '{$type}'." ); - } - - return sprintf( $placeholder, $name, $value ); - } - - /** - * Parses the source of a wp-config.php file. - * - * @param string $src Config file source. - * - * @return array - */ - protected function parse_wp_config( $src ) { - $configs = array(); - $configs['constant'] = array(); - $configs['variable'] = array(); - - // Strip comments. - foreach ( token_get_all( $src ) as $token ) { - if ( in_array( $token[0], array( T_COMMENT, T_DOC_COMMENT ), true ) ) { - $src = str_replace( $token[1], '', $src ); - } - } - - preg_match_all( '/(?<=^|;|<\?php\s|<\?\s)(\h*define\s*\(\s*[\'"](\w*?)[\'"]\s*)(,\s*(\'\'|""|\'.*?[^\\\\]\'|".*?[^\\\\]"|.*?)\s*)((?:,\s*(?:true|false)\s*)?\)\s*;)/ims', $src, $constants ); - preg_match_all( '/(?<=^|;|<\?php\s|<\?\s)(\h*\$(\w+)\s*=)(\s*(\'\'|""|\'.*?[^\\\\]\'|".*?[^\\\\]"|.*?)\s*;)/ims', $src, $variables ); - - - if ( ! empty( $constants[0] ) && ! empty( $constants[1] ) && ! empty( $constants[2] ) && ! empty( $constants[3] ) && ! empty( $constants[4] ) && ! empty( $constants[5] ) ) { - foreach ( $constants[2] as $index => $name ) { - $configs['constant'][ $name ] = array( - 'src' => $constants[0][ $index ], - 'value' => $constants[4][ $index ], - 'parts' => array( - $constants[1][ $index ], - $constants[3][ $index ], - $constants[5][ $index ], - ), - ); - } - } - - if ( ! empty( $variables[0] ) && ! empty( $variables[1] ) && ! empty( $variables[2] ) && ! empty( $variables[3] ) && ! empty( $variables[4] ) ) { - // Remove duplicate(s), last definition wins. - $variables[2] = array_reverse( array_unique( array_reverse( $variables[2], true ) ), true ); - foreach ( $variables[2] as $index => $name ) { - $configs['variable'][ $name ] = array( - 'src' => $variables[0][ $index ], - 'value' => $variables[4][ $index ], - 'parts' => array( - $variables[1][ $index ], - $variables[3][ $index ], - ), - ); - } - } - - return $configs; - } - - /** - * Saves new contents to the wp-config.php file. - * - * @throws Exception If the config file content provided is empty. - * @throws Exception If there is a failure when saving the wp-config.php file. - * - * @param string $contents New config contents. - * - * @return bool - */ - protected function save( $contents ) { - if ( ! trim( $contents ) ) { - throw new Exception( 'Cannot save the wp-config.php file with empty contents.' ); - } - - if ( $contents === $this->wp_config_src ) { - return false; - } - - $result = file_put_contents( $this->wp_config_path, $contents, LOCK_EX ); - - if ( false === $result ) { - throw new Exception( 'Failed to update the wp-config.php file.' ); - } - - return true; - } - -} - -endif; diff --git a/lib/config/class.wp.config.tranformer.src.php b/lib/config/class.wp.config.tranformer.src.php deleted file mode 100644 index 6f095156..00000000 --- a/lib/config/class.wp.config.tranformer.src.php +++ /dev/null @@ -1,92 +0,0 @@ -wp_config_src = str_replace(array("\n\r", "\r"), array("\n", "\n"), $wp_config_src); - } - - public function getSrc() - { - return $this->wp_config_src; - } - - /** - * Checks if a config exists in the wp-config.php src - * - * @throws Exception If the wp-config.php file is empty. - * @throws Exception If the requested config type is invalid. - * - * @param string $type Config type (constant or variable). - * @param string $name Config name. - * - * @return bool - */ - public function exists($type, $name) - { - $this->wp_configs = $this->parse_wp_config($this->wp_config_src); - - if (!isset($this->wp_configs[$type])) { - throw new Exception("Config type '{$type}' does not exist."); - } - - return isset($this->wp_configs[$type][$name]); - } - - /** - * Get the value of a config in the wp-config.php src - * - * @param string $type Config type (constant or variable). - * @param string $name Config name. - * - * @return array - */ - public function get_value($type, $name, $get_real_value = true) - { - $this->wp_configs = $this->parse_wp_config($this->wp_config_src); - - if (!isset($this->wp_configs[$type])) { - throw new Exception("Config type '{$type}' does not exist."); - } - - // Duplicator Extra - $val = $this->wp_configs[$type][$name]['value']; - if ($get_real_value) { - return self::getRealValFromVal($val); - } else { - return $val; - } - } - - /** - * update wp_config_src - * - * @param string $contents - * @return boolean - */ - protected function save($contents) - { - $this->wp_config_src = $contents; - return true; - } - } - -endif; diff --git a/lib/dup_archive/classes/class.duparchive.constants.php b/lib/dup_archive/classes/class.duparchive.constants.php deleted file mode 100644 index 4261c266..00000000 --- a/lib/dup_archive/classes/class.duparchive.constants.php +++ /dev/null @@ -1,34 +0,0 @@ -fileHeaders = array(); - $this->directoryHeaders = array(); - } -} -} - -if(!class_exists('DupArchiveItemAlias')) { -class DupArchiveItemAlias -{ - - public $oldName; - public $newName; - -} -} - -if(!class_exists('DupArchiveItemHeaderType')) { -class DupArchiveItemHeaderType -{ - - const None = 0; - const File = 1; - const Directory = 2; - const Glob = 3; - -} -} - -if(!class_exists('DupArchiveEngine')) { -class DupArchiveEngine -{ - - public static $archive; - public static function init($logger, $profilingFunction = null, $archive = null) - { - DupArchiveUtil::$logger = $logger; - DupArchiveUtil::$profilingFunction = $profilingFunction; - self::$archive = $archive; - } - - public static function getNextHeaderType($archiveHandle) - { - $retVal = DupArchiveItemHeaderType::None; - $marker = fgets($archiveHandle, 4); - - if (feof($archiveHandle) === false) { - switch ($marker) { - case '': - $retVal = DupArchiveItemHeaderType::Directory; - break; - - case '': - $retVal = DupArchiveItemHeaderType::File; - break; - - case '': - $retVal = DupArchiveItemHeaderType::Glob; - break; - - default: - throw new Exception("Invalid header marker {$marker}. Location:" . ftell($archiveHandle)); - } - } - - return $retVal; - } - - public static function getArchiveInfo($filepath) - { - $archiveInfo = new DupArchiveInfo(); - - DupArchiveUtil::log("archive size=" . filesize($filepath)); - $archiveHandle = DupLiteSnapLibIOU::fopen($filepath, 'rb'); - $moreFiles = true; - - $archiveInfo->archiveHeader = DupArchiveHeader::readFromArchive($archiveHandle); - - $moreToRead = true; - - while ($moreToRead) { - - $headerType = self::getNextHeaderType($archiveHandle); - - // DupArchiveUtil::log("next header type=$headerType: " . ftell($archiveHandle)); - - switch ($headerType) { - case DupArchiveItemHeaderType::File: - - $fileHeader = DupArchiveFileHeader::readFromArchive($archiveHandle, true, true); - $archiveInfo->fileHeaders[] = $fileHeader; - DupArchiveUtil::log("file" . $fileHeader->relativePath); - break; - - case DupArchiveItemHeaderType::Directory: - $directoryHeader = DupArchiveDirectoryHeader::readFromArchive($archiveHandle, true); - - $archiveInfo->directoryHeaders[] = $directoryHeader; - break; - - case DupArchiveItemHeaderType::None: - $moreToRead = false; - } - } - - return $archiveInfo; - } - - // can't span requests since create state can't store list of files - public static function addDirectoryToArchiveST($archiveFilepath, $directory, $basepath, $includeFiles = false, $newBasepath = null, $globSize = DupArchiveCreateState::DEFAULT_GLOB_SIZE) - { - if ($includeFiles) { - $scan = DupArchiveScanUtil::createScanObject($directory); - } else { - $scan->Files = array(); - $scan->Dirs = array(); - } - - $createState = new DupArchiveSimpleCreateState(); - - $createState->archiveOffset = filesize($archiveFilepath); - $createState->archivePath = $archiveFilepath; - $createState->basePath = $basepath; - $createState->timerEnabled = false; - $createState->globSize = $globSize; - $createState->newBasePath = $newBasepath; - - self::addItemsToArchive($createState, $scan); - - $retVal = new stdClass(); - $retVal->numDirsAdded = $createState->currentDirectoryIndex; - $retVal->numFilesAdded = $createState->currentFileIndex; - - if($createState->skippedFileCount > 0) { - - throw new Exception("One or more files were were not able to be added when adding {$directory} to {$archiveFilepath}"); - } - else if($createState->skippedDirectoryCount > 0) { - - throw new Exception("One or more directories were not able to be added when adding {$directory} to {$archiveFilepath}"); - } - - return $retVal; - } - - public static function addRelativeFileToArchiveST($archiveFilepath, $filepath, $relativePath, $globSize = DupArchiveCreateState::DEFAULT_GLOB_SIZE) - { - $createState = new DupArchiveSimpleCreateState(); - - $createState->archiveOffset = filesize($archiveFilepath); - $createState->archivePath = $archiveFilepath; - $createState->basePath = null; - $createState->timerEnabled = false; - $createState->globSize = $globSize; - - $scan = new stdClass(); - - $scan->Files = array(); - $scan->Dirs = array(); - - $scan->Files[] = $filepath; - - if ($relativePath != null) { - - $scan->FileAliases = array(); - $scan->FileAliases[$filepath] = $relativePath; - } - - self::addItemsToArchive($createState, $scan); - } - - public static function addFileToArchiveUsingBaseDirST($archiveFilepath, $basePath, $filepath, $globSize = DupArchiveCreateState::DEFAULT_GLOB_SIZE) - { - $createState = new DupArchiveSimpleCreateState(); - - $createState->archiveOffset = filesize($archiveFilepath); - $createState->archivePath = $archiveFilepath; - $createState->basePath = $basePath; - $createState->timerEnabled = false; - $createState->globSize = $globSize; - - $scan = new stdClass(); - - $scan->Files = array(); - $scan->Dirs = array(); - - $scan->Files[] = $filepath; - - self::addItemsToArchive($createState, $scan); - } - - public static function createArchive($archivePath, $isCompressed) - { - $archiveHandle = DupLiteSnapLibIOU::fopen($archivePath, 'w+b'); - - /* @var $archiveHeader DupArchiveHeader */ - $archiveHeader = DupArchiveHeader::create($isCompressed); - - $archiveHeader->writeToArchive($archiveHandle); - - // Intentionally do not write build state since if something goes wrong we went it to start over on the archive - - DupLiteSnapLibIOU::fclose($archiveHandle); - } - - public static function addItemsToArchive($createState, $scanFSInfo) - { - if ($createState->globSize == -1) { - - $createState->globSize = DupArchiveCreateState::DEFAULT_GLOB_SIZE; - } - /* @var $createState DupArchiveCreateState */ - DupArchiveUtil::tlogObject("addItemsToArchive start", $createState); - - $directoryCount = count($scanFSInfo->Dirs); - $fileCount = count($scanFSInfo->Files); - - $createState->startTimer(); - - /* @var $createState DupArchiveCreateState */ - $basepathLength = strlen($createState->basePath); - - $archiveHandle = DupLiteSnapLibIOU::fopen($createState->archivePath, 'r+b'); - - DupArchiveUtil::tlog("Archive size=", filesize($createState->archivePath)); - DupArchiveUtil::tlog("Archive location is now " . DupLiteSnapLibIOU::ftell($archiveHandle)); - - $archiveHeader = DupArchiveHeader::readFromArchive($archiveHandle); - - $createState->isCompressed = $archiveHeader->isCompressed; - - if ($createState->archiveOffset == filesize($createState->archivePath)) { - DupArchiveUtil::tlog("Seeking to end of archive location because of offset {$createState->archiveOffset} for file size " . filesize($createState->archivePath)); - DupLiteSnapLibIOU::fseek($archiveHandle, 0, SEEK_END); - } else { - DupArchiveUtil::tlog("Seeking archive offset {$createState->archiveOffset} for file size " . filesize($createState->archivePath)); - DupLiteSnapLibIOU::fseek($archiveHandle, $createState->archiveOffset); - } - - while (($createState->currentDirectoryIndex < $directoryCount) && (!$createState->timedOut())) { - - if ($createState->throttleDelayInUs !== 0) { - usleep($createState->throttleDelayInUs); - } - - $directory = $scanFSInfo->Dirs[$createState->currentDirectoryIndex]; - - try { - $relativeDirectoryPath = null; - - if (isset($scanFSInfo->DirectoryAliases) && array_key_exists($directory, $scanFSInfo->DirectoryAliases)) { - $relativeDirectoryPath = $scanFSInfo->DirectoryAliases[$directory]; - } else { - if (null === self::$archive) { - $relativeDirectoryPath = substr($directory, $basepathLength); - $relativeDirectoryPath = ltrim($relativeDirectoryPath, '/'); - if ($createState->newBasePath !== null) { - $relativeDirectoryPath = $createState->newBasePath . $relativeDirectoryPath; - } - } else { - $relativeDirectoryPath = self::$archive->getLocalDirPath($directory, $createState->newBasePath); - } - } - - if($relativeDirectoryPath !== '') { - DupArchiveDirectoryProcessor::writeDirectoryToArchive($createState, $archiveHandle, $directory, $relativeDirectoryPath); - } else { - $createState->skippedDirectoryCount++; - $createState->currentDirectoryIndex++; - } - } catch (Exception $ex) { - DupArchiveUtil::log("Failed to add {$directory} to archive. Error: " . $ex->getMessage(), true); - - $createState->addFailure(DupArchiveFailureTypes::Directory, $directory, $ex->getMessage(), false); - $createState->currentDirectoryIndex++; - $createState->skippedDirectoryCount++; - $createState->save(); - } - } - - $createState->archiveOffset = DupLiteSnapLibIOU::ftell($archiveHandle); - - $workTimestamp = time(); - while (($createState->currentFileIndex < $fileCount) && (!$createState->timedOut())) { - - $filepath = $scanFSInfo->Files[$createState->currentFileIndex]; - - try { - - $relativeFilePath = null; - - if (isset($scanFSInfo->FileAliases) && array_key_exists($filepath, $scanFSInfo->FileAliases)) { - $relativeFilePath = $scanFSInfo->FileAliases[$filepath]; - } else { - if (null === self::$archive) { - $relativeFilePath = substr($filepath, $basepathLength); - $relativeFilePath = ltrim($relativeFilePath, '/'); - if ($createState->newBasePath !== null) { - $relativeFilePath = $createState->newBasePath . $relativeFilePath; - } - } else { - $relativeFilePath = self::$archive->getLocalFilePath($filepath, $createState->newBasePath); - } - } - - // Uncomment when testing error handling -// if((strpos($relativeFilePath, 'dup-installer') !== false) || (strpos($relativeFilePath, 'lib') !== false)) { -// Dup_Log::Trace("Was going to do intentional error to {$relativeFilePath} but skipping"); -// } else { -// throw new Exception("#### intentional file error when writing " . $relativeFilePath); -// } -// } - - DupArchiveFileProcessor::writeFilePortionToArchive($createState, $archiveHandle, $filepath, $relativeFilePath); - - if(($createState->isRobust) && (time() - $workTimestamp >= 1)){ - DupArchiveUtil::log("Robust mode create state save"); - - // When in robustness mode save the state every second - $workTimestamp = time(); - $createState->working = ($createState->currentDirectoryIndex < $directoryCount) || ($createState->currentFileIndex < $fileCount); - $createState->save(); - } - } catch (Exception $ex) { - DupArchiveUtil::log("Failed to add {$filepath} to archive. Error: " . $ex->getMessage() . $ex->getTraceAsString(), true); - $createState->currentFileIndex++; - $createState->skippedFileCount++; - $createState->addFailure(DupArchiveFailureTypes::File, $filepath, $ex->getMessage(), ($ex->getCode() === DupArchiveExceptionCodes::Fatal)); - $createState->save(); - } - } - - $createState->working = ($createState->currentDirectoryIndex < $directoryCount) || ($createState->currentFileIndex < $fileCount); - $createState->save(); - - DupLiteSnapLibIOU::fclose($archiveHandle); - - if (!$createState->working) { - DupArchiveUtil::log("compress done"); - } else { - DupArchiveUtil::tlog("compress not done so continuing later"); - } - } - public static function expandDirectory($archivePath, $relativePath, $destPath) - { - self::expandItems($archivePath, $relativePath, $destPath); - } - - public static function expandArchive($expandState) - { - /* @var $expandState DupArchiveExpandState */ - $expandState->startTimer(); - - $archiveHandle = DupLiteSnapLibIOU::fopen($expandState->archivePath, 'rb'); - - DupLiteSnapLibIOU::fseek($archiveHandle, $expandState->archiveOffset); - - if ($expandState->archiveOffset == 0) { - - DupArchiveUtil::log("#### seeking to start of archive"); - - $expandState->archiveHeader = DupArchiveHeader::readFromArchive($archiveHandle); - $expandState->isCompressed = $expandState->archiveHeader->isCompressed; - $expandState->archiveOffset = DupLiteSnapLibIOU::ftell($archiveHandle); - - $expandState->save(); - } else { - - DupArchiveUtil::log("#### seeking archive offset {$expandState->archiveOffset}"); - } - - if ((!$expandState->validateOnly) || ($expandState->validationType == DupArchiveValidationTypes::Full)) { - $moreItems = self::expandItems($expandState, $archiveHandle); - } else { - // profile ok - $moreItems = self::standardValidateItems($expandState, $archiveHandle); - // end profile ok - } - - $expandState->working = $moreItems; - $expandState->save(); - - DupLiteSnapLibIOU::fclose($archiveHandle, false); - - if (!$expandState->working) { - - DupArchiveUtil::log("expand done"); - DupArchiveUtil::logObject('expandstate', $expandState); - - if (($expandState->expectedFileCount != -1) && ($expandState->expectedFileCount != $expandState->fileWriteCount)) { - - $expandState->addFailure(DupArchiveFailureTypes::File, 'Archive', "Number of files expected ({$expandState->expectedFileCount}) doesn't equal number written ({$expandState->fileWriteCount})."); - } - - if (($expandState->expectedDirectoryCount != -1) && ($expandState->expectedDirectoryCount != $expandState->directoryWriteCount)) { - $expandState->addFailure(DupArchiveFailureTypes::Directory, 'Archive', "Number of directories expected ({$expandState->expectedDirectoryCount}) doesn't equal number written ({$expandState->directoryWriteCount})."); - } - } else { - DupArchiveUtil::tlogObject("expand not done so continuing later", $expandState); - } - } - - private static function skipFileInArchive($archiveHandle, $fileHeader) - { - if ($fileHeader->fileSize > 0) { - - $dataSize = 0; - - do { - $globHeader = DupArchiveGlobHeader::readFromArchive($archiveHandle, true); - - $dataSize += $globHeader->originalSize; - - $moreGlobs = ($dataSize < $fileHeader->fileSize); - } while ($moreGlobs); - } - } - - // Assumes we are on one header and just need to get to the next - private static function skipToNextHeader($archiveHandle) - { - $headerType = self::getNextHeaderType($archiveHandle); - - switch ($headerType) { - case DupArchiveItemHeaderType::File: - $fileHeader = DupArchiveFileHeader::readFromArchive($archiveHandle, false, true); - - self::skipFileInArchive($archiveHandle, $fileHeader); - - break; - - case DupArchiveItemHeaderType::Directory: - - $directoryHeader = DupArchiveDirectoryHeader::readFromArchive($archiveHandle, true); - - break; - - case DupArchiveItemHeaderType::None: - $moreToRead = false; - } - } - - // Single-threaded file expansion - public static function expandFiles($archiveFilePath, $relativeFilePaths, $destPath) - { - // Not setting timeout timestamp so it will never timeout - DupArchiveUtil::tlog("opening archive {$archiveFilePath}"); - - $archiveHandle = DupLiteSnapLibIOU::fopen($archiveFilePath, 'r'); - - /* @var $expandState DupArchiveSimpleExpandState */ - $expandState = new DupArchiveSimpleExpandState(); - - $expandState->archiveHeader = DupArchiveHeader::readFromArchive($archiveHandle); - $expandState->isCompressed = $expandState->archiveHeader->isCompressed; - $expandState->archiveOffset = DupLiteSnapLibIOU::ftell($archiveHandle); - $expandState->includedFiles = $relativeFilePaths; - $expandState->filteredDirectories = array('*'); - $expandState->filteredFiles = array('*'); -// $expandState->basePath = $destPath . '/tempExtract'; // RSR remove once extract works - $expandState->basePath = $destPath; // RSR remove once extract works - - // TODO: Filter out all directories/files except those in the list - self::expandItems($expandState, $archiveHandle); - - } - - private static function expandItems(&$expandState, $archiveHandle) - { - /* @var $expandState DupArchiveExpandState */ - - $moreToRead = true; - - $workTimestamp = time(); - - while ($moreToRead && (!$expandState->timedOut())) { - - if ($expandState->throttleDelayInUs !== 0) { - usleep($expandState->throttleDelayInUs); - } - - if ($expandState->currentFileHeader != null) { - - DupArchiveUtil::tlog("Writing file {$expandState->currentFileHeader->relativePath}"); - - if (self::filePassesFilters($expandState->filteredDirectories, $expandState->filteredFiles, $expandState->includedFiles, $expandState->currentFileHeader->relativePath)) { - try { - $fileCompleted = DupArchiveFileProcessor::writeToFile($expandState, $archiveHandle); - } catch (Exception $ex) { - DupArchiveUtil::log("Failed to write to {$expandState->currentFileHeader->relativePath}. Error: " . $ex->getMessage(), true); - - // Reset things - skip over this file within the archive. - - DupLiteSnapLibIOU::fseek($archiveHandle, $expandState->lastHeaderOffset); - - self::skipToNextHeader($archiveHandle, $expandState->currentFileHeader); - - $expandState->archiveOffset = ftell($archiveHandle); - - $expandState->addFailure(DupArchiveFailureTypes::File, $expandState->currentFileHeader->relativePath, $ex->getMessage(), false); - - $expandState->resetForFile(); - - $expandState->lastHeaderOffset = -1; - - $expandState->save(); - } - } else { - DupArchiveUtil::log("skipping {$expandState->currentFileHeader->relativePath} because its part of the exclusion filter"); - self::skipFileInArchive($archiveHandle, $expandState->currentFileHeader); - - $expandState->resetForFile(); - } - } else { - // Header is null so read in the next one - - $expandState->lastHeaderOffset = @ftell($archiveHandle); - - // profile ok - $headerType = self::getNextHeaderType($archiveHandle); - // end profile ok - - DupArchiveUtil::tlog('header type ' . $headerType); - switch ($headerType) { - case DupArchiveItemHeaderType::File: - DupArchiveUtil::tlog('File header'); - $expandState->currentFileHeader = DupArchiveFileHeader::readFromArchive($archiveHandle, false, true); - - $expandState->archiveOffset = @ftell($archiveHandle); - - DupArchiveUtil::tlog('Just read file header from archive'); - - break; - - case DupArchiveItemHeaderType::Directory: - DupArchiveUtil::tlog('Directory Header'); - - $directoryHeader = DupArchiveDirectoryHeader::readFromArchive($archiveHandle, true); - - if (self::passesDirectoryExclusion($expandState->filteredDirectories, $directoryHeader->relativePath)) { - - $createdDirectory = true; - - if (!$expandState->validateOnly) { - $directory = $expandState->basePath . '/' . $directoryHeader->relativePath; - $mode = 'u+rwx'; - if ($expandState->directoryModeOverride != -1) { - $mode = $expandState->directoryModeOverride; - } - $createdDirectory = DupLiteSnapLibIOU::dirWriteCheckOrMkdir($directory, $mode, true); - } - - if ($createdDirectory) { - $expandState->directoryWriteCount++; - } else { - $expandState->addFailure(DupArchiveFailureTypes::Directory, $directory, "Unable to create directory $directory", false); - } - } - $expandState->archiveOffset = ftell($archiveHandle); - - DupArchiveUtil::tlog('Just read directory header ' . $directoryHeader->relativePath . ' from archive'); - break; - - case DupArchiveItemHeaderType::None: - $moreToRead = false; - } - } - - if(($expandState->isRobust) && (time() - $workTimestamp >= 1)){ - - DupArchiveUtil::log("Robust mode extract state save for standard validate"); - - // When in robustness mode save the state every second - $workTimestamp = time(); - $expandState->save(); - } - } - - $expandState->save(); - - return $moreToRead; - } - - private static function passesDirectoryExclusion($directoryFilters, $candidate) - { - foreach ($directoryFilters as $directoryFilter) { - - if($directoryFilter === '*') { - return false; - } - - if (substr($candidate, 0, strlen($directoryFilter)) == $directoryFilter) { - - return false; - } - } - - return true; - } - - private static function filePassesFilters($excludedDirectories, $excludedFiles, $includedFiles, $candidate) - { - $retVal = true; - - // Included files trumps all exclusion filters - foreach($includedFiles as $includedFile) { - if($includedFile === $candidate) { - return true; - } - } - - if (self::passesDirectoryExclusion($excludedDirectories, $candidate)) { - - foreach ($excludedFiles as $fileFilter) { - - if($fileFilter === '*') { - return false; - } - - if ($fileFilter === $candidate) { - - $retVal = false; - break; - } - } - } else { - - $retVal = false;; - } - - return $retVal; - } - - private static function standardValidateItems(&$expandState, $archiveHandle) - { - $moreToRead = true; - - // profile ok - $to = $expandState->timedOut(); - // end profile ok - - $workTimestamp = time(); - - while ($moreToRead && (!$to)) { - - if ($expandState->throttleDelayInUs !== 0) { - usleep($expandState->throttleDelayInUs); - } - - if ($expandState->currentFileHeader != null) { - - try { - - $fileCompleted = DupArchiveFileProcessor::standardValidateFileEntry($expandState, $archiveHandle); - - if ($fileCompleted) { - $expandState->resetForFile(); - } - - // Expand state taken care of within the write to file to ensure consistency - } catch (Exception $ex) { - - DupArchiveUtil::log("Failed validate file in archive. Error: " . $ex->getMessage(), true); - DupArchiveUtil::logObject("expand state", $expandState, true); - // $expandState->currentFileIndex++; - // RSR TODO: Need way to skip past that file - - $expandState->addFailure(DupArchiveFailureTypes::File, $expandState->currentFileHeader->relativePath, $ex->getMessage()); - $expandState->save(); - - $moreToRead = false; - } - } else { - - // profile ok - $headerType = self::getNextHeaderType($archiveHandle); - - switch ($headerType) { - case DupArchiveItemHeaderType::File: - - // profile ok - $expandState->currentFileHeader = DupArchiveFileHeader::readFromArchive($archiveHandle, false, true); - - $expandState->archiveOffset = ftell($archiveHandle); - - // end profile ok - - break; - - case DupArchiveItemHeaderType::Directory: - - // profile ok - $directoryHeader = DupArchiveDirectoryHeader::readFromArchive($archiveHandle, true); - - $expandState->directoryWriteCount++; - $expandState->archiveOffset = ftell($archiveHandle); - - break; - - case DupArchiveItemHeaderType::None: - $moreToRead = false; - } - } - - if(($expandState->isRobust) && (time() - $workTimestamp >= 1)){ - - DupArchiveUtil::log("Robust mdoe extract state save for standard validate"); - - // When in robustness mode save the state every second - $workTimestamp = time(); - $expandState->save(); - } - - // profile ok - $to = $expandState->timedOut(); - } - - // profile ok - $expandState->save(); - - return $moreToRead; - } -} -} diff --git a/lib/dup_archive/classes/class.duparchive.loggerbase.php b/lib/dup_archive/classes/class.duparchive.loggerbase.php deleted file mode 100644 index cbccb735..00000000 --- a/lib/dup_archive/classes/class.duparchive.loggerbase.php +++ /dev/null @@ -1,8 +0,0 @@ -"; - $expectedEnd = ""; - - $startingElement = fread($archiveHandle, strlen($expectedStart)); - - if($startingElement !== $expectedStart) { - throw new Exception("Invalid starting element. Was expecting {$expectedStart} but got {$startingElement}"); - } - - return stream_get_line($archiveHandle, self::MaxStandardHeaderFieldLength, $expectedEnd); - } -} - -class DupArchiveMiniItemHeaderType -{ - const None = 0; - const File = 1; - const Directory = 2; - const Glob = 3; -} - -class DupArchiveMiniFileHeader -{ - public $fileSize; - public $mtime; - public $permissions; - public $hash; - public $relativePathLength; - public $relativePath; - - static function readFromArchive($archiveHandle) - { - $instance = new DupArchiveMiniFileHeader(); - - $instance->fileSize = DupArchiveHeaderMiniU::readStandardHeaderField($archiveHandle, 'FS'); - $instance->mtime = DupArchiveHeaderMiniU::readStandardHeaderField($archiveHandle, 'MT'); - $instance->permissions = DupArchiveHeaderMiniU::readStandardHeaderField($archiveHandle, 'P'); - $instance->hash = DupArchiveHeaderMiniU::readStandardHeaderField($archiveHandle, 'HA'); - $instance->relativePathLength = DupArchiveHeaderMiniU::readStandardHeaderField($archiveHandle, 'RPL'); - - // Skip - fread($archiveHandle, 4); - - $instance->relativePath = fread($archiveHandle, $instance->relativePathLength); - - // Skip - fread($archiveHandle, 5); - - // Skip the #F! - //fread($archiveHandle, 3); - // Skip the - fread($archiveHandle, 4); - - return $instance; - } -} - -class DupArchiveMiniDirectoryHeader -{ - public $mtime; - public $permissions; - public $relativePathLength; - public $relativePath; - - // const MaxHeaderSize = 8192; - // const MaxStandardHeaderFieldLength = 128; - - static function readFromArchive($archiveHandle) - { - $instance = new DupArchiveMiniDirectoryHeader(); - - $instance->mtime = DupArchiveHeaderMiniU::readStandardHeaderField($archiveHandle, 'MT'); - $instance->permissions = DupArchiveHeaderMiniU::readStandardHeaderField($archiveHandle, 'P'); - $instance->relativePathLength = DupArchiveHeaderMiniU::readStandardHeaderField($archiveHandle, 'RPL'); - - // Skip the - fread($archiveHandle, 4); - - $instance->relativePath = fread($archiveHandle, $instance->relativePathLength); - - // Skip the - fread($archiveHandle, 5); - - // Skip the - fread($archiveHandle, 4); - - return $instance; - } -} - -class DupArchiveMiniGlobHeader //extends HeaderBase -{ - public $originalSize; - public $storedSize; - public $hash; - - // const MaxHeaderSize = 255; - - public static function readFromArchive($archiveHandle, $skipGlob) - { - $instance = new DupArchiveMiniGlobHeader(); - - // DupArchiveUtil::log('Reading glob starting at ' . ftell($archiveHandle)); - - $startElement = fread($archiveHandle, 3); - - //if ($marker != '?G#') { - if ($startElement != '') { - throw new Exception("Invalid glob header marker found {$startElement}. location:" . ftell($archiveHandle)); - } - - $instance->originalSize = DupArchiveHeaderMiniU::readStandardHeaderField($archiveHandle, 'OS'); - $instance->storedSize = DupArchiveHeaderMiniU::readStandardHeaderField($archiveHandle, 'SS'); - $instance->hash = DupArchiveHeaderMiniU::readStandardHeaderField($archiveHandle, 'HA'); - - // Skip the - fread($archiveHandle, 4); - - if ($skipGlob) { - // DupLiteSnapLibIOU::fseek($archiveHandle, $instance->storedSize, SEEK_CUR); - if(fseek($archiveHandle, $instance->storedSize, SEEK_CUR) === -1) - { - throw new Exception("Can't fseek when skipping glob at location:".ftell($archiveHandle)); - } - } - - return $instance; - } -} - -class DupArchiveMiniHeader -{ - public $version; - public $isCompressed; - -// const MaxHeaderSize = 50; - - private function __construct() - { - // Prevent instantiation - if (!class_exists('DUPX_Bootstrap')) { - throw new Exception('Class DUPX_Bootstrap not found'); - } - } - - public static function readFromArchive($archiveHandle) - { - $instance = new DupArchiveMiniHeader(); - - $startElement = fgets($archiveHandle, 4); - - if ($startElement != '') { - throw new Exception("Invalid archive header marker found {$startElement}"); - } - - $instance->version = DupArchiveHeaderMiniU::readStandardHeaderField($archiveHandle, 'V'); - $instance->isCompressed = DupArchiveHeaderMiniU::readStandardHeaderField($archiveHandle, 'C') == 'true' ? true : false; - - // Skip the - fgets($archiveHandle, 5); - - return $instance; - } -} - -class DupArchiveMiniWriteInfo -{ - public $archiveHandle = null; - public $currentFileHeader = null; - public $destDirectory = null; - public $directoryWriteCount = 0; - public $fileWriteCount = 0; - public $isCompressed = false; - public $enableWrite = false; - - public function getCurrentDestFilePath() - { - if($this->destDirectory != null) - { - return "{$this->destDirectory}/{$this->currentFileHeader->relativePath}"; - } - else - { - return null; - } - } - -} - -class DupArchiveMiniExpander -{ - - public static $loggingFunction = null; - - public static function init($loggingFunction) - { - self::$loggingFunction = $loggingFunction; - } - - public static function log($s, $flush=false) - { - if(self::$loggingFunction != null) { - call_user_func(self::$loggingFunction, "MINI EXPAND:$s", $flush); - } - } - - public static function expandDirectory($archivePath, $relativePath, $destPath) - { - self::expandItems($archivePath, $relativePath, $destPath); - } - - private static function expandItems($archivePath, $inclusionFilter, $destDirectory, $ignoreErrors = false) - { - $archiveHandle = fopen($archivePath, 'rb'); - - if ($archiveHandle === false) { - throw new Exception("Can’t open archive at $archivePath!"); - } - - $archiveHeader = DupArchiveMiniHeader::readFromArchive($archiveHandle); - - $writeInfo = new DupArchiveMiniWriteInfo(); - - $writeInfo->destDirectory = $destDirectory; - $writeInfo->isCompressed = $archiveHeader->isCompressed; - - $moreToRead = true; - - while ($moreToRead) { - - if ($writeInfo->currentFileHeader != null) { - - try { - if (self::passesInclusionFilter($inclusionFilter, $writeInfo->currentFileHeader->relativePath)) { - - self::writeToFile($archiveHandle, $writeInfo); - - $writeInfo->fileWriteCount++; - } - else if($writeInfo->currentFileHeader->fileSize > 0) { - // self::log("skipping {$writeInfo->currentFileHeader->relativePath} since it doesn’t match the filter"); - - // Skip the contents since the it isn't a match - $dataSize = 0; - - do { - $globHeader = DupArchiveMiniGlobHeader::readFromArchive($archiveHandle, true); - - $dataSize += $globHeader->originalSize; - - $moreGlobs = ($dataSize < $writeInfo->currentFileHeader->fileSize); - } while ($moreGlobs); - } - - $writeInfo->currentFileHeader = null; - - // Expand state taken care of within the write to file to ensure consistency - } catch (Exception $ex) { - - if (!$ignoreErrors) { - throw $ex; - } - } - } else { - - $headerType = self::getNextHeaderType($archiveHandle); - - switch ($headerType) { - case DupArchiveMiniItemHeaderType::File: - - //$writeInfo->currentFileHeader = DupArchiveMiniFileHeader::readFromArchive($archiveHandle, $inclusionFilter); - $writeInfo->currentFileHeader = DupArchiveMiniFileHeader::readFromArchive($archiveHandle); - - break; - - case DupArchiveMiniItemHeaderType::Directory: - - $directoryHeader = DupArchiveMiniDirectoryHeader::readFromArchive($archiveHandle); - - // self::log("considering $inclusionFilter and {$directoryHeader->relativePath}"); - if (self::passesInclusionFilter($inclusionFilter, $directoryHeader->relativePath)) { - - // self::log("passed"); - $directory = "{$writeInfo->destDirectory}/{$directoryHeader->relativePath}"; - - // $mode = $directoryHeader->permissions; - - // rodo handle this more elegantly @mkdir($directory, $directoryHeader->permissions, true); - DUPX_Bootstrap::mkdir($directory, 'u+rwx', true); - - - $writeInfo->directoryWriteCount++; - } - else { - // self::log("didnt pass"); - } - - - break; - - case DupArchiveMiniItemHeaderType::None: - $moreToRead = false; - } - } - } - - fclose($archiveHandle); - } - - private static function getNextHeaderType($archiveHandle) - { - $retVal = DupArchiveMiniItemHeaderType::None; - $marker = fgets($archiveHandle, 4); - - if (feof($archiveHandle) === false) { - switch ($marker) { - case '': - $retVal = DupArchiveMiniItemHeaderType::Directory; - break; - - case '': - $retVal = DupArchiveMiniItemHeaderType::File; - break; - - case '': - $retVal = DupArchiveMiniItemHeaderType::Glob; - break; - - default: - throw new Exception("Invalid header marker {$marker}. Location:".ftell($archiveHandle)); - } - } - - return $retVal; - } - - private static function writeToFile($archiveHandle, $writeInfo) - { - $destFilePath = $writeInfo->getCurrentDestFilePath(); - - if($writeInfo->currentFileHeader->fileSize > 0) - { - /* @var $writeInfo DupArchiveMiniWriteInfo */ - $parentDir = dirname($destFilePath); - if (!file_exists($parentDir)) { - if (!DUPX_Bootstrap::mkdir($parentDir, 'u+rwx', true)) { - throw new Exception("Couldn't create {$parentDir}"); - } - } - - $destFileHandle = fopen($destFilePath, 'wb+'); - if ($destFileHandle === false) { - throw new Exception("Couldn't open {$destFilePath} for writing."); - } - - do { - - self::appendGlobToFile($archiveHandle, $destFileHandle, $writeInfo); - - $currentFileOffset = ftell($destFileHandle); - - $moreGlobstoProcess = $currentFileOffset < $writeInfo->currentFileHeader->fileSize; - } while ($moreGlobstoProcess); - - fclose($destFileHandle); - - DUPX_Bootstrap::chmod($destFilePath, 'u+rw'); - - self::validateExpandedFile($writeInfo); - } else { - if(touch($destFilePath) === false) { - throw new Exception("Couldn't create $destFilePath"); - } - DUPX_Bootstrap::chmod($destFilePath, 'u+rw'); - } - } - - private static function validateExpandedFile($writeInfo) - { - /* @var $writeInfo DupArchiveMiniWriteInfo */ - - if ($writeInfo->currentFileHeader->hash !== '00000000000000000000000000000000') { - - $hash = hash_file('crc32b', $writeInfo->getCurrentDestFilePath()); - - if ($hash !== $writeInfo->currentFileHeader->hash) { - - throw new Exception("MD5 validation fails for {$writeInfo->getCurrentDestFilePath()}"); - } - } - } - - // Assumption is that archive handle points to a glob header on this call - private static function appendGlobToFile($archiveHandle, $destFileHandle, $writeInfo) - { - /* @var $writeInfo DupArchiveMiniWriteInfo */ - $globHeader = DupArchiveMiniGlobHeader::readFromArchive($archiveHandle, false); - - $globContents = fread($archiveHandle, $globHeader->storedSize); - - if ($globContents === false) { - - throw new Exception("Error reading glob from {$writeInfo->getDestFilePath()}"); - } - - if ($writeInfo->isCompressed) { - $globContents = gzinflate($globContents); - } - - if (fwrite($destFileHandle, $globContents) === false) { - throw new Exception("Error writing data glob to {$destFileHandle}"); - } - } - - private static function passesInclusionFilter($filter, $candidate) - { - return (substr($candidate, 0, strlen($filter)) == $filter); - } -} -?> \ No newline at end of file diff --git a/lib/dup_archive/classes/class.duparchive.processing.failure.php b/lib/dup_archive/classes/class.duparchive.processing.failure.php deleted file mode 100644 index db7086f2..00000000 --- a/lib/dup_archive/classes/class.duparchive.processing.failure.php +++ /dev/null @@ -1,25 +0,0 @@ -permissions = substr(sprintf('%o', fileperms($directoryPath)), -4); -// $instance->mtime = DupLiteSnapLibIOU::filemtime($directoryPath); -// $instance->relativePath = $relativePath; -// $instance->relativePathLength = strlen($instance->relativePath); -// -// return $instance; -// } - - static function readFromArchive($archiveHandle, $skipStartElement = false) - { - $instance = new DupArchiveDirectoryHeader(); - - if(!$skipStartElement) - { - // - $startElement = fread($archiveHandle, 3); - - if ($startElement === false) { - if (feof($archiveHandle)) { - return false; - } else { - throw new Exception('Error reading directory header'); - } - } - - if ($startElement != '') { - throw new Exception("Invalid directory header marker found [{$startElement}] : location ".ftell($archiveHandle)); - } - } - - $instance->mtime = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'MT'); - $instance->permissions = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'P'); - $instance->relativePathLength = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'RPL'); - - // Skip the - fread($archiveHandle, 4); - - $instance->relativePath = fread($archiveHandle, $instance->relativePathLength); - - // Skip the -// fread($archiveHandle, 5); -// -// // Skip the -// fread($archiveHandle, 4); - - // Skip the and the - fread($archiveHandle, 9); - - return $instance; - } - - public function writeToArchive($archiveHandle) - { - if($this->relativePathLength == 0) - { - // Don't allow a base path to be written to the archive - return; - } - - $headerString = ''.$this->mtime.'

        '.$this->permissions.'

        '.$this->relativePathLength.''.$this->relativePath.'
        '; - - //DupLiteSnapLibIOU::fwrite($archiveHandle, $headerString); - $bytes_written = @fwrite($archiveHandle, $headerString); - - if ($bytes_written === false) { - throw new Exception('Error writing to file.'); - } else { - return $bytes_written; - } - } - -} -} \ No newline at end of file diff --git a/lib/dup_archive/classes/headers/class.duparchive.header.file.php b/lib/dup_archive/classes/headers/class.duparchive.header.file.php deleted file mode 100644 index 937f69b8..00000000 --- a/lib/dup_archive/classes/headers/class.duparchive.header.file.php +++ /dev/null @@ -1,145 +0,0 @@ -fileSize = DupLiteSnapLibIOU::filesize($filepath); - // end profile ok - - // profile ok - $instance->permissions = substr(sprintf('%o', fileperms($filepath)), -4); - // end profile ok - - // profile ok - $instance->mtime = DupLiteSnapLibIOU::filemtime($filepath); - // end profile ok - - if($instance->fileSize > DupArchiveConstants::$MaxFilesizeForHashing) { - $instance->hash = false; - } - else { - $instance->hash = hash_file('crc32b', $filepath); - } - - $instance->relativePath = $relativeFilePath; - $instance->relativePathLength = strlen($instance->relativePath); - - // DupArchiveUtil::tlog("paths=$filepath, {$instance->relativePath}"); - if ($instance->hash === false) { - // RSR TODO: Best thing to do here? - $instance->hash = "00000000000000000000000000000000"; - } - - return $instance; - - } - - /* - * delta = 84-22 = 62 bytes per file -> 20000 files -> 1.2MB larger - * xxxxxx - # F#x#x#x#x#x#x! - * - */ - static function readFromArchive($archiveHandle, $skipContents, $skipMarker = false) - { - // RSR TODO Read header from archive handle and populate members - // TODO: return null if end of archive or throw exception if can read something but its not a file header - - $instance = new DupArchiveFileHeader(); - - if (!$skipMarker) { - $marker = @fread($archiveHandle, 3); - - if ($marker === false) { - if (feof($archiveHandle)) { - return false; - } else { - throw new Exception('Error reading file header'); - } - } - - if ($marker != '') { - throw new Exception("Invalid file header marker found [{$marker}] : location ".ftell($archiveHandle)); - } - } - - $instance->fileSize = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'FS'); - $instance->mtime = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'MT'); - $instance->permissions = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'P'); - $instance->hash = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'HA'); - $instance->relativePathLength = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'RPL'); - - // Skip - fread($archiveHandle, 4); - - $instance->relativePath = fread($archiveHandle, $instance->relativePathLength); - - // Skip - // fread($archiveHandle, 5); - - // Skip the -// fread($archiveHandle, 4); - - // Skip the and the
        - fread($archiveHandle, 9); - - if ($skipContents && ($instance->fileSize > 0)) { - - $dataSize = 0; - - $moreGlobs = true; - while ($moreGlobs) { - //echo 'read glob
        '; - /* @var $globHeader DupArchiveGlobHeader */ - $globHeader = DupArchiveGlobHeader::readFromArchive($archiveHandle, true); - - $dataSize += $globHeader->originalSize; - - $moreGlobs = ($dataSize < $instance->fileSize); - } - } - - return $instance; - } - - public function writeToArchive($archiveHandle) - { - $headerString = ''.$this->fileSize.''.$this->mtime.'

        '.$this->permissions.'

        '.$this->hash.''.$this->relativePathLength.''.$this->relativePath.'
        '; - - //DupLiteSnapLibIOU::fwrite($archiveHandle, $headerString); - $bytes_written = @fwrite($archiveHandle, $headerString); - - if ($bytes_written === false) { - throw new Exception('Error writing to file.'); - } else { - return $bytes_written; - } - } -} -} \ No newline at end of file diff --git a/lib/dup_archive/classes/headers/class.duparchive.header.glob.php b/lib/dup_archive/classes/headers/class.duparchive.header.glob.php deleted file mode 100644 index c0400a52..00000000 --- a/lib/dup_archive/classes/headers/class.duparchive.header.glob.php +++ /dev/null @@ -1,66 +0,0 @@ -') { - throw new Exception("Invalid glob header marker found {$startElement}. location:" . ftell($archiveHandle)); - } - - $instance->originalSize = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'OS'); - $instance->storedSize = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'SS'); - $instance->hash = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'HA'); - - // Skip the - fread($archiveHandle, 4); - - if ($skipGlob) { - DupLiteSnapLibIOU::fseek($archiveHandle, $instance->storedSize, SEEK_CUR); - } - - return $instance; - } - - public function writeToArchive($archiveHandle) - { - // xxxx - - $headerString = ''.$this->originalSize.''.$this->storedSize.''.$this->hash.''; - - //DupLiteSnapLibIOU::fwrite($archiveHandle, $headerString); - $bytes_written = @fwrite($archiveHandle, $headerString); - - if ($bytes_written === false) { - throw new Exception('Error writing to file.'); - } else { - return $bytes_written; - } - } -} -} \ No newline at end of file diff --git a/lib/dup_archive/classes/headers/class.duparchive.header.php b/lib/dup_archive/classes/headers/class.duparchive.header.php deleted file mode 100644 index b0580f27..00000000 --- a/lib/dup_archive/classes/headers/class.duparchive.header.php +++ /dev/null @@ -1,74 +0,0 @@ -directoryCount = $directoryCount; - // $instance->fileCount = $fileCount; - $instance->version = DUPARCHIVE_VERSION; - $instance->isCompressed = $isCompressed; - - return $instance; - } - - public static function readFromArchive($archiveHandle) - { - $instance = new DupArchiveHeader(); - - $startElement = fgets($archiveHandle, 4); - - if ($startElement != '
        ') { - throw new Exception("Invalid archive header marker found {$startElement}"); - } - - $instance->version = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'V'); - $instance->isCompressed = DupArchiveHeaderU::readStandardHeaderField($archiveHandle, 'C') == 'true' ? true : false; - - // Skip the - fgets($archiveHandle, 5); - - return $instance; - } - - public function writeToArchive($archiveHandle) - { - $isCompressedString = DupArchiveUtil::boolToString($this->isCompressed); - - //DupLiteSnapLibIOU::fwrite($archiveHandle, "{$this->version}{$isCompressedString}"); - DupLiteSnapLibIOU::fwrite($archiveHandle, ''.$this->version.''.$isCompressedString.''); - } -} -} \ No newline at end of file diff --git a/lib/dup_archive/classes/headers/class.duparchive.header.u.php b/lib/dup_archive/classes/headers/class.duparchive.header.u.php deleted file mode 100644 index 70c0f04f..00000000 --- a/lib/dup_archive/classes/headers/class.duparchive.header.u.php +++ /dev/null @@ -1,36 +0,0 @@ -'; - $expectedEnd = ''; - - $startingElement = fread($archiveHandle, strlen($expectedStart)); - - if($startingElement !== $expectedStart) { - throw new Exception("Invalid starting element. Was expecting {$expectedStart} but got {$startingElement}"); - } - - //return DupLiteSnapLibStreamU::streamGetLine($archiveHandle, self::MaxStandardHeaderFieldLength, $expectedEnd); - - $headerString = stream_get_line($archiveHandle, self::MaxStandardHeaderFieldLength, $expectedEnd); - - if ($headerString === false) { - throw new Exception('Error reading line.'); - } - - return $headerString; - } -} -} \ No newline at end of file diff --git a/lib/dup_archive/classes/headers/index.php b/lib/dup_archive/classes/headers/index.php deleted file mode 100644 index 17a71fa7..00000000 --- a/lib/dup_archive/classes/headers/index.php +++ /dev/null @@ -1,2 +0,0 @@ -permissions = substr(sprintf('%o', fileperms($sourceDirectoryPath)), -4); - $directoryHeader->mtime = DupLiteSnapLibIOU::filemtime($sourceDirectoryPath); - $directoryHeader->relativePath = $relativeDirectoryPath; - $directoryHeader->relativePathLength = strlen($directoryHeader->relativePath); - - $directoryHeader->writeToArchive($archiveHandle); - - // Just increment this here - the actual state save is on the outside after timeout or completion of all directories - $createState->currentDirectoryIndex++; - - } -} -} \ No newline at end of file diff --git a/lib/dup_archive/classes/processors/class.duparchive.processor.file.php b/lib/dup_archive/classes/processors/class.duparchive.processor.file.php deleted file mode 100644 index 4fc10ce2..00000000 --- a/lib/dup_archive/classes/processors/class.duparchive.processor.file.php +++ /dev/null @@ -1,421 +0,0 @@ -archiveOffset = DupLiteSnapLibIOU::ftell($archiveHandle); - $createState->currentFileIndex++; - $createState->currentFileOffset = 0; - $createState->skippedFileCount++; - $createState->addFailure(DupArchiveFailureTypes::File, $sourceFilepath, "Couldn't open $sourceFilepath", false); - - return; - } - - if ($createState->currentFileOffset > 0) { - DupArchiveUtil::tlog("Continuing {$sourceFilepath} so seeking to {$createState->currentFileOffset}"); - - DupLiteSnapLibIOU::fseek($sourceHandle, $createState->currentFileOffset); - } else { - DupArchiveUtil::tlog("Starting new file entry for {$sourceFilepath}"); - - - // profile ok - $fileHeader = DupArchiveFileHeader::createFromFile($sourceFilepath, $relativeFilePath); - // end profile ok - - // profile ok - $fileHeader->writeToArchive($archiveHandle); - // end profile ok - } - - // profile ok - $sourceFileSize = filesize($sourceFilepath); - - DupArchiveUtil::tlog("writeFileToArchive for {$sourceFilepath}, size {$sourceFileSize}"); - - $moreFileDataToProcess = true; - - while ((!$createState->timedOut()) && $moreFileDataToProcess) { - - if($createState->throttleDelayInUs !== 0) { - usleep($createState->throttleDelayInUs); - } - - DupArchiveUtil::tlog("Writing offset={$createState->currentFileOffset}"); - - // profile ok - $moreFileDataToProcess = self::appendGlobToArchive($createState, $archiveHandle, $sourceHandle, $sourceFilepath, $sourceFileSize); - // end profile ok - - // profile ok - if ($moreFileDataToProcess) { - - DupArchiveUtil::tlog("Need to keep writing {$sourceFilepath} to archive"); - $createState->currentFileOffset += $createState->globSize; - $createState->archiveOffset = DupLiteSnapLibIOU::ftell($archiveHandle); //?? - } else { - - DupArchiveUtil::tlog("Completed writing {$sourceFilepath} to archive"); - $createState->archiveOffset = DupLiteSnapLibIOU::ftell($archiveHandle); - $createState->currentFileIndex++; - $createState->currentFileOffset = 0; - } - - // end profile ok - - if ($createState->currentFileIndex % 100 == 0) { - DupArchiveUtil::log("Archive Offset={$createState->archiveOffset}; Current File Index={$createState->currentFileIndex}; Current File Offset={$createState->currentFileOffset}"); - } - - // Only writing state after full group of files have been written - less reliable but more efficient - // $createState->save(); - } - - // profile ok - DupLiteSnapLibIOU::fclose($sourceHandle); - // end profile ok - } - - // Assumption is that this is called at the beginning of a glob header since file header already writtern - public static function writeToFile($expandState, $archiveHandle) - { - /* @var $expandState DupArchiveExpandState */ - $destFilepath = $expandState->basePath.'/'.$expandState->currentFileHeader->relativePath; - - $parentDir = dirname($destFilepath); - - $moreGlobstoProcess = true; - - DupLiteSnapLibIOU::dirWriteCheckOrMkdir($parentDir, 'u+rwx'); - - if ($expandState->currentFileHeader->fileSize > 0) { - - if ($expandState->currentFileOffset > 0) { - $destFileHandle = DupLiteSnapLibIOU::fopen($destFilepath, 'r+b'); - - DupArchiveUtil::tlog('Continuing '.$destFilepath.' so seeking to '.$expandState->currentFileOffset); - - DupLiteSnapLibIOU::fseek($destFileHandle, $expandState->currentFileOffset); - } else { - DupArchiveUtil::tlog('Starting to write new file '.$destFilepath); - $destFileHandle = DupLiteSnapLibIOU::fopen($destFilepath, 'w+b'); - } - - DupArchiveUtil::tlog('writeToFile for '.$destFilepath.', size '.$expandState->currentFileHeader->fileSize); - - while (!$expandState->timedOut()) { - - $moreGlobstoProcess = $expandState->currentFileOffset < $expandState->currentFileHeader->fileSize; - - if ($moreGlobstoProcess) { - DupArchiveUtil::tlog('Need to keep writing to '.$destFilepath.' because current file offset='.$expandState->currentFileOffset.' and file size='.$expandState->currentFileHeader->fileSize); - - if($expandState->throttleDelayInUs !== 0) { - usleep($expandState->throttleDelayInUs); - } - - DupArchiveUtil::tlog('Writing offset='.$expandState->currentFileOffset); - - self::appendGlobToFile($expandState, $archiveHandle, $destFileHandle, $destFilepath); - - DupArchiveUtil::tlog('After glob write'); - - $expandState->currentFileOffset = ftell($destFileHandle); - $expandState->archiveOffset = DupLiteSnapLibIOU::ftell($archiveHandle); - - $moreGlobstoProcess = $expandState->currentFileOffset < $expandState->currentFileHeader->fileSize; - - if(!$moreGlobstoProcess) { - - break; - } - - if (rand(0, 1000) > 990) { - DupArchiveUtil::log("Archive Offset={$expandState->archiveOffset}; Current File={$destFilepath}; Current File Offset={$expandState->currentFileOffset}"); - } - } else { - // No more globs to process - - // Reset the expand state here to ensure it stays consistent - DupArchiveUtil::tlog('Writing of '.$destFilepath.' to archive is done'); - - // rsr todo record fclose error - @fclose($destFileHandle); - $destFileHandle = null; - - self::setFileMode($expandState, $destFilepath); - - if ($expandState->validationType == DupArchiveValidationTypes::Full) { - self::validateExpandedFile($expandState); - } - - break; - } - } - - DupArchiveUtil::tlog('Out of glob loop'); - - if ($destFileHandle != null) { - // rsr todo record file close error - @fclose($destFileHandle); - $destFileHandle = null; - } - - if (!$moreGlobstoProcess && $expandState->validateOnly && ($expandState->validationType == DupArchiveValidationTypes::Full)) { - if (!is_writable($destFilepath)) { - DupLiteSnapLibIOU::chmod($destFilepath, 'u+rw'); - } - if (@unlink($destFilepath) === false) { - // $expandState->addFailure(DupArchiveFailureTypes::File, $destFilepath, "Couldn't delete {$destFilepath} during validation", false); - // TODO: Have to know how to handle this - want to report it but don’t want to mess up validation - some non critical errors could be important to validation - } - } - - } else { - // 0 length file so just touch it - $moreGlobstoProcess = false; - - if(file_exists($destFilepath)) { - @unlink($destFilepath); - } - - if (touch($destFilepath) === false) { - throw new Exception("Couldn't create {$destFilepath}"); - } - - self::setFileMode($expandState, $destFilepath); - } - - if(!$moreGlobstoProcess) { - - DupArchiveUtil::tlog('No more globs to process'); - - if((!$expandState->validateOnly) && (isset($expandState->fileRenames[$expandState->currentFileHeader->relativePath]))) { - $newRelativePath = $expandState->fileRenames[$expandState->currentFileHeader->relativePath]; - $newFilepath = $expandState->basePath.'/'.$newRelativePath; - - $perform_rename = true; - - if(@file_exists($newFilepath)) { - if(@unlink($newFilepath) === false) { - - $perform_rename = false; - - $error_message = "Couldn't delete {$newFilepath} when trying to rename {$destFilepath}"; - - $expandState->addFailure(DupArchiveFailureTypes::File, $expandState->currentFileHeader->relativePath, $error_message, true); - DupArchiveUtil::tlog($error_message); - } - } - - if($perform_rename && @rename($destFilepath, $newFilepath) === false) { - - $error_message = "Couldn't rename {$destFilepath} to {$newFilepath}"; - - $expandState->addFailure(DupArchiveFailureTypes::File, $expandState->currentFileHeader->relativePath, $error_message, true); - DupArchiveUtil::tlog($error_message); - } - } - - $expandState->fileWriteCount++; - $expandState->resetForFile(); - } - - return !$moreGlobstoProcess; - } - - public static function setFileMode($expandState, $filePath) - { - $mode = 'u+rw'; - if($expandState->fileModeOverride !== -1) { - $mode = $expandState->fileModeOverride; - } - DupLiteSnapLibIOU::chmod($filePath, $mode); - } - - public static function standardValidateFileEntry(&$expandState, $archiveHandle) - { - /* @var $expandState DupArchiveExpandState */ - - $moreGlobstoProcess = $expandState->currentFileOffset < $expandState->currentFileHeader->fileSize; - - if (!$moreGlobstoProcess) { - - // Not a 'real' write but indicates that we actually did fully process a file in the archive - $expandState->fileWriteCount++; - } else { - - while ((!$expandState->timedOut()) && $moreGlobstoProcess) { - - // Read in the glob header but leave the pointer at the payload - - // profile ok - $globHeader = DupArchiveGlobHeader::readFromArchive($archiveHandle, false); - - // profile ok - $globContents = fread($archiveHandle, $globHeader->storedSize); - - if ($globContents === false) { - throw new Exception("Error reading glob from $destFilePath"); - } - - $hash = hash('crc32b', $globContents); - - if ($hash != $globHeader->hash) { - $expandState->addFailure(DupArchiveFailureTypes::File, $expandState->currentFileHeader->relativePath, 'Hash mismatch on DupArchive file entry', true); - DupArchiveUtil::tlog("Glob hash mismatch during standard check of {$expandState->currentFileHeader->relativePath}"); - } else { - // DupArchiveUtil::tlog("Glob MD5 passes"); - } - - $expandState->currentFileOffset += $globHeader->originalSize; - - // profile ok - $expandState->archiveOffset = DupLiteSnapLibIOU::ftell($archiveHandle); - - - $moreGlobstoProcess = $expandState->currentFileOffset < $expandState->currentFileHeader->fileSize; - - if (!$moreGlobstoProcess) { - - - $expandState->fileWriteCount++; - - // profile ok - $expandState->resetForFile(); - } - } - } - - return !$moreGlobstoProcess; - } - - private static function validateExpandedFile(&$expandState) - { - /* @var $expandState DupArchiveExpandState */ - $destFilepath = $expandState->basePath.'/'.$expandState->currentFileHeader->relativePath; - - if ($expandState->currentFileHeader->hash !== '00000000000000000000000000000000') { - - $hash = hash_file('crc32b', $destFilepath); - - if ($hash !== $expandState->currentFileHeader->hash) { - $expandState->addFailure(DupArchiveFailureTypes::File, $destFilepath, "MD5 mismatch for {$destFilepath}", false); - } else { - DupArchiveUtil::tlog('MD5 Match for '.$destFilepath); - } - } else { - DupArchiveUtil::tlog('MD5 non match is 0\'s'); - } - } - - private static function appendGlobToArchive($createState, $archiveHandle, $sourceFilehandle, $sourceFilepath, $fileSize) - { - DupArchiveUtil::tlog("Appending file glob to archive for file {$sourceFilepath} at file offset {$createState->currentFileOffset}"); - - if ($fileSize > 0) { - $fileSize -= $createState->currentFileOffset; - - // profile ok - $globContents = @fread($sourceFilehandle, $createState->globSize); - // end profile ok - - if ($globContents === false) { - throw new Exception("Error reading $sourceFilepath"); - } - - // profile ok - $originalSize = strlen($globContents); - // end profile ok - - if ($createState->isCompressed) { - // profile ok - $globContents = gzdeflate($globContents, 2); // 2 chosen as best compromise between speed and size - $storeSize = strlen($globContents); - // end profile ok - } else { - $storeSize = $originalSize; - } - - - $globHeader = new DupArchiveGlobHeader(); - - $globHeader->originalSize = $originalSize; - $globHeader->storedSize = $storeSize; - $globHeader->hash = hash('crc32b',$globContents); - - // profile ok - $globHeader->writeToArchive($archiveHandle); - // end profile ok - - // profile ok - if (@fwrite($archiveHandle, $globContents) === false) { - // Considered fatal since we should always be able to write to the archive - plus the header has already been written (could back this out later though) - throw new Exception("Error writing $sourceFilepath to archive. Ensure site still hasn't run out of space.", DupArchiveExceptionCodes::Fatal); - } - // end profile ok - - $fileSizeRemaining = $fileSize - $createState->globSize; - - $moreFileRemaining = $fileSizeRemaining > 0; - - return $moreFileRemaining; - } else { - // 0 Length file - return false; - } - } - - // Assumption is that archive handle points to a glob header on this call - private static function appendGlobToFile($expandState, $archiveHandle, $destFileHandle, $destFilePath) - { - /* @var $expandState DupArchiveExpandState */ - DupArchiveUtil::tlog('Appending file glob to file '.$destFilePath.' at file offset '.$expandState->currentFileOffset); - - // Read in the glob header but leave the pointer at the payload - $globHeader = DupArchiveGlobHeader::readFromArchive($archiveHandle, false); - - $globContents = @fread($archiveHandle, $globHeader->storedSize); - - if ($globContents === false) { - throw new Exception("Error reading glob from $destFilePath"); - } - - if ($expandState->isCompressed) { - $globContents = gzinflate($globContents); - } - - if (@fwrite($destFileHandle, $globContents) === false) { - throw new Exception("Error writing glob to $destFilePath"); - } else { - DupArchiveUtil::tlog('Successfully wrote glob'); - } - } -} -} \ No newline at end of file diff --git a/lib/dup_archive/classes/processors/index.php b/lib/dup_archive/classes/processors/index.php deleted file mode 100644 index 17a71fa7..00000000 --- a/lib/dup_archive/classes/processors/index.php +++ /dev/null @@ -1,2 +0,0 @@ -failures = array(); - } - - public function isCriticalFailurePresent() - { - if(count($this->failures) > 0) { - foreach($this->failures as $failure) { - /* @var $failure DupArchiveProcessingFailure */ - if($failure->isCritical) { - return true; - } - } - } - - return false; - } - - public function getFailureSummary($includeCritical = true, $includeWarnings = false) - { - if(count($this->failures) > 0) - { - $message = ''; - - foreach($this->failures as $failure) - { - /* @var $failure DupArchiveProcessingFailure */ - if($includeCritical || !$failure->isCritical) { - - $message .= "\n" . $this->getFailureString($failure); - } - } - - return $message; - } - else - { - if($includeCritical) - { - if($includeWarnings) { - return 'No errors or warnings.'; - } else { - return 'No errors.'; - } - } else { - return 'No warnings.'; - } - } - } - - public function getFailureString($failure) - { - $s = ''; - - if($failure->isCritical) { - $s = 'CRITICAL: '; - } - - return "{$s}{$failure->subject} : {$failure->description}"; - } - - public function addFailure($type, $subject, $description, $isCritical = true) - { - $failure = new DupArchiveProcessingFailure(); - - $failure->type = $type; - $failure->subject = $subject; - $failure->description = $description; - $failure->isCritical = $isCritical; - - $this->failures[] = $failure; - - return $failure; - } - - public function startTimer() - { - if ($this->timerEnabled) { - $this->timeoutTimestamp = time() + $this->timeSliceInSecs; - } - } - - public function timedOut() - { - if ($this->timerEnabled) { - if ($this->timeoutTimestamp != -1) { - return time() >= $this->timeoutTimestamp; - } else { - return false; - } - } else { - return false; - } - } - // abstract public function save(); -} -} \ No newline at end of file diff --git a/lib/dup_archive/classes/states/class.duparchive.state.create.php b/lib/dup_archive/classes/states/class.duparchive.state.create.php deleted file mode 100644 index 17c9d050..00000000 --- a/lib/dup_archive/classes/states/class.duparchive.state.create.php +++ /dev/null @@ -1,24 +0,0 @@ -currentFileHeader = null; - $this->currentFileOffset = 0; - } - } -} \ No newline at end of file diff --git a/lib/dup_archive/classes/states/class.duparchive.state.simplecreate.php b/lib/dup_archive/classes/states/class.duparchive.state.simplecreate.php deleted file mode 100644 index bc8e1855..00000000 --- a/lib/dup_archive/classes/states/class.duparchive.state.simplecreate.php +++ /dev/null @@ -1,26 +0,0 @@ -currentDirectoryIndex = 0; - $this->currentFileIndex = 0; - $this->currentFileOffset = 0; - } - - public function save() - { - - } -} -} \ No newline at end of file diff --git a/lib/dup_archive/classes/states/class.duparchive.state.simpleexpand.php b/lib/dup_archive/classes/states/class.duparchive.state.simpleexpand.php deleted file mode 100644 index 5d0fd328..00000000 --- a/lib/dup_archive/classes/states/class.duparchive.state.simpleexpand.php +++ /dev/null @@ -1,23 +0,0 @@ - 'No error has occurred', - JSON_ERROR_DEPTH => 'The maximum stack depth has been exceeded', - JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON', - JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded', - JSON_ERROR_SYNTAX => 'Syntax error', - JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded. To resolve see https://snapcreek.com/duplicator/docs/faqs-tech/#faq-package-170-q' - ); - - public static function customEncode($value, $iteration = 1) - { - $encoded = DupLiteSnapJsonU::wp_json_encode($value); - - switch (json_last_error()) { - case JSON_ERROR_NONE: - return $encoded; - case JSON_ERROR_DEPTH: - throw new RuntimeException('Maximum stack depth exceeded'); // or trigger_error() or throw new Exception() - case JSON_ERROR_STATE_MISMATCH: - throw new RuntimeException('Underflow or the modes mismatch'); // or trigger_error() or throw new Exception() - case JSON_ERROR_CTRL_CHAR: - throw new RuntimeException('Unexpected control character found'); - case JSON_ERROR_SYNTAX: - throw new RuntimeException('Syntax error, malformed JSON'); // or trigger_error() or throw new Exception() - case JSON_ERROR_UTF8: - if ($iteration == 1) { - $clean = self::makeUTF8($value); - return self::customEncode($clean, $iteration + 1); - } else { - throw new RuntimeException('UTF-8 error loop'); - } - default: - throw new RuntimeException('Unknown error'); // or trigger_error() or throw new Exception() - } - } - - public static function encode($value, $options = 0) - { - $result = DupLiteSnapJsonU::wp_json_encode($value, $options); - - if ($result !== FALSE) { - - return $result; - } - - if (function_exists('json_last_error')) { - $message = self::$_messages[json_last_error()]; - } else { - $message = 'One or more filenames isn\'t compatible with JSON encoding'; - } - - throw new RuntimeException($message); - } - - public static function decode($json, $assoc = false) - { - $result = json_decode($json, $assoc); - - if ($result) { - return $result; - } - - throw new RuntimeException(self::$_messages[json_last_error()]); - } - - - /** ======================================================== - * PRIVATE METHODS - * ===================================================== */ - - - private static function makeUTF8($mixed) - { - if (is_array($mixed)) { - foreach ($mixed as $key => $value) { - $mixed[$key] = self::makeUTF8($value); - } - } else if (is_string($mixed)) { - return utf8_encode($mixed); - } - return $mixed; - } - - private static function escapeString($str) - { - return addcslashes($str, "\v\t\n\r\f\"\\/"); - } - - private static function oldCustomEncode($in) - { - $out = ""; - - if (is_object($in)) { - //$class_vars = get_object_vars(($in)); - //$arr = array(); - //foreach ($class_vars as $key => $val) - //{ - $arr[$key] = "\"".self::escapeString($key)."\":\"{$val}\""; - //} - //$val = implode(',', $arr); - //$out .= "{{$val}}"; - $in = get_object_vars($in); - } - //else - if (is_array($in)) { - $obj = false; - $arr = array(); - - foreach ($in AS $key => $val) { - if (!is_numeric($key)) { - $obj = true; - } - $arr[$key] = self::oldCustomEncode($val); - } - - if ($obj) { - foreach ($arr AS $key => $val) { - $arr[$key] = "\"".self::escapeString($key)."\":{$val}"; - } - $val = implode(',', $arr); - $out .= "{{$val}}"; - } else { - $val = implode(',', $arr); - $out .= "[{$val}]"; - } - } elseif (is_bool($in)) { - $out .= $in ? 'true' : 'false'; - } elseif (is_null($in)) { - $out .= 'null'; - } elseif (is_string($in)) { - $out .= "\"".self::escapeString($in)."\""; - } else { - $out .= $in; - } - - return "{$out}"; - } - - private static function oldMakeUTF8($val) - { - if (is_array($val)) { - foreach ($val as $k => $v) { - $val[$k] = self::oldMakeUTF8($v); - } - } else if (is_object($val)) { - foreach ($val as $k => $v) { - $val->$k = self::oldMakeUTF8($v); - } - } else { - if (mb_detect_encoding($val, 'UTF-8', true)) { - return $val; - } else { - return utf8_encode($val); - } - } - - return $val; - } -} -} \ No newline at end of file diff --git a/lib/dup_archive/classes/util/class.duparchive.util.php b/lib/dup_archive/classes/util/class.duparchive.util.php deleted file mode 100644 index a9a72cc2..00000000 --- a/lib/dup_archive/classes/util/class.duparchive.util.php +++ /dev/null @@ -1,190 +0,0 @@ - $dir) { - // find first non-matching dir - if ($dir === $to[$depth]) { - // ignore this directory - array_shift($relPath); - } else { - // get number of remaining dirs to $from - $remaining = count($from) - $depth; - if ($remaining > 1) { - // add traversals up to first matching dir - $padLength = (count($relPath) + $remaining - 1) * -1; - $relPath = array_pad($relPath, $padLength, '..'); - break; - } else { - //$relPath[0] = './' . $relPath[0]; - } - } - } - - $r = implode('/', $relPath); - - if($newBasePath != null) { - $r = $newBasePath . $r; - } - - return $r; - } - - public static function log($s, $flush = false, $callingFunctionName = null) - { - if(self::$logger != null) - { - if($callingFunctionName === null) - { - $callingFunctionName = DupLiteSnapLibUtil::getCallingFunctionName(); - } - - self::$logger->log($s, $flush, $callingFunctionName); - } - else - { - // throw new Exception('Logging object not initialized'); - } - } - - // rodo fold into log - public static function tlog($s, $flush = false, $callingFunctionName = null) - { - if (self::$TRACE_ON) { - - if($callingFunctionName === null) - { - $callingFunctionName = DupLiteSnapLibUtil::getCallingFunctionName(); - } - - self::log("####{$s}", $flush, $callingFunctionName); - } - } - - public static function profileEvent($s, $start) - { - if(self::$profilingFunction != null) - { - call_user_func(self::$profilingFunction, $s, $start); - } - } - - // rodo fold into logObject - public static function tlogObject($s, $o, $flush = false, $callingFunctionName = null) - { - if(is_object($o)) - { - $o = get_object_vars($o); - } - - $ostring = print_r($o, true); - - if($callingFunctionName === null) - { - $callingFunctionName = DupLiteSnapLibUtil::getCallingFunctionName(); - } - - self::tlog($s, $flush, $callingFunctionName); - self::tlog($ostring, $flush, $callingFunctionName); - } - - public static function logObject($s, $o, $flush = false, $callingFunctionName = null) - { - $ostring = print_r($o, true); - - if($callingFunctionName === null) - { - $callingFunctionName = DupLiteSnapLibUtil::getCallingFunctionName(); - } - - self::log($s, $flush, $callingFunctionName); - self::log($ostring, $flush, $callingFunctionName); - } -} -} \ No newline at end of file diff --git a/lib/dup_archive/classes/util/class.duparchive.util.scan.php b/lib/dup_archive/classes/util/class.duparchive.util.scan.php deleted file mode 100644 index aaebb925..00000000 --- a/lib/dup_archive/classes/util/class.duparchive.util.scan.php +++ /dev/null @@ -1,84 +0,0 @@ -Dirs = DupArchiveUtil::expandDirectories($sourceDirectory, true); - $scan->Files = DupArchiveUtil::expandFiles($sourceDirectory, true); - - return $scan; - } - - public static function createScan($scanFilepath, $sourceDirectory) - { - DupArchiveUtil::tlog("Creating scan"); -// $scan = new stdClass(); -// -// $scan->Dirs = DupArchiveUtil::expandDirectories($sourceDirectory, true); -// $scan->Files = DupArchiveUtil::expandFiles($sourceDirectory, true); -////$scan->Files = array(); - - $scan = self::createScanObject($sourceDirectory); - - $scan_handle = fopen($scanFilepath, 'w'); - - if ($scan_handle === false) { - echo "Couldn't create scan file"; - die(); - } - - $jsn = DupArchiveJsonU::customEncode($scan); - - fwrite($scan_handle, $jsn); - - // DupArchiveUtil::tlogObject('jsn', $jsn); - - return $scan; - } -} -} \ No newline at end of file diff --git a/lib/dup_archive/classes/util/index.php b/lib/dup_archive/classes/util/index.php deleted file mode 100644 index 17a71fa7..00000000 --- a/lib/dup_archive/classes/util/index.php +++ /dev/null @@ -1,2 +0,0 @@ -setFromData($data); - - self::$instance->fileRenames = (array)(self::$instance->fileRenames); - - // DupLiteSnapLibIOU::flock($stateHandle, LOCK_UN); - - DupLiteSnapLibIOU::fclose($stateHandle); - } else { - $reset = true; - } - } - - if ($reset) { - self::$instance = new DAWSExpandState(); - - self::$instance->reset(); - } - - return self::$instance; - } - - private function setFromData($data) - { - $this->currentFileHeader = $data->currentFileHeader; - $this->archiveHeader = $data->archiveHeader; - $this->archiveOffset = $data->archiveOffset; - $this->archivePath = $data->archivePath; - $this->basePath = $data->basePath; - $this->currentFileOffset = $data->currentFileOffset; - $this->failures = $data->failures; - $this->isCompressed = $data->isCompressed; - $this->startTimestamp = $data->startTimestamp; - $this->timeSliceInSecs = $data->timeSliceInSecs; - $this->validateOnly = $data->validateOnly; - $this->fileWriteCount = $data->fileWriteCount; - $this->directoryWriteCount = $data->directoryWriteCount; - $this->working = $data->working; - $this->filteredDirectories = $data->filteredDirectories; - $this->filteredFiles = $data->filteredFiles; - $this->fileRenames = $data->fileRenames; - $this->directoryModeOverride = $data->directoryModeOverride; - $this->fileModeOverride = $data->fileModeOverride; - $this->lastHeaderOffset = $data->lastHeaderOffset; - $this->throttleDelayInUs = $data->throttleDelayInUs; - $this->timerEnabled = $data->timerEnabled; - } - - public function reset() - { - $stateFilepath = dirname(__FILE__).'/'.self::StateFilename; - - $stateHandle = DupLiteSnapLibIOU::fopen($stateFilepath, 'w'); - - DupLiteSnapLibIOU::flock($stateHandle, LOCK_EX); - - $this->initMembers(); - - DupLiteSnapLibIOU::fwrite($stateHandle, DupLiteSnapJsonU::wp_json_encode($this)); - - DupLiteSnapLibIOU::flock($stateHandle, LOCK_UN); - - DupLiteSnapLibIOU::fclose($stateHandle); - } - - public function save() - { - $stateFilepath = dirname(__FILE__).'/'.self::StateFilename; - - $stateHandle = DupLiteSnapLibIOU::fopen($stateFilepath, 'w'); - - DupLiteSnapLibIOU::flock($stateHandle, LOCK_EX); - - DupArchiveUtil::tlog("saving state"); - DupLiteSnapLibIOU::fwrite($stateHandle, DupLiteSnapJsonU::wp_json_encode($this)); - - DupLiteSnapLibIOU::flock($stateHandle, LOCK_UN); - - DupLiteSnapLibIOU::fclose($stateHandle); - } - - private function initMembers() - { - $this->currentFileHeader = null; - - $this->archiveOffset = 0; - $this->archiveHeader = 0; - $this->archivePath = null; - $this->basePath = null; - $this->currentFileOffset = 0; - $this->failures = array(); - $this->isCompressed = false; - $this->startTimestamp = time(); - $this->timeSliceInSecs = -1; - $this->working = false; - $this->validateOnly = false; - $this->filteredDirectories = array(); - $this->filteredFiles = array(); - $this->fileRenames = array(); - $this->directoryModeOverride = -1; - $this->fileModeOverride = -1; - $this->lastHeaderOffset = -1; - $this->throttleDelayInUs = 0; - $this->timerEnabled = true; - } -} diff --git a/lib/dup_archive/daws/daws.php b/lib/dup_archive/daws/daws.php deleted file mode 100644 index 5d18799f..00000000 --- a/lib/dup_archive/daws/daws.php +++ /dev/null @@ -1,294 +0,0 @@ -pass = false; - - DupLiteSnapLibLogger::logObject('params', $params); - DupLiteSnapLibLogger::logObject('keys', array_keys($params)); - - $action = $params['action']; - - $initializeState = false; - - $isClientDriven = DupLiteSnapLibUtil::getArrayValue($params, 'client_driven', false); - - if ($action == 'start_expand') { - - $initializeState = true; - - DAWSExpandState::purgeStatefile(); - DupLiteSnapLibLogger::clearLog(); - - DupLiteSnapLibIOU::rm(DAWSConstants::$PROCESS_CANCEL_FILEPATH); - $archiveFilepath = DupLiteSnapLibUtil::getArrayValue($params, 'archive_filepath'); - $restoreDirectory = DupLiteSnapLibUtil::getArrayValue($params, 'restore_directory'); - $workerTime = DupLiteSnapLibUtil::getArrayValue($params, 'worker_time', false, DAWSConstants::$DEFAULT_WORKER_TIME); - $filteredDirectories = DupLiteSnapLibUtil::getArrayValue($params, 'filtered_directories', false, array()); - $filteredFiles = DupLiteSnapLibUtil::getArrayValue($params, 'filtered_files', false, array()); - $fileRenames = DupLiteSnapLibUtil::getArrayValue($params, 'file_renames', false, array()); - - $action = 'expand'; - - DupLiteSnapLibLogger::log('startexpand->expand'); - } else if($action == 'start_create') { - - $archiveFilepath = DupLiteSnapLibUtil::getArrayValue($params, 'archive_filepath'); - $workerTime = DupLiteSnapLibUtil::getArrayValue($params, 'worker_time', false, DAWSConstants::$DEFAULT_WORKER_TIME); - - $createState->basePath = $dataDirectory; - $createState->isCompressed = $isCompressed; - - $sourceDirectory = DupLiteSnapLibUtil::getArrayValue($params, 'source_directory'); - $isCompressed = DupLiteSnapLibUtil::getArrayValue($params, 'is_compressed') === 'true' ? true : false; - } - - $throttleDelayInMs = DupLiteSnapLibUtil::getArrayValue($params, 'throttle_delay', false, 0); - - if ($action == 'expand') { - - DupLiteSnapLibLogger::log('expand action'); - - /* @var $expandState DAWSExpandState */ - $expandState = DAWSExpandState::getInstance($initializeState); - - $this->lock_handle = DupLiteSnapLibIOU::fopen(DAWSConstants::$PROCESS_LOCK_FILEPATH, 'c+'); - DupLiteSnapLibIOU::flock($this->lock_handle, LOCK_EX); - - if($initializeState || $expandState->working) { - - if ($initializeState) { - - DupLiteSnapLibLogger::logObject('file renames', $fileRenames); - - $expandState->archivePath = $archiveFilepath; - $expandState->working = true; - $expandState->timeSliceInSecs = $workerTime; - $expandState->basePath = $restoreDirectory; - $expandState->working = true; - $expandState->filteredDirectories = $filteredDirectories; - $expandState->filteredFiles = $filteredFiles; - $expandState->fileRenames = $fileRenames; - $expandState->fileModeOverride = 0644; - $expandState->directoryModeOverride = 'u+rwx'; - - $expandState->save(); - } - - $expandState->throttleDelayInUs = 1000 * $throttleDelayInMs; - - DupLiteSnapLibLogger::logObject('Expand State In', $expandState); - - DupArchiveEngine::expandArchive($expandState); - } - - if (!$expandState->working) { - - $deltaTime = time() - $expandState->startTimestamp; - DupLiteSnapLibLogger::log("###### Processing ended. Seconds taken:$deltaTime"); - - if (count($expandState->failures) > 0) { - DupLiteSnapLibLogger::log('Errors detected'); - - foreach ($expandState->failures as $failure) { - DupLiteSnapLibLogger::log("{$failure->subject}:{$failure->description}"); - } - } else { - DupLiteSnapLibLogger::log('Expansion done, archive checks out!'); - } - } - else { - DupLiteSnapLibLogger::log("Processing will continue"); - } - - - DupLiteSnapLibIOU::flock($this->lock_handle, LOCK_UN); - - $retVal->pass = true; - $retVal->status = $this->getStatus($expandState); - } else if ($action == 'create') { - - DupLiteSnapLibLogger::log('create action'); - - /* @var $expandState DAWSExpandState */ - $createState = DAWSCreateState::getInstance($initializeState); - - $this->lock_handle = DupLiteSnapLibIOU::fopen(DAWSConstants::$PROCESS_LOCK_FILEPATH, 'c+'); - DupLiteSnapLibIOU::flock($this->lock_handle, LOCK_EX); - - if($initializeState || $createState->working) { - - DupArchiveEngine::createArchive($archiveFilepath, $isCompressed); - - $createState->archivePath = $archiveFilepath; - $createState->archiveOffset = DupLiteSnapLibIOU::filesize($archiveFilepath); - $createState->working = true; - $createState->timeSliceInSecs = $workerTime; - $createState->basePath = $dataDirectory; - $createState->isCompressed = $isCompressed; - $createState->throttleDelayInUs = $throttleDelayInUs; - - // $daTesterCreateState->globSize = self::GLOB_SIZE; - - $createState->save(); - - $scan = DupArchiveScanUtil::createScan($this->paths->scanFilepath, $this->paths->dataDirectory); - } - - $createState->throttleDelayInUs = 1000 * $throttleDelayInMs; - - if (!$createState->working) { - - $deltaTime = time() - $createState->startTimestamp; - DupLiteSnapLibLogger::log("###### Processing ended. Seconds taken:$deltaTime"); - - if (count($createState->failures) > 0) { - DupLiteSnapLibLogger::log('Errors detected'); - - foreach ($createState->failures as $failure) { - DupLiteSnapLibLogger::log("{$failure->subject}:{$failure->description}"); - } - } else { - DupLiteSnapLibLogger::log('Creation done, archive checks out!'); - } - } - else { - DupLiteSnapLibLogger::log("Processing will continue"); - } - - DupLiteSnapLibIOU::flock($this->lock_handle, LOCK_UN); - - $retVal->pass = true; - $retVal->status = $this->getStatus($createState); - } else if ($action == 'get_status') { - /* @var $expandState DAWSExpandState */ - $expandState = DAWSExpandState::getInstance($initializeState); - - $retVal->pass = true; - $retVal->status = $this->getStatus($expandState); - } else if ($action == 'cancel') { - if (!DupLiteSnapLibIOU::touch(DAWSConstants::$PROCESS_CANCEL_FILEPATH)) { - throw new Exception("Couldn't update time on ".DAWSConstants::$PROCESS_CANCEL_FILEPATH); - } - $retVal->pass = true; - } else { - throw new Exception('Unknown command.'); - } - - session_write_close(); - - } catch (Exception $ex) { - $error_message = "Error Encountered:" . $ex->getMessage() . '
        ' . $ex->getTraceAsString(); - - DupLiteSnapLibLogger::log($error_message); - - $retVal->pass = false; - $retVal->error = $error_message; - } - - DupLiteSnapLibLogger::logObject("before json encode retval", $retVal); - - $jsonRetVal = DupLiteSnapJsonU::wp_json_encode($retVal); - DupLiteSnapLibLogger::logObject("json encoded retval", $jsonRetVal); - echo $jsonRetVal; - } - - private function getStatus($state) - { - /* @var $state DupArchiveStateBase */ - - $ret_val = new stdClass(); - - $ret_val->archive_offset = $state->archiveOffset; - $ret_val->archive_size = @filesize($state->archivePath); - $ret_val->failures = $state->failures; - $ret_val->file_index = $state->fileWriteCount; - $ret_val->is_done = !$state->working; - $ret_val->timestamp = time(); - - return $ret_val; - } -} - -function generateCallTrace() -{ - $e = new Exception(); - $trace = explode("\n", $e->getTraceAsString()); - // reverse array to make steps line up chronologically - $trace = array_reverse($trace); - array_shift($trace); // remove {main} - array_pop($trace); // remove call to this method - $length = count($trace); - $result = array(); - - for ($i = 0; $i < $length; $i++) { - $result[] = ($i + 1) . ')' . substr($trace[$i], strpos($trace[$i], ' ')); // replace '#someNum' with '$i)', set the right ordering - } - - return "\t" . implode("\n\t", $result); -} - -function terminate_missing_variables($errno, $errstr, $errfile, $errline) -{ - DupLiteSnapLibLogger::log("ERROR $errno, $errstr, {$errfile}:{$errline}"); - DupLiteSnapLibLogger::log(generateCallTrace()); - // DaTesterLogging::clearLog(); - - /** - * INTERCEPT ON processRequest AND RETURN JSON STATUS - */ - throw new Exception("ERROR:{$errfile}:{$errline} | ".$errstr , $errno); -} diff --git a/lib/dup_archive/daws/dawslock.bin b/lib/dup_archive/daws/dawslock.bin deleted file mode 100644 index e69de29b..00000000 diff --git a/lib/dup_archive/daws/index.php b/lib/dup_archive/daws/index.php deleted file mode 100644 index 17a71fa7..00000000 --- a/lib/dup_archive/daws/index.php +++ /dev/null @@ -1,2 +0,0 @@ -logFilepath = $logFilepath; - } - - public function clearLog() - { - if (file_exists($this->logFilepath)) { - if ($this->logHandle !== null) { - fflush($this->logHandle); - fclose($this->logHandle); - $this->logHandle = null; - } - @unlink($this->logFilepath); - } - } - - public function logObject($s, $o, $flush = false, $callingFunctionOverride = null) - { - $this->log($s, false, $callingFunctionOverride); - $this->log(print_r($o, true), false, $callingFunctionOverride); - - if ($flush) { - fflush($this->logHandle); - } - } - - public function log($s, $flush = false, $callingFunctionOverride = null) - { - $lfp = $this->logFilepath; - - if ($this->logFilepath === null) { - error_log('logging not initialized'); - throw new Exception('Logging not initialized'); - } - - if(isset($_SERVER['REQUEST_TIME_FLOAT'])){ - $timepart = $_SERVER['REQUEST_TIME_FLOAT']; - } else { - $timepart = $_SERVER['REQUEST_TIME']; - } - - $thread_id = sprintf("%08x", abs(crc32($_SERVER['REMOTE_ADDR'].$timepart.$_SERVER['REMOTE_PORT']))); - - $s = $thread_id.' '.date('h:i:s').":$s"; - - if ($this->logHandle === null) { - - $this->logHandle = fopen($this->logFilepath, 'a'); - } - - fwrite($this->logHandle, "$s\n"); - - if ($flush) { - fflush($this->logHandle); - fclose($this->logHandle); - - $this->logHandle = fopen($this->logFilepath, 'a'); - } - } - private static $profileLogArray = null; - - public static function initProfiling() - { - self::$profileLogArray = array(); - } -} \ No newline at end of file diff --git a/lib/dup_archive/tester/classes/class.datester.state.create.php b/lib/dup_archive/tester/classes/class.datester.state.create.php deleted file mode 100644 index 1bf6dd7b..00000000 --- a/lib/dup_archive/tester/classes/class.datester.state.create.php +++ /dev/null @@ -1,121 +0,0 @@ -setFromData($data); - - DupLiteSnapLibIOU::flock($stateHandle, LOCK_UN); - - DupLiteSnapLibIOU::fclose($stateHandle); - } else { - $reset = true; - } - } - if ($reset) { - self::$instance = new DaTesterCreateState(); - - self::$instance->reset(); - } - - return self::$instance; - } - - private function setFromData($data) - { - $this->archiveOffset = $data->archiveOffset; - $this->archivePath = $data->archivePath; - $this->basePath = $data->basePath; - $this->globSize = $data->globSize; - $this->currentFileIndex = $data->currentFileIndex; - $this->currentDirectoryIndex = $data->currentDirectoryIndex; - $this->currentFileOffset = $data->currentFileOffset; - $this->failures = $data->failures; - $this->isCompressed = $data->isCompressed; - $this->startTimestamp = $data->startTimestamp; - $this->timeSliceInSecs = $data->timeSliceInSecs; - $this->working = $data->working; - $this->throttleDelayInUs = $data->throttleDelayInUs; - } - - public function reset() - { - $stateFilepath = dirname(__FILE__).'/'.self::StateFilename; - - $stateHandle = DupLiteSnapLibIOU::fopen($stateFilepath, 'w'); - - DupLiteSnapLibIOU::flock($stateHandle, LOCK_EX); - - $this->initMembers(); - - DupLiteSnapLibIOU::fwrite($stateHandle, json_encode($this)); - - DupLiteSnapLibIOU::fclose($stateHandle); - } - - public function save() - { - $stateFilepath = dirname(__FILE__).'/'.self::StateFilename; - - $stateHandle = DupLiteSnapLibIOU::fopen($stateFilepath, 'w'); - - DupLiteSnapLibIOU::flock($stateHandle, LOCK_EX); - - DupArchiveUtil::tlog("saving state"); - DupLiteSnapLibIOU::fwrite($stateHandle, json_encode($this)); - - DupLiteSnapLibIOU::fclose($stateHandle); - } - - private function initMembers() - { - $this->archiveOffset = 0; - $this->archivePath = null; - $this->basePath = null; - $this->globSize = -1; - $this->currentFileIndex = 0; - $this->currentFileOffset = 0; - $this->currentDirectoryIndex = 0; - $this->fileWriteCount = 0; - $this->directoryWriteCount = 0; - $this->failures = array(); - $this->isCompressed = false; - $this->startTimestamp = time(); - $this->timeSliceInSecs = -1; - $this->working = false; - $this->throttleDelayInUs = 0; - } -} \ No newline at end of file diff --git a/lib/dup_archive/tester/classes/class.datester.state.expand.php b/lib/dup_archive/tester/classes/class.datester.state.expand.php deleted file mode 100644 index 6e45b6bc..00000000 --- a/lib/dup_archive/tester/classes/class.datester.state.expand.php +++ /dev/null @@ -1,121 +0,0 @@ -setFromData($data); - - DupLiteSnapLibIOU::flock($stateHandle, LOCK_UN); - - DupLiteSnapLibIOU::fclose($stateHandle); - } else { - $reset = true; - } - } - - if ($reset) { - self::$instance = new DaTesterExpandState(); - - self::$instance->reset(); - } - - return self::$instance; - } - - private function setFromData($data) - { - $this->currentFileHeader = $data->currentFileHeader; - $this->archiveHeader = $data->archiveHeader; - $this->archiveOffset = $data->archiveOffset; - $this->archivePath = $data->archivePath; - $this->basePath = $data->basePath; - $this->currentFileOffset = $data->currentFileOffset; - $this->failures = $data->failures; - $this->isCompressed = $data->isCompressed; - $this->startTimestamp = $data->startTimestamp; - $this->timeSliceInSecs = $data->timeSliceInSecs; - $this->validateOnly = $data->validateOnly; - $this->fileWriteCount = $data->fileWriteCount; - $this->directoryWriteCount = $data->directoryWriteCount; - $this->working = $data->working; - $this->directoryModeOverride = $data->directoryModeOverride; - $this->fileModeOverride = $data->fileModeOverride; - $this->throttleDelayInUs = $data->throttleDelayInUs; - } - - public function reset() - { - $stateFilepath = dirname(__FILE__).'/'.self::StateFilename; - - $stateHandle = DupLiteSnapLibIOU::fopen($stateFilepath, 'w'); - - DupLiteSnapLibIOU::flock($stateHandle, LOCK_EX); - - $this->initMembers(); - - DupLiteSnapLibIOU::fwrite($stateHandle, json_encode($this)); - - DupLiteSnapLibIOU::fclose($stateHandle); - } - - public function save() - { - $stateFilepath = dirname(__FILE__).'/'.self::StateFilename; - - $stateHandle = DupLiteSnapLibIOU::fopen($stateFilepath, 'w'); - - DupLiteSnapLibIOU::flock($stateHandle, LOCK_EX); - - DupArchiveUtil::tlog("saving state"); - DupLiteSnapLibIOU::fwrite($stateHandle, json_encode($this)); - - DupLiteSnapLibIOU::fclose($stateHandle); - } - - private function initMembers() - { - $this->currentFileHeader = null; - - $this->archiveOffset = 0; - $this->archiveHeader = 0; - $this->archivePath = null; - $this->basePath = null; - $this->currentFileOffset = 0; - $this->failures = array(); - $this->isCompressed = false; - $this->startTimestamp = time(); - $this->timeSliceInSecs = -1; - $this->working = false; - $this->validateOnly = false; - $this->directoryModeOverride = -1; - $this->fileModeOverride = -1; - $this->throttleDelayInUs = 0; - } -} \ No newline at end of file diff --git a/lib/dup_archive/tester/classes/expandstate.json b/lib/dup_archive/tester/classes/expandstate.json deleted file mode 100644 index dd806a5d..00000000 --- a/lib/dup_archive/tester/classes/expandstate.json +++ /dev/null @@ -1 +0,0 @@ -{"archiveHeader":{"version":2,"isCompressed":true},"currentFileHeader":null,"validateOnly":true,"validationType":2,"fileWriteCount":6,"directoryWriteCount":0,"expectedFileCount":6,"expectedDirectoryCount":0,"filteredDirectories":[],"directoryModeOverride":-1,"fileModeOverride":-1,"lastHeaderOffset":196796990,"basePath":"C:\\Users\\Bob\\AppData\\Local\\Temp\/duparchivetester\/temp","archivePath":"C:\\Users\\Bob\\AppData\\Local\\Temp\/duparchivetester\/archive.daf","isCompressed":true,"currentFileOffset":0,"archiveOffset":196796990,"timeSliceInSecs":10,"working":false,"failures":[],"startTimestamp":1501534630,"throttleDelayInUs":0,"timeoutTimestamp":1501534640,"timerEnabled":true} \ No newline at end of file diff --git a/lib/dup_archive/tester/classes/index.php b/lib/dup_archive/tester/classes/index.php deleted file mode 100644 index 17a71fa7..00000000 --- a/lib/dup_archive/tester/classes/index.php +++ /dev/null @@ -1,2 +0,0 @@ -dataRoot = getenv("TEMP").'/duparchivetester'; - - $this->scanFilepath = "{$this->dataRoot}/scan.json"; - $this->processLockFilepath = "{$this->dataRoot}/lock.bin"; - - if ($isSmallArchive) { - - $this->dataDirectory = "{$this->dataRoot}/smalldata"; - $this->archiveFilepath = "{$this->dataRoot}/archivesmall.daf"; - } else { - $this->dataDirectory = "{$this->dataRoot}/data"; - $this->archiveFilepath = "{$this->dataRoot}/archive.daf"; - } - - $this->restoreDirectory = "{$this->dataRoot}/restore"; - $this->tempDirectory = "{$this->dataRoot}/temp"; - $this->logFilepath = "{$this->dataRoot}/tester.log"; - - if (!file_exists($this->dataRoot)) { - @mkdir($this->dataRoot); - } - - if (!file_exists($this->dataDirectory)) { - @mkdir($this->dataDirectory); - } - - if (!file_exists($this->restoreDirectory)) { - @mkdir($this->restoreDirectory); - } - - if (!file_exists($this->tempDirectory)) { - @mkdir($this->tempDirectory); - } - } -} - -class DaTesterParams -{ - public $compress = true; - public $isSmallArchive = true; - public $action; - public $p1 = null; - public $workerTime = 10; - public $throttleDelayInUs = 100000; - - function __construct() - { - if (isset($_REQUEST['worker_time'])) { - $this->workerTime = (int) $_REQUEST['worker_time']; - } - - if (isset($_REQUEST['small_archive'])) { - $this->isSmallArchive = ($_REQUEST['small_archive'] == 1); - } - - if (isset($_REQUEST['compress'])) { - $this->compress = ($_REQUEST['compress'] == 1); - } - - if (isset($_REQUEST['action'])) { - $this->action = $_REQUEST['action']; - } else { - $this->action = 'get_archive_info'; - } - - if (isset($_REQUEST['p1'])) { - $this->p1 = $_REQUEST['p1']; - } - } - - public function getQueryStringData() - { - $qsa = array(); - - $qsa['worker_time'] = $this->workerTime; - $qsa['small_archive'] = ($this->isSmallArchive ? 1 : 0); - $qsa['compress'] = ($this->compress ? 1 : 0); - $qsa['action'] = $this->action; - - if ($this->p1 != null) { - $qsa['p1'] = $this->p1; - } - - return $qsa; - } -} - -class DaTester -{ - private $paths; - private $params; - private $lockHandle; - private $logger; - - public function __construct() - { - $this->params = new DaTesterParams(); - $this->paths = new DaTesterPaths($this->params->isSmallArchive); - - } - - public function processRequest() - { - try { - $this->lockHandle = DupLiteSnapLibIOU::fopen($this->paths->processLockFilepath, 'c+'); - - DupLiteSnapLibIOU::flock($this->lockHandle, LOCK_EX); - - $this->logger = new DaTesterLogging($this->paths->logFilepath); - - $this->logger->log("incoming request"); - - DupArchiveEngine::init($this->logger); - - $this->logger->log("Got file lock"); - - $this->logger->log("Action set to {$this->params->action}"); - $initializeState = false; - - if ($this->params->action == 'start_create_test') { - - $initializeState = true; - - $this->params->action = 'create_test'; - } else if ($this->params->action == 'start_expand_test') { - - $initializeState = true; - - $this->params->action = 'expand_test'; - } else if ($this->params->action == 'start_validate_test') { - - $initializeState = true; - - $this->params->action = 'validate_test'; - } - - $this->logger->log("incoming request after lock"); - - $spawnAnotherThread = false; - - echo "action={$this->params->action}
        "; - - if ($this->params->action == 'get_status') { - - $this->get_status(); - } else if ($this->params->action == 'create_test') { - - /* @var $daTesterCreateState DaTesterCreateState */ - $daTesterCreateState = DaTesterCreateState::getInstance($initializeState); - - $daTesterState = &$daTesterCreateState; - if ($initializeState) { - - $this->logger->log("Clearing files"); - - $this->clearCreateFiles(); - - DupArchiveEngine::createArchive($this->paths->archiveFilepath, $this->params->compress); - - $daTesterCreateState->archivePath = $this->paths->archiveFilepath; - $daTesterCreateState->archiveOffset = DupLiteSnapLibIOU::filesize($this->paths->archiveFilepath); - $daTesterCreateState->working = true; - $daTesterCreateState->timeSliceInSecs = $this->params->workerTime; - $daTesterCreateState->basePath = $this->paths->dataDirectory; - $daTesterCreateState->isCompressed = $this->params->compress; - $daTesterCreateState->throttleDelayInUs = $this->params->throttleDelayInUs; - - // $daTesterCreateState->globSize = self::GLOB_SIZE; - - $daTesterCreateState->save(); - $this->logger->log("Cleared files"); - - $scan = DupArchiveScanUtil::createScan($this->paths->scanFilepath, $this->paths->dataDirectory); - } else { - - $scan = DupArchiveScanUtil::getScan($this->paths->scanFilepath); - } - - $this->logger->logObject("createstate", $daTesterCreateState); - DupArchiveEngine::addItemsToArchive($daTesterCreateState, $scan); - - $spawnAnotherThread = $daTesterCreateState->working; - - if (!$spawnAnotherThread) { - $this->logger->logObject("Done. Failures:", $daTesterCreateState->failures, true); - } - } else if ($this->params->action == 'start_add_file_test') { - //DupArchiveUtil::writeToPLog("Start add file test"); - $this->logger->clearLog(); - - $tmpname = tempnam($this->paths->dataDirectory, 'tmp'); - - $this->logger->log("tempname $tmpname"); - file_put_contents($tmpname, 'test'); - - DupArchiveEngine::addFileToArchiveUsingBaseDirST($this->paths->archiveFilepath, $this->paths->dataDirectory, $tmpname); - - echo "$tmpname added"; - - unlink($tmpname); - exit(1); - } else if ($this->params->action == 'mini_expand_test') { - - $this->logger->log("Clearing files"); - $this->clearExpandFiles(); - $this->logger->log("Cleared files"); - - try { - DupArchiveMiniExpander::init("$this->logger->log"); - DupArchiveMiniExpander::expandDirectory($this->paths->archiveFilepath, 'dup-installer', $this->paths->restoreDirectory); - } catch (Exception $ex) { - $message = $ex->getMessage(); - - echo "Exception: {$ex} ".$ex->getTraceAsString(); - } - - echo "Mini-extract done.
        "; - exit(1); - } else if ($this->params->action == 'expand_test') { - /* @var $daTesterExpandState DaTesterExpandState */ - $daTesterExpandState = DaTesterExpandState::getInstance($initializeState); - - $daTesterState = &$daTesterExpandState; - - if ($initializeState) { - - $this->logger->log("Clearing files"); - - $this->clearExpandFiles(); - $this->logger->log("Cleared files"); - - $daTesterExpandState->archivePath = $this->paths->archiveFilepath; - $daTesterExpandState->working = true; - $daTesterExpandState->timeSliceInSecs = $this->params->workerTime; - $daTesterExpandState->basePath = $this->paths->restoreDirectory; - $daTesterExpandState->working = true; - $daTesterExpandState->throttleDelayInUs = $this->params->throttleDelayInUs;; - $daTesterExpandState->save(); - } - - DupArchiveEngine::expandArchive($daTesterExpandState); - - $spawnAnotherThread = $daTesterExpandState->working; - - if (!$spawnAnotherThread) { - - if (count($daTesterExpandState->failures) > 0) { - $this->logger->log('Errors detected'); - echo 'Expanson done, but errors detected!'; - echo '

        '; - - foreach ($daTesterExpandState->failures as $failure) { - $this->logger->log($failure->description); - echo $failure->description; - echo '

        '; - } - } else { - echo 'Expansion done, archive checks out!'; - $this->logger->log('Expansion done, archive checks out!'); - } - } - } else if ($this->params->action == 'validate_test') { - - $validationType = DupArchiveValidationTypes::Full; - - if ($this->params->p1 != null) { - if ($this->params->p1 == 's') { - $validationType = DupArchiveValidationTypes::Standard; - } - } - - /* @var $daTesterExpandState DaTesterExpandState */ - $daTesterExpandState = DaTesterExpandState::getInstance($initializeState); - - $daTesterState = &$daTesterExpandState; - - if ($initializeState) { - - $this->logger->log("Clearing files"); - $this->clearExpandFiles(); - $this->logger->log("Cleared files"); - - $this->logger->log("Validation Type:" . (($validationType == DupArchiveValidationTypes::Full) ? 'Full' : 'Quick')); - - $scan = DupArchiveScanUtil::getScan($this->paths->scanFilepath); - - $daTesterExpandState->archivePath = $this->paths->archiveFilepath; - $daTesterExpandState->working = true; - $daTesterExpandState->timeSliceInSecs = $this->params->workerTime; - $daTesterExpandState->basePath = $this->paths->tempDirectory; - $daTesterExpandState->validateOnly = true; - $daTesterExpandState->validationType = $validationType; - $daTesterExpandState->working = true; - $daTesterExpandState->expectedDirectoryCount = count($scan->Dirs); - $daTesterExpandState->expectedFileCount = count($scan->Files); - $daTesterExpandState->save(); - } - - DupArchiveEngine::expandArchive($daTesterExpandState); - - $spawnAnotherThread = $daTesterExpandState->working; - - if (!$spawnAnotherThread) { - - if (count($daTesterExpandState->failures) > 0) { - echo 'Errors detected!'; - echo '

        '; - - foreach ($daTesterExpandState->failures as $failure) { - echo esc_html($failure->description); - echo '

        '; - } - } else { - echo 'Archive checks out!'; - } - } - } else if ($this->params->action == 'get_archive_info') { - $this->logger->log("get_archive_info()"); - - $this->logger->clearLog(); - - $archiveInfo = DupArchiveEngine::getArchiveInfo($this->paths->archiveFilepath); - - $sizeInArchive = 0; - - foreach($archiveInfo->fileHeaders as $fileHeader) { - $sizeInArchive += $fileHeader->fileSize; - } - - $archiveSize = filesize($this->paths->archiveFilepath); - - echo "Version: {$archiveInfo->archiveHeader->version}"; - echo '
        '; - echo "IsCompressed: ".DupArchiveUtil::boolToString($archiveInfo->archiveHeader->isCompressed); - echo '
        '; - // echo "Expected Directory Count: {$archiveInfo->archiveHeader->directoryCount}"; - // echo '
        '; - echo "Total file size: {$sizeInArchive} bytes"; - echo '
        '; - echo "Archive size: {$archiveSize} bytes"; - echo '
        '; - $directoryCount = count($archiveInfo->directoryHeaders); - echo "Actual Directory Count: {$directoryCount}"; - echo '
        '; - // echo "Expected File Count: {$archiveInfo->archiveHeader->fileCount}"; - // echo '
        '; - $fileCount = count($archiveInfo->fileHeaders); - echo "Actual File Count: {$fileCount}"; - echo '
        '; - echo '
        '; - echo 'DIRECTORIES'; - echo '
        '; - $c = 1; - //print_r($archiveInfo); - foreach ($archiveInfo->directoryHeaders as $directoryHeader) { - /* @var $directoryHeader DupArchiveDirectoryHeader */ - echo "{$c}:{$directoryHeader->relativePath} P:{$directoryHeader->permissions}
        "; - $c++; - } - echo '
        '; - echo 'FILES'; - echo '
        '; - $c = 1; - //print_r($archiveInfo); - foreach ($archiveInfo->fileHeaders as $fileHeader) { - /* @var $fileHeader DupArchiveFileHeader */ - echo "{$c}:{$fileHeader->relativePath} ({$fileHeader->fileSize} bytes)
        "; - $c++; - } - exit(1); - } else { - echo 'unknown command.'; - exit(1); - } - - DupLiteSnapLibIOU::flock($this->lockHandle, LOCK_UN); - - $this->logger->log("Unlocked file"); - - session_write_close(); - if ($spawnAnotherThread) { - - $url = "http://$_SERVER[HTTP_HOST]".strtok($_SERVER["REQUEST_URI"], '?'); - - $data = $this->params->getQueryStringData(); - - $this->logger->logObject("SPAWNING CUSTOM WORKER AT $url FOR ACTION {$this->params->action}", $data); - - DupLiteSnapLibNetU::postWithoutWait($url, $data); - - $this->logger->log('After post without wait'); - } else { - $this->logger->log("start timestamp {$daTesterState->startTimestamp}"); - $deltaTime = time() - $daTesterState->startTimestamp; - $this->logger->log("###### Processing ended. Seconds taken:$deltaTime"); - $this->logger->logObject("##### FAILURES:", $daTesterState->failures); - } - } catch (Exception $ex) { - $error_message = "Error Encountered:".$ex->getMessage().'
        '.$ex->getTraceAsString(); - - $this->logger->log($error_message); - echo $error_message; - } - } - - // Returns json - // { - // status: 0|-1 (success, failure) - // data : true|false (for working) || {failure message} - // } - function get_status() - { - $error_message = null; - $ret_val = new stdClass(); - - try { - $build_state = CompressExtractState::getInstance(); - - $ret_val->status = 0; - $ret_val->data = $build_state; - } catch (Exception $ex) { - $ret_val->status = -1; - $ret_val->data = $error_message; - } - - echo json_encode($ret_val); - // JSON_U::customEncode($ret_val); - } - - private function clearCreateFiles() - { - if (file_exists($this->paths->scanFilepath)) { - @unlink($this->paths->scanFilepath); - } - - $handle = DupLiteSnapLibIOU::fopen($this->paths->archiveFilepath, 'w'); - DupLiteSnapLibIOU::fclose($handle); - - //$this->logger->clearLog(); - } - - private function clearExpandFiles() - { - if (file_exists($this->paths->restoreDirectory)) { - DupLiteSnapLibIOU::rrmdir($this->paths->restoreDirectory); - } - - if (file_exists($this->paths->tempDirectory)) { - DupLiteSnapLibIOU::rrmdir($this->paths->tempDirectory); - } - - mkdir($this->paths->restoreDirectory); - // $this->logger->clearLog(); - } -// private function fake_crash($worker_string, $next_scan_index, $next_file_offset) -// { -// $url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; -// $data = array('action' => $worker_string, 'next_scan_index' => $next_scan_index, -// 'next_file_offset' => $next_file_offset); -// -// $this->logger->log("spawning new custom worker at $url"); -// $this->post_without_wait($url, $data); -// -// exit(); -// } -// private function try_crash($source_filepath, $next_file_offset) -// { -// $should_crash = (self::CRASH_PROBABILITY >= rand(1, 100)); -// -// $should_crash = false; -// -// if ($should_crash) { -// $this->logger->log("##### Crashing for $source_filepath at $next_file_offset"); -// -// $this->fake_crash('compress', $next_scan_index, $next_file_offset); -// } -// } -} - -function generateCallTrace() -{ - $e = new Exception(); - $trace = explode("\n", $e->getTraceAsString()); - // reverse array to make steps line up chronologically - $trace = array_reverse($trace); - array_shift($trace); // remove {main} - array_pop($trace); // remove call to this method - $length = count($trace); - $result = array(); - - for ($i = 0; $i < $length; $i++) { - $result[] = ($i + 1).')'.substr($trace[$i], strpos($trace[$i], ' ')); // replace '#someNum' with '$i)', set the right ordering - } - - return "\t".implode("\n\t", $result); -} - -function terminate_missing_variables($errno, $errstr, $errfile, $errline) -{ - echo "
        ERROR: $errstr $errfile $errline
        "; - // if (($errno == E_NOTICE) and ( strstr($errstr, "Undefined variable"))) die("$errstr in $errfile line $errline"); - - $logfilepath = getenv("TEMP").'/duparchivetester'; - $logfilepath = "{$logfilepath}/tester2.log"; - - $logger = new DaTesterLogging($this->paths->logFilepath); - - - $logger->log("ERROR $errno, $errstr, {$errfile}:{$errline}"); - $logger->log(generateCallTrace()); - // $this->logger->clearLog(); - - exit(1); - //return false; // Let the PHP error handler handle all the rest -} - -$daTester = new DaTester(); -$daTester->processRequest(); diff --git a/lib/dup_archive/tester/index.php b/lib/dup_archive/tester/index.php deleted file mode 100644 index 17a71fa7..00000000 --- a/lib/dup_archive/tester/index.php +++ /dev/null @@ -1,2 +0,0 @@ -setFromData($data); - - // self::$instance->fileRenames = (array)(self::$instance->fileRenames); - - DupLiteSnapLibIOU::flock($stateHandle, LOCK_UN); - - DupLiteSnapLibIOU::fclose($stateHandle); - } else { - $reset = true; - } - } - - if ($reset) { - self::$instance = new FileOpsState(); - - self::$instance->reset(); - } - - return self::$instance; - } - - private function setFromData($data) - { - // $this->currentFileHeader = $data->currentFileHeader; - } - - public function reset() - { - $stateFilepath = dirname(__FILE__).'/'.self::StateFilename; - - $stateHandle = DupLiteSnapLibIOU::fopen($stateFilepath, 'w'); - - DupLiteSnapLibIOU::flock($stateHandle, LOCK_EX); - - $this->initMembers(); - - DupLiteSnapLibIOU::fwrite($stateHandle, json_encode($this)); - - DupLiteSnapLibIOU::fclose($stateHandle); - } - - public function save() - { - $stateFilepath = dirname(__FILE__).'/'.self::StateFilename; - - $stateHandle = DupLiteSnapLibIOU::fopen($stateFilepath, 'w'); - - DupLiteSnapLibIOU::flock($stateHandle, LOCK_EX); - - DupArchiveUtil::tlog("saving state"); - DupLiteSnapLibIOU::fwrite($stateHandle, json_encode($this)); - - DupLiteSnapLibIOU::fclose($stateHandle); - } - - private function initMembers() - { - // $this->currentFileHeader = null; - - } -} \ No newline at end of file diff --git a/lib/fileops/class.fileops.u.delete.php b/lib/fileops/class.fileops.u.delete.php deleted file mode 100644 index 6b99386f..00000000 --- a/lib/fileops/class.fileops.u.delete.php +++ /dev/null @@ -1,46 +0,0 @@ -pass = false; - - - if (isset($_REQUEST['action'])) { - //$params = $_REQUEST; - $params = array(); - DupLiteSnapLibLogger::logObject('REQUEST', $_REQUEST); - - foreach($_REQUEST as $key => $value) - { - $params[$key] = json_decode($value, true); - } - - } else { - $json = file_get_contents('php://input'); - DupLiteSnapLibLogger::logObject('json1', $json); - $params = json_decode($json, true); - DupLiteSnapLibLogger::logObject('json2', $json); - } - - DupLiteSnapLibLogger::logObject('params', $params); - DupLiteSnapLibLogger::logObject('keys', array_keys($params)); - - $action = $params['action']; - - if ($action == 'deltree') { - - DupLiteSnapLibLogger::log('deltree'); - - - - $config = DeleteConfig(); - - $config->workerTime = DupLiteSnapLibUtil::GetArrayValue($params, 'worker_time'); - $config->directories = DupLiteSnapLibUtil::getArrayValue($params, 'directories'); - $config->throttleDelayInUs = DupLiteSnapLibUtil::getArrayValue($params, 'throttleDelay', false, 0) * 1000000; - $config->excludedDirectories = DupLiteSnapLibUtil::getArrayValue($params, 'excluded_directories', false, array()); - $config->excludedFiles = DupLiteSnapLibUtil::getArrayValue($params, 'excluded_files', false, array()); - $config->fileLock = DupLiteSnapLibUtil::GetArrayValue($params, 'fileLock'); - - DupLiteSnapLibLogger::logObject('Config', $config); - - - - // TODO use appropriate lock type - DupLiteSnapLibIOU::flock($this->lock_handle, LOCK_EX); - - $this->lock_handle = DupLiteSnapLibIOU::fopen(FileOpsConstants::$PROCESS_LOCK_FILEPATH, 'c+'); - - - - - - DupLiteSnapLibIOU::flock($this->lock_handle, LOCK_UN); - - $retVal->pass = true; - $retVal->status = new stdClass; - //todo $retVal->status->errors = $moveErrors; // RSR TODO ensure putting right thing in here - - } else if($action === 'move_files') { - - $directories = DupLiteSnapLibUtil::getArrayValue($params, 'directories', false, array()); - $files = DupLiteSnapLibUtil::getArrayValue($params, 'files', false, array()); - $excludedFiles = DupLiteSnapLibUtil::getArrayValue($params, 'excluded_files', false, array()); - $destination = DupLiteSnapLibUtil::getArrayValue($params, 'destination'); - - DupLiteSnapLibLogger::log('before move'); - $moveErrors = FileOpsMoveU::move($directories, $files, $excludedFiles, $destination); - - DupLiteSnapLibLogger::log('after move'); - - $retVal->pass = true; - $retVal->status = new stdClass(); - $retVal->status->errors = $moveErrors; // RSR TODO ensure putting right thing in here - } - else { - - throw new Exception('Unknown command.'); - } - - session_write_close(); - - } catch (Exception $ex) { - $error_message = "Error Encountered:" . $ex->getMessage() . '
        ' . $ex->getTraceAsString(); - - DupLiteSnapLibLogger::log($error_message); - - $retVal->pass = false; - $retVal->error = $error_message; - } - - DupLiteSnapLibLogger::logObject("before json encode retval", $retVal); - - $jsonRetVal = json_encode($retVal); - DupLiteSnapLibLogger::logObject("json encoded retval", $jsonRetVal); - echo $jsonRetVal; - } -} - -function generateCallTrace() -{ - $e = new Exception(); - $trace = explode("\n", $e->getTraceAsString()); - // reverse array to make steps line up chronologically - $trace = array_reverse($trace); - array_shift($trace); // remove {main} - array_pop($trace); // remove call to this method - $length = count($trace); - $result = array(); - - for ($i = 0; $i < $length; $i++) { - $result[] = ($i + 1) . ')' . substr($trace[$i], strpos($trace[$i], ' ')); // replace '#someNum' with '$i)', set the right ordering - } - - return "\t" . implode("\n\t", $result); -} - -function terminate_missing_variables($errno, $errstr, $errfile, $errline) -{ -// echo "
        ERROR: $errstr $errfile $errline
        "; - // if (($errno == E_NOTICE) and ( strstr($errstr, "Undefined variable"))) die("$errstr in $errfile line $errline"); - - - DupLiteSnapLibLogger::log("ERROR $errno, $errstr, {$errfile}:{$errline}"); - DupLiteSnapLibLogger::log(generateCallTrace()); - // DaTesterLogging::clearLog(); - - // exit(1); - //return false; // Let the PHP error handler handle all the rest -} - -$fileOps = new FileOps(); - -$fileOps->processRequest(); \ No newline at end of file diff --git a/lib/fileops/index.php b/lib/fileops/index.php deleted file mode 100644 index 17a71fa7..00000000 --- a/lib/fileops/index.php +++ /dev/null @@ -1,2 +0,0 @@ - $reflect->name - ); - - if (version_compare(PHP_VERSION, '5.3.0') >= 0) { - /** - * get all props of current class but not props private of parent class - */ - $props = $reflect->getProperties(); - - foreach ($props as $prop) { - $prop->setAccessible(true); - $propName = $prop->getName(); - $propValue = $prop->getValue($obj); - - $result[$propName] = self::parseValueToArray($propValue); - } - } else { - $objArray = (array) $obj; - $re = '/(?:.*\x00)?(.+)/'; - $subst = '$1'; - - foreach ($objArray as $origPropName => $propValue) { - $propName = preg_replace($re, $subst, $origPropName, 1); - $result[$propName] = self::parseValueToArray($propValue); - } - } - return $result; - } - - protected static function parseValueToArray($value) - { - if (is_object($value)) { - return self::objectToPublicArrayClass($value); - } else if (is_array($value)) { - $result = array(); - foreach ($value as $key => $arrayVal) { - $result[$key] = self::parseValueToArray($arrayVal); - } - return $result; - } else { - return $value; - } - } - - protected static function parseArrayToValue($value, $classFromProp = null) - { - if (($newClassName = self::getClassFromArray($value, $classFromProp)) !== false) { - if (class_exists($newClassName)) { - $newObj = new $newClassName(); - } else { - $newObj = new StdClass(); - } - - if (is_subclass_of($newObj, __CLASS__)) { - $newObj->initFromPublicArray($value, $classFromProp); - } else { - $reflect = new ReflectionObject($newObj); - $excludeProps = array(self::CLASS_KEY_FOR_JSON_SERIALIZE); - - $privateProps = $reflect->getProperties(ReflectionProperty::IS_PROTECTED + ReflectionProperty::IS_PRIVATE + ReflectionProperty::IS_STATIC); - foreach ($privateProps as $pros) { - $excludeProps[] = $pros->getName(); - } - - foreach ($value as $arrayProp => $arrayValue) { - if (in_array($arrayProp, $excludeProps)) { - continue; - } - $newObj->{$arrayProp} = self::parseArrayToValue($arrayValue, $classFromProp); - } - } - return $newObj; - } else if (is_array($value)) { - $result = array(); - foreach ($value as $key => $arrayVal) { - $result[$key] = self::parseArrayToValue($arrayVal); - } - return $result; - } else { - return $value; - } - } - - protected function initFromPublicArray($array, $classFromProp = null) - { - if (!is_array($array)) { - return false; - } - - $reflect = new ReflectionObject($this); - $classFromArray = self::getClassFromArray($array, $classFromProp); - - if ($classFromArray == false || $classFromArray !== $reflect->name) { - return false; - } - - $excludeProps = array(self::CLASS_KEY_FOR_JSON_SERIALIZE); - $privateProps = $reflect->getProperties(ReflectionProperty::IS_PRIVATE + ReflectionProperty::IS_STATIC); - - foreach ($privateProps as $pros) { - $excludeProps[] = $pros->getName(); - } - - foreach ($array as $propName => $propValue) { - if (in_array($propName, $excludeProps)) { - continue; - } - $this->{$propName} = self::parseArrayToValue($propValue, $classFromProp); - } - } - - protected static function getClassFromArray($array, $classFromProp = null) - { - if (!is_array($array)) { - return false; - } else if (isset($array[self::CLASS_KEY_FOR_JSON_SERIALIZE])) { - return $array[self::CLASS_KEY_FOR_JSON_SERIALIZE]; - } else if (!is_null($classFromProp) && isset($array[$classFromProp])) { - return $array[$classFromProp]; - } else { - return false; - } - } - - /** - * - */ - public function jsonSerialize() - { - return DupLiteSnapJsonU::wp_json_encode_pprint(self::objectToPublicArrayClass($this)); - } - - /** - * - * @param string $json - * @return type - */ - public static function jsonUnserialize($json, $classFromProp = null) - { - $publicArray = json_decode($json, true); - return self::parseArrayToValue($publicArray, $classFromProp); - } - } -} diff --git a/lib/snaplib/class.snaplib.logger.php b/lib/snaplib/class.snaplib.logger.php deleted file mode 100644 index e5b53fd4..00000000 --- a/lib/snaplib/class.snaplib.logger.php +++ /dev/null @@ -1,144 +0,0 @@ -"; - $lfp = self::$logFilepath; - // echo "logging $s to {$lfp}
        "; - if (self::$logFilepath === null) { - throw new Exception('Logging not initialized'); - } - - if (isset($_SERVER['REQUEST_TIME_FLOAT'])) { - $timepart = $_SERVER['REQUEST_TIME_FLOAT']; - } else { - $timepart = $_SERVER['REQUEST_TIME']; - } - - $thread_id = sprintf("%08x", abs(crc32($_SERVER['REMOTE_ADDR'].$timepart.$_SERVER['REMOTE_PORT']))); - - $s = $thread_id.' '.date('h:i:s').":$s"; - - if (self::$logHandle === null) { - - self::$logHandle = fopen(self::$logFilepath, 'a'); - } - - fwrite(self::$logHandle, "$s\n"); - - if ($flush) { - fflush(self::$logHandle); - - fclose(self::$logHandle); - - self::$logHandle = fopen(self::$logFilepath, 'a'); - } - } - private static $profileLogArray = null; - private static $prevTS = -1; - - public static function initProfiling() - { - self::$profileLogArray = array(); - } - - public static function writeToPLog($s) - { - throw new exception('not implemented'); - $currentTime = microtime(true); - - if (array_key_exists($s, self::$profileLogArray)) { - $dSame = $currentTime - self::$profileLogArray[$s]; - $dSame = number_format($dSame, 7); - } else { - $dSame = 'N/A'; - } - - if (self::$prevTS != -1) { - $dPrev = $currentTime - self::$prevTS; - $dPrev = number_format($dPrev, 7); - } else { - $dPrev = 'N/A'; - } - - self::$profileLogArray[$s] = $currentTime; - self::$prevTS = $currentTime; - - self::log(" {$dPrev} : {$dSame} : {$currentTime} : {$s}"); - } - - /** - * - * @param mixed $var - * @param bool $checkCallable // if true check if var is callable and display it - * @return string - */ - public static function varToString($var, $checkCallable = false) - { - if ($checkCallable && is_callable($var)) { - return '(callable) '.print_r($var, true); - } - switch (gettype($var)) { - case "boolean": - return $var ? 'true' : 'false'; - case "integer": - case "double": - return (string) $var; - case "string": - return '"'.$var.'"'; - case "array": - case "object": - return print_r($var, true); - case "resource": - case "resource (closed)": - case "NULL": - case "unknown type": - default: - return gettype($var); - } - } - } -} diff --git a/lib/snaplib/class.snaplib.u.db.php b/lib/snaplib/class.snaplib.u.db.php deleted file mode 100644 index c85c1694..00000000 --- a/lib/snaplib/class.snaplib.u.db.php +++ /dev/null @@ -1,241 +0,0 @@ -num_rows == 0) { - self::$cache[$cacheKey] = false; - } else { - $primary = false; - $unique = false; - - while ($row = $result->fetch_assoc()) { - switch ($row['Key']) { - case 'PRI': - if ($primary === false) { - $primary = $row['Field']; - } else { - if (is_scalar($primary)) { - $primary = array($primary); - } - $primary[] = $row['Field']; - } - break; - case 'UNI': - $unique = $row['Field']; - break; - default: - break; - } - } - if ($primary !== false) { - self::$cache[$cacheKey] = $primary; - } else if ($unique !== false) { - self::$cache[$cacheKey] = $unique; - } else { - self::$cache[$cacheKey] = false; - } - } - - $result->free(); - } - - return self::$cache[$cacheKey]; - } - - /** - * - * @param array $row - * @param string|string[] $indexColumns - * @return string|string[] - */ - public static function getOffsetFromRowAssoc($row, $indexColumns, $lastOffset) - { - if (is_array($indexColumns)) { - $result = array(); - foreach ($indexColumns as $col) { - $result[$col] = isset($row[$col]) ? $row[$col] : 0; - } - return $result; - } else if (strlen($indexColumns) > 0) { - return isset($row[$indexColumns]) ? $row[$indexColumns] : 0; - } else { - return $lastOffset + 1; - } - } - - /** - * This function performs a select by structuring the primary key as offset if the table has a primary key. - * For optimization issues, no checks are performed on the input query and it is assumed that the select has at least a where value. - * If there are no conditions, you still have to perform an always true condition, for example - * SELECT * FROM `copy1_postmeta` WHERE 1 - * - * @param mysqli $dbh // Database connection handle - * @param string $query - * @param string $table - * @param int $offset - * @param int $limit // 0 no limit - * @param mixed $lastRowOffset // last offset to use on next function call - * @return mysqli_result - * @throws Exception // exception on query fail - */ - public static function selectUsingPrimaryKeyAsOffset(\mysqli $dbh, $query, $table, $offset, $limit, &$lastRowOffset = null, $logCallback = null) - { - $where = ''; - $orderby = ''; - $offsetStr = ''; - $limitStr = $limit > 0 ? ' LIMIT '.$limit : ''; - - if (($primaryColumn = self::getUniqueIndexColumn($dbh, $table, $logCallback)) == false) { - $offsetStr = ' OFFSET '.(is_scalar($offset) ? $offset : 0); - } else { - if (is_array($primaryColumn)) { - // COMPOSITE KEY - $orderByCols = array(); - foreach ($primaryColumn as $colIndex => $col) { - $orderByCols[] = '`'.$col.'` ASC'; - } - $orderby = ' ORDER BY '.implode(',', $orderByCols); - } else { - $orderby = ' ORDER BY `'.$primaryColumn.'` ASC'; - } - $where = self::getOffsetKeyCondition($dbh, $primaryColumn, $offset); - } - $query .= $where.$orderby.$limitStr.$offsetStr; - - if (($result = mysqli_query($dbh, $query)) === false) { - if (is_callable($logCallback)) { - call_user_func($logCallback, $dbh, $result, $query); - } - throw new Exception('SELECT ERROR: '.mysqli_error($dbh)); - } - - if (is_callable($logCallback)) { - call_user_func($logCallback, $dbh, $result, $query); - } - - if ($primaryColumn == false) { - $lastRowOffset = $offset + $result->num_rows; - } else { - if ($result->num_rows == 0) { - $lastRowOffset = $offset; - } else { - $result->data_seek(($result->num_rows - 1)); - $row = $result->fetch_assoc(); - if (is_array($primaryColumn)) { - $lastRowOffset = array(); - foreach ($primaryColumn as $col) { - $lastRowOffset[$col] = $row[$col]; - } - } else { - $lastRowOffset = $row[$primaryColumn]; - } - $result->data_seek(0); - } - } - - return $result; - } - - /** - * Depending on the structure type of the primary key returns the condition to position at the right offset - * - * @param string|string[] $primaryColumn - * @param mixed $offset - * @return string - */ - protected static function getOffsetKeyCondition(\mysqli $dbh, $primaryColumn, $offset) - { - $condition = ''; - - if ($offset === 0) { - return ''; - } - - // COUPOUND KEY - if (is_array($primaryColumn)) { - foreach ($primaryColumn as $colIndex => $col) { - if (is_array($offset) && isset($offset[$col]) && $offset[$col] > 0) { - $condition .= ($colIndex == 0 ? '' : ' OR '); - $condition .= ' ('; - for ($prevColIndex = 0; $prevColIndex < $colIndex; $prevColIndex++) { - $condition .= ' `'.$primaryColumn[$prevColIndex].'` = "'.mysqli_real_escape_string($dbh, $offset[$primaryColumn[$prevColIndex]]).'" AND '; - } - $condition .= ' `'.$col.'` > "'.mysqli_real_escape_string($dbh, $offset[$col]).'")'; - } - } - } else { - $condition = '`'.$primaryColumn.'` > "'.mysqli_real_escape_string($dbh, (is_scalar($offset) ? $offset : 0)).'"'; - } - - return (strlen($condition) ? ' AND ('.$condition.')' : ''); - } - - public static function getDBEngine(\mysqli $dbh) - { - $result = mysqli_query($dbh, "SHOW VARIABLES LIKE 'version%'"); - $rows = @mysqli_fetch_all($result); - @mysqli_free_result($result); - - $version = isset($rows[0][1]) ? $rows[0][1] : false; - $versionComment = isset($rows[1][1]) ? $rows[1][1] : false; - - //Default is mysql - if ($version === false && $versionComment === false) { - return self::DB_ENGINE_MYSQL; - } - - if (stripos($version, 'maria') !== false || stripos($versionComment, 'maria') !== false) { - return self::DB_ENGINE_MARIA; - } - - if (stripos($version, 'percona') !== false || stripos($versionComment, 'percona') !== false) { - return self::DB_ENGINE_PERCONA; - } - - return self::DB_ENGINE_MYSQL; - } -} diff --git a/lib/snaplib/class.snaplib.u.io.php b/lib/snaplib/class.snaplib.u.io.php deleted file mode 100644 index 2cc17b11..00000000 --- a/lib/snaplib/class.snaplib.u.io.php +++ /dev/null @@ -1,1302 +0,0 @@ - $value) { - ${$var} = $value; - } - - ob_start(); - if ($required) { - require ($path); - } else { - include ($path); - } - return ob_get_clean(); - } - - public static function chmodPattern($filePathPattern, $mode) - { - $filePaths = glob($filePathPattern); - - $modes = array(); - - foreach ($filePaths as $filePath) { - $modes[] = $mode; - } - array_map(array(__CLASS__, 'chmod'), $filePaths, $modes); - } - - public static function copy($source, $dest, $overwriteIfExists = true) - { - if (file_exists($dest)) { - if ($overwriteIfExists) { - self::rm($dest); - } else { - return false; - } - } - return copy($source, $dest); - } - - /** - * - * @param string $source - * @param string $dest - * @return boolean false if fail - */ - public static function rcopy($source, $dest) - { - if (!is_readable($source)) { - return false; - } - - if (is_dir($source)) { - if (!file_exists($dest)) { - if (!self::mkdir($dest)) { - return false; - } - } - - if (($handle = opendir($source)) != false) { - return false; - } - - while ($file = readdir($handle)) { - if ($file == "." && $file == "..") { - continue; - } - - if (is_dir($source.'/'.$file)) { - if (!self::rcopy($source.'/'.$file, $dest.'/'.$file)) { - return false; - } - } else { - if (!self::copy($source.'/'.$file, $dest.'/'.$file)) { - return false; - } - } - } - closedir($handle); - return true; - } else { - return self::copy($source, $dest); - } - } - - public static function untrailingslashit($path) - { - return rtrim($path, '/\\'); - } - - public static function trailingslashit($path) - { - return self::untrailingslashit($path).'/'; - } - - public static function safePath($path, $real = false) - { - if ($real) { - $res = realpath($path); - } else { - $res = $path; - } - return self::normalize_path($path); - } - - public static function safePathUntrailingslashit($path, $real = false) - { - if ($real) { - $res = realpath($path); - } else { - $res = $path; - } - return rtrim(self::normalize_path($res), '/'); - } - - public static function safePathTrailingslashit($path, $real = false) - { - return self::safePathUntrailingslashit($path, $real).'/'; - } - - /** - * - * @param string $sourceFolder - * @param string $destFolder - * @param bool $skipIfExists - * @return boolean - */ - public static function moveContentDirToTarget($sourceFolder, $destFolder, $skipIfExists = false) - { - if (!is_dir($sourceFolder) || !is_readable($sourceFolder)) { - return false; - } - - if (!is_dir($destFolder) || !is_writable($destFolder)) { - return false; - } - - $sourceIterator = new DirectoryIterator($sourceFolder); - foreach ($sourceIterator as $fileinfo) { - if ($fileinfo->isDot()) { - continue; - } - $destPath = $destFolder.'/'.$fileinfo->getBasename(); - - if (file_exists($destPath)) { - if ($skipIfExists) { - continue; - } else { - return false; - } - } - - if (self::rename($fileinfo->getPathname(), $destPath) == false) { - return false; - } - } - - return true; - } - - public static function massMove($fileSystemObjects, $destination, $exclusions = null, $exceptionOnError = true) - { - $failures = array(); - - $destination = rtrim($destination, '/\\'); - - if (!file_exists($destination) || !is_writeable($destination)) { - self::mkdir($destination, 'u+rwx'); - } - - foreach ($fileSystemObjects as $fileSystemObject) { - $shouldMove = true; - - if ($exclusions != null) { - - foreach ($exclusions as $exclusion) { - if (preg_match($exclusion, $fileSystemObject) === 1) { - $shouldMove = false; - break; - } - } - } - - if ($shouldMove) { - - $newName = $destination.'/'.basename($fileSystemObject); - - if (!file_exists($fileSystemObject)) { - $failures[] = "Tried to move {$fileSystemObject} to {$newName} but it didn't exist!"; - } else if (!@rename($fileSystemObject, $newName)) { - $failures[] = "Couldn't move {$fileSystemObject} to {$newName}"; - } - } - } - - if ($exceptionOnError && count($failures) > 0) { - throw new Exception(implode(',', $failures)); - } - - return $failures; - } - - /** - * Remove file path - * - * @param string $file path - * - * @return bool

        Returns TRUE on success or FALSE on failure.

        - */ - public static function unlink($file) - { - try { - if (!file_exists($file)) { - return true; - } - if (!function_exists('unlink') || is_dir($file)) { - return false; - } - self::chmod($file, 'u+rw'); - return @unlink($file); - } catch (Exception $e) { - return false; - } catch (Error $e) { - return false; - } - } - - /** - * Rename file from old name to new name - * - * @param string $oldname path - * @param string $newname path - * @param bool $removeIfExists if true remove exists file - * - * @return bool

        Returns TRUE on success or FALSE on failure.

        - */ - public static function rename($oldname, $newname, $removeIfExists = false) - { - try { - if (!file_exists($oldname) || !function_exists('rename')) { - return false; - } - - if ($removeIfExists && file_exists($newname)) { - if (!self::rrmdir($newname)) { - return false; - } - } - return @rename($oldname, $newname); - } catch (Exception $e) { - return false; - } catch (Error $e) { - return false; - } - } - - public static function fopen($filepath, $mode, $throwOnError = true) - { - if (strlen($filepath) > DupLiteSnapLibOSU::maxPathLen()) { - throw new Exception('Skipping a file that exceeds allowed max path length ['.DupLiteSnapLibOSU::maxPathLen().']. File: '.$filepath); - } - - if (DupLiteSnapLibStringU::startsWith($mode, 'w') || DupLiteSnapLibStringU::startsWith($mode, 'c') || file_exists($filepath)) { - $file_handle = @fopen($filepath, $mode); - } else { - if ($throwOnError) { - throw new Exception("$filepath doesn't exist"); - } else { - return false; - } - } - - if (!is_resource($file_handle)) { - if ($throwOnError) { - throw new Exception("Error opening $filepath"); - } else { - return false; - } - } else { - return $file_handle; - } - } - - public static function touch($filepath, $time = null) - { - if (!function_exists('touch')) { - return false; - } - - if ($time === null) { - $time = time(); - } - return @touch($filepath, $time); - } - - public static function rmdir($dirname, $mustExist = false) - { - if (file_exists($dirname)) { - self::chmod($dirname, 'u+rwx'); - if (self::rrmdir($dirname) === false) { - throw new Exception("Couldn't remove {$dirname}"); - } - } else if ($mustExist) { - throw new Exception("{$dirname} doesn't exist"); - } - } - - public static function rm($filepath, $mustExist = false) - { - if (file_exists($filepath)) { - self::chmod($filepath, 'u+rw'); - if (@unlink($filepath) === false) { - throw new Exception("Couldn't remove {$filepath}"); - } - } else if ($mustExist) { - throw new Exception("{$filepath} doesn't exist"); - } - } - - /** - * - * @param resource $handle - * @param string $string - * @return int - * @throws Exception - */ - public static function fwrite($handle, $string) - { - $bytes_written = @fwrite($handle, $string); - - if ($bytes_written != strlen($string)) { - throw new Exception('Error writing to file.'); - } else { - return $bytes_written; - } - } - - /** - * wrinte file in chunk mode. For big data. - * @param resource $handle - * @param string $content - * @return int - * @throws Exception - */ - public static function fwriteChunked($handle, $content) - { - $pieces = str_split($content, self::FWRITE_CHUNK_SIZE); - $written = 0; - - foreach ($pieces as $piece) { - if (($fwResult = @fwrite($handle, $piece, self::FWRITE_CHUNK_SIZE)) === false) { - throw new Exception('Error writing to file.'); - } - $written += $fwResult; - } - - if ($written != strlen($content)) { - throw new Exception('Error writing to file.'); - } - - return $written; - } - - public static function fgets($handle, $length) - { - $line = fgets($handle, $length); - - if ($line === false) { - throw new Exception('Error reading line.'); - } - - return $line; - } - - public static function fclose($handle, $exception_on_fail = true) - { - if ((@fclose($handle) === false) && $exception_on_fail) { - throw new Exception("Error closing file"); - } - } - - public static function flock($handle, $operation) - { - if (@flock($handle, $operation) === false) { - throw new Exception("Error locking file"); - } - } - - public static function ftell($file_handle) - { - $position = @ftell($file_handle); - - if ($position === false) { - throw new Exception("Couldn't retrieve file offset."); - } else { - return $position; - } - } - - /** - * Safely remove a directory and recursively files and directory upto multiple sublevels - * - * @param path $dir 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; - } - } - } - - public static function filesize($filename) - { - $file_size = @filesize($filename); - - if ($file_size === false) { - throw new Exception("Error retrieving file size of $filename"); - } - - return $file_size; - } - - public static function fseek($handle, $offset, $whence = SEEK_SET) - { - $ret_val = @fseek($handle, $offset, $whence); - - if ($ret_val !== 0) { - $filepath = stream_get_meta_data($handle); - $filepath = $filepath["uri"]; - $filesize = self::filesize($filepath); - // For future debug - /* - error_log('$offset: '.$offset); - error_log('$filesize: '.$filesize); - error_log($whence. ' == '. SEEK_SET); - */ - if ($ret_val === false) { - throw new Exception("Trying to fseek($offset, $whence) and came back false"); - } - //This check is not strict, but in most cases 32 Bit PHP will be the issue - else if (abs($offset) > self::FileSizeLimit32BitPHP || $filesize > self::FileSizeLimit32BitPHP || ($offset <= 0 && ($whence == SEEK_SET || $whence == SEEK_END))) { - throw new DupLiteSnapLib_32BitSizeLimitException("Trying to seek on a file beyond the capability of 32 bit PHP. offset=$offset filesize=$filesize"); - } else { - throw new Exception("Error seeking to file offset $offset. Retval = $ret_val"); - } - } - } - - public static function filemtime($filename) - { - $mtime = filemtime($filename); - - if ($mtime === E_WARNING) { - throw new Exception("Cannot retrieve last modified time of $filename"); - } - - return $mtime; - } - - /** - * exetute a file put contents after some checks. throw exception if fail. - * - * @param string $filename - * @param mixed $data - * @return boolean - * @throws Exception if putcontents fails - */ - public static function filePutContents($filename, $data) - { - if (($dirFile = realpath(dirname($filename))) === false) { - throw new Exception('FILE ERROR: put_content for file '.$filename.' failed [realpath fail]'); - } - if (!is_dir($dirFile)) { - throw new Exception('FILE ERROR: put_content for file '.$filename.' failed [dir '.$dirFile.' don\'t exists]'); - } - if (!is_writable($dirFile)) { - throw new Exception('FILE ERROR: put_content for file '.$filename.' failed [dir '.$dirFile.' exists but isn\'t writable]'); - } - $realFileName = $dirFile.basename($filename); - if (file_exists($realFileName) && !is_writable($realFileName)) { - throw new Exception('FILE ERROR: put_content for file '.$filename.' failed [file exist '.$realFileName.' but isn\'t writable'); - } - if (file_put_contents($filename, $data) === false) { - throw new Exception('FILE ERROR: put_content for file '.$filename.' failed [Couldn\'t write data to '.$realFileName.']'); - } - return true; - } - - public static function getFileName($file_path) - { - $info = new SplFileInfo($file_path); - return $info->getFilename(); - } - - public static function getPath($file_path) - { - $info = new SplFileInfo($file_path); - return $info->getPath(); - } - - /** - * 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 - * @param int|string $mode - * @return boolean - */ - public static function chmod($file, $mode) - { - if (!file_exists($file)) { - return false; - } - - $octalMode = 0; - - if (is_int($mode)) { - $octalMode = $mode; - } else if (is_numeric($mode)) { - $octalMode = intval((($mode[0] === '0' ? '' : '0').$mode), 8); - } else if (is_string($mode) && 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; - } - } - } - } else { - return true; - } - - // 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); - } - - /** - * return file perms in string - * - * @param int|string $perms - * @return string|bool // false if fail - */ - public static function permsToString($perms) - { - if (is_int($perms)) { - return decoct($perms); - } else if (is_numeric($perms)) { - return ($perms[0] === '0' ? '' : '0').$perms; - } else if (is_string($perms)) { - return $perms; - } else { - false; - } - } - - /** - * 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 - * @param int|string $mode - * @param bool $recursive - * @param resource $context // not used fo 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) > DupLiteSnapLibOSU::maxPathLen()) { - throw new Exception('Skipping a file that exceeds allowed max path length ['.DupLiteSnapLibOSU::maxPathLen().']. File: '.$path); - } - - if (!file_exists($path)) { - if (!function_exists('mkdir')) { - return false; - } - if (!@mkdir($path, 0777, $recursive)) { - return false; - } - } - - return self::chmod($path, $mode); - } - - /** - * this function call snap mkdir if te folder don't exists od don't have write or exec permissions - * - * this function handles the variable MODE in a way similar to the chmod of lunux - * The mode variable can be set to have more flexibility but not giving the user write and read and exec permissions doesn't make much sense - * - * @param string $path - * @param int|string $mode - * @param bool $recursive - * @param resource $context - * @return boolean - */ - public static function dirWriteCheckOrMkdir($path, $mode = 'u+rwx', $recursive = false, $context = null) - { - if (!file_exists($path)) { - return self::mkdir($path, $mode, $recursive, $context); - } else if (!is_writable($path) || !is_executable($path)) { - return self::chmod($path, $mode); - } else { - return true; - } - } - - /** - * from wordpress function wp_is_stream - * - * @param string $path The resource path or URL. - * @return bool True if the path is a stream URL. - */ - public static function is_stream($path) - { - $scheme_separator = strpos($path, '://'); - - if (false === $scheme_separator) { - // $path isn't a stream - return false; - } - - $stream = substr($path, 0, $scheme_separator); - - return in_array($stream, stream_get_wrappers(), true); - } - - /** - * From Wordpress function: wp_mkdir_p - * - * Recursive directory creation based on full path. - * - * Will attempt to set permissions on folders. - * - * @param string $target Full path to attempt to create. - * @return bool Whether the path was created. True if path already exists. - */ - public static function mkdir_p($target) - { - $wrapper = null; - - // Strip the protocol. - if (self::is_stream($target)) { - list( $wrapper, $target ) = explode('://', $target, 2); - } - - // From php.net/mkdir user contributed notes. - $target = str_replace('//', '/', $target); - - // Put the wrapper back on the target. - if ($wrapper !== null) { - $target = $wrapper.'://'.$target; - } - - /* - * Safe mode fails with a trailing slash under certain PHP versions. - * Use rtrim() instead of untrailingslashit to avoid formatting.php dependency. - */ - $target = rtrim($target, '/'); - if (empty($target)) { - $target = '/'; - } - - if (file_exists($target)) { - return @is_dir($target); - } - - // We need to find the permissions of the parent folder that exists and inherit that. - $target_parent = dirname($target); - while ('.' != $target_parent && !is_dir($target_parent) && dirname($target_parent) !== $target_parent) { - $target_parent = dirname($target_parent); - } - - // Get the permission bits. - if ($stat = @stat($target_parent)) { - $dir_perms = $stat['mode'] & 0007777; - } else { - $dir_perms = 0777; - } - - if (@mkdir($target, $dir_perms, true)) { - - /* - * If a umask is set that modifies $dir_perms, we'll have to re-set - * the $dir_perms correctly with chmod() - */ - if ($dir_perms != ( $dir_perms & ~umask() )) { - $folder_parts = explode('/', substr($target, strlen($target_parent) + 1)); - for ($i = 1, $c = count($folder_parts); $i <= $c; $i++) { - @chmod($target_parent.'/'.implode('/', array_slice($folder_parts, 0, $i)), $dir_perms); - } - } - - return true; - } - - return false; - } - - /** - * - * @param string|bool $path // return false if path isn't a sub path of main path or return the relative path - */ - public static function getRelativePath($path, $mainPath) - { - if (strlen($mainPath) == 0) { - return ltrim(self::safePathUntrailingslashit($path), '/'); - } - - $safePath = self::safePathUntrailingslashit($path); - $safeMainPath = self::safePathUntrailingslashit($mainPath); - - if ($safePath === $safeMainPath) { - return ''; - } else if (strpos($safePath, self::trailingslashit($safeMainPath)) === 0) { - return ltrim(substr($safePath, strlen($safeMainPath)), '/'); - } else { - return false; - } - } - - /** - * from wp_normalize_path - * - * @param string $path Path to normalize. - * @return string Normalized path. - */ - public static function normalize_path($path) - { - $wrapper = ''; - if (self::is_stream($path)) { - list( $wrapper, $path ) = explode('://', $path, 2); - $wrapper .= '://'; - } - - // Standardise all paths to use / - $path = str_replace('\\', '/', $path); - - // Replace multiple slashes down to a singular, allowing for network shares having two slashes. - $path = preg_replace('|(?<=.)/+|', '/', $path); - if (strpos($path, '//') === 0) { - $path = substr($path, 1); - } - - // Windows paths should uppercase the drive letter - if (':' === substr($path, 1, 1)) { - $path = ucfirst($path); - } - - return $wrapper.$path; - } - - /** - * Get common parent path from given paths - * - * @param array $paths - array of paths - * @return common parent path - */ - public static function getCommonPath($paths = array()) - { - if (empty($paths)) { - return ''; - } if (!is_array($paths)) { - $paths = array($paths); - } else { - $paths = array_values($paths); - } - - $pathAssoc = array(); - $numPaths = count($paths); - $minPathCouts = PHP_INT_MAX; - - for ($i = 0; $i < $numPaths; $i++) { - $pathAssoc[$i] = explode('/', self::safePathUntrailingslashit($paths[$i])); - $pathCount = count($pathAssoc[$i]); - if ($minPathCouts > $pathCount) { - $minPathCouts = $pathCount; - } - } - - for ($partIndex = 0; $partIndex < $minPathCouts; $partIndex++) { - $currentPart = $pathAssoc[0][$partIndex]; - for ($currentPath = 1; $currentPath < $numPaths; $currentPath++) { - if ($pathAssoc[$currentPath][$partIndex] != $currentPart) { - break 2; - } - } - } - - $resultParts = array_slice($pathAssoc[0], 0, $partIndex); - - return implode('/', $resultParts); - } - - /** - * remove root path transforming the current path into a relative path - * - * ex. /aaa/bbb become aaa/bbb - * ex. C:\aaa\bbb become aaa\bbb - * - * @param string $path - * @return string - */ - public static function removeRootPath($path) - { - return preg_replace('/^(?:[A-Za-z]:)?[\/](.*)/', '$1', $path); - } - - /** - * Returns the last N lines of a file. Simular to tail command - * - * @param string $filepath The full path to the file to be tailed - * @param int $lines The number of lines to return with each tail call - * - * @return string The last N parts of the file - */ - public static function tailFile($filepath, $lines = 2) - { - // Open file - $f = @fopen($filepath, "rb"); - if ($f === false) - return false; - - // Sets buffer size - $buffer = 256; - - // Jump to last character - fseek($f, -1, SEEK_END); - - // Read it and adjust line number if necessary - // (Otherwise the result would be wrong if file doesn't end with a blank line) - if (fread($f, 1) != "\n") - $lines -= 1; - - // Start reading - $output = ''; - $chunk = ''; - - // While we would like more - while (ftell($f) > 0 && $lines >= 0) { - // Figure out how far back we should jump - $seek = min(ftell($f), $buffer); - // Do the jump (backwards, relative to where we are) - fseek($f, -$seek, SEEK_CUR); - // Read a chunk and prepend it to our output - $output = ($chunk = fread($f, $seek)).$output; - // Jump back to where we started reading - fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR); - // Decrease our line counter - $lines -= substr_count($chunk, "\n"); - } - - // While we have too many lines - // (Because of buffer size we might have read too many) - while ($lines++ < 0) { - // Find first newline and remove all text before that - $output = substr($output, strpos($output, "\n") + 1); - } - fclose($f); - return trim($output); - } - - /** - * @param string $path Path to the file - * @param int $n Number of lines to get - * @param int $charLimit Number of chars to include in each line - * @return bool|array Last $n lines of file - * @throws Exception - */ - public static function getLastLinesOfFile($path, $n, $charLimit = null) - { - if (!is_readable($path)) { - return false; - } - - if (($handle = self::fopen($path, 'r', false)) === false) { - return false; - } - - $result = array(); - $pos = -1; - $currentLine = ''; - $counter = 0; - - while ($counter < $n && -1 !== fseek($handle, $pos, SEEK_END)) { - $char = fgetc($handle); - if (PHP_EOL == $char) { - $trimmedValue = trim($currentLine); - if (is_null($charLimit)) { - $currentLine = substr($currentLine, 0); - } else { - $currentLine = substr($currentLine, 0, (int) $charLimit); - if (strlen($currentLine) == $charLimit) { - $currentLine .= '...'; - } - } - - if (!empty($trimmedValue)) { - $result[] = $currentLine; - $counter++; - } - $currentLine = ''; - } else { - $currentLine = $char.$currentLine; - } - $pos--; - } - self::fclose($handle, false); - - return array_reverse($result); - } - - /** - * return a list of paths - * - * @param string $dir - * @param callable $callback - * @param array $options // array( - * 'regexFile' => [bool|string|array], // if is bool alrays or never match, if is string o array of string check if rexeses match file name - * 'regexFolder' => [bool|string|array], // if is bool alrays or never match, if is string o array of string check if rexeses match file name - * 'checkFullPath' => bool, // if false only current file/folder name is passed at regex if true is passed the full path - * 'recursive' => bool, // if false check only passed folder or all sub folder recursively - * 'invert' => bool, // if false pass invert the result - * 'childFirst' => bool // if false is parsed parent folters first or child folders first - * ) - * - * @return boolean - */ - public static function regexGlob($dir, $options) - { - $result = array(); - - self::regexGlobCallback($dir, function ($path) use (&$result) { - $result[] = $path; - }, $options); - - return $result; - } - - /** - * execute the callback function foreach right element, private function for optimization - * - * @param string $dir - * @param callable $callback - * @param array $options // array( - * 'regexFile' => [bool|string|array], // if is bool alrays or never match, if is string o array of string check if rexeses match file name - * 'regexFolder' => [bool|string|array], // if is bool alrays or never match, if is string o array of string check if rexeses match file name - * 'checkFullPath' => bool, // if false only current file/folder name is passed at regex if true is passed the full path - * 'recursive' => bool, // if false check only passed folder or all sub folder recursively - * 'invert' => bool, // if false pass invert the result - * 'childFirst' => bool // if false is parsed parent folters first or child folders first - * ) - * - * @return boolean - */ - protected static function regexGlobCallbackPrivate($dir, $callback, $options) - { - if (!is_dir($dir) || !is_readable($dir)) { - return false; - } - - if (($dh = opendir($dir)) == false) { - return false; - } - - $trailingslashitDir = self::trailingslashit($dir); - - while (($elem = readdir($dh)) !== false) { - if ($elem === '.' || $elem === '..') { - continue; - } - - $fullPath = $trailingslashitDir.$elem; - $regex = is_dir($fullPath) ? $options['regexFolder'] : $options['regexFile']; - $pathCheck = $options['checkFullPath'] ? $fullPath : $elem; - - if (is_bool($regex)) { - $match = ($regex xor $options['invert']); - } else { - $match = false; - foreach ($regex as $currentRegex) { - if (preg_match($currentRegex, $pathCheck) === 1) { - $match = true; - break; - } - } - - if ($options['invert']) { - $match = !$match; - } - } - - if ($match) { - if ($options['recursive'] && $options['childFirst'] === true && is_dir($fullPath)) { - self::regexGlobCallbackPrivate($fullPath, $callback, $options); - } - - call_user_func($callback, $fullPath); - - if ($options['recursive'] && $options['childFirst'] === false && is_dir($fullPath)) { - self::regexGlobCallbackPrivate($fullPath, $callback, $options); - } - } - } - closedir($dh); - - return true; - } - - /** - * execute the callback function foreach right element (folder or files) - * - * @param string $dir - * @param callable $callback - * @param array $options // array( - * 'regexFile' => [bool|string|array], // if is bool alrays or never match, if is string o array of string check if rexeses match file name - * 'regexFolder' => [bool|string|array], // if is bool alrays or never match, if is string o array of string check if rexeses match file name - * 'checkFullPath' => bool, // if false only current file/folder name is passed at regex if true is passed the full path - * 'recursive' => bool, // if false check only passed folder or all sub folder recursively - * 'invert' => bool, // if false pass invert the result - * 'childFirst' => bool // if false is parsed parent folters first or child folders first - * ) - * - * @return boolean - */ - public static function regexGlobCallback($dir, $callback, $options = array()) - { - if (!is_callable($callback)) { - return false; - } - - $options = array_merge(array( - 'regexFile' => true, - 'regexFolder' => true, - 'checkFullPath' => false, - 'recursive' => false, - 'invert' => false, - 'childFirst' => false - ), (array) $options); - - if (is_scalar($options['regexFile']) && !is_bool($options['regexFile'])) { - $options['regexFile'] = array($options['regexFile']); - } - - if (is_scalar($options['regexFolder']) && !is_bool($options['regexFolder'])) { - $options['regexFolder'] = array($options['regexFolder']); - } - - return self::regexGlobCallbackPrivate(self::safePath($dir), $callback, $options); - } - - public static function emptyDir($dir) - { - $dir = self::safePathTrailingslashit($dir); - if (!is_dir($dir) || !is_readable($dir)) { - return false; - } - - if (($dh = opendir($dir)) == false) { - return false; - } - - $listToDelete = array(); - - while (($elem = readdir($dh)) !== false) { - if ($elem === '.' || $elem === '..') { - continue; - } - - $fullPath = $dir.$elem; - if (is_writable($fullPath)) { - $listToDelete[] = $fullPath; - } - } - closedir($dh); - - foreach ($listToDelete as $path) { - self::rrmdir($path); - } - return true; - } - - /** - * Returns a path to the base root folder of path taking into account the - * open_basedir setting. - * - * @param $path - * @return bool|string Base root path of $path if it's accessible, otherwise false; - */ - public static function getMaxAllowedRootOfPath($path) - { - $path = self::safePathUntrailingslashit($path, true); - - if (!self::isOpenBaseDirEnabled()) { - $parts = explode("/", $path); - return $parts[0]."/"; - } else { - return self::getOpenBaseDirRootOfPath($path); - } - } - - /** - * @return bool true if open_basedir is set - */ - public static function isOpenBaseDirEnabled() - { - $iniVar = ini_get("open_basedir"); - return !empty($iniVar); - } - - /** - * @return array Paths contained in the open_basedir setting. Empty array if the setting - * is not enabled. - */ - public static function getOpenBaseDirPaths() - { - if (!($openBase = ini_get("open_basedir"))) { - return array(); - } - return explode(PATH_SEPARATOR, $openBase); - } - - /** - * @param $path - * @return bool|mixed|string Path to the base dir of $path if it exists, otherwise false - */ - public static function getOpenBaseDirRootOfPath($path) - { - foreach (self::getOpenBaseDirPaths() as $allowedPath) { - $allowedPath = $allowedPath !== "/" ? self::safePathUntrailingslashit($allowedPath) : "/"; - if (strpos($path, $allowedPath) === 0) { - return $allowedPath; - } - } - - return false; - } - } -} diff --git a/lib/snaplib/class.snaplib.u.json.php b/lib/snaplib/class.snaplib.u.json.php deleted file mode 100644 index 6c0b4f0d..00000000 --- a/lib/snaplib/class.snaplib.u.json.php +++ /dev/null @@ -1,311 +0,0 @@ -=')) { - $args = array($data, $options, $depth); - } elseif (version_compare(PHP_VERSION, '5.3', '>=')) { - $args = array($data, $options); - } else { - $args = array($data); - } - - // Prepare the data for JSON serialization. - $args[0] = self::_wp_json_prepare_data($data); - - $json = @call_user_func_array('json_encode', $args); - - // If json_encode() was successful, no need to do more sanity checking. - // ... unless we're in an old version of PHP, and json_encode() returned - // a string containing 'null'. Then we need to do more sanity checking. - if (false !== $json && ( version_compare(PHP_VERSION, '5.5', '>=') || false === strpos($json, 'null') )) { - return $json; - } - - try { - $args[0] = self::_wp_json_sanity_check($data, $depth); - } - catch (Exception $e) { - return false; - } - - return call_user_func_array('json_encode', $args); - } - - /** - * wp_json_encode with pretty print if define exists - * - * @param mixed $data Variable (usually an array or object) to encode as JSON. - * @param int $options Optional. Options to be passed to json_encode(). Default 0. - * @param int $depth Optional. Maximum depth to walk through $data. Must be - * greater than 0. Default 512. - * @return string|false The JSON encoded string, or false if it cannot be encoded. - */ - public static function wp_json_encode_pprint($data, $options = 0, $depth = 512) - { - if (defined('JSON_PRETTY_PRINT')) { - return self::wp_json_encode($data, JSON_PRETTY_PRINT | $options, $depth); - } else { - return self::wp_json_encode($data, $options, $depth); - } - } - - /** - * Prepares response data to be serialized to JSON. - * - * This supports the JsonSerializable interface for PHP 5.2-5.3 as well. - * - * @ignore - * @since 4.4.0 - * @access private - * - * @param mixed $data Native representation. - * @return bool|int|float|null|string|array Data ready for `json_encode()`. - */ - private static function _wp_json_prepare_data($data) - { - if (!defined('SNAP_WP_JSON_SERIALIZE_COMPATIBLE') || SNAP_WP_JSON_SERIALIZE_COMPATIBLE === false || !defined('WP_JSON_SERIALIZE_COMPATIBLE') || WP_JSON_SERIALIZE_COMPATIBLE === false) { - return $data; - } - - switch (gettype($data)) { - case 'boolean': - case 'integer': - case 'double': - case 'string': - case 'NULL': - // These values can be passed through. - return $data; - - case 'array': - // Arrays must be mapped in case they also return objects. - return array_map(array(__CLASS__, '_wp_json_prepare_data'), $data); - - case 'object': - // If this is an incomplete object (__PHP_Incomplete_Class), bail. - if (!is_object($data)) { - return null; - } - - if ($data instanceof JsonSerializable) { - $data = $data->jsonSerialize(); - } else { - $data = get_object_vars($data); - } - - // Now, pass the array (or whatever was returned from jsonSerialize through). - return self::_wp_json_prepare_data($data); - - default: - return null; - } - } - - /** - * Perform sanity checks on data that shall be encoded to JSON. - * - * @ignore - * @since 4.1.0 - * @access private - * - * @see wp_json_encode() - * - * @param mixed $data Variable (usually an array or object) to encode as JSON. - * @param int $depth Maximum depth to walk through $data. Must be greater than 0. - * @return mixed The sanitized data that shall be encoded to JSON. - */ - private static function _wp_json_sanity_check($data, $depth) - { - if ($depth < 0) { - throw new Exception('Reached depth limit'); - } - - if (is_array($data)) { - $output = array(); - foreach ($data as $id => $el) { - // Don't forget to sanitize the ID! - if (is_string($id)) { - $clean_id = self::_wp_json_convert_string($id); - } else { - $clean_id = $id; - } - - // Check the element type, so that we're only recursing if we really have to. - if (is_array($el) || is_object($el)) { - $output[$clean_id] = self::_wp_json_sanity_check($el, $depth - 1); - } elseif (is_string($el)) { - $output[$clean_id] = self::_wp_json_convert_string($el); - } else { - $output[$clean_id] = $el; - } - } - } elseif (is_object($data)) { - $output = new stdClass; - foreach ($data as $id => $el) { - if (is_string($id)) { - $clean_id = self::_wp_json_convert_string($id); - } else { - $clean_id = $id; - } - - if (is_array($el) || is_object($el)) { - $output->$clean_id = self::_wp_json_sanity_check($el, $depth - 1); - } elseif (is_string($el)) { - $output->$clean_id = self::_wp_json_convert_string($el); - } else { - $output->$clean_id = $el; - } - } - } elseif (is_string($data)) { - return self::_wp_json_convert_string($data); - } else { - return $data; - } - - return $output; - } - - private static function _wp_json_convert_string($string) - { - static $use_mb = null; - if (is_null($use_mb)) { - $use_mb = function_exists('mb_convert_encoding'); - } - - if ($use_mb) { - $encoding = mb_detect_encoding($string, mb_detect_order(), true); - if ($encoding) { - return mb_convert_encoding($string, 'UTF-8', $encoding); - } else { - return mb_convert_encoding($string, 'UTF-8', 'UTF-8'); - } - } else { - return self::wp_check_invalid_utf8($string, true); - } - } - - /** - * Checks for invalid UTF8 in a string. - * - * @since 2.8.0 - * - * @staticvar bool $utf8_pcre - * - * @param string $string The text which is to be checked. - * @param bool $strip Optional. Whether to attempt to strip out invalid UTF8. Default is false. - * @return string The checked text. - */ - public static function wp_check_invalid_utf8($string, $strip = false) - { - $string = (string) $string; - - if (0 === strlen($string)) { - return ''; - } - - // Check for support for utf8 in the installed PCRE library once and store the result in a static - static $utf8_pcre = null; - if (!isset($utf8_pcre)) { - $utf8_pcre = @preg_match('/^./u', 'a'); - } - // We can't demand utf8 in the PCRE installation, so just return the string in those cases - if (!$utf8_pcre) { - return $string; - } - - // preg_match fails when it encounters invalid UTF8 in $string - if (1 === @preg_match('/^./us', $string)) { - return $string; - } - - // Attempt to strip the bad chars if requested (not recommended) - if ($strip && function_exists('iconv')) { - return iconv('utf-8', 'utf-8', $string); - } - - return ''; - } - - /** - * @param mixed $val object to be encoded - * @return string escaped json string - */ - public static function json_encode_esc_attr($val) - { - return esc_attr(json_encode($val)); - } - - /** - * this function return a json encoded string without quotes at the beginning and the end - * - * @param string $string - * @return string - * @throws Exception - */ - public static function getJsonWithoutQuotes($string) - { - if (!is_string($string)) { - throw new Exception('the function getJsonStringWithoutQuotes take only strings'); - } - - return substr(self::wp_json_encode($string), 1, -1); - } - } -} diff --git a/lib/snaplib/class.snaplib.u.net.php b/lib/snaplib/class.snaplib.u.net.php deleted file mode 100644 index 9799e4cb..00000000 --- a/lib/snaplib/class.snaplib.u.net.php +++ /dev/null @@ -1,65 +0,0 @@ - &$val) { - if (is_array($val)) { - $val = implode(',', $val); - } - $post_params[] = $key.'='.urlencode($val); - } - - $post_string = implode('&', $post_params); - - $parts = parse_url($url); - - $fp = fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80, $errno, $errstr, 60); - - $out = "POST ".$parts['path']." HTTP/1.1\r\n"; - $out .= "Host: ".$parts['host']."\r\n"; - $out .= "Content-Type: application/x-www-form-urlencoded\r\n"; - $out .= "Content-Length: ".strlen($post_string)."\r\n"; - $out .= "Connection: Close\r\n\r\n"; - - if (isset($post_string)) { - $out .= $post_string; - } - - fwrite($fp, $out); - - fclose($fp); - } - - public static function getRequestValue($paramName, $isRequired = true, $default = null) - { - if (isset($_REQUEST[$paramName])) { - - return $_REQUEST[$paramName]; - } else { - - if ($isRequired) { - throw new Exception("Parameter $paramName not present"); - } - - return $default; - } - } - } -} \ No newline at end of file diff --git a/lib/snaplib/class.snaplib.u.orig.files.manager.php b/lib/snaplib/class.snaplib.u.orig.files.manager.php deleted file mode 100644 index f563f41d..00000000 --- a/lib/snaplib/class.snaplib.u.orig.files.manager.php +++ /dev/null @@ -1,348 +0,0 @@ -rootPath = DupLiteSnapLibIOU::safePathUntrailingslashit($root, true); - $this->origFilesFolder = DupLiteSnapLibIOU::safePathTrailingslashit($origFolderParentPath, true).self::ORIG_FOLDER_PREFIX.$hash; - $this->persistanceFile = $this->origFilesFolder.'/'.self::PERSISTANCE_FILE_NAME; - } - - /** - * create a main folder if don't exist and load the entries - * - * @param boolen $reset - */ - public function init($reset = false) - { - $this->createMainFolder($reset); - $this->load(); - } - - /** - * - * @param boolean $reset // if true delete current folder - * @return boolean // return true if succeded - * @throws Exception - */ - public function createMainFolder($reset = false) - { - if ($reset) { - $this->deleteMainFolder(); - } - - if (!file_exists($this->origFilesFolder)) { - if (!DupLiteSnapLibIOU::mkdir($this->origFilesFolder, 'u+rwx')) { - throw new Exception('Can\'t create the original files folder '.DupLiteSnapLibLogger::varToString($this->origFilesFolder)); - } - } - - $htaccessFile = $this->origFilesFolder.'/.htaccess'; - if (!file_exists($htaccessFile)) { - $htfile = @fopen($htaccessFile, 'w'); - $content = <<persistanceFile)) { - $this->save(); - } - - return true; - } - - /** - * @return string Main folder path - * @throws Exception - */ - public function getMainFolder() - { - if (!file_exists($this->origFilesFolder)) { - throw new Exception('Can\'t get the original files folder '.DupLiteSnapLibLogger::varToString($this->origFilesFolder)); - } - - return $this->origFilesFolder; - } - - /** - * delete origianl files folder - * - * @return boolean - * @throws Exception - */ - public function deleteMainFolder() - { - if (file_exists($this->origFilesFolder) && !DupLiteSnapLibIOU::rrmdir($this->origFilesFolder)) { - throw new Exception('Can\'t delete the original files folder '.DupLiteSnapLibLogger::varToString($this->origFilesFolder)); - } - $this->origFolderEntries = array(); - - return true; - } - - /** - * add a entry on original folder. - * - * @param string $identifier // entry identifier - * @param string $path // entry path. can be a file or a folder - * @param string $mode // MODE_MOVE move the item in original folder - * MODE_COPY copy the item in original folder - * @param bool|string $rename // if rename is a string the item is renamed in original folder. - * @return boolean // true if succeded - * @throws Exception - */ - public function addEntry($identifier, $path, $mode = self::MODE_MOVE, $rename = false) - { - if (!file_exists($path)) { - return false; - } - - $baseName = empty($rename) ? basename($path) : $rename; - - if (($relativePath = DupLiteSnapLibIOU::getRelativePath($path, $this->rootPath)) === false) { - $isRelative = false; - } else { - $isRelative = true; - } - $parentFolder = $isRelative ? dirname($relativePath) : DupLiteSnapLibIOU::removeRootPath(dirname($path)); - if (empty($parentFolder) || $parentFolder === '.') { - $parentFolder = ''; - } else { - $parentFolder .= '/'; - } - $targetFolder = $this->origFilesFolder.'/'.$parentFolder; - if (!file_exists($targetFolder)) { - DupLiteSnapLibIOU::mkdir_p($targetFolder); - } - $dest = $targetFolder.$baseName; - - switch ($mode) { - case self::MODE_MOVE: - if (!DupLiteSnapLibIOU::rename($path, $dest)) { - throw new Exception('Can\'t move the original file '.DupLiteSnapLibLogger::varToString($path)); - } - break; - case self::MODE_COPY: - if (!DupLiteSnapLibIOU::rcopy($path, $dest)) { - throw new Exception('Can\'t copy the original file '.DupLiteSnapLibLogger::varToString($path)); - } - break; - default: - throw new Exception('invalid mode addEntry'); - } - - $this->origFolderEntries[$identifier] = array( - 'baseName' => $baseName, - 'source' => $isRelative ? $relativePath : $path, - 'stored' => $parentFolder.$baseName, - 'mode' => $mode, - 'isRelative' => $isRelative - ); - - $this->save(); - return true; - } - - /** - * get entry info from itendifier - * - * @param string $identifier - * @return boolean // false if entry don't exists - */ - public function getEntry($identifier) - { - if (isset($this->origFolderEntries[$identifier])) { - return $this->origFolderEntries[$identifier]; - } else { - return false; - } - } - - /** - * get entry stored path in original folder - * - * @param string $identifier - * @return boolean // false if entry don't exists - */ - public function getEntryStoredPath($identifier) - { - if (isset($this->origFolderEntries[$identifier])) { - return $this->origFilesFolder.'/'.$this->origFolderEntries[$identifier]['stored']; - } else { - return false; - } - } - - public function isRelative($identifier) - { - if (isset($this->origFolderEntries[$identifier])) { - $this->origFolderEntries[$identifier]['isRelative']; - } else { - return false; - } - } - - /** - * get entry target restore path - * - * @param string $identifier - * @param type $defaultIfIsAbsolute - * @return boolean // false if entry don't exists - */ - public function getEntryTargetPath($identifier, $defaultIfIsAbsolute = null) - { - if (isset($this->origFolderEntries[$identifier])) { - if ($this->origFolderEntries[$identifier]['isRelative']) { - return $this->rootPath.'/'.$this->origFolderEntries[$identifier]['source']; - } else { - if (is_null($defaultIfIsAbsolute)) { - return $this->origFolderEntries[$identifier]['source']; - } else { - return $defaultIfIsAbsolute; - } - } - } else { - return false; - } - } - - /** - * this function restore current entry in original position. - * If mode is copy it simply delete the entry else move the entry in original position - * - * @param string $identifier // identified of current entrye - * @param boolean $save // update saved entries - * @return boolean // true if succeded - * @throws Exception - */ - public function restoreEntry($identifier, $save = true, $defaultIfIsntRelative = null) - { - if (!isset($this->origFolderEntries[$identifier])) { - return false; - } - - $stored = $this->getEntryStoredPath($identifier); - if (($original = $this->getEntryTargetPath($identifier, $defaultIfIsntRelative)) === false) { - return false; - } - - switch ($this->origFolderEntries[$identifier]['mode']) { - case self::MODE_MOVE: - if (!DupLiteSnapLibIOU::rename($stored, $original)) { - throw new Exception('Can\'t move the original file '.DupLiteSnapLibLogger::varToString($stored)); - } - break; - case self::MODE_COPY: - if (!DupLiteSnapLibIOU::rrmdir($stored)) { - throw new Exception('Can\'t delete entry '.DupLiteSnapLibLogger::varToString($stored)); - } - break; - default: - throw new Exception('invalid mode addEntry'); - } - - unset($this->origFolderEntries[$identifier]); - if ($save) { - $this->save(); - } - return true; - } - - /** - * put all entries on original position and empty original folder - * - * @return boolean - */ - public function restoreAll($exclude = array()) - { - foreach (array_keys($this->origFolderEntries) as $ident) { - if (in_array($ident, $exclude)) { - continue; - } - $this->restoreEntry($ident, false); - } - $this->save(); - return true; - } - - /** - * save notices from json file - */ - public function save() - { - if (!file_put_contents($this->persistanceFile, DupLiteSnapJsonU::wp_json_encode_pprint($this->origFolderEntries))) { - throw new Exception('Can\'t write persistence file'); - } - return true; - } - - /** - * load notice from json file - */ - private function load() - { - if (file_exists($this->persistanceFile)) { - $json = file_get_contents($this->persistanceFile); - $this->origFolderEntries = json_decode($json, true); - } else { - $this->origFolderEntries = array(); - } - return true; - } - } -} diff --git a/lib/snaplib/class.snaplib.u.os.php b/lib/snaplib/class.snaplib.u.os.php deleted file mode 100644 index 2de85306..00000000 --- a/lib/snaplib/class.snaplib.u.os.php +++ /dev/null @@ -1,66 +0,0 @@ - $maxWidth) { - $s = substr($s, 0, $maxWidth - 3).'...'; - } - - return $s; - } - - /** - * Returns true if the $haystack string starts with the $needle - * - * @param string $haystack The full string to search in - * @param string $needle The string to for - * - * @return bool Returns true if the $haystack string starts with the $needle - */ - public static function startsWith($haystack, $needle) - { - $length = strlen($needle); - return (substr($haystack, 0, $length) === $needle); - } - - /** - * Returns true if the $haystack string end with the $needle - * - * @param string $haystack The full string to search in - * @param string $needle The string to for - * - * @return bool Returns true if the $haystack string starts with the $needle - */ - public static function endsWith($haystack, $needle) - { - $length = strlen($needle); - if ($length == 0) { - return true; - } - - return (substr($haystack, -$length) === $needle); - } - - /** - * Returns true if the $needle is found in the $haystack - * - * @param string $haystack The full string to search in - * @param string $needle The string to for - * - * @return bool - */ - public static function contains($haystack, $needle) - { - $pos = strpos($haystack, $needle); - return ($pos !== false); - } - - /** - * - * @param string $glue - * @param array $pieces - * @param string $format - * @return string - */ - public static function implodeKeyVals($glue, $pieces, $format = '%s="%s"') - { - $strList = array(); - foreach ($pieces as $key => $value) { - if (is_scalar($value)) { - $strList[] = sprintf($format, $key, $value); - } else { - $strList[] = sprintf($format, $key, print_r($value, true)); - } - } - return implode($glue, $strList); - } - - /** - * Replace last occurrence - * - * @param String $search The value being searched for - * @param String $replace The replacement value that replaces found search values - * @param String $str The string or array being searched and replaced on, otherwise known as the haystack - * @param Boolean $caseSensitive Whether the replacement should be case sensitive or not - * - * @return String - */ - public static function strLastReplace($search, $replace, $str, $caseSensitive = true) - { - $pos = $caseSensitive ? strrpos($str, $search) : strripos($str, $search); - if (false !== $pos) { - $str = substr_replace($str, $replace, $pos, strlen($search)); - } - return $str; - } - - /** - * - * @param string $string - * @return boolean - */ - public static function isHTML($string) - { - return ($string != strip_tags($string)); - } - } -} diff --git a/lib/snaplib/class.snaplib.u.ui.php b/lib/snaplib/class.snaplib.u.ui.php deleted file mode 100644 index aa1f9c82..00000000 --- a/lib/snaplib/class.snaplib.u.ui.php +++ /dev/null @@ -1,49 +0,0 @@ -= php 5.2 - if (function_exists('filter_var') && defined('FILTER_VALIDATE_BOOLEAN')) { - echo filter_var($val, FILTER_VALIDATE_BOOLEAN) ? 'checked' : ''; - } else { - echo $val ? 'checked' : ''; - } - } - - public static function echoDisabled($val) - { - echo $val ? 'disabled' : ''; - } - - public static function echoSelected($val) - { - echo $val ? 'selected' : ''; - } - - public static function getSelected($val) - { - return ($val ? 'selected' : ''); - } - } -} \ No newline at end of file diff --git a/lib/snaplib/class.snaplib.u.url.php b/lib/snaplib/class.snaplib.u.url.php deleted file mode 100644 index 33c3ceb4..00000000 --- a/lib/snaplib/class.snaplib.u.url.php +++ /dev/null @@ -1,182 +0,0 @@ - false, - 'host' => false, - 'port' => false, - 'user' => false, - 'pass' => false, - 'path' => '', - 'scheme' => false, - 'query' => false, - 'fragment' => false - ); - - /** - * Append a new query value to the end of a URL - * - * @param string $url The URL to append the new value to - * @param string $key The new key name - * @param string $value The new key name value - * - * @return string Returns the new URL with with the query string name and value - */ - public static function appendQueryValue($url, $key, $value) - { - $separator = (parse_url($url, PHP_URL_QUERY) == NULL) ? '?' : '&'; - $modified_url = $url."$separator$key=$value"; - - return $modified_url; - } - - /** - * add www. in url if don't have - * - * @param string $url - * @return string - */ - public static function wwwAdd($url) - { - return preg_replace('/^((?:\w+\:)?\/\/)(?!www\.)(.+)/', '$1www.$2', $url); - } - - /** - * remove www. in url if don't have - * - * @param string $url - * @return string - */ - public static function wwwRemove($url) - { - return preg_replace('/^((?:\w+\:)?\/\/)www\.(.+)/', '$1$2', $url); - } - - /** - * Fetches current URL via php - * - * @param bool $queryString If true the query string will also be returned. - * @param int $getParentDirLevel if 0 get current script name or parent folder, if 1 parent folder if 2 parent of parent folder ... - * - * @returns The current page url - */ - 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; - } - - /** - * this function is a native PHP parse_url wrapper - * this function returns an associative array with all the keys present and the values = false if they do not exist. - * - * @param string $url

        The URL to parse. Invalid characters are replaced by _.

        - * @param int $component - * @return mixed

        On seriously malformed URLs, parse_url() may return FALSE.

        If the component parameter is omitted, an associative array is returned. At least one element will be present within the array. Potential keys within this array are:

        • scheme - e.g. http
        • host
        • port
        • user
        • pass
        • path
        • query - after the question mark ?
        • fragment - after the hashmark #

        If the component parameter is specified, parse_url() returns a string (or an integer, in the case of PHP_URL_PORT) instead of an array. If the requested component doesn't exist within the given URL, NULL will be returned.

        - */ - public static function parseUrl($url, $component = -1) - { - $result = parse_url($url, $component); - if (is_array($result)) { - $result = array_merge(self::$DEF_ARRAY_PARSE_URL, $result); - } - - return $result; - } - - /** - * this function build a url from array result of parse url. - * if work with both parse_url native function result and snap parseUrl result - * - * @param array $parts - * @return bool|string return false if param isn't array - */ - public static function buildUrl($parts) - { - if (!is_array($parts)) { - return false; - } - - $result = ''; - $result .= (isset($parts['scheme']) && $parts['scheme'] !== false) ? $parts['scheme'].':' : ''; - $result .= ( - (isset($parts['user']) && $parts['user'] !== false) || - (isset($parts['host']) && $parts['host'] !== false)) ? '//' : ''; - - $result .= (isset($parts['user']) && $parts['user'] !== false) ? $parts['user'] : ''; - $result .= (isset($parts['pass']) && $parts['pass'] !== false) ? ':'.$parts['pass'] : ''; - $result .= (isset($parts['user']) && $parts['user'] !== false) ? '@' : ''; - - $result .= (isset($parts['host']) && $parts['host'] !== false) ? $parts['host'] : ''; - $result .= (isset($parts['port']) && $parts['port'] !== false) ? ':'.$parts['port'] : ''; - - $result .= (isset($parts['path']) && $parts['path'] !== false) ? $parts['path'] : ''; - $result .= (isset($parts['query']) && $parts['query'] !== false) ? '?'.$parts['query'] : ''; - $result .= (isset($parts['fragment']) && $parts['fragment'] !== false) ? '#'.$parts['fragment'] : ''; - - return $result; - } - - /** - * encode alla chars - * - * @param string $url - * @return string - */ - public static function urlEncodeAll($url) - { - $hex = unpack('H*', urldecode($url)); - return preg_replace('~..~', '%$0', strtoupper($hex[1])); - } - } -} diff --git a/lib/snaplib/class.snaplib.u.util.php b/lib/snaplib/class.snaplib.u.util.php deleted file mode 100644 index 2f84defd..00000000 --- a/lib/snaplib/class.snaplib.u.util.php +++ /dev/null @@ -1,463 +0,0 @@ - 0) { - $percent = $startingPercent + (($endingPercent - $startingPercent) * ($currentTaskCount / (float) $totalTaskCount)); - } else { - $percent = $startingPercent; - } - - return min(max($startingPercent, $percent), $endingPercent); - } - - public static function make_hash() - { - // IMPORTANT! Be VERY careful in changing this format - the FTP delete logic requires 3 segments with the last segment to be the date in YmdHis format. - try { - if (function_exists('random_bytes') && self::PHP53()) { - return bin2hex(random_bytes(8)).mt_rand(1000, 9999).'_'.date("YmdHis"); - } else { - return strtolower(md5(uniqid(rand(), true))).'_'.date("YmdHis"); - } - } - catch (Exception $exc) { - return strtolower(md5(uniqid(rand(), true))).'_'.date("YmdHis"); - } - } - - public static function PHP53() - { - return version_compare(PHP_VERSION, '5.3.2', '>='); - } - - /** - * Groups an array into arrays by a given key, or set of keys, shared between all array members. - * - * Based on {@author Jake Zatecky}'s {@link https://github.com/jakezatecky/array_group_by array_group_by()} function. - * This variant allows $key to be closures. - * - * @param array $array The array to have grouping performed on. - * @param mixed $key,... The key to group or split by. Can be a _string_, an _integer_, a _float_, or a _callable_. - * - If the key is a callback, it must return a valid key from the array. - * - If the key is _NULL_, the iterated element is skipped. - * - string|int callback ( mixed $item ) - * - * @return array|null Returns a multidimensional array or `null` if `$key` is invalid. - */ - public static function arrayGroupBy(array $array, $key) - { - if (!is_string($key) && !is_int($key) && !is_float($key) && !is_callable($key)) { - trigger_error('array_group_by(): The key should be a string, an integer, or a callback', E_USER_ERROR); - return null; - } - $func = (!is_string($key) && is_callable($key) ? $key : null); - $_key = $key; - // Load the new array, splitting by the target key - $grouped = array(); - foreach ($array as $value) { - $key = null; - if (is_callable($func)) { - $key = call_user_func($func, $value); - } elseif (is_object($value) && isset($value->{$_key})) { - $key = $value->{$_key}; - } elseif (isset($value[$_key])) { - $key = $value[$_key]; - } - if ($key === null) { - continue; - } - $grouped[$key][] = $value; - } - // Recursively build a nested grouping if more parameters are supplied - // Each grouped array value is grouped according to the next sequential key - if (func_num_args() > 2) { - $args = func_get_args(); - foreach ($grouped as $key => $value) { - $params = array_merge(array($value), array_slice($args, 2, func_num_args())); - $grouped[$key] = call_user_func_array(array(__CLASS__, 'arrayGroupBy'), $params); - } - } - return $grouped; - } - - /** - * Converts human readable types (10GB) to bytes - * - * @param string $from A human readable byte size such as 100MB - * - * @return int Returns and integer of the byte size - */ - public static function convertToBytes($from) - { - if (is_numeric($from)) { - return $from; - } - - $number = substr($from, 0, -2); - switch (strtoupper(substr($from, -2))) { - case "KB": return $number * 1024; - case "MB": return $number * pow(1024, 2); - case "GB": return $number * pow(1024, 3); - case "TB": return $number * pow(1024, 4); - case "PB": return $number * pow(1024, 5); - } - - $number = substr($from, 0, -1); - switch (strtoupper(substr($from, -1))) { - case "K": return $number * 1024; - case "M": return $number * pow(1024, 2); - case "G": return $number * pow(1024, 3); - case "T": return $number * pow(1024, 4); - case "P": return $number * pow(1024, 5); - } - return $from; - } - - /** - * Sanitize input for XSS code - * - * @param string $val The value to sanitize - * - * @return string Returns the input value cleaned up. - */ - public static function sanitize($input) - { - return filter_var($input, FILTER_SANITIZE_FULL_SPECIAL_CHARS); - } - - /** - * remove all non stamp chars from string - * - * @param string $string - * @return string - */ - public static function sanitize_non_stamp_chars($string) - { - return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/u', '', $string); - } - - /** - * remove all non stamp chars from string and newline - * trim string - * - * @param string $string - * @return string - */ - public static function sanitize_non_stamp_chars_and_newline($string) - { - return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F\r\n]/u', '', $string); - } - - /** - * remove all non stamp chars from string and newline - * trim string - * - * @param string $string - * @return string - */ - public static function sanitize_non_stamp_chars_newline_and_trim($string) - { - return trim(self::sanitize_non_stamp_chars_and_newline($string)); - } - - /** - * Determines whether a PHP ini value is changeable at runtime. - * - * @since 4.6.0 - * - * @staticvar array $ini_all - * - * @link https://secure.php.net/manual/en/function.ini-get-all.php - * - * @param string $setting The name of the ini setting to check. - * @return bool True if the value is changeable at runtime. False otherwise. - */ - public static function wp_is_ini_value_changeable($setting) - { - // if ini_set is disabled can change the values - if (!function_exists('ini_set')) { - return false; - } - - if (function_exists('wp_is_ini_value_changeable')) { - return wp_is_ini_value_changeable($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(); - } - } - - // Bit operator to workaround https://bugs.php.net/bug.php?id=44936 which changes access level to 63 in PHP 5.2.6 - 5.2.17. - if (isset($ini_all[$setting]['access']) && ( INI_ALL === ( $ini_all[$setting]['access'] & 7 ) || INI_USER === ( $ini_all[$setting]['access'] & 7 ) )) { - return true; - } - - // If we were unable to retrieve the details, fail gracefully to assume it's changeable. - if (!is_array($ini_all)) { - return true; - } - - return false; - } - - /** - * The val value returns if it is between min and max otherwise it returns min or max - * - * @param int $val - * @param int $min - * @param int $max - * @return int - */ - public static function getIntBetween($val, $min, $max) - { - return min((int) $max, max((int) $min, (int) $val)); - } - - /** - * Find matching string from $strArr1 and $strArr2 until first numeric occurence - * - * @param array $strArr1 array of strings - * @param array $strArr2 array of strings - * @return string matching str which will be best for replacement - */ - public static function getMatchingStrFromArrayElemsUntilFirstNumeric($strArr1, $strArr2) - { - $matchingStr = ''; - $strPartialArr = array(); - foreach ($strArr1 as $str1) { - $str1_str_length = strlen($str1); - $tempStr1Chars = str_split($str1); - $tempPartialStr = ''; - // The flag is for whether non-numeric character passed after numeric character occurence in str1. For ex. str1 is utf8mb4, the flag wil be true when parsing m after utf8. - $numericCharPassFlag = false; - $charPositionInStr1 = 0; - while ($charPositionInStr1 < $str1_str_length) { - if ($numericCharPassFlag && !is_numeric($tempStr1Chars[$charPositionInStr1])) { - break; - } - if (is_numeric($tempStr1Chars[$charPositionInStr1])) { - $numericCharPassFlag = true; - } - $tempPartialStr .= $tempStr1Chars[$charPositionInStr1]; - $charPositionInStr1++; - } - $strPartialArr[] = $tempPartialStr; - } - foreach ($strPartialArr as $strPartial) { - if (!empty($matchingStr)) { - break; - } - foreach ($strArr2 as $str2) { - if (0 === stripos($str2, $strPartial)) { - $matchingStr = $str2; - break; - } - } - } - - return $matchingStr; - } - - /** - * Find matching string from $strArr1 and $strArr2 - * - * @param array $strArr1 array of strings - * @param array $strArr2 array of strings - * @param boolean $match_until_first_numeric only match until first numeric occurrence - * @return string matching str which will be best for replacement - */ - public static function getMatchingStrFromArrayElemsBasedOnUnderScore($strArr1, $strArr2) - { - $matchingStr = ''; - - $str1PartialFirstArr = array(); - $str1PartialFirstArr = array(); - $str1PartialStartNMiddleArr = array(); - $str1PartialMiddleNLastArr = array(); - $str1PartialLastArr = array(); - foreach ($strArr1 as $str1) { - $str1PartialArr = explode('_', $str1); - $str1_parts_count = count($str1PartialArr); - $str1PartialFirstArr[] = $str1PartialArr[0]; - $str1LastPartIndex = $str1_parts_count - 1; - if ($str1LastPartIndex > 0) { - $str1PartialLastArr[] = $str1PartialArr[$str1LastPartIndex]; - $str1PartialStartNMiddleArr[] = substr($str1, 0, strripos($str1, '_')); - $str1PartialMiddleNLastArr[] = substr($str1, stripos($str1, '_') + 1); - } - } - for ($caseNo = 1; $caseNo <= 5; $caseNo++) { - if (!empty($matchingStr)) { - break; - } - foreach ($strArr2 as $str2) { - switch ($caseNo) { - // Both Start and End match - case 1: - $str2PartialArr = explode('_', $str2); - $str2FirstPart = $str2PartialArr[0]; - $str2PartsCount = count($str2PartialArr); - $str2LastPartIndex = $str2PartsCount - 1; - if ($str2LastPartIndex > 0) { - $str2LastPart = $str2PartialArr[$str2LastPartIndex]; - } else { - $str2LastPart = ''; - } - if (!empty($str2LastPart) && !empty($str1PartialLastArr) && in_array($str2FirstPart, $str1PartialFirstArr) && in_array($str2LastPart, $str1PartialLastArr)) { - $matchingStr = $str2; - } - break; - // Start Middle Match - case 2: - $str2PartialFirstNMiddleParts = substr($str2, 0, strripos($str2, '_')); - if (in_array($str2PartialFirstNMiddleParts, $str1PartialStartNMiddleArr)) { - $matchingStr = $str2; - } - break; - // End Middle Match - case 3: - $str2PartialMiddleNLastParts = stripos($str2, '_') !== false ? substr($str2, stripos($str2, '_') + 1) : ''; - if (!empty($str2PartialMiddleNLastParts) && in_array($str2PartialMiddleNLastParts, $str1PartialMiddleNLastArr)) { - $matchingStr = $str2; - } - break; - // Start Match - case 4: - $str2PartialArr = explode('_', $str2); - $str2FirstPart = $str2PartialArr[0]; - if (in_array($str2FirstPart, $str1PartialFirstArr)) { - $matchingStr = $str2; - } - break; - // End Match - case 5: - $str2PartialArr = explode('_', $str2); - $str2PartsCount = count($str2PartialArr); - $str2LastPartIndex = $str2PartsCount - 1; - if ($str2LastPartIndex > 0) { - $str2LastPart = $str2PartialArr[$str2LastPartIndex]; - } else { - $str2LastPart = ''; - } - if (!empty($str2LastPart) && in_array($str2LastPart, $str1PartialLastArr)) { - $matchingStr = $str2; - } - break; - } - if (!empty($matchingStr)) { - break; - } - } - } - return $matchingStr; - } - - /** - * Gets a specific external variable by name and optionally filters it - * @param int $type

        One of INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, or INPUT_ENV.

        - * @param string $variable_name

        Name of a variable to get.

        - * @param int $filter

        The ID of the filter to apply. The Types of filters manual page lists the available filters.

        If omitted, FILTER_DEFAULT will be used, which is equivalent to FILTER_UNSAFE_RAW. This will result in no filtering taking place by default.

        - * @param mixed $options

        Associative array of options or bitwise disjunction of flags. If filter accepts options, flags can be provided in "flags" field of array.

        - * @return mixed

        Value of the requested variable on success, FALSE if the filter fails, or NULL if the variable_name variable is not set. If the flag FILTER_NULL_ON_FAILURE is used, it returns FALSE if the variable is not set and NULL if the filter fails.

        - * @link http://php.net/manual/en/function.filter-input.php - * @see filter_var(), filter_input_array(), filter_var_array() - * @since PHP 5 >= 5.2.0, PHP 7 - */ - public static function filterInputRequest($variable_name, $filter = FILTER_DEFAULT, $options = NULL) - { - if (isset($_GET[$variable_name]) && !isset($_POST[$variable_name])) { - return filter_input(INPUT_GET, $variable_name, $filter, $options); - } - - return filter_input(INPUT_POST, $variable_name, $filter, $options); - } - - /** - * Implemented array_key_first - * - * @link https://www.php.net/manual/en/function.array-key-first.php - * @param array $arr - * @return int|string|null - */ - public static function arrayKeyFirst($arr) - { - if (!function_exists('array_key_first')) { - foreach ($arr as $key => $unused) { - return $key; - } - return null; - } else { - return array_key_first($arr); - } - } - - /** - * Get number of bit supported by PHP - * - * @return string - */ - public static function getArchitectureString() - { - return (PHP_INT_SIZE * 8).'-bit'; - } - } -} diff --git a/lib/snaplib/class.snaplib.u.wp.php b/lib/snaplib/class.snaplib.u.wp.php deleted file mode 100644 index 6742be3c..00000000 --- a/lib/snaplib/class.snaplib.u.wp.php +++ /dev/null @@ -1,247 +0,0 @@ - [ - * 's-folder1' => [ - * file1 => [], - * file2 => [], - * ], - * 's-folder2' => [], - * file1 => [] - * ] - * ] - * - * @return array - */ - public static function getCorePathsList() - { - if (is_null(self::$corePathList)) { - require_once(dirname(__FILE__).'/wordpress.core.files.php'); - } - return self::$corePathList; - } - - /** - * return object list of sites - * - * @return boolean - */ - public static function getSites($args = array()) - { - if (!function_exists('is_multisite') || !is_multisite()) { - return false; - } - - if (function_exists('get_sites')) { - return get_sites($args); - } else { - $result = array(); - $blogs = wp_get_sites($args); - foreach ($blogs as $blog) { - $result[] = (object) $blog; - } - return $result; - } - } - } -} diff --git a/lib/snaplib/index.php b/lib/snaplib/index.php deleted file mode 100644 index 17a71fa7..00000000 --- a/lib/snaplib/index.php +++ /dev/null @@ -1,2 +0,0 @@ ->>>>> THIS FILE IS AUTOGENERATED DON'T MODIFY THIS DIRECTLY <<<<< - * >>>>>> USE THE GENERATOR SCRIPT <<<<< - * - * >>>>>> THIS FILE IS AUTOGENERATED DON'T MODIFY THIS DIRECTLY <<<<< - * >>>>>> USE THE GENERATOR SCRIPT <<<<< - * - * >>>>>> THIS FILE IS AUTOGENERATED DON'T MODIFY THIS DIRECTLY <<<<< - * >>>>>> USE THE GENERATOR SCRIPT <<<<< - * - * Core wordpress file list - * - * Standard: PSR-2 - * @link http://www.php-fig.org/psr/psr-2 - * - * @package snaplib - * @subpackage classes/utilities - * @copyright (c) 2017, Snapcreek LLC - * @license https://opensource.org/licenses/GPL-3.0 GNU Public License - * - */ -defined('ABSPATH') || defined('DUPXABSPATH') || exit; - -/* - * >>>>>> THIS FILE IS AUTOGENERATED DON'T MODIFY THIS DIRECTLY <<<<< - * >>>>>> USE THE GENERATOR SCRIPT <<<<< - * - * >>>>>> THIS FILE IS AUTOGENERATED DON'T MODIFY THIS DIRECTLY <<<<< - * >>>>>> USE THE GENERATOR SCRIPT <<<<< - * - * >>>>>> THIS FILE IS AUTOGENERATED DON'T MODIFY THIS DIRECTLY <<<<< - * >>>>>> USE THE GENERATOR SCRIPT <<<<< - * - */ -self::$corePathList = array( - 'wp-login.php' => array(), - 'wp-config-sample.php' => array(), - 'wp-activate.php' => array(), - 'wp-comments-post.php' => array(), - 'wp-signup.php' => array(), - 'wp-mail.php' => array(), - 'wp-links-opml.php' => array(), - 'wp-load.php' => array(), - 'wp-blog-header.php' => array(), - 'wp-content' => array( - 'index.php' => array() - ), - 'wp-includes' => array( - 'category-template.php' => array(), - 'class-wp-recovery-mode-email-service.php' => array(), - 'default-constants.php' => array(), - 'class-wp-http-requests-hooks.php' => array(), - 'class-wp-block-patterns-registry.php' => array(), - 'media.php' => array(), - 'block-patterns.php' => array(), - 'functions.php' => array(), - 'ms-network.php' => array(), - 'class-requests.php' => array(), - 'cache.php' => array(), - 'class-wp-dependency.php' => array(), - 'class-wp-http-proxy.php' => array(), - 'class-phpass.php' => array(), - 'ms-settings.php' => array(), - 'class-wp-customize-manager.php' => array(), - 'class-wp-block-styles-registry.php' => array(), - 'class-wp-recovery-mode-key-service.php' => array(), - 'class-walker-category.php' => array(), - 'class-wp-metadata-lazyloader.php' => array(), - 'blocks.php' => array(), - 'l10n.php' => array(), - 'cron.php' => array(), - 'template.php' => array(), - 'class-wp-widget-factory.php' => array(), - 'class-wp-network.php' => array(), - 'nav-menu-template.php' => array(), - 'class-wp-matchesmapregex.php' => array(), - 'feed-rdf.php' => array(), - 'widgets' => array( - 'class-wp-widget-pages.php' => array(), - 'class-wp-widget-text.php' => array(), - 'class-wp-widget-custom-html.php' => array(), - 'class-wp-widget-recent-comments.php' => array(), - 'class-wp-widget-tag-cloud.php' => array(), - 'class-wp-widget-links.php' => array(), - 'class-wp-widget-media-video.php' => array(), - 'class-wp-widget-archives.php' => array(), - 'class-wp-widget-search.php' => array(), - 'class-wp-widget-calendar.php' => array(), - 'class-wp-widget-meta.php' => array(), - 'class-wp-widget-media.php' => array(), - 'class-wp-nav-menu-widget.php' => array(), - 'class-wp-widget-media-audio.php' => array(), - 'class-wp-widget-recent-posts.php' => array(), - 'class-wp-widget-categories.php' => array(), - 'class-wp-widget-rss.php' => array(), - 'class-wp-widget-media-image.php' => array(), - 'class-wp-widget-media-gallery.php' => array() - ), - 'class-wp-paused-extensions-storage.php' => array(), - 'class-walker-page-dropdown.php' => array(), - 'class-wp-text-diff-renderer-inline.php' => array(), - 'theme-compat' => array( - 'sidebar.php' => array(), - 'embed-404.php' => array(), - 'embed-content.php' => array(), - 'footer-embed.php' => array(), - 'header-embed.php' => array(), - 'header.php' => array(), - 'footer.php' => array(), - 'embed.php' => array(), - 'comments.php' => array(), - 'comments-popup.php' => array() - ), - 'class-phpmailer.php' => array(), - 'class-wp-post-type.php' => array(), - 'class-wp-locale-switcher.php' => array(), - 'load.php' => array(), - 'class-wp-recovery-mode-cookie-service.php' => array(), - 'class-wp-role.php' => array(), - 'pluggable-deprecated.php' => array(), - 'class-wp-oembed-controller.php' => array(), - 'class-wp-term.php' => array(), - 'class-smtp.php' => array(), - 'capabilities.php' => array(), - 'IXR' => array( - 'class-IXR-server.php' => array(), - 'class-IXR-date.php' => array(), - 'class-IXR-request.php' => array(), - 'class-IXR-error.php' => array(), - 'class-IXR-client.php' => array(), - 'class-IXR-base64.php' => array(), - 'class-IXR-clientmulticall.php' => array(), - 'class-IXR-value.php' => array(), - 'class-IXR-message.php' => array(), - 'class-IXR-introspectionserver.php' => array() - ), - 'class-wp-text-diff-renderer-table.php' => array(), - 'class-wp-xmlrpc-server.php' => array(), - 'class-wp-site-query.php' => array(), - 'class-wp-admin-bar.php' => array(), - 'session.php' => array(), - 'class-wp-block-type-registry.php' => array(), - 'rewrite.php' => array(), - 'registration-functions.php' => array(), - 'option.php' => array(), - 'class-walker-comment.php' => array(), - 'post-formats.php' => array(), - 'class-wp-customize-setting.php' => array(), - 'pluggable.php' => array(), - 'class-wp-block-type.php' => array(), - 'class-wp-http-response.php' => array(), - 'class-wp-error.php' => array(), - 'deprecated.php' => array(), - 'blocks' => array( - 'pullquote' => array( - 'block.json' => array() - ), - 'gallery' => array( - 'block.json' => array() - ), - 'code' => array( - 'block.json' => array() - ), - 'more' => array( - 'block.json' => array() - ), - 'social-link.php' => array(), - 'image' => array( - 'block.json' => array() - ), - 'latest-posts' => array( - 'block.json' => array() - ), - 'block' => array( - 'block.json' => array() - ), - 'media-text' => array( - 'block.json' => array() - ), - 'archives.php' => array(), - 'spacer' => array( - 'block.json' => array() - ), - 'buttons' => array( - 'block.json' => array() - ), - 'video' => array( - 'block.json' => array() - ), - 'subhead' => array( - 'block.json' => array() - ), - 'audio' => array( - 'block.json' => array() - ), - 'table' => array( - 'block.json' => array() - ), - 'latest-comments.php' => array(), - 'social-links' => array( - 'block.json' => array() - ), - 'button' => array( - 'block.json' => array() - ), - 'rss' => array( - 'block.json' => array() - ), - 'columns' => array( - 'block.json' => array() - ), - 'calendar.php' => array(), - 'calendar' => array( - 'block.json' => array() - ), - 'quote' => array( - 'block.json' => array() - ), - 'text-columns' => array( - 'block.json' => array() - ), - 'separator' => array( - 'block.json' => array() - ), - 'archives' => array( - 'block.json' => array() - ), - 'social-link' => array( - 'block.json' => array() - ), - 'missing' => array( - 'block.json' => array() - ), - 'shortcode.php' => array(), - 'verse' => array( - 'block.json' => array() - ), - 'categories' => array( - 'block.json' => array() - ), - 'classic' => array( - 'block.json' => array() - ), - 'tag-cloud' => array( - 'block.json' => array() - ), - 'latest-posts.php' => array(), - 'rss.php' => array(), - 'shortcode' => array( - 'block.json' => array() - ), - 'file' => array( - 'block.json' => array() - ), - 'categories.php' => array(), - 'index.php' => array(), - 'search' => array( - 'block.json' => array() - ), - 'list' => array( - 'block.json' => array() - ), - 'column' => array( - 'block.json' => array() - ), - 'group' => array( - 'block.json' => array() - ), - 'preformatted' => array( - 'block.json' => array() - ), - 'html' => array( - 'block.json' => array() - ), - 'nextpage' => array( - 'block.json' => array() - ), - 'latest-comments' => array( - 'block.json' => array() - ), - 'block.php' => array(), - 'heading' => array( - 'block.json' => array() - ), - 'search.php' => array(), - 'tag-cloud.php' => array(), - 'paragraph' => array( - 'block.json' => array() - ) - ), - 'default-filters.php' => array(), - 'ms-load.php' => array(), - 'class-wp-feed-cache.php' => array(), - 'plugin.php' => array(), - 'fonts' => array( - 'dashicons.svg' => array(), - 'dashicons.woff2' => array(), - 'dashicons.ttf' => array(), - 'dashicons.woff' => array(), - 'dashicons.eot' => array() - ), - 'query.php' => array(), - 'class-pop3.php' => array(), - 'class-wp-user-request.php' => array(), - 'class-wp-user-meta-session-tokens.php' => array(), - 'class-wp-oembed.php' => array(), - 'class-wp-editor.php' => array(), - 'class-wp-image-editor-gd.php' => array(), - 'class.wp-scripts.php' => array(), - 'class-walker-nav-menu.php' => array(), - 'author-template.php' => array(), - 'ms-blogs.php' => array(), - 'class-wp-simplepie-sanitize-kses.php' => array(), - 'class-wp-walker.php' => array(), - 'taxonomy.php' => array(), - 'compat.php' => array(), - 'class-wp-block.php' => array(), - 'category.php' => array(), - 'atomlib.php' => array(), - 'class.wp-dependencies.php' => array(), - 'class-wp-recovery-mode.php' => array(), - 'Requests' => array( - 'Utility' => array( - 'CaseInsensitiveDictionary.php' => array(), - 'FilteredIterator.php' => array() - ), - 'IDNAEncoder.php' => array(), - 'Transport' => array( - 'cURL.php' => array(), - 'fsockopen.php' => array() - ), - 'Proxy.php' => array(), - 'IPv6.php' => array(), - 'Exception.php' => array(), - 'Hooks.php' => array(), - 'Proxy' => array( - 'HTTP.php' => array() - ), - 'Response.php' => array(), - 'IRI.php' => array(), - 'SSL.php' => array(), - 'Auth' => array( - 'Basic.php' => array() - ), - 'Response' => array( - 'Headers.php' => array() - ), - 'Session.php' => array(), - 'Exception' => array( - 'Transport' => array( - 'cURL.php' => array() - ), - 'HTTP' => array( - '431.php' => array(), - '415.php' => array(), - '428.php' => array(), - '414.php' => array(), - '408.php' => array(), - '417.php' => array(), - '502.php' => array(), - '306.php' => array(), - '412.php' => array(), - '410.php' => array(), - '416.php' => array(), - '505.php' => array(), - '401.php' => array(), - '305.php' => array(), - '404.php' => array(), - '403.php' => array(), - '411.php' => array(), - '500.php' => array(), - '429.php' => array(), - '504.php' => array(), - '402.php' => array(), - '501.php' => array(), - '405.php' => array(), - '409.php' => array(), - '406.php' => array(), - '413.php' => array(), - '304.php' => array(), - '418.php' => array(), - '511.php' => array(), - '407.php' => array(), - '503.php' => array(), - '400.php' => array(), - 'Unknown.php' => array() - ), - 'HTTP.php' => array(), - 'Transport.php' => array() - ), - 'Auth.php' => array(), - 'Cookie' => array( - 'Jar.php' => array() - ), - 'Transport.php' => array(), - 'Cookie.php' => array(), - 'Hooker.php' => array() - ), - 'revision.php' => array(), - 'wp-diff.php' => array(), - 'class-wp-roles.php' => array(), - 'sitemaps' => array( - 'class-wp-sitemaps-index.php' => array(), - 'class-wp-sitemaps-renderer.php' => array(), - 'class-wp-sitemaps-stylesheet.php' => array(), - 'class-wp-sitemaps-registry.php' => array(), - 'class-wp-sitemaps.php' => array(), - 'class-wp-sitemaps-provider.php' => array(), - 'providers' => array( - 'class-wp-sitemaps-posts.php' => array(), - 'class-wp-sitemaps-taxonomies.php' => array(), - 'class-wp-sitemaps-users.php' => array() - ) - ), - 'js' => array( - 'hoverIntent.js' => array(), - 'wp-a11y.min.js' => array(), - 'media-audiovideo.js' => array(), - 'zxcvbn-async.js' => array(), - 'media-models.js' => array(), - 'twemoji.js' => array(), - 'wp-pointer.js' => array(), - 'customize-preview-nav-menus.min.js' => array(), - 'wp-pointer.min.js' => array(), - 'json2.min.js' => array(), - 'backbone.js' => array(), - 'swfupload' => array( - 'handlers.js' => array(), - 'license.txt' => array(), - 'handlers.min.js' => array(), - 'swfupload.js' => array(), - 'plugins' => array( - 'swfupload.swfobject.js' => array(), - 'swfupload.cookies.js' => array(), - 'swfupload.queue.js' => array(), - 'swfupload.speed.js' => array() - ), - 'swfupload.swf' => array() - ), - 'twemoji.min.js' => array(), - 'mce-view.min.js' => array(), - 'swfobject.js' => array(), - 'colorpicker.min.js' => array(), - 'wp-emoji.js' => array(), - 'customize-preview-widgets.min.js' => array(), - 'zxcvbn.min.js' => array(), - 'wp-ajax-response.js' => array(), - 'wp-util.js' => array(), - 'underscore.js' => array(), - 'wp-emoji.min.js' => array(), - 'customize-preview-nav-menus.js' => array(), - 'underscore.min.js' => array(), - 'admin-bar.min.js' => array(), - 'wp-sanitize.js' => array(), - 'imagesloaded.min.js' => array(), - 'thickbox' => array( - 'loadingAnimation.gif' => array(), - 'thickbox.css' => array(), - 'thickbox.js' => array(), - 'macFFBgHack.png' => array() - ), - 'wplink.min.js' => array(), - 'tinymce' => array( - 'wp-mce-help.php' => array(), - 'themes' => array( - 'modern' => array( - 'theme.js' => array(), - 'theme.min.js' => array() - ), - 'inlite' => array( - 'theme.js' => array(), - 'theme.min.js' => array() - ) - ), - 'wp-tinymce.js' => array(), - 'langs' => array( - 'wp-langs-en.js' => array() - ), - 'wp-tinymce.js.gz' => array(), - 'license.txt' => array(), - 'utils' => array( - 'mctabs.js' => array(), - 'form_utils.js' => array(), - 'editable_selects.js' => array(), - 'validate.js' => array() - ), - 'plugins' => array( - 'wordpress' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'directionality' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'image' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'wpview' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'wpeditimage' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'hr' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'lists' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'wpfullscreen' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'wptextpattern' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'link' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'fullscreen' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'wpembed' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'wplink' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'wpdialogs' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'textcolor' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'wpemoji' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'colorpicker' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'paste' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'compat3x' => array( - 'css' => array( - 'dialog.css' => array() - ), - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'charmap' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'tabfocus' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'wpgallery' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ), - 'media' => array( - 'plugin.js' => array(), - 'moxieplayer.swf' => array(), - 'plugin.min.js' => array() - ), - 'wpautoresize' => array( - 'plugin.js' => array(), - 'plugin.min.js' => array() - ) - ), - 'wp-tinymce.php' => array(), - 'tiny_mce_popup.js' => array(), - 'skins' => array( - 'wordpress' => array( - 'wp-content.css' => array(), - 'images' => array( - 'gallery-2x.png' => array(), - 'playlist-video.png' => array(), - 'more-2x.png' => array(), - 'pagebreak.png' => array(), - 'audio.png' => array(), - 'playlist-audio.png' => array(), - 'dashicon-no-alt.png' => array(), - 'dashicon-no.png' => array(), - 'dashicon-edit.png' => array(), - 'embedded.png' => array(), - 'video.png' => array(), - 'pagebreak-2x.png' => array(), - 'gallery.png' => array(), - 'more.png' => array() - ) - ), - 'lightgray' => array( - 'content.inline.min.css' => array(), - 'content.min.css' => array(), - 'skin.ie7.min.css' => array(), - 'fonts' => array( - 'tinymce-small.json' => array(), - 'tinymce.ttf' => array(), - 'tinymce-small.svg' => array(), - 'tinymce-small.woff' => array(), - 'tinymce.json' => array(), - 'readme.md' => array(), - 'tinymce.svg' => array(), - 'tinymce.woff' => array(), - 'tinymce-small.ttf' => array(), - 'tinymce-small.eot' => array(), - 'tinymce.eot' => array() - ), - 'img' => array( - 'loader.gif' => array(), - 'object.gif' => array(), - 'trans.gif' => array(), - 'anchor.gif' => array() - ), - 'skin.min.css' => array() - ) - ), - 'tinymce.min.js' => array() - ), - 'wp-emoji-release.min.js' => array(), - 'wp-emoji-loader.min.js' => array(), - 'wp-list-revisions.min.js' => array(), - 'wp-auth-check.js' => array(), - 'api-request.min.js' => array(), - 'customize-models.js' => array(), - 'clipboard.min.js' => array(), - 'customize-preview.min.js' => array(), - 'quicktags.js' => array(), - 'wp-list-revisions.js' => array(), - 'customize-models.min.js' => array(), - 'wp-util.min.js' => array(), - 'customize-preview-widgets.js' => array(), - 'admin-bar.js' => array(), - 'wpdialog.min.js' => array(), - 'wp-lists.min.js' => array(), - 'wp-emoji-loader.js' => array(), - 'clipboard.js' => array(), - 'autosave.min.js' => array(), - 'quicktags.min.js' => array(), - 'customize-selective-refresh.js' => array(), - 'jcrop' => array( - 'Jcrop.gif' => array(), - 'jquery.Jcrop.min.js' => array(), - 'jquery.Jcrop.min.css' => array() - ), - 'wp-backbone.js' => array(), - 'media-editor.js' => array(), - 'media-editor.min.js' => array(), - 'plupload' => array( - 'handlers.js' => array(), - 'moxie.js' => array(), - 'moxie.min.js' => array(), - 'license.txt' => array(), - 'plupload.flash.swf' => array(), - 'wp-plupload.min.js' => array(), - 'handlers.min.js' => array(), - 'plupload.full.min.js' => array(), - 'wp-plupload.js' => array(), - 'plupload.silverlight.xap' => array(), - 'plupload.js' => array(), - 'plupload.min.js' => array() - ), - 'media-grid.js' => array(), - 'hoverintent-js.min.js' => array(), - 'media-views.min.js' => array(), - 'wp-embed.js' => array(), - 'heartbeat.min.js' => array(), - 'wp-api.min.js' => array(), - 'customize-views.js' => array(), - 'customize-loader.js' => array(), - 'autosave.js' => array(), - 'crop' => array( - 'cropper.js' => array(), - 'cropper.css' => array(), - 'marqueeHoriz.gif' => array(), - 'marqueeVert.gif' => array() - ), - 'wp-auth-check.min.js' => array(), - 'jquery' => array( - 'jquery.js' => array(), - 'jquery.form.min.js' => array(), - 'jquery.ui.touch-punch.js' => array(), - 'jquery.table-hotkeys.js' => array(), - 'jquery.query.js' => array(), - 'jquery.hotkeys.min.js' => array(), - 'jquery-migrate.min.js' => array(), - 'jquery.schedule.js' => array(), - 'jquery.hotkeys.js' => array(), - 'suggest.js' => array(), - 'jquery-migrate.js' => array(), - 'jquery.form.js' => array(), - 'ui' => array( - 'jquery.ui.dialog.min.js' => array(), - 'jquery.ui.menu.min.js' => array(), - 'progressbar.min.js' => array(), - 'jquery.ui.core.min.js' => array(), - 'spinner.min.js' => array(), - 'dialog.min.js' => array(), - 'jquery.ui.position.min.js' => array(), - 'jquery.ui.effect-drop.min.js' => array(), - 'accordion.min.js' => array(), - 'effect-clip.min.js' => array(), - 'jquery.ui.sortable.min.js' => array(), - 'jquery.ui.effect.min.js' => array(), - 'effect-explode.min.js' => array(), - 'jquery.ui.effect-transfer.min.js' => array(), - 'jquery.ui.draggable.min.js' => array(), - 'draggable.min.js' => array(), - 'effect-fold.min.js' => array(), - 'jquery.ui.spinner.min.js' => array(), - 'effect-fade.min.js' => array(), - 'droppable.min.js' => array(), - 'effect.min.js' => array(), - 'effect-drop.min.js' => array(), - 'jquery.ui.effect-slide.min.js' => array(), - 'selectable.min.js' => array(), - 'tooltip.min.js' => array(), - 'effect-shake.min.js' => array(), - 'effect-highlight.min.js' => array(), - 'jquery.ui.datepicker.min.js' => array(), - 'effect-blind.min.js' => array(), - 'sortable.min.js' => array(), - 'position.min.js' => array(), - 'jquery.ui.effect-pulsate.min.js' => array(), - 'jquery.ui.mouse.min.js' => array(), - 'jquery.ui.effect-explode.min.js' => array(), - 'jquery.ui.autocomplete.min.js' => array(), - 'effect-size.min.js' => array(), - 'jquery.ui.effect-bounce.min.js' => array(), - 'core.min.js' => array(), - 'jquery.ui.progressbar.min.js' => array(), - 'effect-puff.min.js' => array(), - 'jquery.ui.selectable.min.js' => array(), - 'effect-transfer.min.js' => array(), - 'menu.min.js' => array(), - 'jquery.ui.tabs.min.js' => array(), - 'resizable.min.js' => array(), - 'jquery.ui.effect-highlight.min.js' => array(), - 'jquery.ui.tooltip.min.js' => array(), - 'jquery.ui.droppable.min.js' => array(), - 'mouse.min.js' => array(), - 'jquery.ui.effect-fade.min.js' => array(), - 'jquery.ui.effect-clip.min.js' => array(), - 'jquery.ui.accordion.min.js' => array(), - 'jquery.ui.resizable.min.js' => array(), - 'effect-pulsate.min.js' => array(), - 'effect-bounce.min.js' => array(), - 'widget.min.js' => array(), - 'jquery.ui.effect-blind.min.js' => array(), - 'tabs.min.js' => array(), - 'datepicker.min.js' => array(), - 'button.min.js' => array(), - 'selectmenu.min.js' => array(), - 'jquery.ui.effect-shake.min.js' => array(), - 'slider.min.js' => array(), - 'effect-scale.min.js' => array(), - 'jquery.ui.slider.min.js' => array(), - 'jquery.ui.effect-scale.min.js' => array(), - 'jquery.ui.button.min.js' => array(), - 'effect-slide.min.js' => array(), - 'jquery.ui.widget.min.js' => array(), - 'autocomplete.min.js' => array(), - 'jquery.ui.effect-fold.min.js' => array() - ), - 'jquery.table-hotkeys.min.js' => array(), - 'suggest.min.js' => array(), - 'jquery.serialize-object.js' => array(), - 'jquery.masonry.min.js' => array(), - 'jquery.color.min.js' => array() - ), - 'wpdialog.js' => array(), - 'shortcode.js' => array(), - 'colorpicker.js' => array(), - 'tw-sack.min.js' => array(), - 'heartbeat.js' => array(), - 'wp-api.js' => array(), - 'customize-base.js' => array(), - 'media-models.min.js' => array(), - 'wp-custom-header.js' => array(), - 'media-audiovideo.min.js' => array(), - 'mce-view.js' => array(), - 'media-views.js' => array(), - 'wp-embed-template.js' => array(), - 'hoverIntent.min.js' => array(), - 'wp-embed.min.js' => array(), - 'utils.min.js' => array(), - 'customize-views.min.js' => array(), - 'customize-base.min.js' => array(), - 'customize-selective-refresh.min.js' => array(), - 'wp-ajax-response.min.js' => array(), - 'zxcvbn-async.min.js' => array(), - 'wp-lists.js' => array(), - 'comment-reply.min.js' => array(), - 'wp-embed-template.min.js' => array(), - 'wp-backbone.min.js' => array(), - 'wp-a11y.js' => array(), - 'backbone.min.js' => array(), - 'dist' => array( - 'api-fetch.js' => array(), - 'notices.min.js' => array(), - 'data-controls.min.js' => array(), - 'wordcount.min.js' => array(), - 'editor.min.js' => array(), - 'rich-text.js' => array(), - 'dom.js' => array(), - 'element.js' => array(), - 'blocks.min.js' => array(), - 'components.min.js' => array(), - 'editor.js' => array(), - 'blob.min.js' => array(), - 'components.js' => array(), - 'url.js' => array(), - 'i18n.min.js' => array(), - 'data-controls.js' => array(), - 'deprecated.js' => array(), - 'priority-queue.js' => array(), - 'token-list.min.js' => array(), - 'dom-ready.js' => array(), - 'a11y.min.js' => array(), - 'element.min.js' => array(), - 'keycodes.js' => array(), - 'list-reusable-blocks.js' => array(), - 'autop.js' => array(), - 'warning.js' => array(), - 'escape-html.js' => array(), - 'blob.js' => array(), - 'block-directory.min.js' => array(), - 'dom-ready.min.js' => array(), - 'annotations.js' => array(), - 'viewport.js' => array(), - 'viewport.min.js' => array(), - 'server-side-render.js' => array(), - 'autop.min.js' => array(), - 'compose.js' => array(), - 'plugins.js' => array(), - 'block-directory.js' => array(), - 'primitives.js' => array(), - 'block-editor.min.js' => array(), - 'primitives.min.js' => array(), - 'keyboard-shortcuts.js' => array(), - 'html-entities.min.js' => array(), - 'notices.js' => array(), - 'wordcount.js' => array(), - 'core-data.js' => array(), - 'compose.min.js' => array(), - 'warning.min.js' => array(), - 'url.min.js' => array(), - 'block-serialization-default-parser.js' => array(), - 'data.min.js' => array(), - 'edit-post.js' => array(), - 'server-side-render.min.js' => array(), - 'redux-routine.min.js' => array(), - 'i18n.js' => array(), - 'redux-routine.js' => array(), - 'escape-html.min.js' => array(), - 'edit-post.min.js' => array(), - 'shortcode.js' => array(), - 'token-list.js' => array(), - 'date.min.js' => array(), - 'hooks.min.js' => array(), - 'html-entities.js' => array(), - 'core-data.min.js' => array(), - 'keycodes.min.js' => array(), - 'priority-queue.min.js' => array(), - 'blocks.js' => array(), - 'format-library.min.js' => array(), - 'is-shallow-equal.min.js' => array(), - 'date.js' => array(), - 'list-reusable-blocks.min.js' => array(), - 'block-library.js' => array(), - 'plugins.min.js' => array(), - 'nux.min.js' => array(), - 'media-utils.js' => array(), - 'is-shallow-equal.js' => array(), - 'media-utils.min.js' => array(), - 'dom.min.js' => array(), - 'vendor' => array( - 'moment.min.js' => array(), - 'wp-polyfill-element-closest.min.js' => array(), - 'wp-polyfill-fetch.js' => array(), - 'wp-polyfill-node-contains.js' => array(), - 'moment.js' => array(), - 'wp-polyfill-url.js' => array(), - 'react.js' => array(), - 'wp-polyfill.min.js' => array(), - 'wp-polyfill-formdata.js' => array(), - 'wp-polyfill-element-closest.js' => array(), - 'wp-polyfill-dom-rect.min.js' => array(), - 'react.min.js' => array(), - 'wp-polyfill-dom-rect.js' => array(), - 'lodash.min.js' => array(), - 'wp-polyfill-fetch.min.js' => array(), - 'react-dom.min.js' => array(), - 'wp-polyfill-formdata.min.js' => array(), - 'wp-polyfill-node-contains.min.js' => array(), - 'react-dom.js' => array(), - 'wp-polyfill-url.min.js' => array(), - 'wp-polyfill.js' => array(), - 'lodash.js' => array() - ), - 'annotations.min.js' => array(), - 'block-editor.js' => array(), - 'data.js' => array(), - 'rich-text.min.js' => array(), - 'hooks.js' => array(), - 'api-fetch.min.js' => array(), - 'a11y.js' => array(), - 'block-serialization-default-parser.min.js' => array(), - 'shortcode.min.js' => array(), - 'format-library.js' => array(), - 'block-library.min.js' => array(), - 'deprecated.min.js' => array(), - 'nux.js' => array(), - 'keyboard-shortcuts.min.js' => array() - ), - 'api-request.js' => array(), - 'customize-loader.min.js' => array(), - 'imgareaselect' => array( - 'jquery.imgareaselect.js' => array(), - 'jquery.imgareaselect.min.js' => array(), - 'border-anim-v.gif' => array(), - 'border-anim-h.gif' => array(), - 'imgareaselect.css' => array() - ), - 'customize-preview.js' => array(), - 'utils.js' => array(), - 'wplink.js' => array(), - 'comment-reply.js' => array(), - 'mediaelement' => array( - 'controls.png' => array(), - 'mediaelement-migrate.js' => array(), - 'renderers' => array( - 'vimeo.js' => array(), - 'vimeo.min.js' => array() - ), - 'mediaelement-migrate.min.js' => array(), - 'mediaelementplayer-legacy.min.css' => array(), - 'jumpforward.png' => array(), - 'skipback.png' => array(), - 'wp-mediaelement.css' => array(), - 'background.png' => array(), - 'mediaelement-and-player.min.js' => array(), - 'mediaelement.min.js' => array(), - 'mejs-controls.svg' => array(), - 'mediaelementplayer.min.css' => array(), - 'bigplay.png' => array(), - 'controls.svg' => array(), - 'wp-mediaelement.js' => array(), - 'mediaelement.js' => array(), - 'mediaelementplayer-legacy.css' => array(), - 'mejs-controls.png' => array(), - 'mediaelement-and-player.js' => array(), - 'wp-mediaelement.min.js' => array(), - 'wp-playlist.js' => array(), - 'bigplay.svg' => array(), - 'wp-mediaelement.min.css' => array(), - 'mediaelementplayer.css' => array(), - 'wp-playlist.min.js' => array(), - 'loading.gif' => array(), - 'froogaloop.min.js' => array() - ), - 'media-grid.min.js' => array(), - 'wp-custom-header.min.js' => array(), - 'masonry.min.js' => array(), - 'shortcode.min.js' => array(), - 'wp-sanitize.min.js' => array(), - 'tw-sack.js' => array(), - 'json2.js' => array(), - 'codemirror' => array( - 'esprima.js' => array(), - 'htmlhint-kses.js' => array(), - 'csslint.js' => array(), - 'jsonlint.js' => array(), - 'codemirror.min.css' => array(), - 'codemirror.min.js' => array(), - 'fakejshint.js' => array(), - 'htmlhint.js' => array(), - 'jshint.js' => array() - ) - ), - 'css' => array( - 'wp-embed-template.min.css' => array(), - 'admin-bar-rtl.css' => array(), - 'wp-auth-check.min.css' => array(), - 'buttons.min.css' => array(), - 'wp-embed-template-ie.min.css' => array(), - 'dashicons.css' => array(), - 'buttons.css' => array(), - 'editor.min.css' => array(), - 'buttons-rtl.css' => array(), - 'jquery-ui-dialog.css' => array(), - 'dashicons.min.css' => array(), - 'jquery-ui-dialog-rtl.min.css' => array(), - 'wp-embed-template-ie.css' => array(), - 'customize-preview.css' => array(), - 'editor.css' => array(), - 'editor-rtl.css' => array(), - 'admin-bar.min.css' => array(), - 'wp-auth-check-rtl.min.css' => array(), - 'admin-bar-rtl.min.css' => array(), - 'wp-pointer.min.css' => array(), - 'wp-pointer-rtl.css' => array(), - 'admin-bar.css' => array(), - 'customize-preview-rtl.min.css' => array(), - 'jquery-ui-dialog.min.css' => array(), - 'wp-pointer-rtl.min.css' => array(), - 'wp-pointer.css' => array(), - 'editor-rtl.min.css' => array(), - 'media-views.min.css' => array(), - 'customize-preview-rtl.css' => array(), - 'media-views-rtl.min.css' => array(), - 'buttons-rtl.min.css' => array(), - 'jquery-ui-dialog-rtl.css' => array(), - 'wp-embed-template.css' => array(), - 'dist' => array( - 'list-reusable-blocks' => array( - 'style-rtl.min.css' => array(), - 'style.css' => array(), - 'style-rtl.css' => array(), - 'style.min.css' => array() - ), - 'format-library' => array( - 'style-rtl.min.css' => array(), - 'style.css' => array(), - 'style-rtl.css' => array(), - 'style.min.css' => array() - ), - 'nux' => array( - 'style-rtl.min.css' => array(), - 'style.css' => array(), - 'style-rtl.css' => array(), - 'style.min.css' => array() - ), - 'edit-post' => array( - 'style-rtl.min.css' => array(), - 'style.css' => array(), - 'style-rtl.css' => array(), - 'style.min.css' => array() - ), - 'block-directory' => array( - 'style-rtl.min.css' => array(), - 'style.css' => array(), - 'style-rtl.css' => array(), - 'style.min.css' => array() - ), - 'editor' => array( - 'style-rtl.min.css' => array(), - 'editor-styles-rtl.css' => array(), - 'editor-styles-rtl.min.css' => array(), - 'editor-styles.min.css' => array(), - 'style.css' => array(), - 'style-rtl.css' => array(), - 'editor-styles.css' => array(), - 'style.min.css' => array() - ), - 'block-library' => array( - 'style-rtl.min.css' => array(), - 'editor.min.css' => array(), - 'editor.css' => array(), - 'theme-rtl.css' => array(), - 'editor-rtl.css' => array(), - 'theme-rtl.min.css' => array(), - 'editor-rtl.min.css' => array(), - 'theme.css' => array(), - 'style.css' => array(), - 'style-rtl.css' => array(), - 'theme.min.css' => array(), - 'style.min.css' => array() - ), - 'block-editor' => array( - 'style-rtl.min.css' => array(), - 'style.css' => array(), - 'style-rtl.css' => array(), - 'style.min.css' => array() - ), - 'components' => array( - 'style-rtl.min.css' => array(), - 'style.css' => array(), - 'style-rtl.css' => array(), - 'style.min.css' => array() - ) - ), - 'media-views-rtl.css' => array(), - 'customize-preview.min.css' => array(), - 'wp-auth-check.css' => array(), - 'media-views.css' => array(), - 'wp-auth-check-rtl.css' => array() - ), - 'bookmark-template.php' => array(), - 'rest-api.php' => array(), - 'class-http.php' => array(), - 'post-template.php' => array(), - 'user.php' => array(), - 'class-wp-comment.php' => array(), - 'class-wp-customize-section.php' => array(), - 'registration.php' => array(), - 'Text' => array( - 'Diff.php' => array(), - 'Diff' => array( - 'Engine' => array( - 'string.php' => array(), - 'xdiff.php' => array(), - 'native.php' => array(), - 'shell.php' => array() - ), - 'Renderer.php' => array(), - 'Renderer' => array( - 'inline.php' => array() - ) - ) - ), - 'class-json.php' => array(), - 'shortcodes.php' => array(), - 'vars.php' => array(), - 'spl-autoload-compat.php' => array(), - 'class-wp-taxonomy.php' => array(), - 'class-wp-site.php' => array(), - 'post.php' => array(), - 'version.php' => array(), - 'ms-files.php' => array(), - 'certificates' => array( - 'ca-bundle.crt' => array() - ), - 'admin-bar.php' => array(), - 'class-wp-meta-query.php' => array(), - 'link-template.php' => array(), - 'class-snoopy.php' => array(), - 'class-wp-image-editor.php' => array(), - 'class-wp-widget.php' => array(), - 'feed-atom-comments.php' => array(), - 'class-wp-http-streams.php' => array(), - 'functions.wp-scripts.php' => array(), - 'rss.php' => array(), - 'PHPMailer' => array( - 'PHPMailer.php' => array(), - 'Exception.php' => array(), - 'SMTP.php' => array() - ), - 'class-wp-feed-cache-transient.php' => array(), - 'class-wp-user.php' => array(), - 'post-thumbnail-template.php' => array(), - 'class-wp-recovery-mode-link-service.php' => array(), - 'class-IXR.php' => array(), - 'general-template.php' => array(), - 'ms-site.php' => array(), - 'wlwmanifest.xml' => array(), - 'class-wp-session-tokens.php' => array(), - 'rest-api' => array( - 'class-wp-rest-response.php' => array(), - 'fields' => array( - 'class-wp-rest-term-meta-fields.php' => array(), - 'class-wp-rest-post-meta-fields.php' => array(), - 'class-wp-rest-meta-fields.php' => array(), - 'class-wp-rest-user-meta-fields.php' => array(), - 'class-wp-rest-comment-meta-fields.php' => array() - ), - 'endpoints' => array( - 'class-wp-rest-block-renderer-controller.php' => array(), - 'class-wp-rest-block-types-controller.php' => array(), - 'class-wp-rest-taxonomies-controller.php' => array(), - 'class-wp-rest-search-controller.php' => array(), - 'class-wp-rest-terms-controller.php' => array(), - 'class-wp-rest-autosaves-controller.php' => array(), - 'class-wp-rest-posts-controller.php' => array(), - 'class-wp-rest-blocks-controller.php' => array(), - 'class-wp-rest-block-directory-controller.php' => array(), - 'class-wp-rest-settings-controller.php' => array(), - 'class-wp-rest-post-statuses-controller.php' => array(), - 'class-wp-rest-post-types-controller.php' => array(), - 'class-wp-rest-comments-controller.php' => array(), - 'class-wp-rest-themes-controller.php' => array(), - 'class-wp-rest-plugins-controller.php' => array(), - 'class-wp-rest-attachments-controller.php' => array(), - 'class-wp-rest-revisions-controller.php' => array(), - 'class-wp-rest-users-controller.php' => array(), - 'class-wp-rest-controller.php' => array() - ), - 'search' => array( - 'class-wp-rest-search-handler.php' => array(), - 'class-wp-rest-post-search-handler.php' => array() - ), - 'class-wp-rest-server.php' => array(), - 'class-wp-rest-request.php' => array() - ), - 'media-template.php' => array(), - 'class-wp.php' => array(), - 'images' => array( - 'blank.gif' => array(), - 'wpicons-2x.png' => array(), - 'toggle-arrow.png' => array(), - 'rss.png' => array(), - 'w-logo-blue-white-bg.png' => array(), - 'xit-2x.gif' => array(), - 'uploader-icons-2x.png' => array(), - 'wlw' => array( - 'wp-comments.png' => array(), - 'wp-watermark.png' => array(), - 'wp-icon.png' => array() - ), - 'arrow-pointer-blue.png' => array(), - 'down_arrow.gif' => array(), - 'admin-bar-sprite-2x.png' => array(), - 'crystal' => array( - 'document.png' => array(), - 'audio.png' => array(), - 'license.txt' => array(), - 'default.png' => array(), - 'text.png' => array(), - 'interactive.png' => array(), - 'spreadsheet.png' => array(), - 'archive.png' => array(), - 'video.png' => array(), - 'code.png' => array() - ), - 'uploader-icons.png' => array(), - 'w-logo-blue.png' => array(), - 'down_arrow-2x.gif' => array(), - 'xit.gif' => array(), - 'wpspin-2x.gif' => array(), - 'wpicons.png' => array(), - 'arrow-pointer-blue-2x.png' => array(), - 'toggle-arrow-2x.png' => array(), - 'rss-2x.png' => array(), - 'media' => array( - 'document.png' => array(), - 'audio.png' => array(), - 'default.png' => array(), - 'text.png' => array(), - 'interactive.png' => array(), - 'spreadsheet.png' => array(), - 'archive.png' => array(), - 'video.png' => array(), - 'code.png' => array() - ), - 'spinner-2x.gif' => array(), - 'smilies' => array( - 'icon_sad.gif' => array(), - 'icon_question.gif' => array(), - 'mrgreen.png' => array(), - 'icon_mrgreen.gif' => array(), - 'icon_surprised.gif' => array(), - 'frownie.png' => array(), - 'icon_razz.gif' => array(), - 'simple-smile.png' => array(), - 'icon_neutral.gif' => array(), - 'icon_eek.gif' => array(), - 'icon_confused.gif' => array(), - 'icon_biggrin.gif' => array(), - 'icon_exclaim.gif' => array(), - 'icon_idea.gif' => array(), - 'icon_mad.gif' => array(), - 'icon_cool.gif' => array(), - 'icon_rolleyes.gif' => array(), - 'rolleyes.png' => array(), - 'icon_redface.gif' => array(), - 'icon_wink.gif' => array(), - 'icon_lol.gif' => array(), - 'icon_arrow.gif' => array(), - 'icon_evil.gif' => array(), - 'icon_cry.gif' => array(), - 'icon_smile.gif' => array(), - 'icon_twisted.gif' => array() - ), - 'spinner.gif' => array(), - 'admin-bar-sprite.png' => array(), - 'icon-pointer-flag.png' => array(), - 'icon-pointer-flag-2x.png' => array(), - 'wpspin.gif' => array() - ), - 'template-loader.php' => array(), - 'class-wp-embed.php' => array(), - 'rss-functions.php' => array(), - 'class-wp-http-requests-response.php' => array(), - 'class-wp-ajax-response.php' => array(), - 'date.php' => array(), - 'class-wp-simplepie-file.php' => array(), - 'meta.php' => array(), - 'kses.php' => array(), - 'class-wp-tax-query.php' => array(), - 'class-wp-network-query.php' => array(), - 'class-wp-hook.php' => array(), - 'ms-deprecated.php' => array(), - 'class-walker-category-dropdown.php' => array(), - 'class-wp-rewrite.php' => array(), - 'class-simplepie.php' => array(), - 'class.wp-styles.php' => array(), - 'comment.php' => array(), - 'sitemaps.php' => array(), - 'pomo' => array( - 'entry.php' => array(), - 'mo.php' => array(), - 'translations.php' => array(), - 'streams.php' => array(), - 'po.php' => array(), - 'plural-forms.php' => array() - ), - 'class-wp-customize-panel.php' => array(), - 'class-wp-http-cookie.php' => array(), - 'ms-default-filters.php' => array(), - 'class-walker-page.php' => array(), - 'bookmark.php' => array(), - 'customize' => array( - 'class-wp-customize-background-image-setting.php' => array(), - 'class-wp-customize-nav-menu-setting.php' => array(), - 'class-wp-customize-filter-setting.php' => array(), - 'class-wp-customize-date-time-control.php' => array(), - 'class-wp-customize-header-image-control.php' => array(), - 'class-wp-customize-nav-menus-panel.php' => array(), - 'class-wp-customize-nav-menu-item-control.php' => array(), - 'class-wp-customize-nav-menu-control.php' => array(), - 'class-wp-customize-custom-css-setting.php' => array(), - 'class-wp-widget-form-customize-control.php' => array(), - 'class-wp-customize-code-editor-control.php' => array(), - 'class-wp-widget-area-customize-control.php' => array(), - 'class-wp-customize-new-menu-control.php' => array(), - 'class-wp-customize-theme-control.php' => array(), - 'class-wp-customize-new-menu-section.php' => array(), - 'class-wp-customize-site-icon-control.php' => array(), - 'class-wp-customize-cropped-image-control.php' => array(), - 'class-wp-customize-upload-control.php' => array(), - 'class-wp-customize-image-control.php' => array(), - 'class-wp-customize-nav-menu-section.php' => array(), - 'class-wp-customize-background-image-control.php' => array(), - 'class-wp-customize-header-image-setting.php' => array(), - 'class-wp-customize-nav-menu-location-control.php' => array(), - 'class-wp-customize-partial.php' => array(), - 'class-wp-customize-nav-menu-auto-add-control.php' => array(), - 'class-wp-customize-sidebar-section.php' => array(), - 'class-wp-customize-themes-section.php' => array(), - 'class-wp-customize-themes-panel.php' => array(), - 'class-wp-customize-nav-menu-item-setting.php' => array(), - 'class-wp-customize-nav-menu-name-control.php' => array(), - 'class-wp-customize-nav-menu-locations-control.php' => array(), - 'class-wp-customize-background-position-control.php' => array(), - 'class-wp-customize-color-control.php' => array(), - 'class-wp-customize-media-control.php' => array(), - 'class-wp-customize-selective-refresh.php' => array() - ), - 'class-wp-customize-control.php' => array(), - 'class-wp-locale.php' => array(), - 'theme.php' => array(), - 'class-wp-user-query.php' => array(), - 'class-wp-http-ixr-client.php' => array(), - 'ms-functions.php' => array(), - 'SimplePie' => array( - 'Locator.php' => array(), - 'Author.php' => array(), - 'Sanitize.php' => array(), - 'Registry.php' => array(), - 'Caption.php' => array(), - 'HTTP' => array( - 'Parser.php' => array() - ), - 'Item.php' => array(), - 'Exception.php' => array(), - 'File.php' => array(), - 'Rating.php' => array(), - 'Restriction.php' => array(), - 'IRI.php' => array(), - 'Parser.php' => array(), - 'Enclosure.php' => array(), - 'Cache.php' => array(), - 'XML' => array( - 'Declaration' => array( - 'Parser.php' => array() - ) - ), - 'Decode' => array( - 'HTML' => array( - 'Entities.php' => array() - ) - ), - 'Misc.php' => array(), - 'Copyright.php' => array(), - 'Parse' => array( - 'Date.php' => array() - ), - 'Content' => array( - 'Type' => array( - 'Sniffer.php' => array() - ) - ), - 'Source.php' => array(), - 'Net' => array( - 'IPv6.php' => array() - ), - 'Credit.php' => array(), - 'Cache' => array( - 'DB.php' => array(), - 'Memcache.php' => array(), - 'MySQL.php' => array(), - 'Redis.php' => array(), - 'File.php' => array(), - 'Base.php' => array(), - 'Memcached.php' => array() - ), - 'Core.php' => array(), - 'gzdecode.php' => array(), - 'Category.php' => array() - ), - 'class-oembed.php' => array(), - 'class-wp-object-cache.php' => array(), - 'assets' => array( - 'script-loader-packages.php' => array() - ), - 'class-feed.php' => array(), - 'class-wp-term-query.php' => array(), - 'class-wp-fatal-error-handler.php' => array(), - 'ms-default-constants.php' => array(), - 'feed-rss2.php' => array(), - 'locale.php' => array(), - 'class-wp-list-util.php' => array(), - 'embed.php' => array(), - 'class-wp-customize-widgets.php' => array(), - 'feed-rss2-comments.php' => array(), - 'default-widgets.php' => array(), - 'class-wp-block-parser.php' => array(), - 'error-protection.php' => array(), - 'ID3' => array( - 'getid3.lib.php' => array(), - 'module.tag.lyrics3.php' => array(), - 'license.commercial.txt' => array(), - 'module.audio.dts.php' => array(), - 'license.txt' => array(), - 'getid3.php' => array(), - 'module.audio.ac3.php' => array(), - 'module.audio.flac.php' => array(), - 'module.tag.apetag.php' => array(), - 'module.audio-video.matroska.php' => array(), - 'module.audio-video.quicktime.php' => array(), - 'module.audio.ogg.php' => array(), - 'module.audio.mp3.php' => array(), - 'module.audio-video.flv.php' => array(), - 'readme.txt' => array(), - 'module.tag.id3v2.php' => array(), - 'module.audio-video.riff.php' => array(), - 'module.audio-video.asf.php' => array(), - 'module.tag.id3v1.php' => array() - ), - 'embed-template.php' => array(), - 'update.php' => array(), - 'comment-template.php' => array(), - 'nav-menu.php' => array(), - 'class-wp-query.php' => array(), - 'widgets.php' => array(), - 'formatting.php' => array(), - 'http.php' => array(), - 'class-wp-http-curl.php' => array(), - 'class-wp-block-pattern-categories-registry.php' => array(), - 'cache-compat.php' => array(), - 'feed-atom.php' => array(), - 'feed.php' => array(), - 'class-wp-block-list.php' => array(), - 'class-wp-customize-nav-menus.php' => array(), - 'class-wp-http-encoding.php' => array(), - 'class-wp-theme.php' => array(), - 'canonical.php' => array(), - 'sodium_compat' => array( - 'lib' => array( - 'namespaced.php' => array(), - 'constants.php' => array(), - 'php72compat_const.php' => array(), - 'sodium_compat.php' => array(), - 'php72compat.php' => array() - ), - 'src' => array( - 'Core32' => array( - 'Salsa20.php' => array(), - 'Util.php' => array(), - 'BLAKE2b.php' => array(), - 'HSalsa20.php' => array(), - 'SipHash.php' => array(), - 'Poly1305' => array( - 'State.php' => array() - ), - 'XSalsa20.php' => array(), - 'Poly1305.php' => array(), - 'X25519.php' => array(), - 'Int64.php' => array(), - 'Curve25519.php' => array(), - 'Int32.php' => array(), - 'HChaCha20.php' => array(), - 'Curve25519' => array( - 'Fe.php' => array(), - 'H.php' => array(), - 'Ge' => array( - 'Precomp.php' => array(), - 'P2.php' => array(), - 'P1p1.php' => array(), - 'Cached.php' => array(), - 'P3.php' => array() - ), - 'README.md' => array() - ), - 'ChaCha20.php' => array(), - 'XChaCha20.php' => array(), - 'Ed25519.php' => array(), - 'ChaCha20' => array( - 'Ctx.php' => array(), - 'IetfCtx.php' => array() - ), - 'SecretStream' => array( - 'State.php' => array() - ) - ), - 'Compat.php' => array(), - 'Crypto32.php' => array(), - 'File.php' => array(), - 'Core' => array( - 'Salsa20.php' => array(), - 'Util.php' => array(), - 'BLAKE2b.php' => array(), - 'HSalsa20.php' => array(), - 'SipHash.php' => array(), - 'Base64' => array( - 'UrlSafe.php' => array(), - 'Original.php' => array(), - 'Common.php' => array() - ), - 'Poly1305' => array( - 'State.php' => array() - ), - 'XSalsa20.php' => array(), - 'Poly1305.php' => array(), - 'X25519.php' => array(), - 'Curve25519.php' => array(), - 'HChaCha20.php' => array(), - 'Curve25519' => array( - 'Fe.php' => array(), - 'H.php' => array(), - 'Ge' => array( - 'Precomp.php' => array(), - 'P2.php' => array(), - 'P1p1.php' => array(), - 'Cached.php' => array(), - 'P3.php' => array() - ), - 'README.md' => array() - ), - 'ChaCha20.php' => array(), - 'XChaCha20.php' => array(), - 'Ed25519.php' => array(), - 'ChaCha20' => array( - 'Ctx.php' => array(), - 'IetfCtx.php' => array() - ), - 'SecretStream' => array( - 'State.php' => array() - ) - ), - 'Crypto.php' => array(), - 'SodiumException.php' => array(), - 'PHP52' => array( - 'SplFixedArray.php' => array() - ) - ), - 'composer.json' => array(), - 'namespaced' => array( - 'Compat.php' => array(), - 'File.php' => array(), - 'Core' => array( - 'Salsa20.php' => array(), - 'Util.php' => array(), - 'BLAKE2b.php' => array(), - 'HSalsa20.php' => array(), - 'SipHash.php' => array(), - 'Poly1305' => array( - 'State.php' => array() - ), - 'Poly1305.php' => array(), - 'X25519.php' => array(), - 'Curve25519.php' => array(), - 'Xsalsa20.php' => array(), - 'HChaCha20.php' => array(), - 'Curve25519' => array( - 'Fe.php' => array(), - 'H.php' => array(), - 'Ge' => array( - 'Precomp.php' => array(), - 'P2.php' => array(), - 'P1p1.php' => array(), - 'Cached.php' => array(), - 'P3.php' => array() - ) - ), - 'ChaCha20.php' => array(), - 'XChaCha20.php' => array(), - 'Ed25519.php' => array(), - 'ChaCha20' => array( - 'Ctx.php' => array(), - 'IetfCtx.php' => array() - ) - ), - 'Crypto.php' => array() - ), - 'autoload.php' => array(), - 'LICENSE' => array() - ), - 'class-wp-post.php' => array(), - 'random_compat' => array( - 'random_bytes_dev_urandom.php' => array(), - 'random_bytes_libsodium.php' => array(), - 'random_bytes_libsodium_legacy.php' => array(), - 'error_polyfill.php' => array(), - 'random_bytes_openssl.php' => array(), - 'random.php' => array(), - 'random_bytes_mcrypt.php' => array(), - 'cast_to_int.php' => array(), - 'random_int.php' => array(), - 'random_bytes_com_dotnet.php' => array(), - 'byte_safe_strings.php' => array() - ), - 'feed-rss.php' => array(), - 'class-wp-date-query.php' => array(), - 'functions.wp-styles.php' => array(), - 'script-loader.php' => array(), - 'class-wp-image-editor-imagick.php' => array(), - 'block-patterns' => array( - 'quote.php' => array(), - 'heading-paragraph.php' => array(), - 'text-two-columns.php' => array(), - 'text-two-columns-with-images.php' => array(), - 'text-three-columns-buttons.php' => array(), - 'three-buttons.php' => array(), - 'large-header-button.php' => array(), - 'two-buttons.php' => array(), - 'large-header.php' => array(), - 'two-images.php' => array() - ), - 'class-wp-comment-query.php' => array(), - 'wp-db.php' => array() - ), - 'wp-cron.php' => array(), - 'index.php' => array(), - 'xmlrpc.php' => array(), - 'wp-settings.php' => array(), - 'wp-trackback.php' => array(), - 'wp-admin' => array( - 'export.php' => array(), - 'media.php' => array(), - 'media-new.php' => array(), - 'freedoms.php' => array(), - 'my-sites.php' => array(), - 'edit-tags.php' => array(), - 'erase-personal-data.php' => array(), - 'edit-link-form.php' => array(), - 'ms-users.php' => array(), - 'customize.php' => array(), - 'user-new.php' => array(), - 'about.php' => array(), - 'export-personal-data.php' => array(), - 'edit-form-blocks.php' => array(), - 'load-scripts.php' => array(), - 'theme-editor.php' => array(), - 'load-styles.php' => array(), - 'setup-config.php' => array(), - 'upload.php' => array(), - 'tools.php' => array(), - 'upgrade.php' => array(), - 'edit-form-comment.php' => array(), - 'options-privacy.php' => array(), - 'themes.php' => array(), - 'users.php' => array(), - 'edit.php' => array(), - 'options-writing.php' => array(), - 'credits.php' => array(), - 'includes' => array( - 'class-custom-image-header.php' => array(), - 'image-edit.php' => array(), - 'export.php' => array(), - 'ms.php' => array(), - 'media.php' => array(), - 'class-wp-theme-install-list-table.php' => array(), - 'class-bulk-upgrader-skin.php' => array(), - 'class-wp-ms-themes-list-table.php' => array(), - 'class-wp-plugins-list-table.php' => array(), - 'class-wp-upgrader-skins.php' => array(), - 'class-wp-links-list-table.php' => array(), - 'class-walker-nav-menu-checklist.php' => array(), - 'class-wp-ms-users-list-table.php' => array(), - 'class-wp-privacy-data-export-requests-list-table.php' => array(), - 'class-bulk-theme-upgrader-skin.php' => array(), - 'template.php' => array(), - 'class-wp-press-this.php' => array(), - 'class-wp-filesystem-ftpsockets.php' => array(), - 'class-wp-site-health-auto-updates.php' => array(), - 'class-wp-internal-pointers.php' => array(), - 'class-wp-site-health.php' => array(), - 'image.php' => array(), - 'class-plugin-upgrader.php' => array(), - 'edit-tag-messages.php' => array(), - 'class-wp-upgrader.php' => array(), - 'class-theme-upgrader.php' => array(), - 'class-core-upgrader.php' => array(), - 'deprecated.php' => array(), - 'class-wp-comments-list-table.php' => array(), - 'class-wp-privacy-requests-table.php' => array(), - 'dashboard.php' => array(), - 'class-wp-themes-list-table.php' => array(), - 'plugin.php' => array(), - 'class-wp-posts-list-table.php' => array(), - 'upgrade.php' => array(), - 'class-file-upload-upgrader.php' => array(), - 'class-wp-filesystem-base.php' => array(), - 'class-wp-ajax-upgrader-skin.php' => array(), - 'class-wp-privacy-policy-content.php' => array(), - 'class-wp-media-list-table.php' => array(), - 'class-wp-filesystem-ftpext.php' => array(), - 'class-wp-ms-sites-list-table.php' => array(), - 'class-wp-users-list-table.php' => array(), - 'taxonomy.php' => array(), - 'credits.php' => array(), - 'class-wp-list-table.php' => array(), - 'noop.php' => array(), - 'revision.php' => array(), - 'class-language-pack-upgrader-skin.php' => array(), - 'class-wp-post-comments-list-table.php' => array(), - 'class-wp-privacy-data-removal-requests-list-table.php' => array(), - 'import.php' => array(), - 'menu.php' => array(), - 'class-wp-community-events.php' => array(), - 'class-pclzip.php' => array(), - 'user.php' => array(), - 'class-theme-installer-skin.php' => array(), - 'class-wp-filesystem-ssh2.php' => array(), - 'class-wp-upgrader-skin.php' => array(), - 'plugin-install.php' => array(), - 'class-wp-screen.php' => array(), - 'post.php' => array(), - 'class-wp-importer.php' => array(), - 'list-table.php' => array(), - 'class-ftp-pure.php' => array(), - 'class-bulk-plugin-upgrader-skin.php' => array(), - 'continents-cities.php' => array(), - 'class-wp-site-icon.php' => array(), - 'theme-install.php' => array(), - 'class-wp-plugin-install-list-table.php' => array(), - 'admin.php' => array(), - 'options.php' => array(), - 'class-plugin-upgrader-skin.php' => array(), - 'class-language-pack-upgrader.php' => array(), - 'class-plugin-installer-skin.php' => array(), - 'translation-install.php' => array(), - 'misc.php' => array(), - 'class-wp-terms-list-table.php' => array(), - 'class-wp-debug-data.php' => array(), - 'class-walker-category-checklist.php' => array(), - 'ms-deprecated.php' => array(), - 'class-wp-automatic-updater.php' => array(), - 'comment.php' => array(), - 'screen.php' => array(), - 'bookmark.php' => array(), - 'admin-filters.php' => array(), - 'theme.php' => array(), - 'class-wp-list-table-compat.php' => array(), - 'class-automatic-upgrader-skin.php' => array(), - 'privacy-tools.php' => array(), - 'class-walker-nav-menu-edit.php' => array(), - 'class-custom-background.php' => array(), - 'network.php' => array(), - 'class-ftp.php' => array(), - 'update.php' => array(), - 'nav-menu.php' => array(), - 'widgets.php' => array(), - 'class-wp-filesystem-direct.php' => array(), - 'schema.php' => array(), - 'update-core.php' => array(), - 'ms-admin-filters.php' => array(), - 'class-theme-upgrader-skin.php' => array(), - 'ajax-actions.php' => array(), - 'file.php' => array(), - 'class-ftp-sockets.php' => array(), - 'meta-boxes.php' => array() - ), - 'ms-options.php' => array(), - 'link.php' => array(), - 'revision.php' => array(), - 'privacy.php' => array(), - 'js' => array( - 'xfn.min.js' => array(), - 'theme-plugin-editor.min.js' => array(), - 'comment.min.js' => array(), - 'tags.min.js' => array(), - 'theme.js' => array(), - 'press-this.js' => array(), - 'privacy-tools.min.js' => array(), - 'user-profile.min.js' => array(), - 'media.js' => array(), - 'word-count.min.js' => array(), - 'password-strength-meter.min.js' => array(), - 'editor.min.js' => array(), - 'site-health.js' => array(), - 'media-gallery.js' => array(), - 'language-chooser.js' => array(), - 'custom-background.js' => array(), - 'widgets' => array( - 'media-image-widget.min.js' => array(), - 'media-image-widget.js' => array(), - 'text-widgets.min.js' => array(), - 'media-gallery-widget.js' => array(), - 'media-audio-widget.js' => array(), - 'text-widgets.js' => array(), - 'custom-html-widgets.min.js' => array(), - 'media-gallery-widget.min.js' => array(), - 'media-widgets.min.js' => array(), - 'media-video-widget.min.js' => array(), - 'media-audio-widget.min.js' => array(), - 'media-video-widget.js' => array(), - 'custom-html-widgets.js' => array(), - 'media-widgets.js' => array() - ), - 'widgets.js' => array(), - 'widgets.min.js' => array(), - 'accordion.min.js' => array(), - 'wp-fullscreen-stub.min.js' => array(), - 'editor.js' => array(), - 'inline-edit-tax.min.js' => array(), - 'theme-plugin-editor.js' => array(), - 'password-strength-meter.js' => array(), - 'image-edit.min.js' => array(), - 'editor-expand.min.js' => array(), - 'inline-edit-post.js' => array(), - 'color-picker.js' => array(), - 'user-suggest.min.js' => array(), - 'edit-comments.min.js' => array(), - 'link.js' => array(), - 'plugin-install.min.js' => array(), - 'xfn.js' => array(), - 'media.min.js' => array(), - 'revisions.min.js' => array(), - 'accordion.js' => array(), - 'color-picker.min.js' => array(), - 'common.js' => array(), - 'svg-painter.js' => array(), - 'wp-fullscreen.min.js' => array(), - 'set-post-thumbnail.min.js' => array(), - 'post.js' => array(), - 'farbtastic.js' => array(), - 'gallery.js' => array(), - 'image-edit.js' => array(), - 'site-health.min.js' => array(), - 'link.min.js' => array(), - 'tags-box.js' => array(), - 'customize-nav-menus.js' => array(), - 'nav-menu.js' => array(), - 'media-gallery.min.js' => array(), - 'nav-menu.min.js' => array(), - 'editor-expand.js' => array(), - 'word-count.js' => array(), - 'privacy-tools.js' => array(), - 'code-editor.js' => array(), - 'post.min.js' => array(), - 'press-this.min.js' => array(), - 'customize-widgets.min.js' => array(), - 'theme.min.js' => array(), - 'wp-fullscreen.js' => array(), - 'edit-comments.js' => array(), - 'inline-edit-tax.js' => array(), - 'customize-controls.js' => array(), - 'user-profile.js' => array(), - 'media-upload.js' => array(), - 'revisions.js' => array(), - 'dashboard.min.js' => array(), - 'dashboard.js' => array(), - 'comment.js' => array(), - 'customize-controls.min.js' => array(), - 'custom-header.js' => array(), - 'inline-edit-post.min.js' => array(), - 'set-post-thumbnail.js' => array(), - 'wp-fullscreen-stub.js' => array(), - 'updates.js' => array(), - 'code-editor.min.js' => array(), - 'updates.min.js' => array(), - 'iris.min.js' => array(), - 'svg-painter.min.js' => array(), - 'common.min.js' => array(), - 'customize-nav-menus.min.js' => array(), - 'bookmarklet.min.js' => array(), - 'tags.js' => array(), - 'customize-widgets.js' => array(), - 'gallery.min.js' => array(), - 'bookmarklet.js' => array(), - 'postbox.js' => array(), - 'tags-suggest.min.js' => array(), - 'postbox.min.js' => array(), - 'tags-box.min.js' => array(), - 'tags-suggest.js' => array(), - 'language-chooser.min.js' => array(), - 'plugin-install.js' => array(), - 'user-suggest.js' => array(), - 'custom-background.min.js' => array(), - 'media-upload.min.js' => array() - ), - 'css' => array( - 'forms-rtl.min.css' => array(), - 'customize-controls-rtl.css' => array(), - 'site-icon.min.css' => array(), - 'themes-rtl.min.css' => array(), - 'press-this-editor-rtl.css' => array(), - 'revisions-rtl.min.css' => array(), - 'press-this-rtl.css' => array(), - 'wp-admin.css' => array(), - 'install-rtl.css' => array(), - 'code-editor-rtl.min.css' => array(), - 'widgets.min.css' => array(), - 'themes-rtl.css' => array(), - 'list-tables-rtl.css' => array(), - 'press-this-editor.min.css' => array(), - 'forms.min.css' => array(), - 'customize-nav-menus-rtl.css' => array(), - 'l10n.css' => array(), - 'list-tables.min.css' => array(), - 'press-this.css' => array(), - 'media-rtl.css' => array(), - 'customize-nav-menus.css' => array(), - 'admin-menu.css' => array(), - 'color-picker-rtl.min.css' => array(), - 'login-rtl.min.css' => array(), - 'press-this-editor.css' => array(), - 'color-picker-rtl.css' => array(), - 'nav-menus.css' => array(), - 'site-icon-rtl.css' => array(), - 'ie.css' => array(), - 'edit.css' => array(), - 'edit.min.css' => array(), - 'media.min.css' => array(), - 'about-rtl.min.css' => array(), - 'widgets-rtl.min.css' => array(), - 'common.min.css' => array(), - 'customize-nav-menus.min.css' => array(), - 'press-this-rtl.min.css' => array(), - 'revisions-rtl.css' => array(), - 'farbtastic.min.css' => array(), - 'install-rtl.min.css' => array(), - 'themes.css' => array(), - 'l10n-rtl.min.css' => array(), - 'edit-rtl.min.css' => array(), - 'nav-menus-rtl.min.css' => array(), - 'site-icon-rtl.min.css' => array(), - 'media-rtl.min.css' => array(), - 'colors' => array( - 'sunrise' => array( - 'colors.min.css' => array(), - 'colors.scss' => array(), - 'colors-rtl.min.css' => array(), - 'colors.css' => array(), - 'colors-rtl.css' => array() - ), - 'blue' => array( - 'colors.min.css' => array(), - 'colors.scss' => array(), - 'colors-rtl.min.css' => array(), - 'colors.css' => array(), - 'colors-rtl.css' => array() - ), - 'ectoplasm' => array( - 'colors.min.css' => array(), - 'colors.scss' => array(), - 'colors-rtl.min.css' => array(), - 'colors.css' => array(), - 'colors-rtl.css' => array() - ), - 'modern' => array( - 'colors.min.css' => array(), - 'colors.scss' => array(), - 'colors-rtl.min.css' => array(), - 'colors.css' => array(), - 'colors-rtl.css' => array() - ), - '_mixins.scss' => array(), - '_admin.scss' => array(), - 'coffee' => array( - 'colors.min.css' => array(), - 'colors.scss' => array(), - 'colors-rtl.min.css' => array(), - 'colors.css' => array(), - 'colors-rtl.css' => array() - ), - 'ocean' => array( - 'colors.min.css' => array(), - 'colors.scss' => array(), - 'colors-rtl.min.css' => array(), - 'colors.css' => array(), - 'colors-rtl.css' => array() - ), - 'light' => array( - 'colors.min.css' => array(), - 'colors.scss' => array(), - 'colors-rtl.min.css' => array(), - 'colors.css' => array(), - 'colors-rtl.css' => array() - ), - 'midnight' => array( - 'colors.min.css' => array(), - 'colors.scss' => array(), - 'colors-rtl.min.css' => array(), - 'colors.css' => array(), - 'colors-rtl.css' => array() - ), - '_variables.scss' => array() - ), - 'revisions.min.css' => array(), - 'about.min.css' => array(), - 'common-rtl.min.css' => array(), - 'customize-nav-menus-rtl.min.css' => array(), - 'customize-controls-rtl.min.css' => array(), - 'site-health.css' => array(), - 'code-editor-rtl.css' => array(), - 'edit-rtl.css' => array(), - 'forms.css' => array(), - 'wp-admin-rtl.min.css' => array(), - 'code-editor.css' => array(), - 'customize-widgets-rtl.min.css' => array(), - 'color-picker.min.css' => array(), - 'l10n-rtl.css' => array(), - 'site-icon.css' => array(), - 'customize-widgets.css' => array(), - 'color-picker.css' => array(), - 'dashboard.css' => array(), - 'deprecated-media-rtl.css' => array(), - 'press-this-editor-rtl.min.css' => array(), - 'deprecated-media.min.css' => array(), - 'customize-widgets.min.css' => array(), - 'admin-menu-rtl.min.css' => array(), - 'widgets.css' => array(), - 'revisions.css' => array(), - 'dashboard-rtl.css' => array(), - 'admin-menu-rtl.css' => array(), - 'widgets-rtl.css' => array(), - 'login.min.css' => array(), - 'nav-menus-rtl.css' => array(), - 'ie-rtl.min.css' => array(), - 'ie.min.css' => array(), - 'install.css' => array(), - 'press-this.min.css' => array(), - 'about.css' => array(), - 'admin-menu.min.css' => array(), - 'login-rtl.css' => array(), - 'farbtastic.css' => array(), - 'dashboard.min.css' => array(), - 'forms-rtl.css' => array(), - 'l10n.min.css' => array(), - 'ie-rtl.css' => array(), - 'themes.min.css' => array(), - 'install.min.css' => array(), - 'site-health.min.css' => array(), - 'customize-widgets-rtl.css' => array(), - 'farbtastic-rtl.css' => array(), - 'wp-admin-rtl.css' => array(), - 'common.css' => array(), - 'list-tables.css' => array(), - 'customize-controls.css' => array(), - 'common-rtl.css' => array(), - 'login.css' => array(), - 'dashboard-rtl.min.css' => array(), - 'list-tables-rtl.min.css' => array(), - 'nav-menus.min.css' => array(), - 'deprecated-media.css' => array(), - 'about-rtl.css' => array(), - 'customize-controls.min.css' => array(), - 'site-health-rtl.css' => array(), - 'site-health-rtl.min.css' => array(), - 'media.css' => array(), - 'code-editor.min.css' => array(), - 'deprecated-media-rtl.min.css' => array(), - 'farbtastic-rtl.min.css' => array(), - 'wp-admin.min.css' => array() - ), - 'site-health-info.php' => array(), - 'user' => array( - 'freedoms.php' => array(), - 'about.php' => array(), - 'credits.php' => array(), - 'privacy.php' => array(), - 'menu.php' => array(), - 'user-edit.php' => array(), - 'admin.php' => array(), - 'profile.php' => array(), - 'index.php' => array() - ), - 'options-permalink.php' => array(), - 'import.php' => array(), - 'edit-form-advanced.php' => array(), - 'menu.php' => array(), - 'term.php' => array(), - 'custom-background.php' => array(), - 'link-manager.php' => array(), - 'network' => array( - 'freedoms.php' => array(), - 'site-info.php' => array(), - 'setup.php' => array(), - 'user-new.php' => array(), - 'about.php' => array(), - 'theme-editor.php' => array(), - 'upgrade.php' => array(), - 'themes.php' => array(), - 'users.php' => array(), - 'edit.php' => array(), - 'credits.php' => array(), - 'privacy.php' => array(), - 'site-themes.php' => array(), - 'menu.php' => array(), - 'site-settings.php' => array(), - 'user-edit.php' => array(), - 'plugin-install.php' => array(), - 'theme-install.php' => array(), - 'settings.php' => array(), - 'admin.php' => array(), - 'profile.php' => array(), - 'plugins.php' => array(), - 'site-new.php' => array(), - 'index.php' => array(), - 'site-users.php' => array(), - 'plugin-editor.php' => array(), - 'sites.php' => array(), - 'update.php' => array(), - 'update-core.php' => array() - ), - 'install-helper.php' => array(), - 'user-edit.php' => array(), - 'async-upload.php' => array(), - 'plugin-install.php' => array(), - 'post.php' => array(), - 'options-discussion.php' => array(), - 'theme-install.php' => array(), - 'admin.php' => array(), - 'options-reading.php' => array(), - 'options.php' => array(), - 'images' => array( - 'list.png' => array(), - 'icons32-vs-2x.png' => array(), - 'resize-rtl.gif' => array(), - 'media-button.png' => array(), - 'comment-grey-bubble-2x.png' => array(), - 'menu-2x.png' => array(), - 'xit-2x.gif' => array(), - 'sort-2x.gif' => array(), - 'media-button-video.gif' => array(), - 'icons32.png' => array(), - 'bubble_bg.gif' => array(), - 'media-button-other.gif' => array(), - 'menu.png' => array(), - 'browser-rtl.png' => array(), - 'align-left-2x.png' => array(), - 'browser.png' => array(), - 'sort.gif' => array(), - 'media-button-2x.png' => array(), - 'post-formats.png' => array(), - 'align-center.png' => array(), - 'icons32-2x.png' => array(), - 'resize-2x.gif' => array(), - 'imgedit-icons.png' => array(), - 'align-right-2x.png' => array(), - 'wpspin_light.gif' => array(), - 'wordpress-logo.svg' => array(), - 'wheel.png' => array(), - 'list-2x.png' => array(), - 'resize.gif' => array(), - 'w-logo-blue.png' => array(), - 'xit.gif' => array(), - 'imgedit-icons-2x.png' => array(), - 'stars.png' => array(), - 'arrows-2x.png' => array(), - 'menu-vs.png' => array(), - 'align-right.png' => array(), - 'align-left.png' => array(), - 'post-formats32.png' => array(), - 'align-none-2x.png' => array(), - 'wpspin_light-2x.gif' => array(), - 'wordpress-logo-white.svg' => array(), - 'resize-rtl-2x.gif' => array(), - 'w-logo-white.png' => array(), - 'se.png' => array(), - 'media-button-image.gif' => array(), - 'yes.png' => array(), - 'wordpress-logo.png' => array(), - 'generic.png' => array(), - 'icons32-vs.png' => array(), - 'menu-vs-2x.png' => array(), - 'align-center-2x.png' => array(), - 'media-button-music.gif' => array(), - 'spinner-2x.gif' => array(), - 'align-none.png' => array(), - 'spinner.gif' => array(), - 'comment-grey-bubble.png' => array(), - 'arrows.png' => array(), - 'date-button-2x.gif' => array(), - 'stars-2x.png' => array(), - 'no.png' => array(), - 'date-button.gif' => array(), - 'bubble_bg-2x.gif' => array(), - 'post-formats-vs.png' => array(), - 'post-formats32-vs.png' => array(), - 'loading.gif' => array(), - 'mask.png' => array(), - 'marker.png' => array() - ), - 'profile.php' => array(), - 'plugins.php' => array(), - 'install.php' => array(), - 'options-head.php' => array(), - 'link-parse-opml.php' => array(), - 'admin-functions.php' => array(), - 'moderation.php' => array(), - 'comment.php' => array(), - 'index.php' => array(), - 'ms-sites.php' => array(), - 'site-health.php' => array(), - 'link-add.php' => array(), - 'edit-comments.php' => array(), - 'plugin-editor.php' => array(), - 'maint' => array( - 'repair.php' => array() - ), - 'nav-menus.php' => array(), - 'privacy-policy-guide.php' => array(), - 'network.php' => array(), - 'custom-header.php' => array(), - 'options-general.php' => array(), - 'options-media.php' => array(), - 'post-new.php' => array(), - 'update.php' => array(), - 'widgets.php' => array(), - 'ms-upgrade-network.php' => array(), - 'media-upload.php' => array(), - 'admin-header.php' => array(), - 'update-core.php' => array(), - 'ms-themes.php' => array(), - 'ms-delete-site.php' => array(), - 'upgrade-functions.php' => array(), - 'menu-header.php' => array(), - 'ms-admin.php' => array(), - 'admin-footer.php' => array(), - 'ms-edit.php' => array(), - 'press-this.php' => array(), - 'admin-ajax.php' => array(), - 'admin-post.php' => array(), - 'edit-tag-form.php' => array() - ) -); From 81a5194a36f555409b89e2c2156db5641e9d558d Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Mon, 29 Aug 2022 00:54:49 +0000 Subject: [PATCH 553/585] version update git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@2776863 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 06a85de8..a422d3cd 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Tags: migration, backup, duplicate, move, migrate, restore, transfer, clone, aut Requires at least: 4.0 Tested up to: 6.0 Requires PHP: 5.3.8 -Stable tag: 1.4.7.2 +Stable tag: 1.5.0 License: GPLv2 WordPress migration and backups are much easier with Duplicator! Clone, backup, move and transfer an entire site from one location to another. From c894c14e583dc9cdd978c4ffa198e43fbc298cb0 Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Mon, 31 Oct 2022 18:43:19 +0000 Subject: [PATCH 554/585] tested upto update git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@2808189 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index a422d3cd..dead88a5 100644 --- a/readme.txt +++ b/readme.txt @@ -2,7 +2,7 @@ Contributors: corylamleorg, bobriley Tags: migration, backup, duplicate, move, migrate, restore, transfer, clone, automate, copy site, migrator Requires at least: 4.0 -Tested up to: 6.0 +Tested up to: 6.1 Requires PHP: 5.3.8 Stable tag: 1.5.0 License: GPLv2 From 80bbda26d53648eccde20020088ed65edae9655f Mon Sep 17 00:00:00 2001 From: "cory@lamle.org" Date: Wed, 16 Nov 2022 22:36:09 +0000 Subject: [PATCH 555/585] Version 1.5.1 updates git-svn-id: https://plugins.svn.wordpress.org/duplicator/trunk@2819351 b8457f37-d9ea-0310-8a92-e5e31aec5664 --- assets/css/style.css | 1 + classes/class.db.php | 17 +- classes/package/class.pack.archive.php | 1 + classes/package/class.pack.installer.php | 4 +- define.php | 4 +- duplicator.php | 4 +- .../classes/class.installer.state.php | 11 +- .../classes/database/class.db.php | 24 +- .../ctrls/classes/class.ctrl.ajax.php | 5 +- .../ctrls/classes/class.ctrl.params.php | 1 + .../ctrls/classes/class.ctrl.s3.funcs.php | 5 +- installer/dup-installer/main.installer.php | 2 +- .../dup-installer/src/Core/Bootstrap.php | 1 - .../src/Core/Deploy/Database/QueryFixes.php | 31 +- .../Params/Descriptors/ParamDescEngines.php | 35 ++- .../Params/Descriptors/ParamDescGeneric.php | 17 +- .../Params/Descriptors/ParamDescReplace.php | 2 +- .../src/Utils/Tests/MessageCustomizer.php | 199 ++++++++++++ .../src/Utils/Tests/MessageCustomizerItem.php | 45 +++ .../src/Utils/Tests/TestInterface.php | 16 + .../src/Utils/Tests/WP/TestsErrorHandler.php | 290 ++++++++++++++++++ .../src/Utils/Tests/WP/TestsExecuter.php | 149 +++++++++ .../src/Utils/Tests/WP/tests_template.php | 121 ++++++++ .../default/pages-parts/help/steps/step-3.php | 19 +- .../step1-parts/advanced-step1-options.php | 16 +- .../steps/step1-parts/basic-step1-setup.php | 100 ++++-- .../info-tabs/overviews/restore-backup.php | 14 +- .../info-tabs/overviews/type-single-site.php | 14 +- .../step3/options-tabs/search-rules.php | 1 + .../database-tests/db-supported-engine.php | 2 +- .../validation/tests/manual-extraction.php | 11 +- .../default/scripts/modules/final-tests.php | 5 +- .../templates/default/scripts/step1-init.php | 8 - src/Libs/Snap/SnapCode.php | 14 +- src/Libs/Snap/wordpress_core_files.php | 106 +++++-- views/packages/details/detail.php | 91 +++--- .../migration-clean-installation-files.php | 2 +- views/settings/packages.php | 11 +- 38 files changed, 1213 insertions(+), 186 deletions(-) create mode 100644 installer/dup-installer/src/Utils/Tests/MessageCustomizer.php create mode 100644 installer/dup-installer/src/Utils/Tests/MessageCustomizerItem.php create mode 100644 installer/dup-installer/src/Utils/Tests/TestInterface.php create mode 100644 installer/dup-installer/src/Utils/Tests/WP/TestsErrorHandler.php create mode 100644 installer/dup-installer/src/Utils/Tests/WP/TestsExecuter.php create mode 100644 installer/dup-installer/src/Utils/Tests/WP/tests_template.php diff --git a/assets/css/style.css b/assets/css/style.css index ae828db7..8f073377 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -15,6 +15,7 @@ i[data-tooltip].fa-lightbulb-o {cursor:pointer; color:gray} span.btn-separator {content:''; display:inline-block; background:silver; margin:2px 3px; height:25px; width:1px; vertical-align:top;} a.grey-icon i.fa {color:#777} i.grey-icon {color:#777} +.maroon {color:maroon} .no-display {display:none !important;} .link-style {color:#0074ab; cursor:pointer; text-decoration:underline;} diff --git a/classes/class.db.php b/classes/class.db.php index b59eccb5..b082d009 100644 --- a/classes/class.db.php +++ b/classes/class.db.php @@ -125,7 +125,9 @@ public static function getMySqlDumpPath() $custom_mysqldump_path = DUP_Settings::Get('package_mysqldump_path'); $custom_mysqldump_path = (strlen($custom_mysqldump_path)) ? $custom_mysqldump_path : ''; -//Common Windows Paths + $custom_mysqldump_path = escapeshellcmd($custom_mysqldump_path); + + // Common Windows Paths if (DUP_Util::isWindows()) { $paths = array( $custom_mysqldump_path, @@ -137,7 +139,7 @@ public static function getMySqlDumpPath() 'C:/Program Files/MySQL/MySQL Server 5.5/bin/mysqldump', 'C:/Program Files/MySQL/MySQL Server 5.4/bin/mysqldump' ); -//Common Linux Paths + // Common Linux Paths } else { $paths = array( $custom_mysqldump_path, @@ -214,10 +216,9 @@ public static function getTableCharSetList($tables) * Returns all collation types that are assigned to the tables and columns table in * the current database. Each element in the array is unique * - * @param array &$tablesToInclude A list of tables to include in the search. - * Parameter does not change in the function, is passed by reference only to avoid copying. + * @param string[] $tablesToInclude A list of tables to include in the search. * - * @return array Returns an array with all the collation types being used + * @return string[] Returns an array with all the collation types being used */ public static function getTableCollationList($tablesToInclude) { @@ -240,6 +241,7 @@ public static function getTableCollationList($tablesToInclude) $collations = array_unique(array_merge($collations, $wpdb->get_col())); } + $collations = array_values($collations); sort($collations); } return $collations; @@ -249,7 +251,7 @@ public static function getTableCollationList($tablesToInclude) * Returns list of MySQL engines used by $tablesToInclude in the current DB * * @param string[] $tablesToInclude tables to check the engines for - * @return null + * @return string[] * @throws Exception */ public static function getTableEngineList($tablesToInclude) @@ -265,8 +267,9 @@ public static function getTableEngineList($tablesToInclude) DUP_Log::info("GET TABLE ENGINES ERROR: " . $wpdb->last_error); } - $engines = array_unique(array_merge($engines, $wpdb->get_col($query))); + $engines = array_merge($engines, $wpdb->get_col($query)); } + $engines = array_values(array_unique($engines)); } return $engines; diff --git a/classes/package/class.pack.archive.php b/classes/package/class.pack.archive.php index 57daf1f3..708d38d0 100644 --- a/classes/package/class.pack.archive.php +++ b/classes/package/class.pack.archive.php @@ -804,6 +804,7 @@ public static function getOriginalUrls($urlKey = null) $origUrls = array( 'home' => $homeUrl, 'abs' => site_url(), + 'login' => wp_login_url(), 'wpcontent' => content_url(), 'uploads' => $updDirs['baseurl'], 'plugins' => plugins_url(), diff --git a/classes/package/class.pack.installer.php b/classes/package/class.pack.installer.php index 1e68e6c0..5b090b54 100644 --- a/classes/package/class.pack.installer.php +++ b/classes/package/class.pack.installer.php @@ -120,9 +120,8 @@ private function create_enhanced_installer() Please contact your host and ask them to enable "PHP" processing on your account. ----------------------------- NOTICE --------------------------------- */ -?> HEADER; - $installer_contents = $header . SnapCode::getSrcClassCode($template_filepath, false) . "\n/* DUPLICATOR_INSTALLER_EOF */"; + $installer_contents = $header . SnapCode::getSrcClassCode($template_filepath, false, true) . "\n/* DUPLICATOR_INSTALLER_EOF */"; // $installer_contents = file_get_contents($template_filepath); // $csrf_class_contents = file_get_contents($csrf_class_filepath); @@ -388,6 +387,7 @@ private function getWpInfo() $originalUrls = DUP_Archive::getOriginalUrls(); $wpInfo->configs->realValues->siteUrl = $originalUrls['abs']; $wpInfo->configs->realValues->homeUrl = $originalUrls['home']; + $wpInfo->configs->realValues->loginUrl = $originalUrls['login']; $wpInfo->configs->realValues->contentUrl = $originalUrls['wpcontent']; $wpInfo->configs->realValues->uploadBaseUrl = $originalUrls['uploads']; $wpInfo->configs->realValues->pluginsUrl = $originalUrls['plugins']; diff --git a/define.php b/define.php index 6b89fccc..26337633 100644 --- a/define.php +++ b/define.php @@ -5,8 +5,8 @@ if (function_exists('plugin_dir_url')) { - define('DUPLICATOR_VERSION', '1.5.0'); - define('DUPLICATOR_VERSION_BUILD', '2022-08-28_19:00'); + define('DUPLICATOR_VERSION', '1.5.1'); + define('DUPLICATOR_VERSION_BUILD', '2022-11-16_13:00'); define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__)); define('DUPLICATOR_SITE_URL', get_site_url()); diff --git a/duplicator.php b/duplicator.php index 65d16000..97480e55 100644 --- a/duplicator.php +++ b/duplicator.php @@ -4,9 +4,9 @@ * Plugin Name: Duplicator * Plugin URI: https://snapcreek.com/duplicator/duplicator-free/ * Description: Migrate and backup a copy of your WordPress files and database. Duplicate and move a site from one location to another quickly. - * Version: 1.5.0 + * Version: 1.5.1 * Requires at least: 4.0 - * Tested up to: 6.0 + * Tested up to: 6.1 * Requires PHP: 5.3.8 * Author: Snap Creek * Author URI: http://www.snapcreek.com/duplicator/ diff --git a/installer/dup-installer/classes/class.installer.state.php b/installer/dup-installer/classes/class.installer.state.php index 467715b4..9436c93f 100644 --- a/installer/dup-installer/classes/class.installer.state.php +++ b/installer/dup-installer/classes/class.installer.state.php @@ -595,9 +595,14 @@ public static function getMigrationData() */ public static function getAdminLogin() { - $paramsManager = PrmMng::getInstance(); - $adminUrl = rtrim($paramsManager->getValue(PrmMng::PARAM_SITE_URL), "/"); - return $adminUrl . '/wp-login.php'; + $paramsManager = PrmMng::getInstance(); + $archiveConfig = \DUPX_ArchiveConfig::getInstance(); + $adminUrl = rtrim($paramsManager->getValue(PrmMng::PARAM_SITE_URL), "/"); + $sourceAdminUrl = rtrim($archiveConfig->getRealValue("siteUrl"), "/"); + $sourceLoginUrl = $archiveConfig->getRealValue("loginUrl"); + $relLoginUrl = substr($sourceLoginUrl, strlen($sourceAdminUrl)); + $loginUrl = $adminUrl . $relLoginUrl; + return $loginUrl; } /** diff --git a/installer/dup-installer/classes/database/class.db.php b/installer/dup-installer/classes/database/class.db.php index 264d1b82..c6628605 100644 --- a/installer/dup-installer/classes/database/class.db.php +++ b/installer/dup-installer/classes/database/class.db.php @@ -11,7 +11,9 @@ */ defined('ABSPATH') || defined('DUPXABSPATH') || exit; + use Duplicator\Installer\Utils\Log\Log; + class DUPX_DB { const DELETE_CHUNK_SIZE = 500; @@ -540,9 +542,9 @@ public static function copyTable($dbh, $existing_name, $new_name, $delete_if_con /** * Sets the MySQL connection's character set. * - * @param \mysqli $dbh The resource given by mysqli_connect - * @param string $charset The character set (optional) - * @param string $collate The collation (optional) + * @param \mysqli $dbh The resource given by mysqli_connect + * @param ?string $charset The character set, null default value + * @param ?string $collate The collation, null default value */ public static function setCharset($dbh, $charset = null, $collate = null) { @@ -552,16 +554,22 @@ public static function setCharset($dbh, $charset = null, $collate = null) $charset = (!isset($charset) ) ? $GLOBALS['DBCHARSET_DEFAULT'] : $charset; $collate = (!isset($collate) ) ? '' : $collate; + if (empty($charset)) { return true; } if (function_exists('mysqli_set_charset') && self::hasAbility($dbh, 'set_charset')) { - if (($result1 = mysqli_set_charset($dbh, $charset)) === false) { - $errMsg = mysqli_error($dbh); - Log::info('DATABASE ERROR: mysqli_set_charset ' . Log::v2str($charset) . ' MSG: ' . $errMsg); - } else { - Log::info('DATABASE: mysqli_set_charset ' . Log::v2str($charset), Log::LV_DETAILED); + try { + if (($result1 = mysqli_set_charset($dbh, $charset)) === false) { + $errMsg = mysqli_error($dbh); + Log::info('DATABASE ERROR: mysqli_set_charset ' . Log::v2str($charset) . ' MSG: ' . $errMsg); + } else { + Log::info('DATABASE: mysqli_set_charset ' . Log::v2str($charset), Log::LV_DETAILED); + } + } catch (Exception $e) { + Log::info('DATABASE ERROR: mysqli_set_charset ' . Log::v2str($charset) . ' MSG: ' . $e->getMessage()); + $result1 = false; } if (!empty($collate)) { diff --git a/installer/dup-installer/ctrls/classes/class.ctrl.ajax.php b/installer/dup-installer/ctrls/classes/class.ctrl.ajax.php index 48d1218f..814adb00 100644 --- a/installer/dup-installer/ctrls/classes/class.ctrl.ajax.php +++ b/installer/dup-installer/ctrls/classes/class.ctrl.ajax.php @@ -14,6 +14,7 @@ use Duplicator\Installer\Utils\Log\Log; use Duplicator\Installer\Core\Params\PrmMng; +use Duplicator\Installer\Utils\Tests\WP\TestsExecuter; use Duplicator\Libs\Snap\SnapJson; use Duplicator\Libs\Snap\SnapString; use Duplicator\Libs\Snap\SnapUtil; @@ -215,10 +216,10 @@ protected static function actions($action) $actionData = DUPX_S3_Funcs::getInstance()->updateWebsite(); break; case self::ACTION_FINAL_TESTS_PREPARE: - $actionData = DUPX_test_wordpress_exec::preTestPrepare(); + $actionData = TestsExecuter::preTestPrepare(); break; case self::ACTION_FINAL_TESTS_AFTER: - $actionData = DUPX_test_wordpress_exec::afterTestClean(); + $actionData = TestsExecuter::afterTestClean(); break; case self::ACTION_SET_AUTO_CLEAN_FILES: if (DUPX_Ctrl_Params::setParamAutoClean()) { diff --git a/installer/dup-installer/ctrls/classes/class.ctrl.params.php b/installer/dup-installer/ctrls/classes/class.ctrl.params.php index 56ca7e50..2cc9eb62 100644 --- a/installer/dup-installer/ctrls/classes/class.ctrl.params.php +++ b/installer/dup-installer/ctrls/classes/class.ctrl.params.php @@ -325,6 +325,7 @@ public static function setParamsStep3() $readParamsList = array( PrmMng::PARAM_EMAIL_REPLACE, PrmMng::PARAM_FULL_SEARCH, + PrmMng::PARAM_SKIP_PATH_REPLACE, PrmMng::PARAM_POSTGUID, PrmMng::PARAM_MAX_SERIALIZE_CHECK, PrmMng::PARAM_PLUGINS, diff --git a/installer/dup-installer/ctrls/classes/class.ctrl.s3.funcs.php b/installer/dup-installer/ctrls/classes/class.ctrl.s3.funcs.php index 5650b7ee..5c16f445 100644 --- a/installer/dup-installer/ctrls/classes/class.ctrl.s3.funcs.php +++ b/installer/dup-installer/ctrls/classes/class.ctrl.s3.funcs.php @@ -358,6 +358,7 @@ public function closeDbConnection() public function initLog() { $paramsManager = PrmMng::getInstance(); + $labelPadSize = 22; // make sure dbConnection is initialized $this->dbConnection(); @@ -378,6 +379,8 @@ public function initLog() "********************************************************************************\n" . "OPTIONS:\n"; + $log .= str_pad('SKIP PATH REPLACE', $labelPadSize, '_', STR_PAD_RIGHT) . ': ' . Log::v2str($paramsManager->getValue(PrmMng::PARAM_SKIP_PATH_REPLACE)) . "\n"; + $wpConfigsKeys = array( PrmMng::PARAM_WP_CONF_DISALLOW_FILE_EDIT, PrmMng::PARAM_WP_CONF_DISALLOW_FILE_MODS, @@ -405,7 +408,7 @@ public function initLog() foreach ($wpConfigsKeys as $key) { $label = $paramsManager->getLabel($key); $value = SnapString::implodeKeyVals(', ', $paramsManager->getValue($key), '[%s = %s]'); - $log .= str_pad($label, 22, '_', STR_PAD_RIGHT) . ': ' . $value . "\n"; + $log .= str_pad($label, $labelPadSize, '_', STR_PAD_RIGHT) . ': ' . $value . "\n"; } $log .= "********************************************************************************\n"; diff --git a/installer/dup-installer/main.installer.php b/installer/dup-installer/main.installer.php index 3a16e8ed..d08a4710 100644 --- a/installer/dup-installer/main.installer.php +++ b/installer/dup-installer/main.installer.php @@ -34,7 +34,7 @@ die; } -define('DUPX_VERSION', '1.5.0'); +define('DUPX_VERSION', '1.5.1'); define('DUPX_INIT', str_replace('\\', '/', dirname(__FILE__))); define('DUPX_ROOT', preg_match('/^[\\\\\/]?$/', dirname(DUPX_INIT)) ? '/' : dirname(DUPX_INIT)); diff --git a/installer/dup-installer/src/Core/Bootstrap.php b/installer/dup-installer/src/Core/Bootstrap.php index a0d4bf8c..84c86d62 100644 --- a/installer/dup-installer/src/Core/Bootstrap.php +++ b/installer/dup-installer/src/Core/Bootstrap.php @@ -204,7 +204,6 @@ public static function includes() require_once(DUPX_INIT . '/classes/config/class.constants.php'); require_once(DUPX_INIT . '/classes/config/class.conf.utils.php'); require_once(DUPX_INIT . '/classes/class.installer.state.php'); - require_once(DUPX_INIT . '/classes/tests/class.test.wordpress.exec.php'); require_once(DUPX_INIT . '/ctrls/classes/class.ctrl.ajax.php'); require_once(DUPX_INIT . '/ctrls/classes/class.ctrl.params.php'); require_once(DUPX_INIT . '/ctrls/ctrl.base.php'); diff --git a/installer/dup-installer/src/Core/Deploy/Database/QueryFixes.php b/installer/dup-installer/src/Core/Deploy/Database/QueryFixes.php index e81b2f29..00a84e24 100644 --- a/installer/dup-installer/src/Core/Deploy/Database/QueryFixes.php +++ b/installer/dup-installer/src/Core/Deploy/Database/QueryFixes.php @@ -45,7 +45,7 @@ public function __construct() /** * Filter props on json encode * - * @return strng[] + * @return string[] */ public function __sleep() { @@ -109,10 +109,9 @@ public function applyFixes($query) } /** - * return search and replace rules + * Set search and replace rules * - * @return array - * @throws Exception + * @return void */ protected function rulesProcAndViews() { @@ -160,6 +159,8 @@ protected function rulesMySQLEngine() } /** + * Set legacy charset adn collation rules + * * regex managed examples * - `meta_value` longtext CHARACTER SET utf16 COLLATE utf16_slovak_ci DEFAULT NULL, * - `comment_author` tinytext COLLATE utf8mb4_unicode_ci NOT NULL, @@ -168,7 +169,7 @@ protected function rulesMySQLEngine() * * accept ['"`]charset['"`] * - * @return boolean|array + * @return void */ public function legacyCharsetAndCollation() { @@ -183,12 +184,12 @@ public function legacyCharsetAndCollation() }, $invalidCharsets)) . ')'; $this->globalRules['search'][] = '/(^.*(?:CHARSET|CHARACTER SET)\s*[\s=]\s*[`\'"]?)(' . - $invalidChrRegex . ')([`\'"]?\s.*COLLATE\s*[\s=]\s*[`\'"]?)([^`\'"\s;]+)([`\'"]?.*$)/m'; + $invalidChrRegex . ')([`\'"]?\s.*COLLATE\s*[\s=]\s*[`\'"]?)([^`\'"\s;,]+)([`\'"]?.*$)/m'; $this->globalRules['replace'][] = '$1' . $defCharsetRegex . '$3' . $defCollateRegex . '$5'; - $this->globalRules['search'][] = '/(^.*COLLATE\s*[\s=]\s*[`\'"]?)([^`\'"\s;]+)([`\'"]?\s.*(?:CHARSET|CHARACTER SET)\s*[\s=]\s*[`\'"]?)(' . - $invalidChrRegex . ')([`\'"]?[\s;].*$)/m'; + $this->globalRules['search'][] = '/(^.*COLLATE\s*[\s=]\s*[`\'"]?)([^`\'"\s;,]+)([`\'"]?\s.*(?:CHARSET|CHARACTER SET)\s*[\s=]\s*[`\'"]?)(' . + $invalidChrRegex . ')([`\'"]?[\s;,].*$)/m'; $this->globalRules['replace'][] = '$1' . $defCollateRegex . '$3' . $defCharsetRegex . '$5'; - $this->globalRules['search'][] = '/(^.*(?:CHARSET|CHARACTER SET)\s*[\s=]\s*[`\'"]?)(' . $invalidChrRegex . ')([`\'"]?[\s;].*$)/m'; + $this->globalRules['search'][] = '/(^.*(?:CHARSET|CHARACTER SET)\s*[\s=]\s*[`\'"]?)(' . $invalidChrRegex . ')([`\'"]?[\s;,].*$)/m'; $this->globalRules['replace'][] = '$1' . $defCharsetRegex . '$3'; $this->generatorLog .= "GLOBAL RULES ADDED: INVALID CHARSETS\n"; @@ -199,13 +200,13 @@ public function legacyCharsetAndCollation() return preg_quote($val, '/'); }, $invalidCollations)) . ')'; - $this->globalRules['search'][] = '/(^.*(?:CHARSET|CHARACTER SET)\s*[\s=]\s*[`\'"]?)([^`\'"\s;]+)([`\'"]?\s.*COLLATE\s*[\s=]\s*[`\'"]?)(' . - $invalidColRegex . ')([`\'"]?[\s;].*$)/m'; + $this->globalRules['search'][] = '/(^.*(?:CHARSET|CHARACTER SET)\s*[\s=]\s*[`\'"]?)([^`\'"\s;,]+)([`\'"]?\s.*COLLATE\s*[\s=]\s*[`\'"]?)(' . + $invalidColRegex . ')([`\'"]?[\s;,].*$)/m'; $this->globalRules['replace'][] = '$1' . $defCharsetRegex . '$3' . $defCollateRegex . '$5'; $this->globalRules['search'][] = '/(^.*COLLATE\s*[\s=]\s*[`\'"]?)(' . - $invalidColRegex . ')([`\'"]?\s.*(?:CHARSET|CHARACTER SET)\s*[\s=]\s*[`\'"]?)([^`\'"\s;]+)([`\'"]?.*$)/m'; + $invalidColRegex . ')([`\'"]?\s.*(?:CHARSET|CHARACTER SET)\s*[\s=]\s*[`\'"]?)([^`\'"\s;,]+)([`\'"]?.*$)/m'; $this->globalRules['replace'][] = '$1' . $defCollateRegex . '$3' . $defCharsetRegex . '$5'; - $this->globalRules['search'][] = '/(^.*COLLATE\s*[\s=]\s*[`\'"]?)(' . $invalidColRegex . ')([`\'"]?[\s;].*$)/m'; + $this->globalRules['search'][] = '/(^.*COLLATE\s*[\s=]\s*[`\'"]?)(' . $invalidColRegex . ')([`\'"]?[\s;,].*$)/m'; $this->globalRules['replace'][] = '$1' . $defCollateRegex . '$3'; $this->generatorLog .= "GLOBAL RULES ADDED: INVALID COLLATIONS\n"; @@ -213,9 +214,9 @@ public function legacyCharsetAndCollation() } /** - * return search and replace table prefix rules + * Set search and replace table prefix rules * - * @return array + * @return void */ protected function rulesTableNames() { diff --git a/installer/dup-installer/src/Core/Params/Descriptors/ParamDescEngines.php b/installer/dup-installer/src/Core/Params/Descriptors/ParamDescEngines.php index 229440bd..93a2f84f 100644 --- a/installer/dup-installer/src/Core/Params/Descriptors/ParamDescEngines.php +++ b/installer/dup-installer/src/Core/Params/Descriptors/ParamDescEngines.php @@ -18,12 +18,15 @@ use Duplicator\Installer\Core\Params\Items\ParamForm; use Duplicator\Installer\Core\Params\Items\ParamOption; use DUPX_InstallerState; +use DUPX_ArchiveConfig; /** * class where all parameters are initialized. Used by the param manager */ final class ParamDescEngines implements DescriptorInterface { + const AUTO_SKIP_PATH_REPLACE_LIST = ['', '/html']; + /** * Init params * @@ -241,7 +244,7 @@ public static function init(&$params) PrmMng::PARAM_DB_CHUNK, ParamForm::TYPE_BOOL, array( - 'default' => ($params[PrmMng::PARAM_DB_ENGINE]->getValue() === \DUPX_DBInstall::ENGINE_CHUNK) + 'default' => ($params[PrmMng::PARAM_DB_ENGINE]->getValue() === \DUPX_DBInstall::ENGINE_CHUNK) ) ); @@ -257,11 +260,25 @@ public static function init(&$params) )) ); - $params[PrmMng::PARAM_SKIP_PATH_REPLACE] = new ParamItem( + $oldHomePath = DUPX_ArchiveConfig::getInstance()->getRealValue('archivePaths')->home; + $params[PrmMng::PARAM_SKIP_PATH_REPLACE] = new ParamForm( PrmMng::PARAM_SKIP_PATH_REPLACE, ParamForm::TYPE_BOOL, + ParamForm::FORM_TYPE_CHECKBOX, + array( + 'default' => in_array($oldHomePath, self::AUTO_SKIP_PATH_REPLACE_LIST) + ), array( - 'default' => false + 'label' => 'Skip Path Replace:', + 'checkboxLabel' => 'Skips the replacement of the source path', + 'status' => function (ParamForm $paramObj) { + $sourcePath = PrmMng::getInstance()->getValue(PrmMng::PARAM_PATH_OLD); + if (strlen($sourcePath) == 0) { + return ParamForm::STATUS_DISABLED; + } else { + return ParamForm::STATUS_ENABLED; + } + } ) ); } @@ -282,12 +299,6 @@ public static function updateParamsAfterOverwrite($params) $params[PrmMng::PARAM_ARCHIVE_ACTION]->setValue(DUP_Extraction::ACTION_REMOVE_WP_FILES); } - if ($params[PrmMng::PARAM_SKIP_PATH_REPLACE]->getStatus() !== ParamItem::STATUS_OVERWRITE) { - if (strlen($params[PrmMng::PARAM_PATH_OLD]->getValue()) === 0) { - $params[PrmMng::PARAM_SKIP_PATH_REPLACE]->setValue(true); - } - } - if (DUPX_InstallerState::isRestoreBackup($params[PrmMng::PARAM_INST_TYPE]->getValue())) { $default = \DUPX_S3_Funcs::MODE_SKIP; } elseif ($params[PrmMng::PARAM_DB_ENGINE]->getValue() === \DUPX_DBInstall::ENGINE_CHUNK) { @@ -412,14 +423,14 @@ function () { ); } - if ($zipEnable) { + if ($manualEnable) { + $default = DUP_Extraction::ENGINE_MANUAL; + } elseif ($zipEnable) { $default = DUP_Extraction::ENGINE_ZIP_CHUNK; } elseif ($shellZipEnable) { $default = DUP_Extraction::ENGINE_ZIP_SHELL; } elseif ($dupEnable) { $default = DUP_Extraction::ENGINE_DUP; - } elseif ($manualEnable) { - $default = DUP_Extraction::ENGINE_MANUAL; } else { $default = null; } diff --git a/installer/dup-installer/src/Core/Params/Descriptors/ParamDescGeneric.php b/installer/dup-installer/src/Core/Params/Descriptors/ParamDescGeneric.php index 69e3c728..d4345cc8 100644 --- a/installer/dup-installer/src/Core/Params/Descriptors/ParamDescGeneric.php +++ b/installer/dup-installer/src/Core/Params/Descriptors/ParamDescGeneric.php @@ -19,6 +19,7 @@ use Duplicator\Installer\Core\Params\Items\ParamFormPass; use Duplicator\Installer\Utils\Log\Log; use Duplicator\Libs\Snap\SnapOS; +use DUPX_ArchiveConfig; use DUPX_InstallerState; /** @@ -149,10 +150,24 @@ public static function init(&$params) ), array( 'label' => 'File Times:', + 'status' => function (ParamItem $paramObj) { + if (DUPX_ArchiveConfig::getInstance()->isZipArchive()) { + return ParamForm::STATUS_ENABLED; + } else { + return ParamForm::STATUS_DISABLED; + } + }, 'options' => array( new ParamOption('current', 'Current', ParamOption::OPT_ENABLED, array('title' => 'Set the files current date time to now')), new ParamOption('original', 'Original', ParamOption::OPT_ENABLED, array('title' => 'Keep the files date time the same')) - ) + ), + 'subNote' => function (ParamItem $paramObj) { + if (DUPX_ArchiveConfig::getInstance()->isZipArchive()) { + return ''; + } else { + return 'This option is not supported for Dup Archive (.daf)'; + } + } ) ); diff --git a/installer/dup-installer/src/Core/Params/Descriptors/ParamDescReplace.php b/installer/dup-installer/src/Core/Params/Descriptors/ParamDescReplace.php index 3914d848..3984da2b 100644 --- a/installer/dup-installer/src/Core/Params/Descriptors/ParamDescReplace.php +++ b/installer/dup-installer/src/Core/Params/Descriptors/ParamDescReplace.php @@ -107,7 +107,7 @@ public static function init(&$params) 'max' => 99, 'step' => 1, 'wrapperClasses' => array('small'), - 'label' => 'Serialized obj max size:', + 'label' => 'Serialized Max Size:', 'postfix' => array('type' => 'label', 'label' => 'MB'), 'subNote' => 'If the serialized object stored in the database exceeds this size, it will not be parsed for replacement.' . '
        Too large a size in low memory installations can generate a fatal error.' diff --git a/installer/dup-installer/src/Utils/Tests/MessageCustomizer.php b/installer/dup-installer/src/Utils/Tests/MessageCustomizer.php new file mode 100644 index 00000000..78dcf79f --- /dev/null +++ b/installer/dup-installer/src/Utils/Tests/MessageCustomizer.php @@ -0,0 +1,199 @@ +conditionSatisfied($longMessage)) { + $shortMessage = $item->apply($shortMessage, self::CONTEXT_SHORT_MESSAGE); + $longMessage = $item->apply($longMessage, self::CONTEXT_LONG_MESSAGE); + $noticeId = $item->apply($noticeId, self::CONTEXT_NOTICE_ID); + return true; + } + } + + return false; + } + + /** + * Get customization to apply at error messages + * + * @return MessageCustomizerItem[] customizations list + * @throws \Exception + */ + protected static function getCustomizationItems() + { + $items = array(); + $items[] = new MessageCustomizerItem( + function ($string) { + if (self::getArchiveConfigData() == false) { + return false; + } + return preg_match("/undefined.*create_function/", $string) && + version_compare(phpversion(), "8") >= 0 && + version_compare(self::getArchiveConfigData()->version_php, "8") < 0; + }, + function ($string, $context) { + if (self::getArchiveConfigData() == false) { + return $string; + } + $phpVersionNew = self::getTwoLevelVersion(phpversion()); + $phpVersionOld = self::getTwoLevelVersion(self::getArchiveConfigData()->version_php); + $longMsgPrefix = "There is code in this site that is not compatible with PHP " . $phpVersionNew . ". " . + "To make the install work you will either have to\ninstall on PHP " . + $phpVersionOld . " or "; + + switch ($context) { + case self::CONTEXT_SHORT_MESSAGE: + return "Source site or plugins are incompatible with PHP " . $phpVersionNew; + case self::CONTEXT_LONG_MESSAGE: + if (($plugin = self::getProblematicPluginFromError($string)) !== false) { + return $longMsgPrefix . "disable the plugin '{$plugin->name}' (slug: $plugin->slug) using a " . + "file manager of your choice.\nSee full error message below: \n\n" . $string; + } elseif (($theme = self::getProblematicThemeFromError($string)) !== false) { + return $longMsgPrefix . "disable the theme '{$theme->themeName}' (slug: $theme->slug) using a " . + "file manager of your choice.\nSee full error message below: \n\n" . $string; + } else { + return $longMsgPrefix . "manually modify the affected files mentioned in the error trace below: \n\n" . + $string; + } + case self::CONTEXT_NOTICE_ID: + return $string . '_php8'; + } + } + ); + + return $items; + } + + /** + * Return the plugin that is causing the error message if present + * + * @param string $longMessage the long error message containing the error trace + * + * @return false|object object containing plugin info or false on failure + */ + protected static function getProblematicPluginFromError($longMessage) + { + if (($archiveConfig = self::getArchiveConfigData()) === false) { + return false; + } + $oldMain = $archiveConfig->wpInfo->targetRoot; + $oldMuPlugins = $archiveConfig->wpInfo->configs->realValues->originalPaths->muplugins; + $oldPlugins = $archiveConfig->wpInfo->configs->realValues->originalPaths->plugins; + $relativeMuPlugins = str_replace($oldMain, "", $oldMuPlugins); + $relativePlugins = str_replace($oldMain, "", $oldPlugins); + $regex = "/(?:" . preg_quote($relativePlugins, "/") . "\/|" . preg_quote($relativeMuPlugins, "/") . "\/)(.*?)(\/|\.php).*$/m"; + if (!preg_match($regex, $longMessage, $matches)) { + return false; + } + + //matches the first part of the slug related to the plugin directory + $slug = $matches[1]; + foreach ($archiveConfig->wpInfo->plugins as $plugin) { + if (strpos($plugin->slug, $slug) === 0) { + return $plugin; + } + } + + return false; + } + + /** + * Returns the theme that is causing the error message if present + * + * @param string $longMessage the long error message containing the error trace + * + * @return false|object object containing theme info or false + */ + protected static function getProblematicThemeFromError($longMessage) + { + $archiveConfig = self::getArchiveConfigData(); + $oldMain = $archiveConfig->wpInfo->targetRoot; + $oldThemes = $archiveConfig->wpInfo->configs->realValues->originalPaths->themes; + $relativeThemes = str_replace($oldMain, "", $oldThemes); + + file_put_contents( + DUPX_INIT . "/my_log.txt", + "OLD THEMES: {$oldThemes} \n" . + "Relative themes: {$relativeThemes} \n" . + "regex: " . "/(" . preg_quote($relativeThemes, "/") . "\/)(.*?)(\/|\.php).*$/m" + ); + + if (!preg_match("/(?:" . preg_quote($relativeThemes, "/") . "\/)(.*?)(?:\/|\.php).*$/m", $longMessage, $matches)) { + return false; + } + + $slug = $matches[1]; + foreach ($archiveConfig->wpInfo->themes as $theme) { + if ($theme->slug == $slug) { + return $theme; + } + } + + return false; + } + + /** + * Get package config data + * + * @return false|object package config data or false on failure + */ + protected static function getArchiveConfigData() + { + static $archiveConfig = null; + if (is_null($archiveConfig)) { + if ( + ($path = glob(DUPX_INIT . "/dup-archive__*.txt")) === false || + count($path) !== 1 + ) { + return $archiveConfig = false; + } + + if (($json = file_get_contents($path[0])) === false) { + return $archiveConfig = false; + } + + $archiveConfig = json_decode($json); + if (!is_object($archiveConfig)) { + $archiveConfig = false; + } + } + return $archiveConfig; + } + + /** + * @param string $version a version number + * @return string returns only the first 2 levels of the version numbers + */ + private static function getTwoLevelVersion($version) + { + $arr = explode(".", $version); + return $arr[0] . "." . $arr[1]; + } +} diff --git a/installer/dup-installer/src/Utils/Tests/MessageCustomizerItem.php b/installer/dup-installer/src/Utils/Tests/MessageCustomizerItem.php new file mode 100644 index 00000000..3277d752 --- /dev/null +++ b/installer/dup-installer/src/Utils/Tests/MessageCustomizerItem.php @@ -0,0 +1,45 @@ +checkCallback = $checkCallback; + + if (!is_callable($applyCallback)) { + throw new \Exception("customization callback must be callable"); + } + $this->applyCallback = $applyCallback; + } + + /** + * @param mixed $input necessary input to check condition + * @return bool + */ + public function conditionSatisfied($input) + { + return (is_bool($this->checkCallback) && $this->checkCallback) || call_user_func($this->checkCallback, $input); + } + + /** + * @param string $string string to be customized + * @param mixed $context context about what to apply + * @return false|mixed + */ + public function apply($string, $context) + { + return call_user_func($this->applyCallback, $string, $context); + } +} diff --git a/installer/dup-installer/src/Utils/Tests/TestInterface.php b/installer/dup-installer/src/Utils/Tests/TestInterface.php new file mode 100644 index 00000000..61e91eee --- /dev/null +++ b/installer/dup-installer/src/Utils/Tests/TestInterface.php @@ -0,0 +1,16 @@ + self::getErrorCategoryFromErrno($errno), + 'errno' => $errno, + 'errno_str' => self::errnoToString($errno), + 'errstr' => $errstr, + 'errfile' => $errfile, + 'errline' => $errline, + 'trace' => array_map(array(__CLASS__, 'normalizeTraceElement'), $trace) + ); + + self::$errors[] = $newError; + + if (function_exists('error_clear_last')) { + error_clear_last(); + } + } + + /** + * @param array $error the error array + * @return string human-readable error message with trace + */ + public static function errorToString($error) + { + $result = $error['errno_str'] . ' ' . $error['errstr'] . "\n"; + $result .= "\t" . 'FILE: ' . $error['errfile'] . '[' . $error['errline'] . ']' . "\n"; + $result .= "\t--- TRACE ---\n"; + foreach ($error['trace'] as $trace) { + $result .= "\t"; + if (!empty($trace['class'])) { + $result .= str_pad('CLASS___: ' . $trace['class'] . $trace['type'] . $trace['function'], 40, ' '); + } else { + $result .= str_pad('FUNCTION: ' . $trace['function'], 40, ' '); + } + $result .= 'FILE: ' . $trace['file'] . '[' . $trace['line'] . ']' . "\n"; + } + + return $result; + } + + /** + * 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) + { + $trace = debug_backtrace(); + array_shift($trace); + self::adderror($errno, $errstr, $errfile, $errline, $trace); + } + + /** + * Exception handler + * + * @param Exception|Error $e // Throwable in php 7 + * @return void + */ + public static function exception($e) + { + self::adderror(self::ERRNO_EXCEPTION, $e->getMessage(), $e->getFile(), $e->getLine(), $e->getTrace()); + } + + /** + * Shutdown handler + * + * @return void + */ + public static function shutdown() + { + self::obCleanAll(); + + if (($error = error_get_last())) { + self::error($error['type'], $error['message'], $error['file'], $error['line']); + } + ob_end_clean(); + + if (is_callable(self::$shutdownCallback)) { + call_user_func(self::$shutdownCallback, self::$errors); + } else { + echo json_encode(self::$errors); + } + + // prevent other shutdown functions + exit(); + } + + /** + * Close all buffers and return content + * + * @param bool $getContent If true it returns buffer content, otherwise it is discarded + * + * @return string + */ + protected static function obCleanAll($getContent = true) + { + $result = ''; + for ($i = 0; $i < ob_get_level(); $i++) { + if ($getContent) { + $result .= ob_get_contents(); + } + ob_clean(); + } + return $result; + } + + /** + * @param array $elem normalize error element + * @return array + */ + public static function normalizeTraceElement($elem) + { + if (!is_array($elem)) { + $elem = array(); + } + + unset($elem['args']); + unset($elem['object']); + + return array_merge(array( + 'file' => '', + 'line' => -1, + 'function' => '', + 'class' => '', + 'type' => ''), $elem); + } + + /** + * + * @param int $errno error number + * @return string + */ + public static function getErrorCategoryFromErrno($errno) + { + switch ($errno) { + case E_PARSE: + case E_ERROR: + case E_CORE_ERROR: + case E_COMPILE_ERROR: + case E_USER_ERROR: + case self::ERRNO_EXCEPTION: + return self::ERR_TYPE_ERROR; + case E_WARNING: + case E_USER_WARNING: + case E_COMPILE_WARNING: + return self::ERR_TYPE_WARNING; + case E_NOTICE: + case E_USER_NOTICE: + return self::ERR_TYPE_NOTICE; + default: + break; + } + if (defined('E_STRICT') && $errno === E_STRICT) { + return self::ERR_TYPE_WARNING; + } + if (defined('E_RECOVERABLE_ERROR') && $errno === E_RECOVERABLE_ERROR) { + return self::ERR_TYPE_WARNING; + } + if (defined('E_DEPRECATED') && $errno === E_DEPRECATED) { + return self::ERR_TYPE_DEPRECATED; + } + if (defined('E_USER_DEPRECATED') && $errno === E_USER_DEPRECATED) { + return self::ERR_TYPE_DEPRECATED; + } + return self::ERR_TYPE_WARNING; + } + + /** + * + * @param int $errno error number + * @return string + */ + public static function errnoToString($errno) + { + switch ($errno) { + case E_PARSE: + return 'E_PARSE'; + case E_ERROR: + return 'E_ERROR'; + case E_CORE_ERROR: + return 'E_CORE_ERROR'; + case E_COMPILE_ERROR: + return 'E_COMPILE_ERROR'; + case E_USER_ERROR: + return 'E_USER_ERROR'; + case E_WARNING: + return 'E_WARNING'; + case E_USER_WARNING: + return 'E_USER_WARNING'; + case E_COMPILE_WARNING: + return 'E_COMPILE_WARNING'; + case E_NOTICE: + return 'E_NOTICE'; + case E_USER_NOTICE: + return 'E_USER_NOTICE'; + case self::ERRNO_EXCEPTION: + return 'EXCEPTION'; + default: + break; + } + if (defined('E_STRICT') && $errno === E_STRICT) { + return 'E_STRICT'; + } + if (defined('E_RECOVERABLE_ERROR') && $errno === E_RECOVERABLE_ERROR) { + return 'E_RECOVERABLE_ERROR'; + } + if (defined('E_DEPRECATED') && $errno === E_DEPRECATED) { + return 'E_DEPRECATED'; + } + if (defined('E_USER_DEPRECATED') && $errno === E_USER_DEPRECATED) { + return 'E_USER_DEPRECATED'; + } + return 'E_UNKNOWN CODE: ' . $errno; + } +} diff --git a/installer/dup-installer/src/Utils/Tests/WP/TestsExecuter.php b/installer/dup-installer/src/Utils/Tests/WP/TestsExecuter.php new file mode 100644 index 00000000..bd50bec8 --- /dev/null +++ b/installer/dup-installer/src/Utils/Tests/WP/TestsExecuter.php @@ -0,0 +1,149 @@ +addFinalReportNotice(array( + 'shortMsg' => 'Can\'t create final text script file', + 'longMsg' => 'Can\'t create file ' . $scriptFilePath, + 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_DEFAULT, + 'level' => DUPX_NOTICE_ITEM::HARD_WARNING, + 'sections' => array('general'), + )); + + return false; + } + + return true; + } + + /** + * @return bool true on success + * @throws \Exception + */ + public static function afterTestClean() + { + $nManager = DUPX_NOTICE_MANAGER::getInstance(); + $scriptFilePath = self::getScriptTestPath(); + Log::info('DELETE FILE AFTER TEST: ' . $scriptFilePath, Log::LV_DETAILED); + if (file_exists($scriptFilePath)) { + if (unlink($scriptFilePath) == false) { + $nManager->addFinalReportNotice(array( + 'shortMsg' => 'Can\'t deleta final text script file', + 'longMsg' => 'Can\'t delete file ' . $scriptFilePath . '. Remove it manually', + 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_DEFAULT, + 'level' => DUPX_NOTICE_ITEM::HARD_WARNING, + 'sections' => array('general'), + )); + } + } + + return true; + } + + /** + * @return string url of WP front-end + * @throws \Exception + */ + public static function getFrontendUrl() + { + $indexPath = PrmMng::getInstance()->getValue(PrmMng::PARAM_PATH_NEW) . '/index.php'; + $data = array( + self::SCRIPT_NAME_HTTP_PARAM => $indexPath + ); + + return self::getScriptTestUrl() . '?' . http_build_query($data); + } + + /** + * @return string url of WP back-end + * @throws \Exception + */ + public static function getBackendUrl() + { + $indexPath = PrmMng::getInstance()->getValue(PrmMng::PARAM_PATH_WP_CORE_NEW) . '/wp-login.php'; + $data = array( + self::SCRIPT_NAME_HTTP_PARAM => $indexPath + ); + + return self::getScriptTestUrl() . '?' . http_build_query($data); + } + + /** + * @return string test script name + */ + protected static function getScriptTestName() + { + return 'wp_test_script_' . DUPX_Security::getInstance()->getSecondaryPackageHash() . '.php'; + } + + /** + * @return string test script path + * @throws \Exception + */ + public static function getScriptTestPath() + { + // use wp-content path and not root path + return PrmMng::getInstance()->getValue(PrmMng::PARAM_PATH_CONTENT_NEW) . '/' . self::getScriptTestName(); + } + + /** + * @return string test script url + * @throws \Exception + */ + public static function getScriptTestUrl() + { + // use wp-content path and not root path + return PrmMng::getInstance()->getValue(PrmMng::PARAM_URL_CONTENT_NEW) . '/' . self::getScriptTestName(); + } + + /** + * @return string contents to be added to the test script file + */ + public static function getExecFileContent() + { + $result = file_get_contents(dirname(__FILE__) . '/tests_template.php'); + $result = preg_replace('/^.*\[REMOVE LINE BY SCRIPT].*\n/m', '', $result); // remove first line with die + return str_replace( + array( + '$_$_NOTICES_FILE_PATH_$_$', + '$_$_DUPX_INIT_$_$' + ), + array( + $GLOBALS["NOTICES_FILE_PATH"], + DUPX_INIT + ), + $result + ); + } +} diff --git a/installer/dup-installer/src/Utils/Tests/WP/tests_template.php b/installer/dup-installer/src/Utils/Tests/WP/tests_template.php new file mode 100644 index 00000000..9fee09b5 --- /dev/null +++ b/installer/dup-installer/src/Utils/Tests/WP/tests_template.php @@ -0,0 +1,121 @@ + $shortMessage, + 'level' => $errorLevel, + 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_PRE, + 'longMsg' => $longMessage, + 'sections' => 'general' + ); + if ($errorLevel == DUPX_NOTICE_ITEM::FATAL) { + $nManager->addBothNextAndFinalReportNotice($data, DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, $noticeId); + } else { + $nManager->addFinalReportNotice($data, DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, $noticeId); + } + } + + if ($nManager->saveNotices()) { + echo json_encode(true); + } else { + echo json_encode(false); + } +}); + +$_SERVER['REQUEST_URI'] = '/'; +if (file_exists($GLOBALS["TEST_SCRIPT"])) { + require_once($GLOBALS["TEST_SCRIPT"]); +} else { + throw new Exception('test script file ' . $GLOBALS["TEST_SCRIPT"] . ' doesn\'t exist'); +} diff --git a/installer/dup-installer/templates/default/pages-parts/help/steps/step-3.php b/installer/dup-installer/templates/default/pages-parts/help/steps/step-3.php index 299421f0..96646023 100644 --- a/installer/dup-installer/templates/default/pages-parts/help/steps/step-3.php +++ b/installer/dup-installer/templates/default/pages-parts/help/steps/step-3.php @@ -57,6 +57,23 @@ It is recommended that this remain enabled so that you do not have unwanted schedules and storage options. + + Skip Path
        Replace + + This is an advanced option that should be used when trying to install from either the "/" or "/html" location. The following + conditions are set with this option when the install location is detected. +
          +
        • Source folder is / the parameter should be visible in read-only mode and not checkable.
        • +
        • Source folder is /html the parameter must be check by default and kept checked.
        • +
        • In other cases, the parameter must be inactive by default and checkable.
        • +
        + + This option helps to resolve issues when the install path is either "/" or "/html". In case the source path is /html this option + is required to prevent data update conflicts. For example the html_type option in the wp_options table with data such as + text/html is replaced with text/[new_path] which can lead to other issues therefore this option is required to be checked to + prevent those types of database update issues. + + Email
        Domains The domain portion of all email addresses will be updated if this option is enabled. @@ -94,7 +111,7 @@ - Serialized obj
        max size + Serialized
        Max Size Large serialized objects can cause a fatal error when Duplicator attempts to transform them.
        If a fatal error is generated, lower this limit.
        diff --git a/installer/dup-installer/templates/default/pages-parts/help/steps/step1-parts/advanced-step1-options.php b/installer/dup-installer/templates/default/pages-parts/help/steps/step1-parts/advanced-step1-options.php index 3470e845..81cf9206 100644 --- a/installer/dup-installer/templates/default/pages-parts/help/steps/step1-parts/advanced-step1-options.php +++ b/installer/dup-installer/templates/default/pages-parts/help/steps/step1-parts/advanced-step1-options.php @@ -84,8 +84,19 @@ Pro Remove all files except add-on sites and extract
        - All files except an add-on site will be removed, and then the archive will be extracted. -
        + All files except an add-on site will be removed, and then the archive will be extracted. An add-on site is a site/domain that is stored in a + directory off of your main site that has been "added on" to your main hosting account. For instance, when you purchased a hosting account it + could be for a.com. Then after that, you decided to add b.com and c.com to the same hosting account. The structure of this setup is often the + following although it can vary some: + +
          +
        • /public_html - contains files for a.com
        • +
        • /public_html/b.com - contains files for b.com
        • +
        • /public_html/c.com - contains files for c.com
        • +
        + + The directories /public_html/b.com and c.com contain the files for the add-on sites b.com and c.com (so the option above means that b.com and c.com + would be preserved and not deleted when you installed to a.com) @@ -116,6 +127,7 @@ When the archive is extracted it should show the current date-time or keep the original time it had when it was built. This setting will be applied to all files and directories. + Note: Setting the Original time is currently only supported when using the ZipArchive Format. diff --git a/installer/dup-installer/templates/default/pages-parts/help/steps/step1-parts/basic-step1-setup.php b/installer/dup-installer/templates/default/pages-parts/help/steps/step1-parts/basic-step1-setup.php index eb87936c..ecdfe8ba 100644 --- a/installer/dup-installer/templates/default/pages-parts/help/steps/step1-parts/basic-step1-setup.php +++ b/installer/dup-installer/templates/default/pages-parts/help/steps/step1-parts/basic-step1-setup.php @@ -4,14 +4,36 @@ use Duplicator\Installer\Utils\Utils; ?> +If no passwords were set on the installer or archive file then users will initially see step one of the installer. The installer has two operating views +that can be toggled via the Basic and Advanced buttons in the right-hand corner of the application. These installer views can only be chosen on step 1. +An overview of each view is explained below. +

        + + Views: +
          +
        • + Basic: + This is a simple two-step mode with all options set to the defaults. This is the default mode. The Basic view is the easiest and fastest and + covers most setup types. This is the recommended view for most installs. +
        • +
        • + Advanced: + This four-step mode allows for higher levels of customization with various detail settings. The Advanced view allows users to implement and apply + additional settings/features to the install process.
          + This is the only mode that Duplicator supported before version 1.5 +
        • +
        +

        Overview

        -The overview section allows users to identify the install type and other details about the archive file. The installer has two operating modes: Basic and -Advanced. Basic mode is the easiest and fastest install mode and covers most setup types. The Advanced mode allows users to implement and apply -additional settings/features to the install process. -

        -Note: Duplicator Lite supports only single WordPress sites, while " target="_blank">Duplicator Pro supports single and multisite websites. +The overview section allows users to identify the status, mode and select from the install type based on the user's install status. Additionally there are +other details about the archive file. Below is an overview of the various status, mode and install types.
        + + + Note: Duplicator Lite supports only single WordPress sites, while + " target="_blank">Duplicator Pro supports single and multisite websites. +

        @@ -21,21 +43,54 @@ This section will give an overview of the various install modes, methods and types that are currently being used.

        - Mode: + Status:
        • - Basic: - This is a simple two-step mode with all options set to the defaults. This is the default mode. + Install - Single Site
          + This will perform the installation of a single WordPress site based on the associated method.
        • - Advanced: - This four-step mode allows for higher levels of customization with various detail settings.
          - This is the only mode that Duplicator supported before version 1.5 + Pro + Install - Multisite-Subdomain:
          + This is a full Multisite installation subdomain (i.e. subdomain.mysite.com) install. All sites in the network will be extracted and installed. +
        • +
        • + Pro + Install - Multisite-Subfolder:
          + This is a full Multisite installation via sub-folders install. All sites in the network will be extracted and installed. +
        • +
        • + Pro + Install - Standalone Site:
          + This installation converts the selected subsite into a standalone website. +
        • +
        • + Pro + Install - Archive Single Site into Subdomain/Subfolder Multisite:
          + This installation will insert the package site into the current multisite subdomain/subfolder setup. +
        • +
        • + Pro + Install - Selected Subsite in Subdomain/Subfolder Multisite:
          + This installation will insert the selected subsite of the package into the current subdomain/subfolder multisite installation. +
        • +
        • + Pro + Recovery - [Site Type]:
          + This status is enabled when the installer detects recovery mode installer was launched. This process will overwrite this site from the recovery + point made on a specific date. The site type will represent the type of site being recovered. +
        • +
        • + Pro + Restore Site Backup:
          + This method is enabled when the installer detects an archive is imported that matches the current setup. The restore backup status restores the + original site by not performing any processing on the database or tables to ensure an exact copy of the original site exists. Restore has the + following status types: Restore: Single Site Backup, Restore - Multisite-Subdomain Backup, Restore - Multisite-Subfolder Backup
        - Method: + Mode:
        • Standard Install @@ -72,18 +127,13 @@
        • Method is enabled when the installer detects an existing WordPress site is present.
        - - - Status: -
        • - Standard Site Setup: - This will perform the installation of a single WordPress site based on the associated method. -
        • -
        • - Restore Site Backup: - The restore backup status restores the original site by not performing any processing on the database or tables to ensure an exact copy - of the original site, exists. + Pro + Custom Install
          +
            +
          • When the mode is custom this indicates the install is specifically driven by the status type.
          • +
          • See the status type of the install for all exact install details.
          • +
        @@ -100,7 +150,7 @@ Archive Tab

        -The archive tab shows various details about the archive file and site details related to the site that was archived. With Duplicator Lite the following +The archive tab shows various details about the archive file and site details related to the site that was archived. With Duplicator the following install modes are currently supported: