diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..3e70515
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,177 @@
+
+ Apache License
+ Version 2.0, January 2004
+ https://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..821b8c4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,4 @@
+OpenSSL Installers/Packagers
+============================
+
+Binary packaging / installers, where such are otherwise lacking.
diff --git a/ms-windows/.gitignore b/ms-windows/.gitignore
new file mode 100644
index 0000000..9d2d90b
--- /dev/null
+++ b/ms-windows/.gitignore
@@ -0,0 +1,2 @@
+temp/*
+versions/*
diff --git a/ms-windows/README.md b/ms-windows/README.md
new file mode 100644
index 0000000..ef1db92
--- /dev/null
+++ b/ms-windows/README.md
@@ -0,0 +1,134 @@
+OpenSSL Installer Build Tools For Windows
+=========================================
+
+This packager prepares binary builds of OpenSSL for the Microsoft Windows operating system and encapsulates the generated files within EXE and MSI installers suitable for distribution.
+
+Basic Setup
+-----------
+
+To perform builds efficiently, a relatively recent desktop class Intel/AMD CPU with at least 8 performance cores is strongly recommended to build all supported versions and architectures simultaneously. At least 15GB of free disk storage should be available as well.
+
+On a Windows computer (or virtual machine), install Visual C++ components from both Microsoft Visual Studio 2017 and Microsoft Visual Studio 2019. During the installation process, be sure to select "MSVC ... ARM64" from the optional items under "Desktop development with C++" to be able to build for arm64. Also be sure to install at least one Windows SDK.
+
+The scripts here are written in the PHP scripting language. Obtain a "Thread Safe" build of PHP for Windows from [windows.php.net](https://windows.php.net/download/). The 'zlib', 'zip', and 'openssl' extensions need to be enabled.
+
+Obtain a copy of this repository. Avoid putting the repository into a directory structure with paths that have spaces in them. Some tools have difficulties with spaces. The various paths also get quite long, so the closer to the root of a drive that this repository sits on the machine, the less likely that limitations in Windows itself will be encountered.
+
+Running Build Tools
+-------------------
+
+The main 'build-tools.php' script performs all of the work to download required dependencies (Perl, NASM, Inno Setup, Wix toolset) from HTTPS enabled websites (hence why the 'openssl' extension in PHP is required to build OpenSSL), validate environments, download, validate and extract OpenSSL release tarballs, run `perl Configure` and `nmake`, and run Inno Setup and Wix toolset.
+
+Inno Setup is an installer builder. It intakes a plain text .iss script file (INI-like) and outputs an EXE that installs bundled files into locations specified by the aforementioned .iss script. It supports custom code via a Pascal-like language. Wix toolset is another installer builder. It intakes a plain text .wxs file (XML) and outputs a MSI. For this project, Wix toolset is used to wrap the EXEs output by Inno Setup in a MSI. MSI is used by mass deployment tools (SCCM/GPO) to deploy applications to large organizations. Some people prefer EXE installers while others prefer MSI while others want a portable ZIP file.
+
+Avoid moving or renaming parent directories after running the build tools script. It is easier to just start from a completely fresh copy of this repository if you need to move or rename parent folders. A number of paths get mapped to the current directory structure during the initialization/preparation and build process and will probably result in errors if the parent directories are moved or renamed.
+
+From a Command Prompt, run:
+
+```
+php build-tools.php -?
+```
+
+To get basic help output from the tool.
+
+Running:
+
+```
+php build-tools.php
+```
+
+Provides an interactive guided interface. All build tools operations aim to be idempotent and repeatable across multiple machines.
+
+Within the 'templates' subdirectory of this repository are the currently supported base versions. To setup a base version, it must first be initialized. For example, initializing OpenSSL 3.1.x begins with:
+
+```
+php build-tools.php init 3.1
+```
+
+This will create several directories and download, validate, and extract/setup the dependencies that are defined in 'templates/3.1/info.json'. During "installation" of Inno Setup 5, an Administrator UAC elevation prompt will appear despite being told to not do that in the options passed to it and it doesn't actually get formally installed on the system (i.e. no registry entries for Add/Remove Programs). All the other dependencies do not require Administrator elevation.
+
+The next step is to create base version environment profiles for your system. Start a Visual Studio Command Prompt for x86, x64, and ARM64. Run 'cl.exe' to confirm that the correct Visual C++ compiler is running. The "Cross Tools" flavors follow the nomenclature of "local_target" (e.g. x64_ARM64 = local machine architecture => target).
+
+Each base version has a preferred version of the Visual C++ compiler but the only actual requirement is that the target architecture matches.
+
+Within each Visual Studio Command Prompt, run the relevant line that matches:
+
+```
+php build-tools.php save-profile 3.1 x86
+php build-tools.php save-profile 3.1 x64
+php build-tools.php save-profile 3.1 arm64
+```
+
+The "save-profile" will run all validations against the environment. If they all pass, the environment is saved to the 'versions/3.1/profiles' directory.
+
+Close the Visual Studio Command Prompts. You won't need them again for that base version.
+
+The above steps only need to be performed one time per base version on a system.
+
+Building OpenSSL
+----------------
+
+Now it is time to build OpenSSL and prepare packaged installers. Preparing to build and package OpenSSL v3.1.0, for example, is accomplished via:
+
+```
+php build-tools.php prepare 3.1.0
+```
+
+Of course, replace the specific version according to what needs to be built. That will download the source tarball, verify and extract it, and also prepare Inno Setup and Wix toolset installer scripts from 'templates/3.1' for each architecture and place them into the 'versions/3.1/3.1.0/installers' subdirectory.
+
+Now comes the fun part...building 6 flavors of OpenSSL (/MD, /MDd, /MT, /MTd + two static variants) and producing 4 different installers (two EXEs and two MSIs) per architecture:
+
+```
+php build-tools.php build-all 3.1.0
+```
+
+That will run builds for all configured architectures simultaneously using the saved environment profiles for the base version. This is where approximately one core of a CPU per architecture is required. To concurrently build and package multiple versions for all configured architectures:
+
+```
+php build-tools.php build-all 1.1.1t 3.0.8 3.1.0
+```
+
+Concurrently building all supported base versions for all architectures currently requires approximately 8 CPU cores, 15GB of disk storage, and over 40 minutes of patient waiting.
+
+When a build finishes, the generated installers will be located in the final Output subdirectory for the specific version and architecture installer (e.g. 'versions/3.1/3.1.0/installers/x86/final/Output').
+
+The 'build-all' command also builds two portable flavors that combines all architectures. One ZIP file only contains essentials like executables and DLLs (about 12MB compressed) while the other includes all compiled libraries designed for Visual C++ developers (about 140MB compressed).
+
+Debugging/Troubleshooting
+-------------------------
+
+The build tools script is designed to capture and log errors and output. Logged output can appear in both 'temp/logs' and 'versions' build output broken down by specific version and architecture (e.g. 'versions/3.1/3.1.0/out_x86/logs').
+
+In general, two log files are generated when the build tool runs an external program like 'nmake': One file for stdout and the other for stderr. This keeps noise on the command line to a minimum but makes it slightly more difficult to diagnose problems. Usually the last few lines of the error log will have the error message details while the other log file will show the relevant last bits of information from the command that were output before the error occurred.
+
+If nothing shows up in the log files, then it is probably environment related and most likely something on the system Path environment variable in the saved environment profile. Windows applications frequently modify the system Path. Look at the JSON files in the 'profiles' subdirectory in the base version (e.g. 'versions/3.1/profiles/x86.json') to see if the Path can be cleaned up by removing extraneous application references. Manually adjusting the Path in those JSON files won't impact the system but could implicitly get rid of conflicting software (e.g. DLLs) that Windows might be picking up during the build process but were not detected during the various validation phases.
+
+The base version 'init' will probably break if dependencies vanish from their source URLs. The locations in the base version JSON files will need to be updated to point at new URLs.
+
+Directory Structure
+-------------------
+
+This directory structure layout, relative to this directory, should help with understanding the output of each major step (init, save-profile, prepare, build/build-all):
+
+* /templates - Main base version JSON and templated Inno Setup and Wix toolset scripts. The base version JSON files drive the entire process to produce consistent results.
+* /versions/3.1/deps - Verified binary dependencies. Required to build and package OpenSSL. Output of 'init'.
+* /versions/3.1/profiles - Stores and preserves environment variables in architecture and system-dependent JSON files. Output of 'save-profile'.
+* /versions/3.1/3.1.0/source - Extracted source code tree. Output of 'prepare'.
+* /versions/3.1/3.1.0/temp_ARCH - A temporary copy of the extracted source code tree to enable concurrent building of multiple architectures for a single version (e.g. temp_x86, temp_x64, temp_arm64). Used during 'build'.
+* /versions/3.1/3.1.0/out_ARCH - Build output for an architecture (e.g. out_x86, out_x64, out_arm64). Output of 'build'.
+* /versions/3.1/3.1.0/installers - Installer structure preparation location and final output. Output of 'build' and 'build-all'.
+
+Creating New Templates
+----------------------
+
+When a new base version is released (e.g. 3.2), the simplest approach to creating a new template is to copy the previous version's template and then make some adjustments to 'info.json' and various installer scripts. For official releases, the various dependencies should be updated to best reflect supported end-user OSes and architectures. The build tools script can be used to evaluate/validate all potential dependencies via 'init-test':
+
+```
+php build-tools.php init-test 3.2
+```
+
+That downloads and validates all dependencies for a base version, which checks all hashes against the hashes in the 'info.json' file. Obviously, changing dependencies can result in breakages, so thorough testing is necessary.
+
+Updating the version of Visual Studio may come with the additional requirement to modify the installer script templates to point at updated VC++ runtimes. The installer scripts are just plain text files with specially formatted codes embedded into them (e.g. `[[DOTTED_VERSION]]`) that get replaced during the 'prepare' pre-build phase. Changes to installer script templates propagate to specific versions when the 'prepare' pre-build phase is run.
+
+When new major versions are produced (e.g. `libssl-3.dll` to `libssl-4.dll`), then the Wix toolset scripts need new GUIDs to allow multiple versions of the OpenSSL DLLs to be installed on the same system.
diff --git a/ms-windows/build-tools.php b/ms-windows/build-tools.php
new file mode 100644
index 0000000..c6a72c4
--- /dev/null
+++ b/ms-windows/build-tools.php
@@ -0,0 +1,1564 @@
+ array(
+ "s" => "suppressoutput",
+ "?" => "help"
+ ),
+ "rules" => array(
+ "suppressoutput" => array("arg" => false),
+ "help" => array("arg" => false)
+ ),
+ "allow_opts_after_param" => false
+ );
+ $args = CLI::ParseCommandLine($options);
+
+ if (isset($args["opts"]["help"]))
+ {
+ echo "The OpenSSL tool to build/generate installer packages for Windows.\n";
+ echo "Purpose: Download and verify sources, build OpenSSL, and generate installers.\n";
+ echo "\n";
+ echo "A relatively recent Intel/AMD CPU with at least 8 performance cores is highly recommended plus several GB of available storage.\n";
+ echo "\n";
+ echo "This tool is question/answer enabled. Just running it will provide a guided interface. It can also be run entirely from the command-line if you know all the answers.\n";
+ echo "\n";
+ echo "Syntax: " . $args["file"] . " [options] [cmd [cmdoptions]]\n";
+ echo "Options:\n";
+ echo "\t-s Suppress most output. Useful for capturing JSON output.\n";
+ echo "\n";
+ echo "Examples:\n";
+ echo "\tphp " . $args["file"] . "\n";
+ echo "\tphp " . $args["file"] . " init 3.1\n";
+ echo "\tphp " . $args["file"] . " save-profile 3.1 x86\n";
+ echo "\tphp " . $args["file"] . " prepare 3.1.0\n";
+ echo "\tphp " . $args["file"] . " build-all 3.1.0\n";
+ echo "\tphp " . $args["file"] . " build-all 1.1.1t 3.0.8 3.1.0\n";
+
+ exit();
+ }
+
+ $origargs = $args;
+ $suppressoutput = (isset($args["opts"]["suppressoutput"]) && $args["opts"]["suppressoutput"]);
+
+ // Check critical dependencies.
+ $os = php_uname("s");
+ $windows = (strtoupper(substr($os, 0, 3)) == "WIN");
+
+ if (!$windows) CLI::DisplayError("This script currently only runs on Windows.");
+ if (!extension_loaded("zlib")) CLI::DisplayError("Please enable the 'zlib' extension in your system's 'php.ini' file. zlib is used by this tool to decompress .tar.gz and .zip files.");
+ if (!extension_loaded("zip")) CLI::DisplayError("Please enable the 'zip' extension in your system's 'php.ini' file. zip is used by this tool to decompress .zip files.");
+ if (!extension_loaded("openssl")) CLI::DisplayError("Please enable the 'openssl' extension in your system's 'php.ini' file. openssl is used by this tool to connect to servers to download source files and dependencies. Yes, this is weird.");
+
+ // Get the command.
+ $cmds = array(
+ "init" => "Initialize a specific base version from a template to download, verify, extract, and configure dependencies",
+ "init-test" => "Verify that all possible downloads for a base version are still working and have correct hashes",
+ "save-profile" => "Validate and save an environment profile for a specific base version and architecture",
+ "prepare" => "Download a source tarball for a specific version, verify and extract, and generate versioned installer scripts",
+ "build-all" => "Perform a build for a specific version for all architectures using saved environment profiles and localized dependencies",
+ "build" => "Perform a build for a specific version and architecture using saved environment profiles and localized dependencies",
+ );
+
+ $cmd = CLI::GetLimitedUserInputWithArgs($args, false, "Command", false, "Available commands:", $cmds, true, $suppressoutput);
+
+ @mkdir($rootpath . "/temp/logs", 0775, true);
+ @mkdir($rootpath . "/versions", 0775, true);
+
+ // Base version information is stored in: /templates/X.X/info.json
+ function GetBaseVersions()
+ {
+ global $rootpath;
+
+ $versions = array();
+
+ $dir = opendir($rootpath . "/templates");
+ if (!$dir) CLI::DisplayError("Failed to open 'templates' directory.");
+
+ while (($file = readdir($dir)) !== false)
+ {
+ $filename = $rootpath . "/templates/" . $file . "/info.json";
+
+ if ($file !== "." && $file !== ".." && file_exists($filename))
+ {
+ $verdata = json_decode(file_get_contents($filename), true);
+
+ if (!is_array($verdata)) CLI::DisplayError("JSON decoding failed for '" . $filename . "'. " . json_last_error_msg(), false, false);
+ else $versions[$file] = $verdata["name"];
+ }
+ }
+
+ closedir($dir);
+
+ if (!count($versions)) CLI::DisplayError("No version templates found.");
+
+ return $versions;
+ }
+
+ // Loads base version information and expands dependencies. The expansion mechanism significantly simplifies the JSON information file.
+ function LoadAndExpandBaseVersionInfo($basever)
+ {
+ global $rootpath;
+
+ $filename = $rootpath . "/templates/" . $basever . "/info.json";
+
+ $verdata = json_decode(file_get_contents($filename), true);
+ if (!is_array($verdata)) CLI::DisplayError("Unable to decode JSON in '" . $filename . "'.");
+
+ if (!isset($verdata["architectures"]) || !count($verdata["architectures"])) CLI::DisplayError("JSON data does not specify any architectures.");
+
+ $archdepmap = array();
+
+ foreach ($verdata["architectures"] as $archinfo)
+ {
+ foreach ($archinfo["dependencies"] as $depinfo)
+ {
+ if (!isset($depinfo["expand_from"])) $archdepmap[$archinfo["architecture"] . "|" . $depinfo["name"]] = $depinfo;
+ }
+ }
+
+ foreach ($verdata["architectures"] as &$archinfo)
+ {
+ $dependencies = array();
+
+ foreach ($archinfo["dependencies"] as $depinfo)
+ {
+ if (!isset($depinfo["expand_from"])) $dependencies[] = $depinfo;
+ else if (isset($archdepmap[$depinfo["expand_from"] . "|" . $depinfo["name"]])) $dependencies[] = $archdepmap[$depinfo["expand_from"] . "|" . $depinfo["name"]];
+ else CLI::DisplayError("Unable to expand '" . $depinfo["name"] . "' for '" . $archinfo["architecture"] . "' in '" . $filename . "'. Mapping does not exist.");
+ }
+
+ $archinfo["dependencies"] = $dependencies;
+ }
+
+ return $verdata;
+ }
+
+ // Extracts a supported base version and specific version from user input.
+ function GetSpecificVersionInput($inputmsg)
+ {
+ global $args, $suppressoutput;
+
+ $versions = GetBaseVersions();
+
+ do
+ {
+ $ver = CLI::GetUserInputWithArgs($args, "version", "Version", false, $inputmsg, $suppressoutput);
+
+ $verparts = explode(".", $ver);
+
+ $basever = false;
+ foreach ($versions as $ver2 => $val)
+ {
+ $verparts2 = explode(".", $ver2);
+ if (count($verparts) >= count($verparts2) && $ver !== $ver2)
+ {
+ $found = true;
+ foreach ($verparts2 as $num => $part)
+ {
+ if ((int)$part !== (int)$verparts[$num]) $found = false;
+ }
+
+ if ($found) $basever = $ver2;
+ }
+ }
+
+ if ($basever === false) CLI::DisplayError("A supported base version was not found for " . $ver . ".", false, false);
+ } while ($basever === false);
+
+ return array("basever" => $basever, "ver" => $ver);
+ }
+
+ // Returns the list of saved architecture environment profiles for a base version.
+ function GetProfileList($basever, $verdata)
+ {
+ global $rootpath;
+
+ $profiles = array();
+
+ $profiledir = $rootpath . "/versions/" . $basever . "/profiles";
+ foreach ($verdata["architectures"] as $archinfo)
+ {
+ if (file_exists($profiledir . "/" . $archinfo["architecture"] . ".json")) $profiles[$archinfo["architecture"]] = $archinfo["name"];
+ }
+
+ return $profiles;
+ }
+
+ function CopyFiles($srcdir, $destdir, $recurse, $pattern = "/.*/", $flatten = false)
+ {
+ $dir = opendir($srcdir);
+ if ($dir)
+ {
+ while (($file = readdir($dir)) !== false)
+ {
+ if ($file !== "." && $file !== "..")
+ {
+ if (is_dir($srcdir . "/" . $file))
+ {
+ if ($recurse) CopyFiles($srcdir . "/" . $file, ($flatten ? $destdir : $destdir . "/" . $file), true, $pattern);
+ }
+ else if (preg_match($pattern, $file))
+ {
+ @mkdir($destdir, 0775, true);
+
+ copy($srcdir . "/" . $file, $destdir . "/" . $file);
+ }
+ }
+ }
+
+ closedir($dir);
+ }
+ }
+
+ function CopyDirectory($srcdir, $destdir, $recurse = true)
+ {
+ $srcdir = rtrim(str_replace("\\", "/", $srcdir), "/");
+ $destdir = rtrim(str_replace("\\", "/", $destdir), "/");
+
+ @mkdir($destdir, 0775, true);
+
+ CopyFiles($srcdir, $destdir, $recurse);
+ }
+
+ function CopyTextFile($srcfile, $destfile)
+ {
+ if (!file_exists($srcfile) && file_exists($srcfile . ".md")) $srcfile .= ".md";
+ if (!file_exists($srcfile) && file_exists($srcfile . ".txt")) $srcfile .= ".txt";
+
+ $data = file_get_contents($srcfile);
+
+ $data = str_replace("\r\n", "\n", $data);
+ $data = str_replace("\r", "\n", $data);
+ $data = str_replace("\n", "\r\n", $data);
+
+ file_put_contents($destfile, $data);
+ }
+
+ function DeleteDirectory($path)
+ {
+ $dir = @opendir($path);
+ if ($dir)
+ {
+ while (($file = readdir($dir)) !== false)
+ {
+ if ($file !== "." && $file !== "..")
+ {
+ if (is_dir($path . "/" . $file)) DeleteDirectory($path . "/" . $file);
+ else @unlink($path . "/" . $file);
+ }
+ }
+
+ closedir($dir);
+
+ @rmdir($path);
+ }
+ }
+
+ // Returns a PHP variable-free environment.
+ function GetCleanEnvironment()
+ {
+ $ignore = array(
+ "PHP_SELF" => true,
+ "SCRIPT_NAME" => true,
+ "SCRIPT_FILENAME" => true,
+ "PATH_TRANSLATED" => true,
+ "DOCUMENT_ROOT" => true,
+ "REQUEST_TIME_FLOAT" => true,
+ "REQUEST_TIME" => true,
+ "argv" => true,
+ "argc" => true,
+ );
+
+ $result = array();
+ foreach ($_SERVER as $key => $val)
+ {
+ if (!isset($ignore[$key]) && is_string($val)) $result[$key] = $val;
+ }
+
+ return $result;
+ }
+
+ function GetEnvironmentKeymap($env)
+ {
+ $result = array();
+ foreach ($env as $key => $val) $result[strtoupper($key)] = $key;
+
+ return $result;
+ }
+
+ // Runs a simple command and returns the results.
+ function RunCommand($cmd, $errorfilename = false, $startdir = NULL, $env = NULL)
+ {
+ $os = php_uname("s");
+ $windows = (strtoupper(substr($os, 0, 3)) == "WIN");
+
+ $descriptors = array(
+ 0 => array("file", ($windows ? "NUL" : "/dev/null"), "r"),
+ 1 => array("pipe", "w"),
+ 2 => array("file", ($errorfilename !== false ? $errorfilename : ($windows ? "NUL" : "/dev/null")), "w")
+ );
+
+ $proc = @proc_open($cmd, $descriptors, $pipes, $startdir, $env, array("suppress_errors" => true, "bypass_shell" => true));
+
+ if (!is_resource($proc) || !isset($pipes[1])) return false;
+
+ if (isset($pipes[0])) @fclose($pipes[0]);
+ if (isset($pipes[2])) @fclose($pipes[2]);
+
+ $fp = $pipes[1];
+
+ $result = "";
+
+ while (!feof($fp))
+ {
+ $data = @fread($fp, 65536);
+ if ($data !== false) $result .= $data;
+ }
+
+ fclose($fp);
+
+ @proc_close($proc);
+
+ return $result;
+ }
+
+ function DownloadFileCallback($response, $data, $opts)
+ {
+ global $suppressoutput;
+
+ if ($response["code"] == 200)
+ {
+ $size = ftell($opts);
+ fwrite($opts, $data);
+
+ if (!$suppressoutput && $size % 1000000 > ($size + strlen($data)) % 1000000) echo ".";
+ }
+
+ return true;
+ }
+
+ $downloadsverified = array();
+
+ // Downloads a file to the /temp directory and verifies it.
+ function DownloadTempFile($pathmap, $downloadinfo, $downloadkey)
+ {
+ global $rootpath, $suppressoutput, $downloadsverified;
+
+ if (isset($downloadinfo[$downloadkey . "_temp"])) $tempfile = $downloadinfo[$downloadkey . "_temp"];
+ else
+ {
+ $url = str_replace(array_keys($pathmap), array_values($pathmap), $downloadinfo[$downloadkey]);
+
+ $pos = strrpos($url, "/");
+ $tempfile = substr($url, $pos + 1);
+ }
+
+ $tempfilename = $rootpath . "/temp/" . $tempfile;
+
+ // Download file.
+ if (!file_exists($tempfilename))
+ {
+ $url = str_replace(array_keys($pathmap), array_values($pathmap), $downloadinfo[$downloadkey]);
+
+ if (!$suppressoutput) echo "Downloading " . $downloadinfo["name"] . " '" . $url . "'...";
+
+ require_once $rootpath . "/support/web_browser.php";
+
+ $web = new WebBrowser();
+
+ $fp = fopen($tempfilename, "wb");
+
+ $options = array(
+ "read_body_callback" => "DownloadFileCallback",
+ "read_body_callback_opts" => $fp
+ );
+
+ $result = $web->Process($url, $options);
+ echo "\n";
+
+ fclose($fp);
+
+ if (!$result["success"]) CLI::DisplayError("Error retrieving URL.", $result);
+ if ($result["response"]["code"] != 200) CLI::DisplayError("Error retrieving URL. Server returned: " . $result["response"]["code"] . " " . $result["response"]["meaning"]);
+ }
+
+ // Verify file integrity.
+ if (isset($downloadinfo[$downloadkey . "_sha256"]) && !isset($downloadsverified[$tempfilename . "|sha256"]))
+ {
+ if (!$suppressoutput) echo "Verifying '" . $tempfilename . "'...\n";
+
+ $hash = hash_file("sha256", $tempfilename);
+ if ($hash !== $downloadinfo[$downloadkey . "_sha256"]) CLI::DisplayError("The SHA256 for '" . $tempfilename . "' is '" . $hash . "'. Expected '" . $downloadinfo[$downloadkey . "_sha256"] . "'.");
+
+ $downloadsverified[$tempfilename . "|sha256"] = true;
+ }
+
+ if (isset($downloadinfo[$downloadkey . "_sha256_url"]) && !isset($downloadsverified[$tempfilename . "|sha256_url"]))
+ {
+ if (!$suppressoutput) echo "Verifying '" . $tempfilename . "'...\n";
+
+ require_once $rootpath . "/support/web_browser.php";
+
+ $url = str_replace(array_keys($pathmap), array_values($pathmap), $downloadinfo[$downloadkey . "_sha256_url"]);
+
+ $web = new WebBrowser();
+
+ $result = $web->Process($url);
+
+ if (!$result["success"]) CLI::DisplayError("Error retrieving URL.", $result);
+ if ($result["response"]["code"] != 200) CLI::DisplayError("Error retrieving URL. Server returned: " . $result["response"]["code"] . " " . $result["response"]["meaning"]);
+
+ $hash = hash_file("sha256", $tempfilename);
+ if ($hash !== strtolower(trim($result["body"]))) CLI::DisplayError("The SHA256 for '" . $tempfilename . "' is '" . $hash . "'. Expected '" . strtolower(trim($result["body"])) . "'.");
+
+ $downloadsverified[$tempfilename . "|sha256_url"] = true;
+ }
+ }
+
+ // Applies PATH and other environment variables from the configuration for a dependency.
+ function ApplyDependencyEnvironment(&$tempenv, &$tempenvkeymap, $pathmap, $depinfo)
+ {
+ // Remove dependency matches from the path.
+ $paths = explode(PATH_SEPARATOR, (isset($tempenv[$tempenvkeymap["PATH"]]) ? $tempenv[$tempenvkeymap["PATH"]] : ""));
+ $paths2 = array();
+ foreach ($paths as $path)
+ {
+ $path = trim($path);
+ if ($path !== "" && !file_exists($path . "/" . $depinfo["verify"])) $paths2[] = $path;
+ }
+ if (!isset($tempenvkeymap["PATH"])) $tempenvkeymap["PATH"] = "Path";
+ $tempenv[$tempenvkeymap["PATH"]] = implode(PATH_SEPARATOR, $paths);
+
+ // Append dependency paths to the path.
+ if (isset($depinfo["env_paths"]))
+ {
+ foreach ($depinfo["env_paths"] as $path)
+ {
+ $path = str_replace(array_keys($pathmap), array_values($pathmap), $path);
+ $path = str_replace("/", "\\", $path);
+
+ $tempenv[$tempenvkeymap["PATH"]] .= ";" . $path;
+
+ putenv($tempenvkeymap["PATH"] . "=" . $tempenv[$tempenvkeymap["PATH"]]);
+ }
+ }
+
+ // Other environment variables.
+ if (isset($depinfo["env_extras"]))
+ {
+ foreach ($depinfo["env_extras"] as $key => $val)
+ {
+ if (strpos($val, "[[") !== false && strpos($val, "]]") !== false)
+ {
+ $val = str_replace(array_keys($pathmap), array_values($pathmap), $val);
+ $val = str_replace("/", "\\", $val);
+ }
+
+ if (isset($tempenvkeymap[strtoupper($key)])) unset($tempenv[$tempenvkeymap[strtoupper($key)]]);
+
+ $tempenv[$key] = $val;
+ }
+ }
+ }
+
+ // Verifies that a dependency appears to be functioning correctly.
+ function VerifyDependency($pathmap, $depinfo, $failpreferred)
+ {
+ global $rootpath, $suppressoutput;
+
+ if (!isset($depinfo["verify"])) return true;
+
+ $tempenv = GetCleanEnvironment();
+
+ $tempenvkeymap = GetEnvironmentKeymap($tempenv);
+
+ ApplyDependencyEnvironment($tempenv, $tempenvkeymap, $pathmap, $depinfo);
+
+ $cmd = str_replace(array_keys($pathmap), array_values($pathmap), $depinfo["verify"]);
+ $cmd = escapeshellarg(str_replace("/", "\\", $cmd));
+ if (isset($depinfo["verify_opts"])) $cmd .= " " . $depinfo["verify_opts"];
+
+ $errorfilename = $rootpath . "/temp/logs/verify_dependency_" . microtime(true) . "_error.log";
+
+ $result = RunCommand($cmd, $errorfilename, NULL, $tempenv);
+
+ // Emitting errors isn't necessarily a problem (yet).
+ $errors = file_get_contents($errorfilename);
+ unlink($errorfilename);
+
+ if ($result === false)
+ {
+ CLI::DisplayError("Process failed to start. Attempted to run: " . $cmd, false, false);
+
+ return false;
+ }
+
+ $result .= "\n" . $errors;
+
+ if ((isset($depinfo["required_output"]) && $depinfo["required_output"] === "") || (isset($depinfo["preferred_output"]) && $depinfo["preferred_output"] === ""))
+ {
+ echo $result . "\n";
+
+ CLI::DisplayError("Required or preferred output are empty strings.");
+ }
+
+ // Check output for required/preferred strings.
+ $foundreq = (!isset($depinfo["required_output"]));
+ $foundpref = false;
+ $lines = explode("\n", $result);
+ foreach ($lines as $line)
+ {
+ if (isset($depinfo["required_output"]) && preg_match($depinfo["required_output"], $line)) $foundreq = true;
+ if (isset($depinfo["preferred_output"]) && preg_match($depinfo["preferred_output"], $line)) $foundpref = true;
+ }
+
+ if (!$foundreq)
+ {
+ if ($errors !== "") CLI::DisplayError("Attempted command: ". $cmd . "\nExecutable emitted errors:\n" . $errors, false, false);
+
+ CLI::DisplayError("Required output not returned. " . $depinfo["required_alert"], false, false);
+
+ return false;
+ }
+
+ if (!$foundpref && isset($depinfo["preferred_output"]))
+ {
+ if ($errors !== "") CLI::DisplayError("Attempted command: ". $cmd . "\nExecutable emitted errors:\n" . $errors, false, false);
+
+ CLI::DisplayError("Preferred output not returned. " . $depinfo["preferred_alert"], false, false);
+
+ if ($failpreferred) return false;
+ }
+
+ return true;
+ }
+
+ // Downloads a file to /temp and extracts/installs it to its target location (e.g. /versions/X.X/deps).
+ function DownloadTempFileAndExtract($pathmap, $downloadinfo, $downloadkey)
+ {
+ global $rootpath, $suppressoutput;
+
+ // Check to see if already downloaded and extracted.
+ $installedfilename = $pathmap["[[DEPS_DIR]]"] . "/installed.json";
+ $installed = @json_decode(file_get_contents($installedfilename), true);
+ if (!is_array($installed)) $installed = array();
+
+ if (!isset($downloadinfo["download_extract_path"])) return;
+
+ $extractpath = str_replace(array_keys($pathmap), array_values($pathmap), $downloadinfo["download_extract_path"]);
+
+ if (!isset($installed[$extractpath]) || $installed[$extractpath] !== $downloadinfo[$downloadkey] || !is_dir($extractpath) || !VerifyDependency($pathmap, $downloadinfo, true))
+ {
+ // Download and verify the file.
+ DownloadTempFile($pathmap, $downloadinfo, $downloadkey);
+
+ // Delete existing installation (if any).
+ DeleteDirectory($extractpath);
+
+ // Extract the downloaded and verified file.
+ if (isset($downloadinfo[$downloadkey . "_temp"])) $tempfile = $downloadinfo[$downloadkey . "_temp"];
+ else
+ {
+ $url = str_replace(array_keys($pathmap), array_values($pathmap), $downloadinfo[$downloadkey]);
+
+ $pos = strrpos($url, "/");
+ $tempfile = substr($url, $pos + 1);
+ }
+
+ $tempfilename = $rootpath . "/temp/" . $tempfile;
+
+ switch ($downloadinfo["download_type"])
+ {
+ case "tar.gz":
+ {
+ @mkdir($extractpath, 0775, true);
+
+ if (!$suppressoutput) echo "Extracting '" . $tempfilename . "' to '" . $extractpath . "'...\n";
+
+ try
+ {
+ $phar = new PharData($tempfilename);
+ }
+ catch (Exception $e)
+ {
+ CLI::DisplayError("Unable to open tar.gz archive '" . $tempfilename . "'. " . $e->getMessage());
+ }
+
+ try
+ {
+ $phar->extractTo($extractpath);
+ }
+ catch (Exception $e)
+ {
+ CLI::DisplayError("Failed to extract '" . $tempfilename . "'. " . $e->getMessage());
+ }
+
+ unset($phar);
+
+ break;
+ }
+ case "zip":
+ {
+ @mkdir($extractpath, 0775, true);
+
+ if (!$suppressoutput) echo "Extracting '" . $tempfilename . "' to '" . $extractpath . "'...\n";
+
+ $zip = new ZipArchive;
+ if (!$zip->open($tempfilename, ZipArchive::RDONLY)) CLI::DisplayError("Unable to open ZIP archive '" . $tempfilename . "'.");
+ if (!$zip->extractTo($extractpath)) CLI::DisplayError("Failed to extract '" . $tempfilename . "'.");
+ $zip->close();
+
+ break;
+ }
+ case "exe":
+ {
+ if (!$suppressoutput) echo "Installing '" . $tempfilename . "' to '" . $extractpath . "'...\n";
+
+ $opts = $downloadinfo["download_install_opts"];
+ foreach ($pathmap as $key => $val) $opts = str_replace($key, str_replace("/", "\\", $val), $opts);
+
+ $cmd = escapeshellarg(str_replace("/", "\\", $tempfilename)) . " " . $opts;
+
+ $errorfilename = $rootpath . "/temp/logs/install_exe_" . microtime(true) . "_error.log";
+
+ $result = RunCommand($cmd, $errorfilename);
+
+ $errors = file_get_contents($errorfilename);
+ unlink($errorfilename);
+
+ if ($result === false) CLI::DisplayError("An error occurred while attempting to run '" . $cmd . "'.");
+
+ if (!$suppressoutput) echo $result;
+
+ if ($errors !== "") CLI::DisplayError("Executable emitted errors:\n" . $errors);
+
+ break;
+ }
+ default:
+ {
+ CLI::DisplayError("Unknown download type '" . $downloadtype . "'.");
+ }
+ }
+
+ if (!VerifyDependency($pathmap, $downloadinfo, true)) CLI::DisplayError("Unable to verify correct setup of the dependency.");
+
+ // Update installed dependencies.
+ $installed[$extractpath] = $downloadinfo[$downloadkey];
+
+ file_put_contents($installedfilename, json_encode($installed, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
+ }
+ }
+
+ if ($cmd === "init")
+ {
+ // Initialize a base version. Sets up directory structure and then downloads and extracts/installs dependencies.
+ $versions = GetBaseVersions();
+
+ $basever = CLI::GetLimitedUserInputWithArgs($args, "version", "Version", false, "Available versions:", $versions, true, $suppressoutput);
+
+ $verdata = LoadAndExpandBaseVersionInfo($basever);
+
+ // Determine current system capabilities (prefer x64 if possible).
+ $downloadpref = (PHP_INT_SIZE >= 8 ? "download_x64" : "download_x86");
+
+ // Download, verify, and extract dependencies.
+ @mkdir($rootpath . "/versions/" . $basever . "/deps", 0775, true);
+
+ $pathmap = array(
+ "[[ROOTPATH]]" => $rootpath,
+ "[[BASE_VERSION_DIR]]" => $rootpath . "/versions/" . $basever,
+ "[[DEPS_DIR]]" => $rootpath . "/versions/" . $basever . "/deps"
+ );
+
+ foreach ($verdata["architectures"] as $archinfo)
+ {
+ foreach ($archinfo["dependencies"] as $depinfo)
+ {
+ if (isset($depinfo[$downloadpref])) DownloadTempFileAndExtract($pathmap, $depinfo, $downloadpref);
+ else if (isset($depinfo["download"])) DownloadTempFileAndExtract($pathmap, $depinfo, "download");
+ }
+ }
+
+ CLI::DisplayResult(array("success" => true, "path" => $pathmap["[[BASE_VERSION_DIR]]"]));
+ }
+ else if ($cmd === "init-test")
+ {
+ // Test the downloads and verify hashes. Should be run when updating dependencies.
+ CLI::ReinitArgs($args, array("version"));
+
+ $versions = GetBaseVersions();
+
+ $basever = CLI::GetLimitedUserInputWithArgs($args, "version", "Version", false, "Available versions:", $versions, true, $suppressoutput);
+
+ $verdata = LoadAndExpandBaseVersionInfo($basever);
+
+ $pathmap = array();
+
+ foreach ($verdata["architectures"] as $archinfo)
+ {
+ foreach ($archinfo["dependencies"] as $depinfo)
+ {
+ if (isset($depinfo["download_x86"])) DownloadTempFile($pathmap, $depinfo, "download_x86");
+ if (isset($depinfo["download_x64"])) DownloadTempFile($pathmap, $depinfo, "download_x64");
+ if (isset($depinfo["download"])) DownloadTempFile($pathmap, $depinfo, "download");
+ }
+ }
+
+ CLI::DisplayResult(array("success" => true));
+ }
+ else if ($cmd === "save-profile")
+ {
+ // Validate and save an environment profile for a specific base version and architecture.
+ CLI::ReinitArgs($args, array("version", "arch"));
+
+ $versions = GetBaseVersions();
+
+ $basever = CLI::GetLimitedUserInputWithArgs($args, "version", "Version", false, "Available versions:", $versions, true, $suppressoutput);
+
+ // Load the base version.
+ $verdata = LoadAndExpandBaseVersionInfo($basever);
+
+ // Get available architectures.
+ $archs = array();
+
+ foreach ($verdata["architectures"] as $archinfo)
+ {
+ if (isset($archinfo["build"])) $archs[$archinfo["architecture"]] = $archinfo["name"];
+ }
+
+ $arch = CLI::GetLimitedUserInputWithArgs($args, "arch", "Architecture", false, "Available architectures:", $archs, true, $suppressoutput);
+
+ $pathmap = array(
+ "[[ROOTPATH]]" => $rootpath,
+ "[[BASE_VERSION_DIR]]" => $rootpath . "/versions/" . $basever,
+ "[[DEPS_DIR]]" => $rootpath . "/versions/" . $basever . "/deps"
+ );
+
+ // Verify dependencies for the selected architecture.
+ foreach ($verdata["architectures"] as $archinfo)
+ {
+ if ($archinfo["architecture"] === $arch)
+ {
+ foreach ($archinfo["dependencies"] as $depinfo)
+ {
+ if (!VerifyDependency($pathmap, $depinfo, false)) CLI::DisplayError("Dependency verification failed for '" . $depinfo["name"] . "'.");
+ }
+ }
+ }
+
+ // Save the environment profile.
+ $tempenv = GetCleanEnvironment();
+
+ $profilepath = $rootpath . "/versions/" . $basever . "/profiles";
+
+ @mkdir($profilepath, 0775, true);
+
+ file_put_contents($profilepath . "/" . $arch . ".json", json_encode($tempenv, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
+
+ CLI::DisplayResult(array("success" => true, "profile" => $profilepath . "/" . $arch . ".json"));
+ }
+ else if ($cmd === "prepare")
+ {
+ // Download a source tarball for a specific version, verify and extract, and generate versioned installer scripts.
+ CLI::ReinitArgs($args, array("version"));
+
+ $result = GetSpecificVersionInput("Enter the version of OpenSSL to download. Must be a release version of a supported base version.");
+
+ $basever = $result["basever"];
+ $ver = $result["ver"];
+
+ // Load the base version.
+ $verdata = LoadAndExpandBaseVersionInfo($basever);
+
+ // Download the OpenSSL source tarball, verify, and extract.
+ $pathmap = array(
+ "[[ROOTPATH]]" => $rootpath,
+ "[[BASE_VERSION_DIR]]" => $rootpath . "/versions/" . $basever,
+ "[[DEPS_DIR]]" => $rootpath . "/versions/" . $basever . "/deps",
+ "[[VERSION_DIR]]" => $rootpath . "/versions/" . $basever . "/" . $ver,
+ "[[DOTTED_VERSION]]" => $ver,
+ "[[WINDOWS_DOTTED_VERSION]]" => implode(".", array_slice(explode(".", preg_replace('/[^0-9.]/', "", $ver)), 0, 4)),
+ "[[MSI_DOTTED_VERSION]]" => implode(".", array_slice(explode(".", preg_replace('/[^0-9.]/', "", $ver)), 0, 3)),
+ "[[UNDERSCORE_VERSION]]" => str_replace(".", "_", $ver),
+ "[[HYPHEN_VERSION]]" => str_replace(".", "-", $ver),
+ );
+
+ DownloadTempFileAndExtract($pathmap, $verdata, "download");
+
+ // Generate versioned installer scripts from the templates.
+ @mkdir($pathmap["[[VERSION_DIR]]"] . "/installers", 0775, true);
+
+ foreach ($verdata["architectures"] as $archinfo)
+ {
+ $path = $rootpath . "/templates/" . $basever . "/" . $archinfo["architecture"];
+
+ $dir = opendir($path);
+ if (!$dir) CLI::DisplayError("Unable to open directory '" . $path . "'.");
+
+ while (($file = readdir($dir)) !== false)
+ {
+ if ($file !== "." && $file !== ".." && is_file($path . "/" . $file))
+ {
+ $data = file_get_contents($path . "/" . $file);
+ if ($data !== false)
+ {
+ $pathmap["[[INSTALLER_SCRIPT_DIR]]"] = $pathmap["[[VERSION_DIR]]"] . "/installers/" . $archinfo["architecture"];
+ $pathmap["[[INSTALLER_SOURCE_DIR]]"] = $pathmap["[[INSTALLER_SCRIPT_DIR]]"] . "/final";
+
+ foreach ($pathmap as $key => $val) $data = str_replace($key, str_replace("/", "\\", $val), $data);
+
+ @mkdir($pathmap["[[INSTALLER_SCRIPT_DIR]]"], 0775, true);
+
+ file_put_contents($pathmap["[[INSTALLER_SCRIPT_DIR]]"] . "/" . $file, $data);
+ }
+ }
+ }
+ }
+
+ CLI::DisplayResult(array("success" => true));
+ }
+ else if ($cmd === "build-all")
+ {
+ // Build all architectures for all specific versions.
+ CLI::ReinitArgs($args, array("version"));
+
+ $specificvers = array();
+
+ do
+ {
+ $result = GetSpecificVersionInput("Enter the version of OpenSSL to build. Must be a prepared version.");
+
+ $basever = $result["basever"];
+ $ver = $result["ver"];
+
+ if (!is_dir($rootpath . "/versions/" . $basever . "/" . $ver . "/installers")) CLI::DisplayError("The entered version (" . $ver . ") does not exist or is not prepared correctly.");
+
+ // Load the base version.
+ $verdata = LoadAndExpandBaseVersionInfo($basever);
+
+ $profiles = GetProfileList($basever, $verdata);
+
+ if (!count($profiles)) CLI::DisplayError("No environment profiles have been defined for " . $ver . ". See README.md on how to configure environment profiles.");
+
+ $specificvers[$ver] = array("basever" => $basever, "verdata" => $verdata, "profiles" => $profiles);
+ } while ((isset($args["opts"]["version"]) && count($args["opts"]["version"])) || count($args["params"]));
+
+ // Start a process for each specific version and architecture.
+ $procs = array();
+ foreach ($specificvers as $ver => $verinfo)
+ {
+ foreach ($verinfo["profiles"] as $arch => $name)
+ {
+ $cmd = escapeshellarg(PHP_BINARY) . " " . escapeshellarg(__FILE__) . " -suppressoutput build " . escapeshellarg($ver) . " " . escapeshellarg($arch);
+
+ if (!$suppressoutput) echo "Starting '" . $cmd . "'...\n";
+
+ $os = php_uname("s");
+ $windows = (strtoupper(substr($os, 0, 3)) == "WIN");
+
+ $descriptors = array(
+ 0 => array("file", ($windows ? "NUL" : "/dev/null"), "r"),
+ 1 => array("socket", "w"),
+ 2 => array("socket", "w")
+ );
+
+ $proc = @proc_open($cmd, $descriptors, $pipes, NULL, NULL, array("suppress_errors" => true, "bypass_shell" => true));
+
+ if (!is_resource($proc) || !isset($pipes[1])) CLI::DisplayError("Failed to start process.");
+
+ if (isset($pipes[0]))
+ {
+ @fclose($pipes[0]);
+
+ unset($pipes[0]);
+ }
+
+ foreach ($pipes as $fp) stream_set_blocking($fp, 0);
+
+ $procs[] = array("proc" => $proc, "pipes" => $pipes);
+ }
+ }
+
+ // Wait for all processes to finish running.
+ while (count($procs))
+ {
+ $readfps = array();
+ foreach ($procs as $num => $procinfo)
+ {
+ foreach ($procinfo["pipes"] as $fp) $readfps[] = $fp;
+ }
+
+ $writefps = array();
+ $exceptfps = NULL;
+ $result = @stream_select($readfps, $writefps, $exceptfps, 3);
+ if ($result === false) CLI::DisplayError("A stream_select() call failed.");
+
+ foreach ($readfps as $readfp)
+ {
+ foreach ($procs as $num => $procinfo)
+ {
+ foreach ($procinfo["pipes"] as $pnum => $fp)
+ {
+ if ($readfp === $fp)
+ {
+ echo @fgets($fp);
+
+ if (feof($fp))
+ {
+ fclose($fp);
+
+ unset($procs[$num]["pipes"][$pnum]);
+ }
+ }
+ }
+
+ if (!count($procs[$num]["pipes"]))
+ {
+ @proc_close($procinfo["proc"]);
+
+ unset($procs[$num]);
+ }
+ }
+ }
+ }
+
+ // Copies a directory tree into a ZIP archive.
+ function CopyDirectoryToZIPFile($zipfilename, $zip, &$size, $srcpath, $destpath)
+ {
+ global $suppressoutput;
+
+ $dir = opendir($srcpath);
+ if (!$dir) CLI::DisplayError("Failed to open directory '" . $srcpath . "' for reading.");
+
+ if (!$zip->addEmptyDir($destpath)) CLI::DisplayError("Failed to create '" . $destpath . "' in '" . $zipfilename . "'.");
+
+ while (($file = readdir($dir)) !== false)
+ {
+ if ($file !== "." && $file !== "..")
+ {
+ if (is_dir($srcpath . "/" . $file)) CopyDirectoryToZIPFile($zipfilename, $zip, $size, $srcpath . "/" . $file, $destpath . "/" . $file);
+ else if (is_file($srcpath . "/" . $file))
+ {
+ if (!$zip->addFile($srcpath . "/" . $file, $destpath . "/" . $file)) CLI::DisplayError("Failed to add file '" . $srcpath . "/" . $file . "' as '" . $destpath . "/" . $file . "' in '" . $zipfilename . "'.");
+ else
+ {
+ $size += filesize($srcpath . "/" . $file);
+
+ if ($size > 1024768)
+ {
+ // Flush data to disk.
+ if (!$suppressoutput) echo ".";
+
+ if (!$zip->close()) CLI::DisplayError("Failed to write to '" . $zipfilename . "'.");
+ if (!$zip->open($zipfilename)) CLI::DisplayError("Failed to reopen '" . $zipfilename . "'.");
+
+ while ($size > 1024768) $size -= 1024768;
+ }
+ }
+ }
+ }
+ }
+
+ closedir($dir);
+ }
+
+ // Creates a ZIP file out of a directory tree.
+ function CreateZIPFile($zipfilename, $srcpath, $destpath)
+ {
+ global $suppressoutput;
+
+ if (!$suppressoutput) echo "Creating '" . $zipfilename . "'...";
+
+ @unlink($zipfilename);
+
+ $zip = new ZipArchive;
+ if (!$zip->open($zipfilename, ZipArchive::CREATE | ZipArchive::EXCL)) CLI::DisplayError("Failed to create '" . $zipfilename . "'.");
+
+ $size = 0;
+ CopyDirectoryToZIPFile($zipfilename, $zip, $size, $srcpath, $destpath);
+
+ if (!$zip->close()) CLI::DisplayError("Failed to write to '" . $zipfilename . "'.");
+
+ echo "\n";
+ }
+
+ // Construct a portable edition for each version.
+ foreach ($specificvers as $ver => $verinfo)
+ {
+ if (!$suppressoutput) echo "Generating portable edition for " . $ver . "...\n";
+
+ $basever = $verinfo["basever"];
+ $verdata = $verinfo["verdata"];
+
+ $pathmap = array(
+ "[[ROOTPATH]]" => $rootpath,
+ "[[BASE_VERSION_DIR]]" => $rootpath . "/versions/" . $basever,
+ "[[VERSION_DIR]]" => $rootpath . "/versions/" . $basever . "/" . $ver,
+ "[[INSTALLERS_DIR]]" => $rootpath . "/versions/" . $basever . "/" . $ver . "/installers"
+ );
+
+ // Remove previous build.
+ DeleteDirectory($pathmap["[[INSTALLERS_DIR]]"] . "/portable");
+
+ $destdir = $pathmap["[[INSTALLERS_DIR]]"] . "/portable/final";
+
+ // Copy executable files from generated installer directories.
+ $first = true;
+
+ foreach ($verinfo["profiles"] as $arch => $name)
+ {
+ $srcdir = $pathmap["[[INSTALLERS_DIR]]"] . "/" . $arch . "/final";
+
+ if (!is_dir($srcdir)) CLI::DisplayError("Directory does not exist '" . $srcdir . "'. Build failed.");
+
+ if ($first)
+ {
+ CopyFiles($srcdir . "/conf", $destdir . "/conf", true);
+ CopyFiles($srcdir . "/text", $destdir . "/text", true);
+ CopyFiles($srcdir . "/tools", $destdir . "/tools", true);
+
+ $first = false;
+ }
+
+ CopyFiles($srcdir . "/bin", $destdir . "/bin/" . $arch, true);
+ CopyFiles($srcdir . "/bin_static", $destdir . "/bin_static/" . $arch, true);
+
+ $data = file_get_contents($srcdir . "/start.bat");
+ $data = str_replace("dp0bin", "dp0bin\\" . $arch, $data);
+ file_put_contents($destdir . "/start_" . $arch . ".bat", $data);
+ }
+
+ // Prepare light ZIP file with executables/DLLs only.
+ CreateZIPFile($pathmap["[[INSTALLERS_DIR]]"] . "/portable/OpenSSL-" . $ver . "-win-portable.zip", $destdir, "openssl-" . $ver);
+
+ // Copy developer files from generated installer directories.
+ foreach ($verinfo["profiles"] as $arch => $name)
+ {
+ $srcdir = $pathmap["[[INSTALLERS_DIR]]"] . "/" . $arch . "/final";
+
+ CopyFiles($srcdir . "/include", $destdir . "/include/" . $arch, true);
+ CopyFiles($srcdir . "/exp", $destdir . "/exp/" . $arch, true);
+ CopyFiles($srcdir . "/lib", $destdir . "/lib/", true);
+ }
+
+ // Prepare ZIP file with developer libraries.
+ CreateZIPFile($pathmap["[[INSTALLERS_DIR]]"] . "/portable/OpenSSL-" . $ver . "-win-portable-dev.zip", $destdir, "openssl-" . $ver . "-dev");
+ }
+
+ CLI::DisplayResult(array("success" => true));
+ }
+ else if ($cmd === "build")
+ {
+ // Build a specific version and architecture.
+ CLI::ReinitArgs($args, array("version", "arch"));
+
+ $result = GetSpecificVersionInput("Enter the version of OpenSSL to build. Must be a prepared version.");
+
+ $basever = $result["basever"];
+ $ver = $result["ver"];
+
+ if (!is_dir($rootpath . "/versions/" . $basever . "/" . $ver . "/installers")) CLI::DisplayError("The entered version (" . $ver . ") does not exist or is not prepared correctly.");
+
+ // Load the base version.
+ $verdata = LoadAndExpandBaseVersionInfo($basever);
+
+ $profiles = GetProfileList($basever, $verdata);
+
+ if (!count($profiles)) CLI::DisplayError("No environment profiles have been defined. See README.md on how to configure environment profiles.");
+
+ $arch = CLI::GetLimitedUserInputWithArgs($args, "arch", "Architecture", false, "Available architectures to build:", $profiles, true, $suppressoutput);
+
+ $echoprefix = "[" . $ver . "; " . $arch . "]";
+
+ // Load the environment profile.
+ $filename = $rootpath . "/versions/" . $basever . "/profiles/" . $arch . ".json";
+ $baseenv = json_decode(file_get_contents($filename), true);
+ if (!is_array($baseenv)) CLI::DisplayError($echoprefix . " Saved environment profile '" . $filename . "' is not valid.");
+
+ // Apply all dependency environment modifications.
+ $pathmap = array(
+ "[[ROOTPATH]]" => $rootpath,
+ "[[BASE_VERSION_DIR]]" => $rootpath . "/versions/" . $basever,
+ "[[DEPS_DIR]]" => $rootpath . "/versions/" . $basever . "/deps",
+ "[[VERSION_DIR]]" => $rootpath . "/versions/" . $basever . "/" . $ver,
+ "[[SOURCE_ORIG_DIR]]" => $rootpath . "/versions/" . $basever . "/" . $ver . "/source/openssl-" . $ver,
+ "[[SOURCE_TEMP_DIR]]" => $rootpath . "/versions/" . $basever . "/" . $ver . "/temp_" . $arch,
+ "[[BUILD_OUTPUT_DIR]]" => $rootpath . "/versions/" . $basever . "/" . $ver . "/out_" . $arch,
+ "[[INSTALLERS_DIR]]" => $rootpath . "/versions/" . $basever . "/" . $ver . "/installers",
+ "[[INSTALLERS_ARCH_DIR]]" => $rootpath . "/versions/" . $basever . "/" . $ver . "/installers/" . $arch,
+ );
+
+ $baseenvkeymap = GetEnvironmentKeymap($baseenv);
+
+ foreach ($verdata["architectures"] as $archinfo)
+ {
+ if ($archinfo["architecture"] === $arch)
+ {
+ if (!isset($archinfo["build"])) CLI::DisplayError($echoprefix . " Unable to build due to missing 'build' information in the JSON data.");
+
+ foreach ($archinfo["dependencies"] as $depinfo)
+ {
+ ApplyDependencyEnvironment($baseenv, $baseenvkeymap, $pathmap, $depinfo);
+ }
+
+ break;
+ }
+ }
+
+ $startts = time();
+
+ // Clean up previous/failed builds.
+ echo $echoprefix . " Cleaning up previous builds...\n";
+ DeleteDirectory($pathmap["[[SOURCE_TEMP_DIR]]"]);
+ DeleteDirectory($pathmap["[[INSTALLERS_ARCH_DIR]]"] . "/final");
+
+ @mkdir($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/logs", 0775, true);
+
+ // Specialty recursive file copy to ignore certain file extensions in the build tree.
+ function CopyBuildFiles($srcdir, $destdir, $path, $recurse, $pattern = "/.*/")
+ {
+ $srcpath = $srcdir . "/" . $path;
+
+ $excludeexts = array(
+ ".c" => true,
+ ".d" => true,
+ ".ec" => true,
+ ".h" => true,
+ ".obj" => true,
+ ".ilk" => true,
+ ".pdb" => true, // While PDB files might be ideal for debug builds, the generated files are about 8 times larger than the DLLs and include local system and build path strings.
+ ".in" => true,
+ ".info" => true,
+ ".md" => true,
+ ".asm" => true,
+ ".mar" => true,
+ );
+
+ if (!is_dir($srcpath)) return;
+
+ $dir = opendir($srcpath);
+ if ($dir)
+ {
+ while (($file = readdir($dir)) !== false)
+ {
+ if ($file !== "." && $file !== "..")
+ {
+ if (is_dir($srcpath . "/" . $file))
+ {
+ if ($recurse) CopyBuildFiles($srcpath, $destdir . "/" . $path, $file, true, $pattern);
+ }
+ else if (strpos($file, ".") !== false && !isset($excludeexts[substr($file, strrpos($file, "."))]) && preg_match($pattern, $file))
+ {
+ @mkdir($destdir . "/" . $path, 0777, true);
+
+ copy($srcpath . "/" . $file, $destdir . "/" . $path . "/" . $file);
+ }
+ }
+ }
+
+ closedir($dir);
+ }
+ }
+
+ // Builds OpenSSL.
+ function RunBuild($ver, $arch, $baseenv, $buildnum, $pathmap, $archinfo, $configuretype, $buildtype, $outdir, $copymodes)
+ {
+ $echoprefix = "[" . $ver . "; " . $arch . "; Build " . $buildnum . "; " . $outdir . "]";
+
+ echo $echoprefix . " Started build at " . date("Y-m-d H:i:s") . ".\n";
+ $ts = time();
+
+ DeleteDirectory($pathmap["[[SOURCE_TEMP_DIR]]"]);
+
+ // Clone the source tree to the temporary architecture directory.
+ // Doing this allows multiple architectures for a base version to be built simultaneously.
+ echo $echoprefix . " Cloning source tree...\n";
+ CopyDirectory($pathmap["[[SOURCE_ORIG_DIR]]"], $pathmap["[[SOURCE_TEMP_DIR]]"]);
+
+
+ // Run perl Configure.
+ $cmd = escapeshellarg("perl.exe") . " Configure " . $archinfo["build"]["configure_target"] . " " . $configuretype . " " . $archinfo["build"]["configure_extra"];
+ echo $echoprefix . " Running '" . $cmd . "'...\n";
+
+ $errorfilename = $pathmap["[[BUILD_OUTPUT_DIR]]"] . "/logs/" . $buildnum . "_perl_configure_" . $outdir . "_error.log";
+ $result = RunCommand($cmd, $errorfilename, $pathmap["[[SOURCE_TEMP_DIR]]"], $baseenv);
+ if ($result === false) CLI::DisplayError($echoprefix . " Failed to start process.");
+
+ file_put_contents($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/logs/" . $buildnum . "_perl_configure_" . $outdir . "_out.log", $result);
+
+ if (!file_exists($pathmap["[[SOURCE_TEMP_DIR]]"] . "/makefile")) CLI::DisplayError($echoprefix . " Failed to generate 'makefile'.");
+
+
+ // Nothing is perfect. Patch the makefile.
+ $data = file_get_contents($pathmap["[[SOURCE_TEMP_DIR]]"] . "/makefile");
+
+ foreach ($archinfo["build"]["patches"] as $key => $val)
+ {
+ $data = str_replace($key, $val, $data);
+ }
+
+ // The 'no-shared' build should only generate statically linked libraries and executables.
+ if (strpos($configuretype, "no-shared") !== false)
+ {
+ $data = str_replace("MODULES=providers\\legacy.dll", "MODULES=", $data);
+ $data = str_replace("MODULEPDBS=providers\\legacy.pdb", "MODULEPDBS=", $data);
+ }
+
+ // Fix the build type.
+ $data = str_replace(" /MTd ", " " . $buildtype . " ", $data);
+ $data = str_replace(" /MTd\r\n", " " . $buildtype . "\r\n", $data);
+ $data = str_replace(" /MT ", " " . $buildtype . " ", $data);
+ $data = str_replace(" /MT\r\n", " " . $buildtype . "\r\n", $data);
+
+ $data = str_replace(" /MDd ", " " . $buildtype . " ", $data);
+ $data = str_replace(" /MDd\r\n", " " . $buildtype . "\r\n", $data);
+ $data = str_replace(" /MD ", " " . $buildtype . " ", $data);
+ $data = str_replace(" /MD\r\n", " " . $buildtype . "\r\n", $data);
+
+ file_put_contents($pathmap["[[SOURCE_TEMP_DIR]]"] . "/makefile", $data);
+
+
+ // Run nmake.
+ $cmd = escapeshellarg("nmake.exe") . " -f makefile";
+ echo $echoprefix . " Running '" . $cmd . "'...\n";
+
+ $errorfilename = $pathmap["[[BUILD_OUTPUT_DIR]]"] . "/logs/" . $buildnum . "_nmake_" . $outdir . "_error.log";
+ $result = RunCommand($cmd, $errorfilename, $pathmap["[[SOURCE_TEMP_DIR]]"], $baseenv);
+ if ($result === false) CLI::DisplayError($echoprefix . " Failed to start process.");
+
+ file_put_contents($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/logs/" . $buildnum . "_nmake_" . $outdir . "_out.log", $result);
+
+ if (!file_exists($pathmap["[[SOURCE_TEMP_DIR]]"] . "/apps/openssl.exe")) CLI::DisplayError($echoprefix . " Failed to generate 'apps/openssl.exe'.");
+
+
+ // Copy files to the build output directory.
+ $indir = $pathmap["[[SOURCE_TEMP_DIR]]"];
+ $outdir2 = $pathmap["[[BUILD_OUTPUT_DIR]]"] . "/" . $outdir;
+ @mkdir($outdir2, 0775, true);
+ if (in_array("all", $copymodes) || in_array("apps", $copymodes)) CopyBuildFiles($indir, $outdir2, "apps", true);
+ if (in_array("all", $copymodes) || in_array("engines", $copymodes)) CopyBuildFiles($indir, $outdir2, "engines", false);
+ if (in_array("all", $copymodes) || in_array("fuzz", $copymodes)) CopyBuildFiles($indir, $outdir2, "fuzz", false);
+ if (in_array("all", $copymodes) || in_array("providers", $copymodes)) CopyBuildFiles($indir, $outdir2, "providers", false);
+ if (in_array("all", $copymodes) || in_array("test", $copymodes)) CopyBuildFiles($indir, $outdir2, "test", true);
+ if (in_array("all", $copymodes) || in_array("tools", $copymodes)) CopyBuildFiles($indir, $outdir2, "tools", true);
+
+ CopyBuildFiles($indir, $outdir2, "", false, '/(\.exp|\.lib|\.def|\.dll|\.pdb)$/');
+
+
+ // Build comleted.
+ $ts2 = time();
+ $secs = $ts2 - $ts;
+ $mins = (int)($secs / 60);
+ $secs %= 60;
+
+ echo $echoprefix . " Finished build at " . date("Y-m-d H:i:s") . ". Build time: " . $mins . " min " . $secs . " sec\n";
+ }
+
+ // Run first build. This build takes much longer due to also building the test suite.
+ if (!is_dir($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD") || !is_dir($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/inc"))
+ {
+ RunBuild($ver, $arch, $baseenv, 1, $pathmap, $archinfo, "shared", "/MD", "dll_MD", array("all"));
+
+ // Copy the include files.
+ @mkdir($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/inc/openssl", 0775, true);
+ $dir = opendir($pathmap["[[SOURCE_TEMP_DIR]]"] . "/include/openssl");
+ if ($dir)
+ {
+ while (($file = readdir($dir)) !== false)
+ {
+ if (strtolower(substr($file, -2)) === ".h")
+ {
+ // Convert line endings to DOS line endings.
+ $data = file_get_contents($pathmap["[[SOURCE_TEMP_DIR]]"] . "/include/openssl/" . $file);
+
+ $data = str_replace("\r\n", "\n", $data);
+ $data = str_replace("\r", "\n", $data);
+ $data = str_replace("\n", "\r\n", $data);
+
+ file_put_contents($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/inc/openssl/" . $file, $data);
+ }
+ }
+
+ closedir($dir);
+ }
+
+ // Copy ms/applink.c too.
+ // Convert line endings to DOS line endings.
+ $data = file_get_contents($pathmap["[[SOURCE_TEMP_DIR]]"] . "/ms/applink.c");
+
+ $data = str_replace("\r\n", "\n", $data);
+ $data = str_replace("\r", "\n", $data);
+ $data = str_replace("\n", "\r\n", $data);
+
+ file_put_contents($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/inc/openssl/applink.c", $data);
+ }
+
+ // Run the remaining builds.
+ if (!is_dir($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MT")) RunBuild($ver, $arch, $baseenv, 2, $pathmap, $archinfo, "shared no-tests", "/MT", "dll_MT", array("apps"));
+ if (!is_dir($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MDd")) RunBuild($ver, $arch, $baseenv, 3, $pathmap, $archinfo, "--debug shared no-tests", "/MDd", "dll_MDd", array());
+ if (!is_dir($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MTd")) RunBuild($ver, $arch, $baseenv, 4, $pathmap, $archinfo, "--debug shared no-tests", "/MTd", "dll_MTd", array());
+
+ if (!is_dir($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/static_MD")) RunBuild($ver, $arch, $baseenv, 5, $pathmap, $archinfo, "no-shared no-tests", "/MD", "static_MD", array("apps"));
+ if (!is_dir($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/static_MT")) RunBuild($ver, $arch, $baseenv, 6, $pathmap, $archinfo, "no-shared no-tests", "/MT", "static_MT", array("apps"));
+
+ // Remove the temporary build directory.
+ DeleteDirectory($pathmap["[[SOURCE_TEMP_DIR]]"]);
+
+ // Prepare installation directory and run installers.
+ if (is_dir($pathmap["[[INSTALLERS_ARCH_DIR]]"]))
+ {
+ if (!isset($archinfo["package"])) CLI::DisplayError($echoprefix . " Unable to package the build due to missing 'package' information in the JSON data.");
+
+ echo $echoprefix . " Started packaging at " . date("Y-m-d H:i:s") . ".\n";
+
+ $destdir = $pathmap["[[INSTALLERS_ARCH_DIR]]"] . "/final";
+
+ echo $echoprefix . " Copying files to '" . $destdir . "'...\n";
+
+ @mkdir($destdir, 0775, true);
+
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD", $destdir, false, '/(\.dll)$/');
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD", $destdir . "/bin", true, '/(\.dll)$/', true);
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD", $destdir . "/exp", true, '/(\.exp)$/', true);
+
+ // VC++ libraries.
+ $libdir = $destdir . "/lib/VC/" . $arch;
+ @mkdir($libdir . "/static", 0775, true);
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD", $libdir . "/MD", true, '/(\.lib|\.def)$/', true);
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MDd", $libdir . "/MDd", false, '/(\.lib|\.def)$/');
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MT", $libdir . "/MT", false, '/(\.lib|\.def)$/');
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MTd", $libdir . "/MTd", false, '/(\.lib|\.def)$/');
+
+ // OpenSSL.exe.
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD/apps", $destdir . "/bin", false, '/(\.exe)$/');
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/static_MT/apps", $destdir . "/bin_static", false, '/(\.exe)$/');
+
+ // Configurations.
+ copy($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD/apps/openssl.cnf", $destdir . "/bin/openssl.cfg"); // This is very old and is a long story.
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD/apps", $destdir . "/bin/cnf", false, '/(\.cnf)$/');
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD/apps", $destdir . "/conf", false, '/(\.cnf)$/');
+
+ // Perl scripts.
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD/apps", $destdir . "/bin", false, '/(\.pl)$/');
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD/tools", $destdir . "/tools", true);
+
+ // Test suites.
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD/test", $destdir . "/tests", true);
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD", $destdir . "/tests", false, '/(\.dll)$/');
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD/fuzz", $destdir . "/tests/fuzz", true);
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD", $destdir . "/tests/fuzz", false, '/(\.dll)$/');
+
+ // PEM files.
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD/apps", $destdir . "/bin/PEM", false, '/(\.pem|\.srl)$/');
+ if (is_dir($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD/apps/demoCA")) CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD/apps/demoCA", $destdir . "/bin/PEM/demoCA", true);
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD/apps/demoSRP", $destdir . "/bin/PEM/demoSRP", true);
+
+ // Includes.
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/inc", $destdir . "/include", true);
+
+ // Text files.
+ @mkdir($destdir . "/text", 0775, true);
+ CopyTextFile($pathmap["[[SOURCE_ORIG_DIR]]"] . "/ACKNOWLEDGEMENTS", $destdir . "/text/acknowledgements.txt");
+ CopyTextFile($pathmap["[[SOURCE_ORIG_DIR]]"] . "/AUTHORS", $destdir . "/text/authors.txt");
+ CopyTextFile($pathmap["[[SOURCE_ORIG_DIR]]"] . "/CHANGES", $destdir . "/text/changes.txt");
+ CopyTextFile($pathmap["[[SOURCE_ORIG_DIR]]"] . "/FAQ", $destdir . "/text/faq.txt");
+ CopyTextFile($pathmap["[[SOURCE_ORIG_DIR]]"] . "/LICENSE", $destdir . "/text/license.txt");
+ CopyTextFile($pathmap["[[SOURCE_ORIG_DIR]]"] . "/NEWS", $destdir . "/text/news.txt");
+ CopyTextFile($pathmap["[[SOURCE_ORIG_DIR]]"] . "/README", $destdir . "/text/readme.txt");
+
+ CopyTextFile($pathmap["[[SOURCE_ORIG_DIR]]"] . "/LICENSE", $destdir . "/license.txt");
+
+ // Start menu batch file.
+ if (file_exists($pathmap["[[INSTALLERS_ARCH_DIR]]"] . "/start.bat")) copy($pathmap["[[INSTALLERS_ARCH_DIR]]"] . "/start.bat", $destdir . "/start.bat");
+
+ // MinGW libraries.
+ if (isset($archinfo["package"]["mingw_dlltool"]) && $archinfo["package"]["mingw_dlltool"] !== "")
+ {
+ echo $echoprefix . " Generating MinGW libraries...\n";
+
+ $mingwlibdir = $destdir . "/lib/MinGW/" . $arch;
+
+ CopyFiles($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/dll_MD", $mingwlibdir, false, '/(\.def)$/');
+
+ $dir = opendir($mingwlibdir);
+ if ($dir)
+ {
+ while (($file = readdir($dir)) !== false)
+ {
+ if (substr($file, -4) === ".def")
+ {
+ $cmd = str_replace(array_keys($pathmap), array_values($pathmap), $archinfo["package"]["mingw_dlltool"]);
+ $cmd = escapeshellarg(str_replace("/", "\\", $cmd));
+
+ $cmd .= " --def .\\lib\\MinGW\\" . $arch . "\\" . $file . " --dllname " . substr($file, 0, -4) . ".dll --output-lib .\\lib\\MinGW\\" . $arch . "\\" . substr($file, 0, -4) . ".dll.a";
+
+ echo $echoprefix . " Running '" . $cmd . "'...\n";
+
+ $errorfilename = $pathmap["[[BUILD_OUTPUT_DIR]]"] . "/logs/package_mingw_dlltool_" . $arch . "_" . substr($file, 0, -4) . "_error.log";
+ $result = RunCommand($cmd, $errorfilename, $destdir, $baseenv);
+ if ($result === false) CLI::DisplayError($echoprefix . " Failed to start process.");
+
+ file_put_contents($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/logs/package_mingw_dlltool_" . $arch . "_" . substr($file, 0, -4) . "_out.log", $result);
+
+ $filename = $mingwlibdir . "/" . substr($file, 0, -4) . ".dll.a";
+ if (!file_exists($filename)) CLI::DisplayError($echoprefix . " Unable to generate '" . $filename . "'.");
+ }
+ }
+
+ closedir($dir);
+ }
+ }
+
+ // Run Inno Setup compiler.
+ if (isset($archinfo["package"]["inno_setup_dir"]) && $archinfo["package"]["inno_setup_dir"] !== "")
+ {
+ echo $echoprefix . " Running Inno Setup compiler...\n";
+
+ $dir = opendir($pathmap["[[INSTALLERS_ARCH_DIR]]"]);
+ if ($dir)
+ {
+ while (($file = readdir($dir)) !== false)
+ {
+ if (substr($file, -4) === ".iss")
+ {
+ $cmd = str_replace(array_keys($pathmap), array_values($pathmap), $archinfo["package"]["inno_setup_dir"] . "/iscc.exe");
+ $cmd = escapeshellarg(str_replace("/", "\\", $cmd));
+
+ $cmd .= " " . escapeshellarg(str_replace("/", "\\", $pathmap["[[INSTALLERS_ARCH_DIR]]"] . "/" . $file));
+
+ echo $echoprefix . " Running '" . $cmd . "'...\n";
+
+ $errorfilename = $pathmap["[[BUILD_OUTPUT_DIR]]"] . "/logs/package_inno_setup_" . $arch . "_" . substr($file, 0, -4) . "_error.log";
+ $result = RunCommand($cmd, $errorfilename, $destdir, $baseenv);
+ if ($result === false) CLI::DisplayError($echoprefix . " Failed to start process.");
+
+ file_put_contents($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/logs/package_inno_setup_" . $arch . "_" . substr($file, 0, -4) . "_out.log", $result);
+
+ // Verify that the EXE was created by looking for the OutputBaseFilename.
+ $filename = false;
+ $lines = explode("\n", file_get_contents($pathmap["[[INSTALLERS_ARCH_DIR]]"] . "/" . $file));
+ foreach ($lines as $line)
+ {
+ $line = trim($line);
+ $pos = strpos($line, "=");
+ if ($pos !== false && trim(substr($line, 0, $pos)) === "OutputBaseFilename") $filename = $destdir . "/Output/" . trim(substr($line, $pos + 1)) . ".exe";
+ }
+
+ if (!file_exists($filename)) CLI::DisplayError($echoprefix . " Unable to generate '" . $filename . "'.");
+ }
+ }
+
+ closedir($dir);
+ }
+ }
+
+ // Run Wix toolset compiler.
+ if (isset($archinfo["package"]["wix_toolset_dir"]) && $archinfo["package"]["wix_toolset_dir"] !== "" && isset($archinfo["package"]["wix_toolset_target"]))
+ {
+ echo $echoprefix . " Running Wix toolset compiler...\n";
+
+ $dir = opendir($pathmap["[[INSTALLERS_ARCH_DIR]]"]);
+ if ($dir)
+ {
+ while (($file = readdir($dir)) !== false)
+ {
+ if (substr($file, -4) === ".wxs")
+ {
+ // Extract SourceSetupFile.
+ $basefilename = false;
+ $lines = explode("\n", file_get_contents($pathmap["[[INSTALLERS_ARCH_DIR]]"] . "/" . $file));
+ foreach ($lines as $line)
+ {
+ $line = trim($line);
+
+ $pos = strpos($line, " SourceSetupFile ");
+ if ($pos !== false)
+ {
+ $basefilename = substr($line, strpos($line, "\"", $pos) + 1);
+ $basefilename = substr($basefilename, 0, strrpos($basefilename, "\"") - 4);
+ }
+ }
+
+ if ($basefilename === false) CLI::DisplayError($echoprefix . " Unable to find 'SourceSetupFile' in '" . $pathmap["[[INSTALLERS_ARCH_DIR]]"] . "/" . $file . "'.");
+
+ $wixobjfilename = $destdir . "/Output/" . $basefilename . ".wixobj";
+ $wixpdbfilename = $destdir . "/Output/" . $basefilename . ".wixpdb";
+ $msifilename = $destdir . "/Output/" . $basefilename . ".msi";
+
+
+ // Run candle.exe to output .wixobj.
+ $cmd = str_replace(array_keys($pathmap), array_values($pathmap), $archinfo["package"]["wix_toolset_dir"] . "/candle.exe");
+ $cmd = escapeshellarg(str_replace("/", "\\", $cmd));
+
+ $cmd .= " " . $archinfo["package"]["wix_toolset_target"] . " -o " . escapeshellarg(str_replace("/", "\\", $wixobjfilename)) . " " . escapeshellarg(str_replace("/", "\\", $pathmap["[[INSTALLERS_ARCH_DIR]]"] . "/" . $file));
+
+ echo $echoprefix . " Running '" . $cmd . "'...\n";
+
+ $errorfilename = $pathmap["[[BUILD_OUTPUT_DIR]]"] . "/logs/package_wix_toolset_candle_" . $arch . "_" . substr($file, 0, -4) . "_error.log";
+ $result = RunCommand($cmd, $errorfilename, $destdir, $baseenv);
+ if ($result === false) CLI::DisplayError($echoprefix . " Failed to start process.");
+
+ file_put_contents($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/logs/package_wix_toolset_candle_" . $arch . "_" . substr($file, 0, -4) . "_out.log", $result);
+
+ // Verify that the .wixobj file was created.
+ if (!file_exists($wixobjfilename)) CLI::DisplayError($echoprefix . " Unable to generate '" . $wixobjfilename . "'.");
+
+
+ // Run light.exe to output .msi.
+ $cmd = str_replace(array_keys($pathmap), array_values($pathmap), $archinfo["package"]["wix_toolset_dir"] . "/light.exe");
+ $cmd = escapeshellarg(str_replace("/", "\\", $cmd));
+
+ $cmd .= " -b " . escapeshellarg(str_replace("/", "\\", $destdir . "/Output")) . " -ext WixUtilExtension.dll -out " . escapeshellarg(str_replace("/", "\\", $msifilename)) . " " . escapeshellarg(str_replace("/", "\\", $wixobjfilename));
+
+ echo $echoprefix . " Running '" . $cmd . "'...\n";
+
+ $errorfilename = $pathmap["[[BUILD_OUTPUT_DIR]]"] . "/logs/package_wix_toolset_light_" . $arch . "_" . substr($file, 0, -4) . "_error.log";
+ $result = RunCommand($cmd, $errorfilename, $destdir, $baseenv);
+ if ($result === false) CLI::DisplayError($echoprefix . " Failed to start process.");
+
+ file_put_contents($pathmap["[[BUILD_OUTPUT_DIR]]"] . "/logs/package_wix_toolset_light_" . $arch . "_" . substr($file, 0, -4) . "_out.log", $result);
+
+ // Verify that the MSI was created.
+ if (!file_exists($msifilename)) CLI::DisplayError($echoprefix . " Unable to generate '" . $msifilename . "'.");
+
+ @unlink($wixobjfilename);
+ @unlink($wixpdbfilename);
+ }
+ }
+
+ closedir($dir);
+ }
+ }
+ }
+
+ // All finished.
+ $ts2 = time();
+ $secs = $ts2 - $startts;
+ $mins = (int)($secs / 60);
+ $secs %= 60;
+
+ echo $echoprefix . " Finished building and packaging at " . date("Y-m-d H:i:s") . ". Total time: " . $mins . " min " . $secs . " sec\n";
+ }
diff --git a/ms-windows/support/SOURCES.txt b/ms-windows/support/SOURCES.txt
new file mode 100644
index 0000000..6451502
--- /dev/null
+++ b/ms-windows/support/SOURCES.txt
@@ -0,0 +1,14 @@
+Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the OpenSSL license (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+https://www.openssl.org/source/license.html
+
+Support Library Sources
+=======================
+
+The files in this directory come from these open source libraries:
+
+https://github.com/cubiclesoft/php-misc (MIT license)
+https://github.com/cubiclesoft/ultimate-web-scraper (MIT license)
diff --git a/ms-windows/support/cacert.pem b/ms-windows/support/cacert.pem
new file mode 100644
index 0000000..2ae7b6c
--- /dev/null
+++ b/ms-windows/support/cacert.pem
@@ -0,0 +1,3372 @@
+##
+## Bundle of CA Root Certificates
+##
+## Certificate data from Mozilla as of: Tue Jan 10 04:12:06 2023 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.29.
+## SHA256: 90c470e705b4b5f36f09684dc50e2b79c8b86989a848b62cd1a7bd6460ee65f6
+##
+
+
+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-----
+
+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-----
+
+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-----
+
+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-----
+
+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 - R5
+===========================
+-----BEGIN CERTIFICATE-----
+MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
+R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
+EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
+R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
+EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
+SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
+h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
+BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
+uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
+yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
+-----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-----
+
+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-----
+
+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-----
+
+Autoridad de Certificacion Firmaprofesional CIF A62634068
+=========================================================
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCRVMxQjBA
+BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
+MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIw
+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+JIwuwIDAQABo4HvMIHsMB0GA1Ud
+DgQWBBRlzeurNR4APn7VdMActHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4w
+gZswgZgGBFUdIAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j
+b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABCAG8AbgBhAG4A
+bwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAwADEANzAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9miWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL
+4QjbEwj4KKE1soCzC1HA01aajTNFSa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDb
+LIpgD7dvlAceHabJhfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1il
+I45PVf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZEEAEeiGaP
+cjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV1aUsIC+nmCjuRfzxuIgA
+LI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2tCsvMo2ebKHTEm9caPARYpoKdrcd7b/+A
+lun4jWq9GJAd/0kakFI3ky88Al2CdgtR5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH
+9IBk9W6VULgRfhVwOEqwf9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpf
+NIbnYrX9ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNKGbqE
+ZycPvEJdvSRUDewdcAZfpLz6IHxV
+-----END CERTIFICATE-----
+
+vTrus ECC Root CA
+=================
+-----BEGIN CERTIFICATE-----
+MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMwRzELMAkGA1UE
+BhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBS
+b290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDczMTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAa
+BgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYw
+EAYHKoZIzj0CAQYFK4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+c
+ToL0v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUde4BdS49n
+TPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIwV53dVvHH4+m4SVBrm2nDb+zDfSXkV5UT
+QJtS0zvzQBm8JsctBp61ezaf9SXUY2sAAjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQL
+YgmRWAD5Tfs0aNoJrSEGGJTO
+-----END CERTIFICATE-----
+
+vTrus Root CA
+=============
+-----BEGIN CERTIFICATE-----
+MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQELBQAwQzELMAkG
+A1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xFjAUBgNVBAMTDXZUcnVzIFJv
+b3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMxMDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoG
+A1UEChMTaVRydXNDaGluYSBDby4sTHRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZots
+SKYcIrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykUAyyNJJrI
+ZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+GrPSbcKvdmaVayqwlHeF
+XgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z98Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KA
+YPxMvDVTAWqXcoKv8R1w6Jz1717CbMdHflqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70
+kLJrxLT5ZOrpGgrIDajtJ8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2
+AXPKBlim0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZNpGvu
+/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQUqqzApVg+QxMaPnu
+1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHWOXSuTEGC2/KmSNGzm/MzqvOmwMVO
+9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMBAAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYg
+scasGrz2iTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOC
+AgEAKbqSSaet8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd
+nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1jbhd47F18iMjr
+jld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvMKar5CKXiNxTKsbhm7xqC5PD4
+8acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIivTDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJn
+xDHO2zTlJQNgJXtxmOTAGytfdELSS8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554Wg
+icEFOwE30z9J4nfrI8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4
+sEb9b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNBUvupLnKW
+nyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1PTi07NEPhmg4NpGaXutIc
+SkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929vensBxXVsFy6K2ir40zSbofitzmdHxghm+H
+l3s=
+-----END CERTIFICATE-----
+
+ISRG Root X2
+============
+-----BEGIN CERTIFICATE-----
+MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQswCQYDVQQGEwJV
+UzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElT
+UkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVT
+MSkwJwYDVQQKEyBJbnRlcm5ldCBTZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNS
+RyBSb290IFgyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0H
+ttwW+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9ItgKbppb
+d9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZIzj0EAwMDaAAwZQIwe3lORlCEwkSHRhtF
+cP9Ymd70/aTSVaYgLXTWNLxBo1BfASdWtL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5
+U6VR5CmD1/iQMVtCnwr1/q4AaOeMSQ+2b1tbFfLn
+-----END CERTIFICATE-----
+
+HiPKI Root CA - G1
+==================
+-----BEGIN CERTIFICATE-----
+MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQG
+EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xGzAZBgNVBAMMEkhpUEtJ
+IFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRaFw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYT
+AlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kg
+Um9vdCBDQSAtIEcxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0
+o9QwqNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twvVcg3Px+k
+wJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6lZgRZq2XNdZ1AYDgr/SE
+YYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnzQs7ZngyzsHeXZJzA9KMuH5UHsBffMNsA
+GJZMoYFL3QRtU6M9/Aes1MU3guvklQgZKILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfd
+hSi8MEyr48KxRURHH+CKFgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj
+1jOXTyFjHluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDry+K4
+9a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ/W3c1pzAtH2lsN0/
+Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgMa/aOEmem8rJY5AIJEzypuxC00jBF
+8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQD
+AgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi
+7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqcSE5XCV0vrPSl
+tJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6FzaZsT0pPBWGTMpWmWSBUdGSquE
+wx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9TcXzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07Q
+JNBAsNB1CI69aO4I1258EHBGG3zgiLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv
+5wiZqAxeJoBF1PhoL5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+Gpz
+jLrFNe85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wrkkVbbiVg
+hUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+vhV4nYWBSipX3tUZQ9rb
+yltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQUYDksswBVLuT1sw5XxJFBAJw/6KXf6vb/
+yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ==
+-----END CERTIFICATE-----
+
+GlobalSign ECC Root CA - R4
+===========================
+-----BEGIN CERTIFICATE-----
+MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYDVQQLExtHbG9i
+YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
+b2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgwMTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9i
+YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
+b2JhbFNpZ24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkW
+ymOxuYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNVHQ8BAf8E
+BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/+wpu+74zyTyjhNUwCgYI
+KoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147bmF0774BxL4YSFlhgjICICadVGNA3jdg
+UM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm
+-----END CERTIFICATE-----
+
+GTS Root R1
+===========
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV
+UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
+UjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
+ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM
+f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7raKb0
+xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnWr4+w
+B7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXW
+nOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk
+9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zq
+kUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92wO1A
+K/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om3xPX
+V2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDW
+cfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T
+AQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQAD
+ggIBAJ+qQibbC5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
+QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuyh6f88/qBVRRi
+ClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM47HLwEXWdyzRSjeZ2axfG34ar
+J45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8JZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYci
+NuaCp+0KueIHoI17eko8cdLiA6EfMgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5me
+LMFrUKTX5hgUvYU/Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJF
+fbdT6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ0E6yove+
+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm2tIMPNuzjsmhDYAPexZ3
+FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bbbP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3
+gm3c
+-----END CERTIFICATE-----
+
+GTS Root R2
+===========
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV
+UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
+UjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
+ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv
+CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo7JUl
+e3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWIm8Wb
+a96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS
++LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7M
+kogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJG
+r61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RWIr9q
+S34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73VululycslaVNV
+J1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy5okL
+dWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T
+AQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQAD
+ggIBAB/Kzt3HvqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8
+0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyCB19m3H0Q/gxh
+swWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2uNmSRXbBoGOqKYcl3qJfEycel
+/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMgyALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVn
+jWQye+mew4K6Ki3pHrTgSAai/GevHyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y5
+9PYjJbigapordwj6xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M
+7YNRTOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924SgJPFI/2R8
+0L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV7LXTWtiBmelDGDfrs7vR
+WGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjW
+HYbL
+-----END CERTIFICATE-----
+
+GTS Root R3
+===========
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi
+MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMw
+HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ
+R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjO
+PQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout
+736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24CejQjBA
+MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP0/Eq
+Er24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azT
+L818+FsuVbu/3ZL3pAzcMeGiAjEA/JdmZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV
+11RZt+cRLInUue4X
+-----END CERTIFICATE-----
+
+GTS Root R4
+===========
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi
+MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQw
+HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ
+R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjO
+PQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu
+hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqjQjBA
+MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV2Py1
+PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/C
+r8deVl5c1RxYIigL9zC2L7F8AjEA8GE8p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh
+4rsUecrNIdSUtUlD
+-----END CERTIFICATE-----
+
+Telia Root CA v2
+================
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQxCzAJBgNVBAYT
+AkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2
+MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQK
+DBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ7
+6zBqAMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9vVYiQJ3q
+9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9lRdU2HhE8Qx3FZLgmEKn
+pNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTODn3WhUidhOPFZPY5Q4L15POdslv5e2QJl
+tI5c0BE0312/UqeBAMN/mUWZFdUXyApT7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW
+5olWK8jjfN7j/4nlNW4o6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNr
+RBH0pUPCTEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6WT0E
+BXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63RDolUK5X6wK0dmBR4
+M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZIpEYslOqodmJHixBTB0hXbOKSTbau
+BcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGjYzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7W
+xy+G2CQ5MB0GA1UdDgQWBBRyrOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ
+8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi0f6X+J8wfBj5
+tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMMA8iZGok1GTzTyVR8qPAs5m4H
+eW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBSSRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+C
+y748fdHif64W1lZYudogsYMVoe+KTTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygC
+QMez2P2ccGrGKMOF6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15
+h2Er3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMtTy3EHD70
+sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pTVmBds9hCG1xLEooc6+t9
+xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAWysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQ
+raVplI/owd8k+BsHMYeB2F326CjYSlKArBPuUBQemMc=
+-----END CERTIFICATE-----
+
+D-TRUST BR Root CA 1 2020
+=========================
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE
+RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEJSIFJvb3QgQ0EgMSAy
+MDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNV
+BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7
+dPYSzuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0QVK5buXu
+QqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/VbNafAkl1bK6CKBrqx9t
+MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu
+bmV0L2NybC9kLXRydXN0X2JyX3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP
+PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD
+AwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFWwKrY7RjEsK70Pvom
+AjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHVdWNbFJWcHwHP2NVypw87
+-----END CERTIFICATE-----
+
+D-TRUST EV Root CA 1 2020
+=========================
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE
+RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEVWIFJvb3QgQ0EgMSAy
+MDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNV
+BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8
+ZRCC/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rDwpdhQntJ
+raOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3OqQo5FD4pPfsazK2/umL
+MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu
+bmV0L2NybC9kLXRydXN0X2V2X3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP
+PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD
+AwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CAy/m0sRtW9XLS/BnR
+AjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJbgfM0agPnIjhQW+0ZT0MW
+-----END CERTIFICATE-----
+
+DigiCert TLS ECC P384 Root G5
+=============================
+-----BEGIN CERTIFICATE-----
+MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURpZ2lDZXJ0IFRMUyBFQ0MgUDM4
+NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMx
+FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQg
+Um9vdCBHNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1Tzvd
+lHJS7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp0zVozptj
+n4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICISB4CIfBFqMA4GA1UdDwEB
+/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQCJao1H5+z8blUD2Wds
+Jk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQLgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIx
+AJSdYsiJvRmEFOml+wG4DXZDjC5Ty3zfDBeWUA==
+-----END CERTIFICATE-----
+
+DigiCert TLS RSA4096 Root G5
+============================
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBNMQswCQYDVQQG
+EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0
+MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcNNDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2
+IFJvb3QgRzUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS8
+7IE+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG02C+JFvuU
+AT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgpwgscONyfMXdcvyej/Ces
+tyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZMpG2T6T867jp8nVid9E6P/DsjyG244gXa
+zOvswzH016cpVIDPRFtMbzCe88zdH5RDnU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnV
+DdXifBBiqmvwPXbzP6PosMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9q
+TXeXAaDxZre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cdLvvy
+z6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvXKyY//SovcfXWJL5/
+MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNeXoVPzthwiHvOAbWWl9fNff2C+MIk
+wcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPLtgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4E
+FgQUUTMc7TZArxfTJc1paPKvTiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8w
+DQYJKoZIhvcNAQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw
+GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7HPNtQOa27PShN
+lnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLFO4uJ+DQtpBflF+aZfTCIITfN
+MBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQREtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/
+u4cnYiWB39yhL/btp/96j1EuMPikAdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9G
+OUrYU9DzLjtxpdRv/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh
+47a+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilwMUc/dNAU
+FvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WFqUITVuwhd4GTWgzqltlJ
+yqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCKovfepEWFJqgejF0pW8hL2JpqA15w8oVP
+bEtoL8pU9ozaMv7Da4M/OMZ+
+-----END CERTIFICATE-----
+
+Certainly Root R1
+=================
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAwPTELMAkGA1UE
+BhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2VydGFpbmx5IFJvb3QgUjEwHhcN
+MjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2Vy
+dGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBANA21B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O
+5MQTvqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbedaFySpvXl
+8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b01C7jcvk2xusVtyWMOvwl
+DbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGI
+XsXwClTNSaa/ApzSRKft43jvRl5tcdF5cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkN
+KPl6I7ENPT2a/Z2B7yyQwHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQ
+AjeZjOVJ6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA2Cnb
+rlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyHWyf5QBGenDPBt+U1
+VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMReiFPCyEQtkA6qyI6BJyLm4SGcprS
+p6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBTgqj8ljZ9EXME66C6ud0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAsz
+HQNTVfSVcOQrPbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d
+8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi1wrykXprOQ4v
+MMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrdrRT90+7iIgXr0PK3aBLXWopB
+GsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9ditaY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+
+gjwN/KUD+nsa2UUeYNrEjvn8K8l7lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgH
+JBu6haEaBQmAupVjyTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7
+fpYnKx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLyyCwzk5Iw
+x06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5nwXARPbv0+Em34yaXOp/S
+X3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6OV+KmalBWQewLK8=
+-----END CERTIFICATE-----
+
+Certainly Root E1
+=================
+-----BEGIN CERTIFICATE-----
+MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQswCQYDVQQGEwJV
+UzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBFMTAeFw0yMTA0
+MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlu
+bHkxGjAYBgNVBAMTEUNlcnRhaW5seSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4
+fxzf7flHh4axpMCK+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9
+YBk2QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4hevIIgcwCgYIKoZIzj0E
+AwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozmut6Dacpps6kFtZaSF4fC0urQe87YQVt8
+rgIwRt7qy12a7DLCZRawTDBcMPPaTnOGBtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR
+-----END CERTIFICATE-----
+
+E-Tugra Global Root CA RSA v3
+=============================
+-----BEGIN CERTIFICATE-----
+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
+-----END CERTIFICATE-----
+
+E-Tugra Global Root CA ECC v3
+=============================
+-----BEGIN CERTIFICATE-----
+MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMwgYAxCzAJBgNV
+BAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAbBgNV
+BAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENB
+IEVDQyB2MzAeFw0yMDAzMTgwOTQ2NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEP
+MA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1
+Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBFQ0MgdjMw
+djAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQKczLWYHMjLiSF4mDKpL2
+w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YKfWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31
+Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQ
+zPUwHQYDVR0OBBYEFP+CMXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO
+PQQDAwNpADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/67W4W
+Aie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFxvmjkI6TZraE3
+-----END CERTIFICATE-----
+
+Security Communication RootCA3
+==============================
+-----BEGIN CERTIFICATE-----
+MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNVBAYTAkpQMSUw
+IwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQDEx5TZWN1cml0eSBD
+b21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQsw
+CQYDVQQGEwJKUDElMCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UE
+AxMeU2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4rCmDvu20r
+hvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzAlrenfna84xtSGc4RHwsE
+NPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MGTfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2
+/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF79+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGm
+npjKIG58u4iFW/vAEGK78vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtY
+XLVqAvO4g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3weGVPK
+p7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst+3A7caoreyYn8xrC
+3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M0V9hvqG8OmpI6iZVIhZdXw3/JzOf
+GAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQT9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0Vcw
+CBEF/VfR2ccCAwEAAaNCMEAwHQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB
+/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS
+YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PAFNr0Y/Dq9HHu
+Tofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd9XbXv8S2gVj/yP9kaWJ5rW4O
+H3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQIUYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASx
+YfQAW0q3nHE3GYV5v4GwxxMOdnE+OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZ
+XSEIx2C/pHF7uNkegr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml
++LLfiAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUVnuiZIesn
+KwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD2NCcnWXL0CsnMQMeNuE9
+dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI//1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm
+6Vwdp6POXiUyK+OVrCoHzrQoeIY8LaadTdJ0MN1kURXbg4NR16/9M51NZg==
+-----END CERTIFICATE-----
+
+Security Communication ECC RootCA1
+==================================
+-----BEGIN CERTIFICATE-----
+MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYTAkpQMSUwIwYD
+VQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYDVQQDEyJTZWN1cml0eSBDb21t
+dW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYxNjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTEL
+MAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNV
+BAMTIlNlY3VyaXR5IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+CnnfdldB9sELLo
+5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpKULGjQjBAMB0GA1UdDgQW
+BBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAK
+BggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3L
+snNdo4gIxwwCMQDAqy0Obe0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70e
+N9k=
+-----END CERTIFICATE-----
diff --git a/ms-windows/support/cli.php b/ms-windows/support/cli.php
new file mode 100644
index 0000000..ec9fc70
--- /dev/null
+++ b/ms-windows/support/cli.php
@@ -0,0 +1,455 @@
+ $val)
+ {
+ if (!isset($options["rules"][$val])) unset($options["shortmap"][$key]);
+ }
+ foreach ($options["rules"] as $key => $val)
+ {
+ if (!isset($val["arg"])) $options["rules"][$key]["arg"] = false;
+ if (!isset($val["multiple"])) $options["rules"][$key]["multiple"] = false;
+ }
+
+ if ($args === false) $args = $_SERVER["argv"];
+ else if (is_string($args))
+ {
+ $args2 = $args;
+ $args = array();
+ $inside = false;
+ $currarg = "";
+ $y = strlen($args2);
+ for ($x = 0; $x < $y; $x++)
+ {
+ $currchr = substr($args2, $x, 1);
+
+ if ($inside === false && $currchr == " " && $currarg != "")
+ {
+ $args[] = $currarg;
+ $currarg = "";
+ }
+ else if ($currchr == "\"" || $currchr == "'")
+ {
+ if ($inside === false) $inside = $currchr;
+ else if ($inside === $currchr) $inside = false;
+ else $currarg .= $currchr;
+ }
+ else if ($currchr == "\\" && $x < $y - 1)
+ {
+ $x++;
+ $currarg .= substr($args2, $x, 1);
+ }
+ else if ($inside !== false || $currchr != " ")
+ {
+ $currarg .= $currchr;
+ }
+ }
+
+ if ($currarg != "") $args[] = $currarg;
+ }
+
+ $result = array("success" => true, "file" => array_shift($args), "opts" => array(), "params" => array());
+
+ // Look over shortmap to determine if options exist that are one byte (flags) and don't have arguments.
+ $chrs = array();
+ foreach ($options["shortmap"] as $key => $val)
+ {
+ if (isset($options["rules"][$val]) && !$options["rules"][$val]["arg"]) $chrs[$key] = true;
+ }
+
+ $allowopt = true;
+ $y = count($args);
+ for ($x = 0; $x < $y; $x++)
+ {
+ $arg = $args[$x];
+
+ // Attempt to process an option.
+ $opt = false;
+ $optval = false;
+ if ($allowopt && substr($arg, 0, 1) == "-")
+ {
+ $pos = strpos($arg, "=");
+ if ($pos === false) $pos = strlen($arg);
+ else $optval = substr($arg, $pos + 1);
+ $arg2 = substr($arg, 1, $pos - 1);
+
+ if (isset($options["rules"][$arg2])) $opt = $arg2;
+ else if (isset($options["shortmap"][$arg2])) $opt = $options["shortmap"][$arg2];
+ else if ($x == 0)
+ {
+ // Attempt to process as a set of flags.
+ $y2 = strlen($arg2);
+ if ($y2 > 0)
+ {
+ for ($x2 = 0; $x2 < $y2; $x2++)
+ {
+ $currchr = substr($arg2, $x2, 1);
+
+ if (!isset($chrs[$currchr])) break;
+ }
+
+ if ($x2 == $y2)
+ {
+ for ($x2 = 0; $x2 < $y2; $x2++)
+ {
+ $opt = $options["shortmap"][substr($arg2, $x2, 1)];
+
+ if (!$options["rules"][$opt]["multiple"]) $result["opts"][$opt] = true;
+ else
+ {
+ if (!isset($result["opts"][$opt])) $result["opts"][$opt] = 0;
+ $result["opts"][$opt]++;
+ }
+ }
+
+ continue;
+ }
+ }
+ }
+ }
+
+ if ($opt === false)
+ {
+ // Is a parameter.
+ if (substr($arg, 0, 1) === "\"" || substr($arg, 0, 1) === "'") $arg = substr($arg, 1);
+ if (substr($arg, -1) === "\"" || substr($arg, -1) === "'") $arg = substr($arg, 0, -1);
+
+ $result["params"][] = $arg;
+
+ if (!$options["allow_opts_after_param"]) $allowopt = false;
+ }
+ else if (!$options["rules"][$opt]["arg"])
+ {
+ // Is a flag by itself.
+ if (!$options["rules"][$opt]["multiple"]) $result["opts"][$opt] = true;
+ else
+ {
+ if (!isset($result["opts"][$opt])) $result["opts"][$opt] = 0;
+ $result["opts"][$opt]++;
+ }
+ }
+ else
+ {
+ // Is an option.
+ if ($optval === false)
+ {
+ $x++;
+ if ($x == $y) break;
+ $optval = $args[$x];
+ }
+
+ if (substr($optval, 0, 1) === "\"" || substr($optval, 0, 1) === "'") $optval = substr($optval, 1);
+ if (substr($optval, -1) === "\"" || substr($optval, -1) === "'") $optval = substr($optval, 0, -1);
+
+ if (!$options["rules"][$opt]["multiple"]) $result["opts"][$opt] = $optval;
+ else
+ {
+ if (!isset($result["opts"][$opt])) $result["opts"][$opt] = array();
+ $result["opts"][$opt][] = $optval;
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ public static function CanGetUserInputWithArgs(&$args, $prefix)
+ {
+ return (($prefix !== false && isset($args["opts"][$prefix]) && is_array($args["opts"][$prefix]) && count($args["opts"][$prefix])) || count($args["params"]));
+ }
+
+ // Gets a line of input from the user. If the user supplies all information via the command-line, this could be entirely automated.
+ public static function GetUserInputWithArgs(&$args, $prefix, $question, $default, $noparamsoutput = "", $suppressoutput = false, $callback = false, $callbackopts = false)
+ {
+ if (!self::CanGetUserInputWithArgs($args, $prefix) && $noparamsoutput != "")
+ {
+ echo "\n" . rtrim($noparamsoutput) . "\n\n";
+
+ $suppressoutput = false;
+ $noparamsoutput = "";
+ }
+
+ do
+ {
+ $prompt = ($suppressoutput ? "" : $question . ($default !== false ? " [" . $default . "]" : "") . ": ");
+
+ if ($prefix !== false && isset($args["opts"][$prefix]) && is_array($args["opts"][$prefix]) && count($args["opts"][$prefix]))
+ {
+ $line = array_shift($args["opts"][$prefix]);
+ if ($line === "") $line = $default;
+ if (!$suppressoutput) echo $prompt . $line . "\n";
+ }
+ else if (count($args["params"]))
+ {
+ $line = array_shift($args["params"]);
+ if ($line === "") $line = $default;
+ if (!$suppressoutput) echo $prompt . $line . "\n";
+ }
+ else if (strtoupper(substr(php_uname("s"), 0, 3)) != "WIN" && function_exists("readline") && function_exists("readline_add_history"))
+ {
+ $line = readline($prompt);
+ if ($line === false) exit();
+
+ $line = trim($line);
+ if ($line === "") $line = $default;
+ if ($line !== false && $line !== "") readline_add_history($line);
+ }
+ else
+ {
+ echo $prompt;
+ fflush(STDOUT);
+ $line = fgets(STDIN);
+ if ($line === false || ($line === "" && feof(STDIN))) exit();
+
+ $line = trim($line);
+ if ($line === "") $line = $default;
+ }
+
+ if ($line === false || (is_callable($callback) && !call_user_func_array($callback, array($line, &$callbackopts))))
+ {
+ if ($line !== false) $line = false;
+ else echo "Please enter a value.\n";
+
+ if (!self::CanGetUserInputWithArgs($args, $prefix) && $noparamsoutput != "")
+ {
+ echo "\n" . $noparamsoutput . "\n";
+
+ $noparamsoutput = "";
+ }
+
+ $suppressoutput = false;
+ }
+ } while ($line === false);
+
+ return $line;
+ }
+
+ // Obtains a valid line of input.
+ public static function GetLimitedUserInputWithArgs(&$args, $prefix, $question, $default, $allowedoptionsprefix, $allowedoptions, $loop = true, $suppressoutput = false, $multipleuntil = false)
+ {
+ $noparamsoutput = $allowedoptionsprefix . "\n\n";
+ $size = 0;
+ foreach ($allowedoptions as $key => $val)
+ {
+ if ($size < strlen($key)) $size = strlen($key);
+ }
+
+ foreach ($allowedoptions as $key => $val)
+ {
+ $newtab = str_repeat(" ", 2 + $size + 3);
+ $noparamsoutput .= " " . $key . ":" . str_repeat(" ", $size - strlen($key)) . " " . str_replace("\n\t", "\n" . $newtab, $val) . "\n";
+ }
+
+ $noparamsoutput .= "\n";
+
+ if ($default === false && count($allowedoptions) == 1)
+ {
+ reset($allowedoptions);
+ $default = key($allowedoptions);
+ }
+
+ $results = array();
+ do
+ {
+ $displayed = (!count($args["params"]));
+ $result = self::GetUserInputWithArgs($args, $prefix, $question, $default, $noparamsoutput, $suppressoutput);
+ if (is_array($multipleuntil) && $multipleuntil["exit"] === $result) break;
+ $result2 = false;
+ if (!count($allowedoptions)) break;
+ foreach ($allowedoptions as $key => $val)
+ {
+ if (!strcasecmp($key, $result) || !strcasecmp($val, $result)) $result2 = $key;
+ }
+ if ($loop)
+ {
+ if ($result2 === false)
+ {
+ echo "Please select an option from the list.\n";
+
+ $suppressoutput = false;
+ }
+ else if (is_array($multipleuntil))
+ {
+ $results[$result2] = $result2;
+
+ $question = $multipleuntil["nextquestion"];
+ $default = $multipleuntil["nextdefault"];
+ }
+ }
+
+ if ($displayed) $noparamsoutput = "";
+ } while ($loop && ($result2 === false || is_array($multipleuntil)));
+
+ return (is_array($multipleuntil) ? $results : $result2);
+ }
+
+ // Obtains Yes/No style input.
+ public static function GetYesNoUserInputWithArgs(&$args, $prefix, $question, $default, $noparamsoutput = "", $suppressoutput = false)
+ {
+ $default = (substr(strtoupper(trim($default)), 0, 1) === "Y" ? "Y" : "N");
+
+ $result = self::GetUserInputWithArgs($args, $prefix, $question, $default, $noparamsoutput, $suppressoutput);
+ $result = (substr(strtoupper(trim($result)), 0, 1) === "Y");
+
+ return $result;
+ }
+
+ public static function GetHexDump($data)
+ {
+ $result = "";
+
+ $x = 0;
+ $y = strlen($data);
+ if ($y <= 256) $padwidth = 2;
+ else if ($y <= 65536) $padwidth = 4;
+ else if ($y <= 16777216) $padwidth = 6;
+ else $padwidth = 8;
+
+ $pad = str_repeat(" ", $padwidth);
+
+ $data2 = str_split(strtoupper(bin2hex($data)), 32);
+ foreach ($data2 as $line)
+ {
+ $result .= sprintf("%0" . $padwidth . "X", $x) . " | ";
+
+ $line = str_split($line, 2);
+ array_splice($line, 8, 0, "");
+ $result .= implode(" ", $line) . "\n";
+
+ $result .= $pad . " |";
+ $y2 = $x + 16;
+ for ($x2 = 0; $x2 < 16 && $x < $y; $x2++)
+ {
+ $result .= " ";
+ if ($x2 === 8) $result .= " ";
+
+ $tempchr = ord($data[$x]);
+ if ($tempchr === 0x09) $result .= "\\t";
+ else if ($tempchr === 0x0D) $result .= "\\r";
+ else if ($tempchr === 0x0A) $result .= "\\n";
+ else if ($tempchr === 0x00) $result .= "\\0";
+ else if ($tempchr < 32 || $tempchr > 126) $result .= " ";
+ else $result .= " " . $data[$x];
+
+ $x++;
+ }
+
+ $result .= "\n";
+ }
+
+ return $result;
+ }
+
+ // Outputs a JSON array (useful for captured output).
+ public static function DisplayResult($result, $exit = true)
+ {
+ if (is_array($result)) echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n";
+ else echo $result . "\n";
+
+ if ($exit) exit();
+ }
+
+ // Useful for reparsing remaining parameters as new arguments.
+ public static function ReinitArgs(&$args, $newargs)
+ {
+ // Process the parameters.
+ $options = array(
+ "shortmap" => array(
+ "?" => "help"
+ ),
+ "rules" => array(
+ )
+ );
+
+ foreach ($newargs as $arg) $options["rules"][$arg] = array("arg" => true, "multiple" => true);
+ $options["rules"]["help"] = array("arg" => false);
+
+ $args = self::ParseCommandLine($options, array_merge(array(""), $args["params"]));
+
+ if (isset($args["opts"]["help"])) self::DisplayResult(array("success" => true, "options" => array_keys($options["rules"])));
+ }
+
+ // Tracks messages for a command-line interface app.
+ private static $messages = array();
+
+ public static function LogMessage($msg, $data = null)
+ {
+ if (isset($data)) $msg .= "\n\t" . trim(str_replace("\n", "\n\t", json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)));
+
+ self::$messages[] = $msg;
+
+ fwrite(STDERR, $msg . "\n");
+ }
+
+ public static function DisplayError($msg, $result = false, $exit = true)
+ {
+ self::LogMessage(($exit ? "[Error] " : "") . $msg);
+
+ if ($result !== false && is_array($result) && isset($result["error"]) && isset($result["errorcode"])) self::LogMessage("[Error] " . $result["error"] . " (" . $result["errorcode"] . ")", (isset($result["info"]) ? $result["info"] : null));
+
+ if ($exit) exit();
+ }
+
+ public static function GetLogMessages($filters = array())
+ {
+ if (is_string($filters)) $filters = array($filters);
+
+ $result = array();
+ foreach (self::$messages as $message)
+ {
+ $found = (!count($filters));
+ foreach ($filters as $filter)
+ {
+ if (preg_match($filter, $message)) $found = true;
+ }
+
+ if ($found) $result[] = $message;
+ }
+
+ return $result;
+ }
+
+ public static function ResetLogMessages()
+ {
+ self::$messages = array();
+ }
+
+
+ private static $timerinfo = array();
+
+ public static function StartTimer()
+ {
+ $ts = microtime(true);
+
+ self::$timerinfo = array(
+ "start" => $ts,
+ "diff" => $ts
+ );
+ }
+
+ public static function UpdateTimer()
+ {
+ $ts = microtime(true);
+ $diff = $ts - self::$timerinfo["diff"];
+ self::$timerinfo["diff"] = $ts;
+
+ $result = array(
+ "success" => true,
+ "diff" => sprintf("%.2f", $diff),
+ "total" => sprintf("%.2f", $ts - self::$timerinfo["start"])
+ );
+
+ return $result;
+ }
+ }
+?>
\ No newline at end of file
diff --git a/ms-windows/support/crc32_stream.php b/ms-windows/support/crc32_stream.php
new file mode 100644
index 0000000..0a68c87
--- /dev/null
+++ b/ms-windows/support/crc32_stream.php
@@ -0,0 +1,119 @@
+ 0x04C11DB7, "start" => 0xFFFFFFFF, "xor" => 0xFFFFFFFF, "refdata" => 1, "refcrc" => 1);
+
+ public function __construct()
+ {
+ $this->open = false;
+ }
+
+ public function Init($options = false)
+ {
+ if ($options === false && function_exists("hash_init")) $this->hash = hash_init("crc32b");
+ else
+ {
+ if ($options === false) $options = self::$default;
+
+ $this->hash = false;
+ $this->crctable = array();
+ $poly = $this->LIM32($options["poly"]);
+ for ($x = 0; $x < 256; $x++)
+ {
+ $c = $this->SHL32($x, 24);
+ for ($y = 0; $y < 8; $y++) $c = $this->SHL32($c, 1) ^ ($c & 0x80000000 ? $poly : 0);
+ $this->crctable[$x] = $c;
+ }
+
+ $this->datareflect = $options["refdata"];
+ $this->crcreflect = $options["refcrc"];
+ $this->firstcrc = $options["start"];
+ $this->currcrc = $options["start"];
+ $this->finalxor = $options["xor"];
+ }
+
+ $this->open = true;
+ }
+
+ public function AddData($data)
+ {
+ if (!$this->open) return false;
+
+ if ($this->hash !== false) hash_update($this->hash, $data);
+ else
+ {
+ $y = strlen($data);
+
+ for ($x = 0; $x < $y; $x++)
+ {
+ if ($this->datareflect) $this->currcrc = $this->SHL32($this->currcrc, 8) ^ $this->crctable[$this->SHR32($this->currcrc, 24) ^ self::$revlookup[ord($data[$x])]];
+ else $this->currcrc = $this->SHL32($this->currcrc, 8) ^ $this->crctable[$this->SHR32($this->currcrc, 24) ^ ord($data[$x])];
+ }
+ }
+
+ return true;
+ }
+
+ public function Finalize()
+ {
+ if (!$this->open) return false;
+
+ if ($this->hash !== false)
+ {
+ $result = hexdec(hash_final($this->hash));
+
+ $this->hash = hash_init("crc32b");
+ }
+ else
+ {
+ if ($this->crcreflect)
+ {
+ $tempcrc = $this->currcrc;
+ $this->currcrc = self::$revlookup[$this->SHR32($tempcrc, 24)] | $this->SHL32(self::$revlookup[$this->SHR32($tempcrc, 16) & 0xFF], 8) | $this->SHL32(self::$revlookup[$this->SHR32($tempcrc, 8) & 0xFF], 16) | $this->SHL32(self::$revlookup[$this->LIM32($tempcrc & 0xFF)], 24);
+ }
+ $result = $this->currcrc ^ $this->finalxor;
+
+ $this->currcrc = $this->firstcrc;
+ }
+
+ return $result;
+ }
+
+ // These functions are a hacky, but effective way of enforcing unsigned 32-bit integers onto a generic signed int.
+ // Allow bitwise operations to work across platforms. Minimum integer size must be 32-bit.
+ private function SHR32($num, $bits)
+ {
+ $num = (int)$num;
+ if ($bits < 0) $bits = 0;
+
+ if ($num < 0 && $bits)
+ {
+ $num = ($num >> 1) & 0x7FFFFFFF;
+ $bits--;
+ }
+
+ return $this->LIM32($num >> $bits);
+ }
+
+ private function SHL32($num, $bits)
+ {
+ if ($bits < 0) $bits = 0;
+
+ return $this->LIM32((int)$num << $bits);
+ }
+
+ private function LIM32($num)
+ {
+ return (int)((int)$num & 0xFFFFFFFF);
+ }
+ }
+?>
\ No newline at end of file
diff --git a/ms-windows/support/deflate_stream.php b/ms-windows/support/deflate_stream.php
new file mode 100644
index 0000000..ab1f70a
--- /dev/null
+++ b/ms-windows/support/deflate_stream.php
@@ -0,0 +1,365 @@
+open = false;
+ }
+
+ public function __destruct()
+ {
+ $this->Finalize();
+ }
+
+ public static function IsSupported()
+ {
+ if (!is_bool(self::$supported))
+ {
+ self::$supported = function_exists("stream_filter_append") && function_exists("stream_filter_remove") && function_exists("gzcompress");
+ if (self::$supported)
+ {
+ $data = self::Compress("test");
+ if ($data === false || $data === "") self::$supported = false;
+ else
+ {
+ $data = self::Uncompress($data);
+ if ($data === false || $data !== "test") self::$supported = false;
+ }
+ }
+ }
+
+ return self::$supported;
+ }
+
+ public static function Compress($data, $compresslevel = -1, $options = array())
+ {
+ $ds = new DeflateStream;
+ if (!$ds->Init("wb", $compresslevel, $options)) return false;
+ if (!$ds->Write($data)) return false;
+ if (!$ds->Finalize()) return false;
+ $data = $ds->Read();
+
+ return $data;
+ }
+
+ public static function Uncompress($data, $options = array("type" => "auto"))
+ {
+ $ds = new DeflateStream;
+ if (!$ds->Init("rb", -1, $options)) return false;
+ if (!$ds->Write($data)) return false;
+ if (!$ds->Finalize()) return false;
+ $data = $ds->Read();
+
+ return $data;
+ }
+
+ public function Init($mode, $compresslevel = -1, $options = array())
+ {
+ if ($mode !== "rb" && $mode !== "wb") return false;
+ if ($this->open) $this->Finalize();
+
+ $this->fp = fopen("php://memory", "w+b");
+ if ($this->fp === false) return false;
+ $this->compress = ($mode == "wb");
+ if (!isset($options["type"])) $options["type"] = "rfc1951";
+
+ if ($options["type"] == "rfc1950") $options["type"] = "zlib";
+ else if ($options["type"] == "rfc1952") $options["type"] = "gzip";
+
+ if ($options["type"] != "zlib" && $options["type"] != "gzip" && ($this->compress || $options["type"] != "auto")) $options["type"] = "raw";
+ $this->options = $options;
+
+ // Add the deflate filter.
+ if ($this->compress) $this->filter = stream_filter_append($this->fp, "zlib.deflate", STREAM_FILTER_WRITE, $compresslevel);
+ else $this->filter = stream_filter_append($this->fp, "zlib.inflate", STREAM_FILTER_READ);
+
+ $this->open = true;
+ $this->indata = "";
+ $this->outdata = "";
+
+ if ($this->compress)
+ {
+ if ($this->options["type"] == "zlib")
+ {
+ $this->outdata .= "\x78\x9C";
+ $this->options["a"] = 1;
+ $this->options["b"] = 0;
+ }
+ else if ($this->options["type"] == "gzip")
+ {
+ if (!class_exists("CRC32Stream", false)) require_once str_replace("\\", "/", dirname(__FILE__)) . "/crc32_stream.php";
+
+ $this->options["crc32"] = new CRC32Stream();
+ $this->options["crc32"]->Init();
+ $this->options["bytes"] = 0;
+
+ $this->outdata .= "\x1F\x8B\x08";
+ $flags = 0;
+ if (isset($this->options["filename"])) $flags |= 0x08;
+ if (isset($this->options["comment"])) $flags |= 0x10;
+ $this->outdata .= chr($flags);
+ $this->outdata .= "\x00\x00\x00\x00";
+ $this->outdata .= "\x00";
+ $this->outdata .= "\x03";
+
+ if (isset($this->options["filename"])) $this->outdata .= str_replace("\x00", " ", $this->options["filename"]) . "\x00";
+ if (isset($this->options["comment"])) $this->outdata .= str_replace("\x00", " ", $this->options["comment"]) . "\x00";
+ }
+ }
+ else
+ {
+ $this->options["header"] = false;
+ }
+
+ return true;
+ }
+
+ public function Read()
+ {
+ $result = $this->outdata;
+ $this->outdata = "";
+
+ return $result;
+ }
+
+ public function Write($data)
+ {
+ if (!$this->open) return false;
+
+ if ($this->compress)
+ {
+ if ($this->options["type"] == "zlib")
+ {
+ // Adler-32.
+ $y = strlen($data);
+ for ($x = 0; $x < $y; $x++)
+ {
+ $this->options["a"] = ($this->options["a"] + ord($data[$x])) % 65521;
+ $this->options["b"] = ($this->options["b"] + $this->options["a"]) % 65521;
+ }
+ }
+ else if ($this->options["type"] == "gzip")
+ {
+ $this->options["crc32"]->AddData($data);
+ $this->options["bytes"] = $this->ADD32($this->options["bytes"], strlen($data));
+ }
+
+ $this->indata .= $data;
+ while (strlen($this->indata) >= 65536)
+ {
+ fwrite($this->fp, substr($this->indata, 0, 65536));
+ $this->indata = substr($this->indata, 65536);
+
+ $this->ProcessOutput();
+ }
+ }
+ else
+ {
+ $this->indata .= $data;
+ $this->ProcessInput();
+ }
+
+ return true;
+ }
+
+ // Finalizes the stream.
+ public function Finalize()
+ {
+ if (!$this->open) return false;
+
+ if (!$this->compress) $this->ProcessInput(true);
+
+ if (strlen($this->indata) > 0)
+ {
+ fwrite($this->fp, $this->indata);
+ $this->indata = "";
+ }
+
+ // Removing the filter pushes the last buffer into the stream.
+ stream_filter_remove($this->filter);
+ $this->filter = false;
+
+ $this->ProcessOutput();
+
+ fclose($this->fp);
+
+ if ($this->compress)
+ {
+ if ($this->options["type"] == "zlib") $this->outdata .= pack("N", $this->SHL32($this->options["b"], 16) | $this->options["a"]);
+ else if ($this->options["type"] == "gzip") $this->outdata .= pack("V", $this->options["crc32"]->Finalize()) . pack("V", $this->options["bytes"]);
+ }
+
+ $this->open = false;
+
+ return true;
+ }
+
+ private function ProcessOutput()
+ {
+ rewind($this->fp);
+
+ // Hack! Because ftell() on a stream with a filter is still broken even under the latest PHP a mere 11 years later.
+ // See: https://bugs.php.net/bug.php?id=49874
+ ob_start();
+ fpassthru($this->fp);
+ $this->outdata .= ob_get_contents();
+ ob_end_clean();
+
+ rewind($this->fp);
+ ftruncate($this->fp, 0);
+ }
+
+ private function ProcessInput($final = false)
+ {
+ // Automatically determine the type of data based on the header signature.
+ if ($this->options["type"] == "auto")
+ {
+ if (strlen($this->indata) >= 3)
+ {
+ $zlibtest = unpack("n", substr($this->indata, 0, 2));
+
+ if (substr($this->indata, 0, 3) === "\x1F\x8B\x08") $this->options["type"] = "gzip";
+ else if ((ord($this->indata[0]) & 0x0F) == 8 && ((ord($this->indata[0]) & 0xF0) >> 4) < 8 && $zlibtest[1] % 31 == 0) $this->options["type"] = "zlib";
+ else $this->options["type"] = "raw";
+ }
+ else if ($final) $this->options["type"] = "raw";
+ }
+
+ if ($this->options["type"] == "gzip")
+ {
+ if (!$this->options["header"])
+ {
+ if (strlen($this->indata) >= 10)
+ {
+ $idcm = substr($this->indata, 0, 3);
+ $flg = ord($this->indata[3]);
+
+ if ($idcm !== "\x1F\x8B\x08") $this->options["type"] = "ignore";
+ else
+ {
+ // Calculate the number of bytes to skip. If flags are set, the size can be dynamic.
+ $size = 10;
+ $y = strlen($this->indata);
+
+ // FLG.FEXTRA
+ if ($size && ($flg & 0x04))
+ {
+ if ($size + 2 >= $y) $size = 0;
+ else
+ {
+ $xlen = unpack("v", substr($this->indata, $size, 2));
+ $size = ($size + 2 + $xlen <= $y ? $size + 2 + $xlen : 0);
+ }
+ }
+
+ // FLG.FNAME
+ if ($size && ($flg & 0x08))
+ {
+ $pos = strpos($this->indata, "\x00", $size);
+ $size = ($pos !== false ? $pos + 1 : 0);
+ }
+
+ // FLG.FCOMMENT
+ if ($size && ($flg & 0x10))
+ {
+ $pos = strpos($this->indata, "\x00", $size);
+ $size = ($pos !== false ? $pos + 1 : 0);
+ }
+
+ // FLG.FHCRC
+ if ($size && ($flg & 0x02)) $size = ($size + 2 <= $y ? $size + 2 : 0);
+
+ if ($size)
+ {
+ $this->indata = substr($this->indata, $size);
+ $this->options["header"] = true;
+ }
+ }
+ }
+ }
+
+ if ($this->options["header"] && strlen($this->indata) > 8)
+ {
+ fwrite($this->fp, substr($this->indata, 0, -8));
+ $this->indata = substr($this->indata, -8);
+
+ $this->ProcessOutput();
+ }
+
+ if ($final) $this->indata = "";
+ }
+ else if ($this->options["type"] == "zlib")
+ {
+ if (!$this->options["header"])
+ {
+ if (strlen($this->indata) >= 2)
+ {
+ $cmf = ord($this->indata[0]);
+ $flg = ord($this->indata[1]);
+ $cm = $cmf & 0x0F;
+ $cinfo = ($cmf & 0xF0) >> 4;
+
+ // Compression method 'deflate' ($cm = 8), window size - 8 ($cinfo < 8), no preset dictionaries ($flg bit 5), checksum validates.
+ if ($cm != 8 || $cinfo > 7 || ($flg & 0x20) || (($cmf << 8 | $flg) % 31) != 0) $this->options["type"] = "ignore";
+ else
+ {
+ $this->indata = substr($this->indata, 2);
+ $this->options["header"] = true;
+ }
+ }
+ }
+
+ if ($this->options["header"] && strlen($this->indata) > 4)
+ {
+ fwrite($this->fp, substr($this->indata, 0, -4));
+ $this->indata = substr($this->indata, -4);
+
+ $this->ProcessOutput();
+ }
+
+ if ($final) $this->indata = "";
+ }
+
+ if ($this->options["type"] == "raw")
+ {
+ fwrite($this->fp, $this->indata);
+ $this->indata = "";
+
+ $this->ProcessOutput();
+ }
+
+ // Only set when an unrecoverable header error has occurred for gzip or zlib.
+ if ($this->options["type"] == "ignore") $this->indata = "";
+ }
+
+ private function SHL32($num, $bits)
+ {
+ if ($bits < 0) $bits = 0;
+
+ return $this->LIM32((int)$num << $bits);
+ }
+
+ private function LIM32($num)
+ {
+ return (int)((int)$num & 0xFFFFFFFF);
+ }
+
+ private function ADD32($num, $num2)
+ {
+ $num = (int)$num;
+ $num2 = (int)$num2;
+ $add = ((($num >> 30) & 0x03) + (($num2 >> 30) & 0x03));
+ $num = ((int)($num & 0x3FFFFFFF) + (int)($num2 & 0x3FFFFFFF));
+ if ($num & 0x40000000) $add++;
+ $num = (int)(($num & 0x3FFFFFFF) | (($add & 0x03) << 30));
+
+ return $num;
+ }
+ }
+?>
\ No newline at end of file
diff --git a/ms-windows/support/http.php b/ms-windows/support/http.php
new file mode 100644
index 0000000..5a665bc
--- /dev/null
+++ b/ms-windows/support/http.php
@@ -0,0 +1,1909 @@
+ "",
+ "authority" => "",
+ "login" => "",
+ "loginusername" => "",
+ "loginpassword" => "",
+ "host" => "",
+ "port" => "",
+ "path" => "",
+ "query" => "",
+ "queryvars" => array(),
+ "fragment" => ""
+ );
+
+ $url = str_replace("&", "&", $url);
+
+ $pos = strpos($url, "#");
+ if ($pos !== false)
+ {
+ $result["fragment"] = substr($url, $pos + 1);
+ $url = substr($url, 0, $pos);
+ }
+
+ $pos = strpos($url, "?");
+ if ($pos !== false)
+ {
+ $result["query"] = str_replace(" ", "+", substr($url, $pos + 1));
+ $url = substr($url, 0, $pos);
+ $vars = explode("&", $result["query"]);
+ foreach ($vars as $var)
+ {
+ $pos = strpos($var, "=");
+ if ($pos === false)
+ {
+ $name = $var;
+ $value = "";
+ }
+ else
+ {
+ $name = substr($var, 0, $pos);
+ $value = urldecode(substr($var, $pos + 1));
+ }
+ $name = urldecode($name);
+ if (!isset($result["queryvars"][$name])) $result["queryvars"][$name] = array();
+ $result["queryvars"][$name][] = $value;
+ }
+ }
+
+ $url = str_replace("\\", "/", $url);
+
+ $pos = strpos($url, ":");
+ $pos2 = strpos($url, "/");
+ if ($pos !== false && ($pos2 === false || $pos < $pos2))
+ {
+ $result["scheme"] = strtolower(substr($url, 0, $pos));
+ $url = substr($url, $pos + 1);
+ }
+
+ if (substr($url, 0, 2) != "//") $result["path"] = $url;
+ else
+ {
+ $url = substr($url, 2);
+ $pos = strpos($url, "/");
+ if ($pos !== false)
+ {
+ $result["path"] = substr($url, $pos);
+ $url = substr($url, 0, $pos);
+ }
+ $result["authority"] = $url;
+
+ $pos = strpos($url, "@");
+ if ($pos !== false)
+ {
+ $result["login"] = substr($url, 0, $pos);
+ $url = substr($url, $pos + 1);
+ $pos = strpos($result["login"], ":");
+ if ($pos === false) $result["loginusername"] = urldecode($result["login"]);
+ else
+ {
+ $result["loginusername"] = urldecode(substr($result["login"], 0, $pos));
+ $result["loginpassword"] = urldecode(substr($result["login"], $pos + 1));
+ }
+ }
+
+ $pos = strpos($url, "]");
+ if (substr($url, 0, 1) == "[" && $pos !== false)
+ {
+ // IPv6 literal address.
+ $result["host"] = substr($url, 0, $pos + 1);
+ $url = substr($url, $pos + 1);
+
+ $pos = strpos($url, ":");
+ if ($pos !== false)
+ {
+ $result["port"] = substr($url, $pos + 1);
+ $url = substr($url, 0, $pos);
+ }
+ }
+ else
+ {
+ // Normal host[:port].
+ $pos = strpos($url, ":");
+ if ($pos !== false)
+ {
+ $result["port"] = substr($url, $pos + 1);
+ $url = substr($url, 0, $pos);
+ }
+
+ $result["host"] = $url;
+
+ // Handle conversion to Punycode for IDNs.
+ if ($idnahost)
+ {
+ $y = strlen($result["host"]);
+ for ($x = 0; $x < $y && ord($result["host"][$x]) <= 0x7F; $x++);
+
+ if ($x < $y)
+ {
+ if (!class_exists("UTFUtils", false)) require_once str_replace("\\", "/", dirname(__FILE__)) . "/utf_utils.php";
+
+ $host = UTFUtils::ConvertToPunycode($result["host"]);
+ if ($host !== false)
+ {
+ $result["orighost"] = $result["host"];
+ $result["host"] = $host;
+ }
+ }
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ // Takes a ExtractURL() array and condenses it into a string.
+ public static function CondenseURL($data)
+ {
+ $result = "";
+ if (isset($data["host"]) && $data["host"] != "")
+ {
+ if (isset($data["scheme"]) && $data["scheme"] != "") $result = $data["scheme"] . "://";
+ if (isset($data["loginusername"]) && $data["loginusername"] != "" && isset($data["loginpassword"])) $result .= rawurlencode($data["loginusername"]) . ($data["loginpassword"] != "" ? ":" . rawurlencode($data["loginpassword"]) : "") . "@";
+ else if (isset($data["login"]) && $data["login"] != "") $result .= $data["login"] . "@";
+
+ $result .= $data["host"];
+ if (isset($data["port"]) && $data["port"] != "") $result .= ":" . $data["port"];
+
+ if (isset($data["path"]))
+ {
+ $data["path"] = str_replace("\\", "/", $data["path"]);
+ if (substr($data["path"], 0, 1) != "/") $data["path"] = "/" . $data["path"];
+ $result .= $data["path"];
+ }
+ }
+ else if (isset($data["authority"]) && $data["authority"] != "")
+ {
+ if (isset($data["scheme"]) && $data["scheme"] != "") $result = $data["scheme"] . "://";
+
+ $result .= $data["authority"];
+
+ if (isset($data["path"]))
+ {
+ $data["path"] = str_replace("\\", "/", $data["path"]);
+ if (substr($data["path"], 0, 1) != "/") $data["path"] = "/" . $data["path"];
+ $result .= $data["path"];
+ }
+ }
+ else if (isset($data["path"]))
+ {
+ if (isset($data["scheme"]) && $data["scheme"] != "") $result = $data["scheme"] . ":";
+
+ $result .= $data["path"];
+ }
+
+ if (isset($data["query"]))
+ {
+ if ($data["query"] != "") $result .= "?" . $data["query"];
+ }
+ else if (isset($data["queryvars"]))
+ {
+ $data["query"] = array();
+ foreach ($data["queryvars"] as $key => $vals)
+ {
+ if (is_string($vals)) $vals = array($vals);
+ foreach ($vals as $val) $data["query"][] = urlencode($key) . "=" . urlencode($val);
+ }
+ $data["query"] = implode("&", $data["query"]);
+
+ if ($data["query"] != "") $result .= "?" . $data["query"];
+ }
+
+ if (isset($data["fragment"]) && $data["fragment"] != "") $result .= "#" . $data["fragment"];
+
+ return $result;
+ }
+
+ public static function ConvertRelativeToAbsoluteURL($baseurl, $relativeurl)
+ {
+ $relative = (is_array($relativeurl) ? $relativeurl : self::ExtractURL($relativeurl));
+ $base = (is_array($baseurl) ? $baseurl : self::ExtractURL($baseurl));
+
+ if ($relative["host"] != "" || ($relative["scheme"] != "" && $relative["scheme"] != $base["scheme"]))
+ {
+ if ($relative["scheme"] == "") $relative["scheme"] = $base["scheme"];
+
+ return self::CondenseURL($relative);
+ }
+
+ $result = array(
+ "scheme" => $base["scheme"],
+ "loginusername" => $base["loginusername"],
+ "loginpassword" => $base["loginpassword"],
+ "host" => $base["host"],
+ "port" => $base["port"],
+ "path" => "",
+ "query" => $relative["query"],
+ "fragment" => $relative["fragment"]
+ );
+
+ if ($relative["path"] == "") $result["path"] = $base["path"];
+ else if (substr($relative["path"], 0, 1) == "/") $result["path"] = $relative["path"];
+ else
+ {
+ $abspath = explode("/", $base["path"]);
+ array_pop($abspath);
+ $relpath = explode("/", $relative["path"]);
+ foreach ($relpath as $piece)
+ {
+ if ($piece == ".")
+ {
+ }
+ else if ($piece == "..") array_pop($abspath);
+ else $abspath[] = $piece;
+ }
+
+ $abspath = implode("/", $abspath);
+ if (substr($abspath, 0, 1) != "/") $abspath = "/" . $abspath;
+
+ $result["path"] = $abspath;
+ }
+
+ return self::CondenseURL($result);
+ }
+
+ public static function GetUserAgent($type)
+ {
+ $type = strtolower($type);
+
+ if ($type == "ie") $type = "ie11";
+
+ // Last updated March 10, 2022.
+ if ($type == "ie6") return "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)";
+ else if ($type == "ie7") return "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 6.0)";
+ else if ($type == "ie8") return "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1)";
+ else if ($type == "ie9") return "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)";
+ else if ($type == "ie10") return "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)";
+ else if ($type == "ie11") return "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko";
+ else if ($type == "edge") return "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.36";
+ else if ($type == "firefox") return "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0";
+ else if ($type == "opera") return "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 OPR/84.0.4316.21";
+ else if ($type == "safari") return "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_2_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Safari/605.1.15";
+ else if ($type == "chrome") return "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36";
+
+ return "";
+ }
+
+ public static function GetSSLCiphers($type = "intermediate")
+ {
+ $type = strtolower($type);
+
+ // Cipher list last updated March 10, 2022.
+ // Source: https://ssl-config.mozilla.org/
+ if ($type == "modern") return "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
+ else if ($type == "old") return "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP";
+
+ return "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS";
+ }
+
+ public static function GetSafeSSLOpts($cafile = true, $cipherstype = "intermediate")
+ {
+ // Result array last updated Feb 15, 2020.
+ $result = array(
+ "ciphers" => self::GetSSLCiphers($cipherstype),
+ "disable_compression" => true,
+ "allow_self_signed" => false,
+ "verify_peer" => true,
+ "verify_depth" => 5,
+ "SNI_enabled" => true
+ );
+
+ if ($cafile === true) $result["auto_cainfo"] = true;
+ else if ($cafile !== false) $result["cafile"] = $cafile;
+
+ return $result;
+ }
+
+ // Reasonably parses RFC1123, RFC850, and asctime() dates.
+ public static function GetDateTimestamp($httpdate)
+ {
+ $timestamp_map = array(
+ "jan" => 1, "feb" => 2, "mar" => 3, "apr" => 4, "may" => 5, "jun" => 6,
+ "jul" => 7, "aug" => 8, "sep" => 9, "oct" => 10, "nov" => 11, "dec" => 12
+ );
+
+ $year = false;
+ $month = false;
+ $day = false;
+ $hour = false;
+ $min = false;
+ $sec = false;
+
+ $items = explode(" ", preg_replace('/\s+/', " ", str_replace("-", " ", strtolower($httpdate))));
+ foreach ($items as $item)
+ {
+ if ($item != "")
+ {
+ if (strpos($item, ":") !== false)
+ {
+ $item = explode(":", $item);
+ $hour = (int)(count($item) > 0 ? array_shift($item) : 0);
+ $min = (int)(count($item) > 0 ? array_shift($item) : 0);
+ $sec = (int)(count($item) > 0 ? array_shift($item) : 0);
+
+ if ($hour > 23) $hour = 23;
+ if ($min > 59) $min = 59;
+ if ($sec > 59) $sec = 59;
+ }
+ else if (is_numeric($item))
+ {
+ if (strlen($item) >= 4) $year = (int)$item;
+ else if ($day === false) $day = (int)$item;
+ else $year = substr(date("Y"), 0, 2) . substr($item, -2);
+ }
+ else
+ {
+ $item = substr($item, 0, 3);
+ if (isset($timestamp_map[$item])) $month = $timestamp_map[$item];
+ }
+ }
+ }
+
+ if ($year === false || $month === false || $day === false || $hour === false || $min === false || $sec === false) return false;
+
+ return gmmktime($hour, $min, $sec, $month, $day, $year);
+ }
+
+ public static function HTTPTranslate()
+ {
+ $args = func_get_args();
+ if (!count($args)) return "";
+
+ return call_user_func_array((defined("CS_TRANSLATE_FUNC") && function_exists(CS_TRANSLATE_FUNC) ? CS_TRANSLATE_FUNC : "sprintf"), $args);
+ }
+
+ public static function HeaderNameCleanup($name)
+ {
+ return preg_replace('/\s+/', "-", ucwords(strtolower(trim(preg_replace('/[^A-Za-z0-9 ]/', " ", $name)))));
+ }
+
+ private static function HeaderValueCleanup($value)
+ {
+ return str_replace(array("\r", "\n"), array("", ""), $value);
+ }
+
+ public static function NormalizeHeaders($headers)
+ {
+ $result = array();
+ foreach ($headers as $name => $val)
+ {
+ $val = self::HeaderValueCleanup($val);
+ if ($val != "") $result[self::HeaderNameCleanup($name)] = $val;
+ }
+
+ return $result;
+ }
+
+ public static function MergeRawHeaders(&$headers, $rawheaders)
+ {
+ foreach ($rawheaders as $name => $val)
+ {
+ $val = self::HeaderValueCleanup($val);
+ if ($val != "")
+ {
+ $name2 = self::HeaderNameCleanup($name);
+ if (isset($headers[$name2])) unset($headers[$name2]);
+
+ $headers[$name] = $val;
+ }
+ }
+ }
+
+ public static function ExtractHeader($data)
+ {
+ $result = array();
+ $data = trim($data);
+ while ($data != "")
+ {
+ // Extract name/value pair.
+ $pos = strpos($data, "=");
+ $pos2 = strpos($data, ";");
+ if (($pos !== false && $pos2 === false) || ($pos !== false && $pos2 !== false && $pos < $pos2))
+ {
+ $name = trim(substr($data, 0, $pos));
+ $data = trim(substr($data, $pos + 1));
+ if (ord($data[0]) == ord("\""))
+ {
+ $pos = strpos($data, "\"", 1);
+ if ($pos !== false)
+ {
+ $value = substr($data, 1, $pos - 1);
+ $data = trim(substr($data, $pos + 1));
+ $pos = strpos($data, ";");
+ if ($pos !== false) $data = substr($data, $pos + 1);
+ else $data = "";
+ }
+ else
+ {
+ $value = $data;
+ $data = "";
+ }
+ }
+ else
+ {
+ $pos = strpos($data, ";");
+ if ($pos !== false)
+ {
+ $value = trim(substr($data, 0, $pos));
+ $data = substr($data, $pos + 1);
+ }
+ else
+ {
+ $value = $data;
+ $data = "";
+ }
+ }
+ }
+ else if ($pos2 !== false)
+ {
+ $name = "";
+ $value = trim(substr($data, 0, $pos2));
+ $data = substr($data, $pos2 + 1);
+ }
+ else
+ {
+ $name = "";
+ $value = $data;
+ $data = "";
+ }
+
+ if ($name != "" || $value != "") $result[strtolower($name)] = $value;
+
+ $data = trim($data);
+ }
+
+ return $result;
+ }
+
+ private static function ProcessSSLOptions(&$options, $key, $host)
+ {
+ if (isset($options[$key]["auto_cainfo"]))
+ {
+ unset($options[$key]["auto_cainfo"]);
+
+ $cainfo = ini_get("curl.cainfo");
+ if ($cainfo !== false && strlen($cainfo) > 0) $options[$key]["cafile"] = $cainfo;
+ else if (file_exists(str_replace("\\", "/", dirname(__FILE__)) . "/cacert.pem")) $options[$key]["cafile"] = str_replace("\\", "/", dirname(__FILE__)) . "/cacert.pem";
+ }
+
+ if (isset($options[$key]["auto_peer_name"]))
+ {
+ unset($options[$key]["auto_peer_name"]);
+
+ if (!isset($options["headers"]["Host"])) $options[$key]["peer_name"] = $host;
+ else
+ {
+ $info = self::ExtractURL("https://" . $options["headers"]["Host"]);
+ $options[$key]["peer_name"] = $info["host"];
+ }
+ }
+
+ if (isset($options[$key]["auto_cn_match"]))
+ {
+ unset($options[$key]["auto_cn_match"]);
+
+ if (!isset($options["headers"]["Host"])) $options[$key]["CN_match"] = $host;
+ else
+ {
+ $info = self::ExtractURL("https://" . $options["headers"]["Host"]);
+ $options[$key]["CN_match"] = $info["host"];
+ }
+ }
+
+ if (isset($options[$key]["auto_sni"]))
+ {
+ unset($options[$key]["auto_sni"]);
+
+ $options[$key]["SNI_enabled"] = true;
+ if (!isset($options["headers"]["Host"])) $options[$key]["SNI_server_name"] = $host;
+ else
+ {
+ $info = self::ExtractURL("https://" . $options["headers"]["Host"]);
+ $options[$key]["SNI_server_name"] = $info["host"];
+ }
+ }
+ }
+
+ // Swiped from str_basics.php so this file can be standalone.
+ public static function ExtractFilename($dirfile)
+ {
+ $dirfile = str_replace("\\", "/", $dirfile);
+ $pos = strrpos($dirfile, "/");
+ if ($pos !== false) $dirfile = substr($dirfile, $pos + 1);
+
+ return $dirfile;
+ }
+
+ public static function FilenameSafe($filename)
+ {
+ return preg_replace('/[_]+/', "_", preg_replace('/[^A-Za-z0-9_.\-]/', "_", $filename));
+ }
+
+ public static function GetTimeLeft($start, $limit)
+ {
+ if ($limit === false) return false;
+
+ $difftime = microtime(true) - $start;
+ if ($difftime >= $limit) return 0;
+
+ return $limit - $difftime;
+ }
+
+ private static function ProcessRateLimit($size, $start, $limit, $async)
+ {
+ $difftime = microtime(true) - $start;
+ if ($difftime > 0.0)
+ {
+ if ($size / $difftime > $limit)
+ {
+ // Sleeping for some amount of time will equalize the rate.
+ // So, solve this for $x: $size / ($x + $difftime) = $limit
+ $amount = ($size - ($limit * $difftime)) / $limit;
+ $amount += 0.001;
+
+ if ($async) return microtime(true) + $amount;
+ else usleep($amount * 1000000);
+ }
+ }
+
+ return -1.0;
+ }
+
+ private static function GetDecodedBody(&$autodecode_ds, $body)
+ {
+ if ($autodecode_ds !== false)
+ {
+ $autodecode_ds->Write($body);
+ $body = $autodecode_ds->Read();
+ }
+
+ return $body;
+ }
+
+ private static function StreamTimedOut($fp)
+ {
+ if (!function_exists("stream_get_meta_data")) return false;
+
+ $info = stream_get_meta_data($fp);
+
+ return $info["timed_out"];
+ }
+
+ public static function InitResponseState($fp, $debug, $options, $startts, $timeout, $result, $close, $nextread, $client = true)
+ {
+ $state = array(
+ "fp" => $fp,
+ "type" => "response",
+ "async" => (isset($options["async"]) ? $options["async"] : false),
+ "debug" => $debug,
+ "startts" => $startts,
+ "timeout" => $timeout,
+ "waituntil" => -1.0,
+ "rawdata" => "",
+ "data" => "",
+ "rawsize" => 0,
+ "rawrecvheadersize" => 0,
+ "numheaders" => 0,
+ "autodecode" => (!isset($options["auto_decode"]) || $options["auto_decode"]),
+
+ "state" => ($client ? "response_line" : "request_line"),
+
+ "options" => $options,
+ "result" => $result,
+ "close" => $close,
+ "nextread" => $nextread,
+ "client" => $client
+ );
+
+ $state["result"]["recvstart"] = microtime(true);
+ $state["result"]["response"] = false;
+ $state["result"]["headers"] = false;
+ $state["result"]["body"] = false;
+
+ return $state;
+ }
+
+ // Handles partially read input. Also deals with the hacky workaround to the second bugfix in ProcessState__WriteData().
+ private static function ProcessState__InternalRead(&$state, $size, $endchar = false)
+ {
+ $y = strlen($state["nextread"]);
+
+ do
+ {
+ if ($size <= $y)
+ {
+ if ($endchar === false) $pos = $size;
+ else
+ {
+ $pos = strpos($state["nextread"], $endchar);
+ if ($pos === false || $pos > $size) $pos = $size;
+ else $pos++;
+ }
+
+ $data = substr($state["nextread"], 0, $pos);
+ $state["nextread"] = (string)substr($state["nextread"], $pos);
+
+ return $data;
+ }
+
+ if ($endchar !== false)
+ {
+ $pos = strpos($state["nextread"], $endchar);
+ if ($pos !== false)
+ {
+ $data = substr($state["nextread"], 0, $pos + 1);
+ $state["nextread"] = (string)substr($state["nextread"], $pos + 1);
+
+ return $data;
+ }
+ }
+
+ if ($state["debug"]) $data2 = fread($state["fp"], $size);
+ else $data2 = @fread($state["fp"], $size);
+
+ if ($data2 === false || $data2 === "")
+ {
+ if ($state["nextread"] === "") return $data2;
+
+ if ($state["async"] && $endchar !== false && $data2 === "") return "";
+
+ $data = $state["nextread"];
+ $state["nextread"] = "";
+
+ return $data;
+ }
+
+ $state["nextread"] .= $data2;
+
+ $y = strlen($state["nextread"]);
+ } while (!$state["async"] || ($size <= $y) || ($endchar !== false && strpos($state["nextread"], $endchar) !== false));
+
+ if ($endchar !== false) return "";
+
+ $data = $state["nextread"];
+ $state["nextread"] = "";
+
+ return $data;
+ }
+
+ // Reads one line.
+ private static function ProcessState__ReadLine(&$state)
+ {
+ while (strpos($state["data"], "\n") === false)
+ {
+ $data2 = self::ProcessState__InternalRead($state, 116000, "\n");
+
+ if ($data2 === false || $data2 === "")
+ {
+ if (feof($state["fp"])) return array("success" => false, "error" => self::HTTPTranslate("Remote peer disconnected."), "errorcode" => "peer_disconnected");
+ else if ($state["async"]) return array("success" => false, "error" => self::HTTPTranslate("Non-blocking read returned no data."), "errorcode" => "no_data");
+ else if ($data2 === false) return array("success" => false, "error" => self::HTTPTranslate("Underlying stream encountered a read error."), "errorcode" => "stream_read_error");
+ }
+ $pos = strpos($data2, "\n");
+ if ($pos === false)
+ {
+ if (feof($state["fp"])) return array("success" => false, "error" => self::HTTPTranslate("Remote peer disconnected."), "errorcode" => "peer_disconnected");
+ if (self::StreamTimedOut($state["fp"])) return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
+
+ $pos = strlen($data2);
+ }
+ if ($state["timeout"] !== false && self::GetTimeLeft($state["startts"], $state["timeout"]) == 0) return array("success" => false, "error" => self::HTTPTranslate("HTTP timeout exceeded."), "errorcode" => "timeout_exceeded");
+ if (isset($state["options"]["readlinelimit"]) && strlen($state["data"]) + $pos > $state["options"]["readlinelimit"]) return array("success" => false, "error" => self::HTTPTranslate("Read line exceeded limit."), "errorcode" => "read_line_limit_exceeded");
+
+ $state["rawsize"] += strlen($data2);
+ $state["data"] .= $data2;
+
+ if (isset($state["options"]["recvlimit"]) && $state["options"]["recvlimit"] < $state["rawsize"]) return array("success" => false, "error" => self::HTTPTranslate("Received data exceeded limit."), "errorcode" => "receive_limit_exceeded");
+ if (isset($state["options"]["recvratelimit"])) $state["waituntil"] = self::ProcessRateLimit($state["rawsize"], $state["recvstart"], $state["options"]["recvratelimit"], $state["async"]);
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("rawrecv", $data2, &$state["options"]["debug_callback_opts"]));
+ else if ($state["debug"]) $state["rawdata"] .= $data2;
+ }
+
+ return array("success" => true);
+ }
+
+ // Reads data in.
+ private static function ProcessState__ReadBodyData(&$state)
+ {
+ while ($state["sizeleft"] === false || $state["sizeleft"] > 0)
+ {
+ $data2 = self::ProcessState__InternalRead($state, ($state["sizeleft"] === false || $state["sizeleft"] > 65536 ? 65536 : $state["sizeleft"]));
+
+ if ($data2 === false) return array("success" => false, "error" => self::HTTPTranslate("Underlying stream encountered a read error."), "errorcode" => "stream_read_error");
+ if ($data2 === "")
+ {
+ if (feof($state["fp"])) return array("success" => false, "error" => self::HTTPTranslate("Remote peer disconnected."), "errorcode" => "peer_disconnected");
+ if (self::StreamTimedOut($state["fp"])) return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
+
+ if ($state["async"]) return array("success" => false, "error" => self::HTTPTranslate("Non-blocking read returned no data."), "errorcode" => "no_data");
+ }
+ if ($state["timeout"] !== false && self::GetTimeLeft($state["startts"], $state["timeout"]) == 0) return array("success" => false, "error" => self::HTTPTranslate("HTTP timeout exceeded."), "errorcode" => "timeout_exceeded");
+
+ $tempsize = strlen($data2);
+ $state["rawsize"] += $tempsize;
+ if ($state["sizeleft"] !== false) $state["sizeleft"] -= $tempsize;
+
+ if ($state["result"]["response"]["code"] == 100 || !isset($state["options"]["read_body_callback"]) || !is_callable($state["options"]["read_body_callback"])) $state["result"]["body"] .= self::GetDecodedBody($state["autodecode_ds"], $data2);
+ else if (!call_user_func_array($state["options"]["read_body_callback"], array($state["result"][($state["client"] ? "response" : "request")], self::GetDecodedBody($state["autodecode_ds"], $data2), &$state["options"]["read_body_callback_opts"]))) return array("success" => false, "error" => self::HTTPTranslate("Read body callback returned with a failure condition."), "errorcode" => "read_body_callback");
+
+ if (isset($state["options"]["recvlimit"]) && $state["options"]["recvlimit"] < $state["rawsize"]) return array("success" => false, "error" => self::HTTPTranslate("Received data exceeded limit."), "errorcode" => "receive_limit_exceeded");
+
+ if (isset($state["options"]["recvratelimit"]))
+ {
+ $state["waituntil"] = self::ProcessRateLimit($state["rawsize"], $state["recvstart"], $state["options"]["recvratelimit"], $state["async"]);
+ if (microtime(true) < $state["waituntil"]) return array("success" => false, "error" => self::HTTPTranslate("Rate limit for non-blocking connection has not been reached."), "errorcode" => "no_data");
+ }
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("rawrecv", $data2, &$state["options"]["debug_callback_opts"]));
+ else if ($state["debug"]) $state["rawdata"] .= $data2;
+ }
+
+ return array("success" => true);
+ }
+
+ // Writes data out.
+ private static function ProcessState__WriteData(&$state, $prefix)
+ {
+ if ($state[$prefix . "data"] !== "")
+ {
+ // Serious bug in PHP core for non-blocking SSL sockets: https://bugs.php.net/bug.php?id=72333
+ if ($state["secure"] && $state["async"] && version_compare(PHP_VERSION, "7.1.4") <= 0)
+ {
+ // This is a huge hack that has a pretty good chance of blocking on the socket.
+ // Peeling off up to just 4KB at a time helps to minimize that possibility. It's better than guaranteed failure of the socket though.
+ @stream_set_blocking($state["fp"], 1);
+ if ($state["debug"]) $result = fwrite($state["fp"], (strlen($state[$prefix . "data"]) > 4096 ? substr($state[$prefix . "data"], 0, 4096) : $state[$prefix . "data"]));
+ else $result = @fwrite($state["fp"], (strlen($state[$prefix . "data"]) > 4096 ? substr($state[$prefix . "data"], 0, 4096) : $state[$prefix . "data"]));
+ @stream_set_blocking($state["fp"], 0);
+ }
+ else
+ {
+ if ($state["debug"]) $result = fwrite($state["fp"], $state[$prefix . "data"]);
+ else $result = @fwrite($state["fp"], $state[$prefix . "data"]);
+ }
+
+ if ($result === false || feof($state["fp"])) return array("success" => false, "error" => self::HTTPTranslate("A fwrite() failure occurred. Most likely cause: Connection failure."), "errorcode" => "fwrite_failed");
+
+ // Serious bug in PHP core for all socket types: https://bugs.php.net/bug.php?id=73535
+ if ($result === 0)
+ {
+ // Temporarily switch to non-blocking sockets and test a one byte read (doesn't matter if data is available or not).
+ // This is a bigger hack than the first hack above.
+ if (!$state["async"]) @stream_set_blocking($state["fp"], 0);
+
+ if ($state["debug"]) $data2 = fread($state["fp"], 1);
+ else $data2 = @fread($state["fp"], 1);
+
+ if ($data2 === false) return array("success" => false, "error" => self::HTTPTranslate("Underlying stream encountered a read error."), "errorcode" => "stream_read_error");
+ if ($data2 === "" && feof($state["fp"])) return array("success" => false, "error" => self::HTTPTranslate("Remote peer disconnected."), "errorcode" => "peer_disconnected");
+
+ if ($data2 !== "") $state["nextread"] .= $data2;
+
+ if (!$state["async"]) @stream_set_blocking($state["fp"], 1);
+ }
+
+ if ($state["timeout"] !== false && self::GetTimeLeft($state["startts"], $state["timeout"]) == 0) return array("success" => false, "error" => self::HTTPTranslate("HTTP timeout exceeded."), "errorcode" => "timeout_exceeded");
+
+ $data2 = (string)substr($state[$prefix . "data"], 0, $result);
+ $state[$prefix . "data"] = (string)substr($state[$prefix . "data"], $result);
+
+ $state["result"]["rawsend" . $prefix . "size"] += $result;
+
+ if (isset($state["options"]["sendratelimit"]))
+ {
+ $state["waituntil"] = self::ProcessRateLimit($state["result"]["rawsendsize"], $state["result"]["connected"], $state["options"]["sendratelimit"], $state["async"]);
+ if (microtime(true) < $state["waituntil"]) return array("success" => false, "error" => self::HTTPTranslate("Rate limit for non-blocking connection has not been reached."), "errorcode" => "no_data");
+ }
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("rawsend", $data2, &$state["options"]["debug_callback_opts"]));
+ else if ($state["debug"]) $state["result"]["rawsend"] .= $data2;
+
+ if ($state["async"] && strlen($state[$prefix . "data"])) return array("success" => false, "error" => self::HTTPTranslate("Non-blocking write did not send all data."), "errorcode" => "no_data");
+ }
+
+ return array("success" => true);
+ }
+
+ public static function ForceClose(&$state)
+ {
+ if ($state["fp"] !== false)
+ {
+ @fclose($state["fp"]);
+ $state["fp"] = false;
+ }
+
+ if (isset($state["currentfile"]) && $state["currentfile"] !== false)
+ {
+ if ($state["currentfile"]["fp"] !== false) @fclose($state["currentfile"]["fp"]);
+ $state["currentfile"] = false;
+ }
+ }
+
+ private static function CleanupErrorState(&$state, $result)
+ {
+ if (!$result["success"] && $result["errorcode"] !== "no_data")
+ {
+ self::ForceClose($state);
+
+ $state["error"] = $result;
+ }
+
+ return $result;
+ }
+
+ public static function WantRead(&$state)
+ {
+ return ($state["type"] === "response" || $state["state"] === "proxy_connect_response" || $state["state"] === "receive_switch" || $state["state"] === "connecting_enable_crypto" || $state["state"] === "proxy_connect_enable_crypto");
+ }
+
+ public static function WantWrite(&$state)
+ {
+ return (!self::WantRead($state) || $state["state"] === "connecting_enable_crypto" || $state["state"] === "proxy_connect_enable_crypto");
+ }
+
+ public static function ProcessState(&$state)
+ {
+ if (isset($state["error"])) return $state["error"];
+
+ if ($state["timeout"] !== false && self::GetTimeLeft($state["startts"], $state["timeout"]) == 0) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("HTTP timeout exceeded."), "errorcode" => "timeout_exceeded"));
+ if (microtime(true) < $state["waituntil"]) return array("success" => false, "error" => self::HTTPTranslate("Rate limit for non-blocking connection has not been reached."), "errorcode" => "no_data");
+
+ if ($state["type"] === "request")
+ {
+ while ($state["state"] !== "done")
+ {
+ switch ($state["state"])
+ {
+ case "connecting":
+ {
+ if (function_exists("stream_select") && $state["async"])
+ {
+ $readfp = NULL;
+ $writefp = array($state["fp"]);
+ $exceptfp = array($state["fp"]);
+ if ($state["debug"]) $result = stream_select($readfp, $writefp, $exceptfp, 0);
+ else $result = @stream_select($readfp, $writefp, $exceptfp, 0);
+ if ($result === false || count($exceptfp)) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("A stream_select() failure occurred. Most likely cause: Connection failure."), "errorcode" => "stream_select_failed"));
+
+ if (!count($writefp)) return array("success" => false, "error" => self::HTTPTranslate("Connection not established yet."), "errorcode" => "no_data");
+ }
+
+ // Deal with failed connections that hang applications.
+ if (isset($state["options"]["streamtimeout"]) && $state["options"]["streamtimeout"] !== false && function_exists("stream_set_timeout")) @stream_set_timeout($state["fp"], $state["options"]["streamtimeout"]);
+
+ // Switch to the next state.
+ if ($state["async"] && function_exists("stream_socket_client") && (($state["useproxy"] && $state["proxysecure"]) || (!$state["useproxy"] && $state["secure"]))) $state["state"] = "connecting_enable_crypto";
+ else $state["state"] = "connection_ready";
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+
+ break;
+ }
+ case "connecting_enable_crypto":
+ {
+ // This is only used by clients that connect asynchronously via SSL.
+ if ($state["debug"]) $result = stream_socket_enable_crypto($state["fp"], true, STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT);
+ else $result = @stream_socket_enable_crypto($state["fp"], true, STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT);
+
+ if ($result === false) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("A stream_socket_enable_crypto() failure occurred. Most likely cause: Connection failure or incompatible crypto setup."), "errorcode" => "stream_socket_enable_crypto_failed"));
+ else if ($result === true) $state["state"] = "connection_ready";
+ else return array("success" => false, "error" => self::HTTPTranslate("Non-blocking enable crypto operation is not complete yet."), "errorcode" => "no_data");
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+
+ break;
+ }
+ case "connection_ready":
+ {
+ // Handle peer certificate retrieval.
+ if (function_exists("stream_context_get_options"))
+ {
+ $contextopts = stream_context_get_options($state["fp"]);
+ if ($state["useproxy"])
+ {
+ if ($state["proxysecure"] && isset($state["options"]["proxysslopts"]) && is_array($state["options"]["proxysslopts"]))
+ {
+ if (isset($state["options"]["peer_cert_callback"]) && is_callable($state["options"]["peer_cert_callback"]))
+ {
+ if (isset($contextopts["ssl"]["peer_certificate"]) && !call_user_func_array($state["options"]["peer_cert_callback"], array("proxypeercert", $contextopts["ssl"]["peer_certificate"], &$state["options"]["peer_cert_callback_opts"]))) return array("success" => false, "error" => self::HTTPTranslate("Peer certificate callback returned with a failure condition."), "errorcode" => "peer_cert_callback");
+ if (isset($contextopts["ssl"]["peer_certificate_chain"]) && !call_user_func_array($state["options"]["peer_cert_callback"], array("proxypeercertchain", $contextopts["ssl"]["peer_certificate_chain"], &$state["options"]["peer_cert_callback_opts"]))) return array("success" => false, "error" => self::HTTPTranslate("Peer certificate callback returned with a failure condition."), "errorcode" => "peer_cert_callback");
+ }
+ }
+ }
+ else
+ {
+ if ($state["secure"] && isset($state["options"]["sslopts"]) && is_array($state["options"]["sslopts"]))
+ {
+ if (isset($state["options"]["peer_cert_callback"]) && is_callable($state["options"]["peer_cert_callback"]))
+ {
+ if (isset($contextopts["ssl"]["peer_certificate"]) && !call_user_func_array($state["options"]["peer_cert_callback"], array("peercert", $contextopts["ssl"]["peer_certificate"], &$state["options"]["peer_cert_callback_opts"]))) return array("success" => false, "error" => self::HTTPTranslate("Peer certificate callback returned with a failure condition."), "errorcode" => "peer_cert_callback");
+ if (isset($contextopts["ssl"]["peer_certificate_chain"]) && !call_user_func_array($state["options"]["peer_cert_callback"], array("peercertchain", $contextopts["ssl"]["peer_certificate_chain"], &$state["options"]["peer_cert_callback_opts"]))) return array("success" => false, "error" => self::HTTPTranslate("Peer certificate callback returned with a failure condition."), "errorcode" => "peer_cert_callback");
+ }
+ }
+ }
+ }
+
+ $state["result"]["connected"] = microtime(true);
+
+ // Switch to the correct state.
+ if ($state["proxyconnect"])
+ {
+ $state["result"]["rawsendproxysize"] = 0;
+ $state["result"]["rawsendproxyheadersize"] = strlen($state["proxydata"]);
+
+ $state["state"] = "proxy_connect_send";
+ }
+ else
+ {
+ $state["result"]["sendstart"] = microtime(true);
+
+ $state["state"] = "send_data";
+ }
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+
+ break;
+ }
+ case "proxy_connect_send":
+ {
+ // Send the HTTP CONNECT request to the proxy.
+ $result = self::ProcessState__WriteData($state, "proxy");
+ if (!$result["success"]) return self::CleanupErrorState($state, $result);
+
+ // Prepare the state for handling the response from the proxy server.
+ $options2 = array();
+ if (isset($state["options"]["async"])) $options2["async"] = $state["options"]["async"];
+ if (isset($state["options"]["recvratelimit"])) $options2["recvratelimit"] = $state["options"]["recvratelimit"];
+ if (isset($state["options"]["debug_callback"]))
+ {
+ $options2["debug_callback"] = $state["options"]["debug_callback"];
+ $options2["debug_callback_opts"] = $state["options"]["debug_callback_opts"];
+ }
+ $state["proxyresponse"] = self::InitResponseState($state["fp"], $state["debug"], $options2, $state["startts"], $state["timeout"], $state["result"], false, $state["nextread"]);
+ $state["proxyresponse"]["proxyconnect"] = true;
+
+ $state["state"] = "proxy_connect_response";
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+
+ break;
+ }
+ case "proxy_connect_response":
+ {
+ // Recursively call this function to handle the proxy response.
+ $result = self::ProcessState($state["proxyresponse"]);
+ if (!$result["success"]) return self::CleanupErrorState($state, $result);
+
+ $state["result"]["rawrecvsize"] += $result["rawrecvsize"];
+ $state["result"]["rawrecvheadersize"] += $result["rawrecvheadersize"];
+
+ if (substr($result["response"]["code"], 0, 1) != "2") return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("Expected a 200 response from the CONNECT request. Received: %s.", $result["response"]["line"]), "info" => $result, "errorcode" => "proxy_connect_tunnel_failed"));
+
+ // Proxy connect tunnel established. Proceed normally.
+ $state["result"]["sendstart"] = microtime(true);
+
+ if ($state["secure"]) $state["state"] = "proxy_connect_enable_crypto";
+ else $state["state"] = "send_data";
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+
+ break;
+ }
+ case "proxy_connect_enable_crypto":
+ {
+ if ($state["debug"]) $result = stream_socket_enable_crypto($state["fp"], true, STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT);
+ else $result = @stream_socket_enable_crypto($state["fp"], true, STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT);
+
+ if ($result === false) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("A stream_socket_enable_crypto() failure occurred. Most likely cause: Tunnel connection failure or incompatible crypto setup."), "errorcode" => "stream_socket_enable_crypto_failed"));
+ else if ($result === true)
+ {
+ // Handle peer certificate retrieval.
+ if (function_exists("stream_context_get_options"))
+ {
+ $contextopts = stream_context_get_options($state["fp"]);
+
+ if (isset($state["options"]["sslopts"]) && is_array($state["options"]["sslopts"]))
+ {
+ if (isset($state["options"]["peer_cert_callback"]) && is_callable($state["options"]["peer_cert_callback"]))
+ {
+ if (isset($contextopts["ssl"]["peer_certificate"]) && !call_user_func_array($state["options"]["peer_cert_callback"], array("peercert", $contextopts["ssl"]["peer_certificate"], &$state["options"]["peer_cert_callback_opts"]))) return array("success" => false, "error" => self::HTTPTranslate("Peer certificate callback returned with a failure condition."), "errorcode" => "peer_cert_callback");
+ if (isset($contextopts["ssl"]["peer_certificate_chain"]) && !call_user_func_array($state["options"]["peer_cert_callback"], array("peercertchain", $contextopts["ssl"]["peer_certificate_chain"], &$state["options"]["peer_cert_callback_opts"]))) return array("success" => false, "error" => self::HTTPTranslate("Peer certificate callback returned with a failure condition."), "errorcode" => "peer_cert_callback");
+ }
+ }
+ }
+
+ // Secure connection established.
+ $state["state"] = "send_data";
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+ }
+
+ break;
+ }
+ case "send_data":
+ {
+ // Send the queued data.
+ $result = self::ProcessState__WriteData($state, "");
+ if (!$result["success"]) return self::CleanupErrorState($state, $result);
+
+ // Queue up more data.
+ if (isset($state["options"]["write_body_callback"]) && is_callable($state["options"]["write_body_callback"]))
+ {
+ if ($state["bodysize"] === false || $state["bodysize"] > 0)
+ {
+ $bodysize2 = $state["bodysize"];
+ $result = call_user_func_array($state["options"]["write_body_callback"], array(&$state["data"], &$bodysize2, &$state["options"]["write_body_callback_opts"]));
+ if (!$result || ($state["bodysize"] !== false && strlen($state["data"]) > $state["bodysize"])) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("HTTP write body callback function failed."), "errorcode" => "write_body_callback"));
+
+ if ($state["bodysize"] === false)
+ {
+ if ($state["data"] !== "" && $state["chunked"]) $state["data"] = dechex(strlen($state["data"])) . "\r\n" . $state["data"] . "\r\n";
+
+ // When $bodysize2 is set to true, it is the last chunk.
+ if ($bodysize2 === true)
+ {
+ if ($state["chunked"])
+ {
+ $state["data"] .= "0\r\n";
+
+ // Allow the body callback function to append additional headers to the content to send.
+ // It is up to the callback function to correctly format the extra headers.
+ $result = call_user_func_array($state["options"]["write_body_callback"], array(&$state["data"], &$bodysize2, &$state["options"]["write_body_callback_opts"]));
+ if (!$result) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("HTTP write body callback function failed."), "errorcode" => "write_body_callback"));
+
+ $state["data"] .= "\r\n";
+ }
+
+ $state["bodysize"] = 0;
+ }
+ }
+ else
+ {
+ $state["bodysize"] -= strlen($state["data"]);
+ }
+ }
+ }
+ else if (isset($state["options"]["files"]) && $state["bodysize"] > 0)
+ {
+ // Select the next file to upload.
+ if ($state["currentfile"] === false && count($state["options"]["files"]))
+ {
+ $state["currentfile"] = array_shift($state["options"]["files"]);
+
+ $name = self::HeaderValueCleanup($state["currentfile"]["name"]);
+ $name = str_replace("\"", "", $name);
+ $filename = self::FilenameSafe(self::ExtractFilename($state["currentfile"]["filename"]));
+ $type = self::HeaderValueCleanup($state["currentfile"]["type"]);
+
+ $state["data"] = "--" . $state["mime"] . "\r\n";
+ $state["data"] .= "Content-Disposition: form-data; name=\"" . $name . "\"; filename=\"" . $filename . "\"\r\n";
+ $state["data"] .= "Content-Type: " . $type . "\r\n";
+ $state["data"] .= "\r\n";
+
+ if (!isset($state["currentfile"]["datafile"]))
+ {
+ $state["data"] .= $state["currentfile"]["data"];
+ $state["data"] .= "\r\n";
+
+ $state["currentfile"] = false;
+ }
+ else
+ {
+ $state["currentfile"]["fp"] = @fopen($state["currentfile"]["datafile"], "rb");
+ if ($state["currentfile"]["fp"] === false) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("The file '%s' does not exist.", $state["currentfile"]["datafile"]), "errorcode" => "file_does_not_exist"));
+ }
+ }
+
+ // Process the next chunk of file information.
+ if ($state["currentfile"] !== false && isset($state["currentfile"]["fp"]))
+ {
+ // Read/Write up to 65K at a time.
+ if ($state["currentfile"]["filesize"] >= 65536)
+ {
+ $data2 = fread($state["currentfile"]["fp"], 65536);
+ if ($data2 === false || strlen($data2) !== 65536) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("A read error was encountered with the file '%s'.", $state["currentfile"]["datafile"]), "errorcode" => "file_read"));
+
+ $state["data"] .= $data2;
+
+ $state["currentfile"]["filesize"] -= 65536;
+ }
+ else
+ {
+ // Read in the rest.
+ if ($state["currentfile"]["filesize"] > 0)
+ {
+ $data2 = fread($state["currentfile"]["fp"], $state["currentfile"]["filesize"]);
+ if ($data2 === false || strlen($data2) != $state["currentfile"]["filesize"]) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("A read error was encountered with the file '%s'.", $state["currentfile"]["datafile"]), "errorcode" => "file_read"));
+
+ $state["data"] .= $data2;
+ }
+
+ $state["data"] .= "\r\n";
+
+ fclose($state["currentfile"]["fp"]);
+
+ $state["currentfile"] = false;
+ }
+ }
+
+ // If there is no more data, write out the closing MIME line.
+ if ($state["data"] === "") $state["data"] = "--" . $state["mime"] . "--\r\n";
+
+ $state["bodysize"] -= strlen($state["data"]);
+ }
+ else if ($state["bodysize"] === false || $state["bodysize"] > 0)
+ {
+ return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("A weird internal HTTP error that should never, ever happen...just happened."), "errorcode" => "impossible"));
+ }
+
+ // All done sending data.
+ if ($state["data"] === "")
+ {
+ if ($state["client"])
+ {
+ $state["state"] = "receive_switch";
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+ }
+ else
+ {
+ $state["result"]["endts"] = microtime(true);
+
+ if ($state["close"]) fclose($state["fp"]);
+ else $state["result"]["fp"] = $state["fp"];
+
+ return $state["result"];
+ }
+ }
+
+ break;
+ }
+ case "receive_switch":
+ {
+ if (function_exists("stream_select") && $state["async"])
+ {
+ $readfp = array($state["fp"]);
+ $writefp = NULL;
+ $exceptfp = NULL;
+ if ($state["debug"]) $result = stream_select($readfp, $writefp, $exceptfp, 0);
+ else $result = @stream_select($readfp, $writefp, $exceptfp, 0);
+ if ($result === false) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("A stream_select() failure occurred. Most likely cause: Connection failure."), "errorcode" => "stream_select_failed"));
+
+ if (!count($readfp)) return array("success" => false, "error" => self::HTTPTranslate("Connection not fully established yet."), "errorcode" => "no_data");
+ }
+
+ $state["state"] = "done";
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+
+ break;
+ }
+ }
+ }
+
+ // The request has been sent. Change the state to a response state.
+ $state = self::InitResponseState($state["fp"], $state["debug"], $state["options"], $state["startts"], $state["timeout"], $state["result"], $state["close"], $state["nextread"]);
+
+ // Run one cycle.
+ return self::ProcessState($state);
+ }
+ else if ($state["type"] === "response")
+ {
+ while ($state["state"] !== "done")
+ {
+ switch ($state["state"])
+ {
+ case "response_line":
+ {
+ $result = self::ProcessState__ReadLine($state);
+ if (!$result["success"]) return self::CleanupErrorState($state, $result);
+
+ // Parse the response line.
+ $pos = strpos($state["data"], "\n");
+ if ($pos === false) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("Unable to retrieve response line."), "errorcode" => "get_response_line"));
+ $line = trim(substr($state["data"], 0, $pos));
+ $state["data"] = substr($state["data"], $pos + 1);
+ $state["rawrecvheadersize"] += $pos + 1;
+ $response = explode(" ", $line, 3);
+
+ $state["result"]["response"] = array(
+ "line" => $line,
+ "httpver" => strtoupper($response[0]),
+ "code" => $response[1],
+ "meaning" => (isset($response[2]) ? $response[2] : "")
+ );
+
+ $state["state"] = "headers";
+ $state["result"]["headers"] = array();
+ $state["lastheader"] = "";
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+
+ break;
+ }
+ case "request_line":
+ {
+ // Server mode only.
+ $result = self::ProcessState__ReadLine($state);
+ if (!$result["success"]) return self::CleanupErrorState($state, $result);
+
+ // Parse the request line.
+ $pos = strpos($state["data"], "\n");
+ if ($pos === false) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("Unable to retrieve request line."), "errorcode" => "get_request_line"));
+ $line = trim(substr($state["data"], 0, $pos));
+ $state["data"] = substr($state["data"], $pos + 1);
+ $state["rawrecvheadersize"] += $pos + 1;
+
+ $request = $line;
+ $pos = strpos($request, " ");
+ if ($pos === false) $pos = strlen($request);
+ $method = (string)substr($request, 0, $pos);
+ $request = trim(substr($request, $pos));
+
+ $pos = strrpos($request, " ");
+ if ($pos === false) $pos = strlen($request);
+ $path = trim(substr($request, 0, $pos));
+ if ($path === "") $path = "/";
+ $version = (string)substr($request, $pos + 1);
+
+ $state["result"]["request"] = array(
+ "line" => $line,
+ "method" => strtoupper($method),
+ "path" => $path,
+ "httpver" => strtoupper($version),
+ );
+
+ // Fake the response line to bypass some client-only code.
+ $state["result"]["response"] = array(
+ "line" => "200",
+ "httpver" => "",
+ "code" => 200,
+ "meaning" => ""
+ );
+
+ $state["state"] = "headers";
+ $state["result"]["headers"] = array();
+ $state["lastheader"] = "";
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+
+ break;
+ }
+ case "headers":
+ case "body_chunked_headers":
+ {
+ $result = self::ProcessState__ReadLine($state);
+ if (!$result["success"] && ($state["state"] === "headers" || ($result["errorcode"] !== "stream_read_error" && $result["errorcode"] !== "peer_disconnected"))) return self::CleanupErrorState($state, $result);
+
+ $pos = strpos($state["data"], "\n");
+ if ($pos === false) $pos = strlen($state["data"]);
+ $header = rtrim(substr($state["data"], 0, $pos));
+ $state["data"] = substr($state["data"], $pos + 1);
+ $state["rawrecvheadersize"] += $pos + 1;
+ if ($header != "")
+ {
+ if ($state["lastheader"] != "" && (substr($header, 0, 1) == " " || substr($header, 0, 1) == "\t")) $state["result"]["headers"][$state["lastheader"]][count($state["result"]["headers"][$state["lastheader"]]) - 1] .= $header;
+ else
+ {
+ $pos = strpos($header, ":");
+ if ($pos === false) $pos = strlen($header);
+ $state["lastheader"] = self::HeaderNameCleanup(substr($header, 0, $pos));
+ if (!isset($state["result"]["headers"][$state["lastheader"]])) $state["result"]["headers"][$state["lastheader"]] = array();
+ $state["result"]["headers"][$state["lastheader"]][] = ltrim(substr($header, $pos + 1));
+ }
+
+ $state["numheaders"]++;
+ if (isset($state["options"]["maxheaders"]) && $state["numheaders"] > $state["options"]["maxheaders"]) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("The number of headers exceeded the limit."), "errorcode" => "headers_limit_exceeded"));
+ }
+ else
+ {
+ if ($state["result"]["response"]["code"] != 100 && isset($state["options"]["read_headers_callback"]) && is_callable($state["options"]["read_headers_callback"]))
+ {
+ if (!call_user_func_array($state["options"]["read_headers_callback"], array(&$state["result"][($state["client"] ? "response" : "request")], &$state["result"]["headers"], &$state["options"]["read_headers_callback_opts"]))) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("Read headers callback returned with a failure condition."), "errorcode" => "read_header_callback"));
+ }
+
+ // Additional headers (optional) are the last bit of data in a chunked response.
+ if ($state["state"] === "body_chunked_headers")
+ {
+ $state["state"] = "body_finalize";
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+ }
+ else
+ {
+ $state["result"]["body"] = "";
+
+ // Handle 100 Continue below OR WebSocket among other things by letting the caller handle reading the body.
+ if ($state["result"]["response"]["code"] == 100 || $state["result"]["response"]["code"] == 101)
+ {
+ $state["state"] = "done";
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+ }
+ else
+ {
+ // Determine if decoding the content is possible and necessary.
+ if ($state["autodecode"] && !isset($state["result"]["headers"]["Content-Encoding"]) || (strtolower($state["result"]["headers"]["Content-Encoding"][0]) != "gzip" && strtolower($state["result"]["headers"]["Content-Encoding"][0]) != "deflate")) $state["autodecode"] = false;
+ if (!$state["autodecode"]) $state["autodecode_ds"] = false;
+ else
+ {
+ if (!class_exists("DeflateStream", false)) require_once str_replace("\\", "/", dirname(__FILE__)) . "/deflate_stream.php";
+
+ // Since servers and browsers do everything wrong, ignore the encoding claim and attempt to auto-detect the encoding.
+ $state["autodecode_ds"] = new DeflateStream();
+ $state["autodecode_ds"]->Init("rb", -1, array("type" => "auto"));
+ }
+
+ // Use the appropriate state for handling the next bit of input.
+ if (isset($state["result"]["headers"]["Transfer-Encoding"]) && strtolower($state["result"]["headers"]["Transfer-Encoding"][0]) == "chunked")
+ {
+ $state["state"] = "body_chunked_size";
+ }
+ else
+ {
+ $state["sizeleft"] = (isset($state["result"]["headers"]["Content-Length"]) ? (double)preg_replace('/[^0-9]/', "", $state["result"]["headers"]["Content-Length"][0]) : false);
+ $state["state"] = (!isset($state["proxyconnect"]) && ($state["sizeleft"] !== false || $state["client"]) ? "body_content" : "done");
+ }
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+
+ // Let servers have a chance to alter limits before processing the input body.
+ if (!$state["client"] && $state["state"] !== "done") return array("success" => false, "error" => self::HTTPTranslate("Intermission for adjustments to limits."), "errorcode" => "no_data");
+ }
+ }
+ }
+
+ break;
+ }
+ case "body_chunked_size":
+ {
+ $result = self::ProcessState__ReadLine($state);
+ if (!$result["success"]) return self::CleanupErrorState($state, $result);
+
+ $pos = strpos($state["data"], "\n");
+ if ($pos === false) $pos = strlen($state["data"]);
+ $line = trim(substr($state["data"], 0, $pos));
+ $state["data"] = substr($state["data"], $pos + 1);
+ $pos = strpos($line, ";");
+ if ($pos === false) $pos = strlen($line);
+ $size = hexdec(substr($line, 0, $pos));
+ if ($size < 0) $size = 0;
+
+ // Retrieve content.
+ $size2 = $size;
+ $size3 = min(strlen($state["data"]), $size);
+ if ($size3 > 0)
+ {
+ $data2 = substr($state["data"], 0, $size3);
+ $state["data"] = substr($state["data"], $size3);
+ $size2 -= $size3;
+
+ if ($state["result"]["response"]["code"] == 100 || !isset($state["options"]["read_body_callback"]) || !is_callable($state["options"]["read_body_callback"])) $state["result"]["body"] .= self::GetDecodedBody($state["autodecode_ds"], $data2);
+ else if (!call_user_func_array($state["options"]["read_body_callback"], array($state["result"][($state["client"] ? "response" : "request")], self::GetDecodedBody($state["autodecode_ds"], $data2), &$state["options"]["read_body_callback_opts"]))) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("Read body callback returned with a failure condition."), "errorcode" => "read_body_callback"));
+ }
+
+ $state["chunksize"] = $size;
+ $state["sizeleft"] = $size2;
+ $state["state"] = "body_chunked_data";
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+
+ break;
+ }
+ case "body_chunked_data":
+ {
+ $result = self::ProcessState__ReadBodyData($state);
+ if (!$result["success"]) return self::CleanupErrorState($state, $result);
+
+ if ($state["chunksize"] > 0) $state["state"] = "body_chunked_skipline";
+ else
+ {
+ $state["lastheader"] = "";
+ $state["state"] = "body_chunked_headers";
+ }
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+
+ break;
+ }
+ case "body_chunked_skipline":
+ {
+ $result = self::ProcessState__ReadLine($state);
+ if (!$result["success"]) return self::CleanupErrorState($state, $result);
+
+ // Ignore one newline.
+ $pos = strpos($state["data"], "\n");
+ if ($pos === false) $pos = strlen($state["data"]);
+ $state["data"] = substr($state["data"], $pos + 1);
+
+ $state["state"] = "body_chunked_size";
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+
+ break;
+ }
+ case "body_content":
+ {
+ $result = self::ProcessState__ReadBodyData($state);
+ if (!$result["success"] && (($state["sizeleft"] !== false && $state["sizeleft"] > 0) || ($state["sizeleft"] === false && $result["errorcode"] !== "stream_read_error" && $result["errorcode"] !== "peer_disconnected" && $result["errorcode"] !== "stream_timeout_exceeded"))) return self::CleanupErrorState($state, $result);
+
+ $state["state"] = "body_finalize";
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+
+ break;
+ }
+ case "body_finalize":
+ {
+ if ($state["autodecode_ds"] !== false)
+ {
+ $state["autodecode_ds"]->Finalize();
+ $data2 = $state["autodecode_ds"]->Read();
+
+ if ($state["result"]["response"]["code"] == 100 || !isset($state["options"]["read_body_callback"]) || !is_callable($state["options"]["read_body_callback"])) $state["result"]["body"] .= $data2;
+ else if (!call_user_func_array($state["options"]["read_body_callback"], array($state["result"][($state["client"] ? "response" : "request")], $data2, &$state["options"]["read_body_callback_opts"]))) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("Read body callback returned with a failure condition."), "errorcode" => "read_body_callback"));
+ }
+
+ $state["state"] = "done";
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+
+ break;
+ }
+ }
+
+ // Handle HTTP 100 Continue status codes.
+ if ($state["state"] === "done" && $state["result"]["response"]["code"] == 100)
+ {
+ $state["autodecode"] = (!isset($state["options"]["auto_decode"]) || $state["options"]["auto_decode"]);
+ $state["state"] = "response";
+ $state["result"]["response"] = false;
+ $state["result"]["headers"] = false;
+ $state["result"]["body"] = false;
+
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
+ }
+ }
+
+ if ($state["debug"]) $state["result"]["rawrecv"] .= $state["rawdata"];
+ $state["result"]["rawrecvsize"] += $state["rawsize"];
+ $state["result"]["rawrecvheadersize"] += $state["rawrecvheadersize"];
+ $state["result"]["endts"] = microtime(true);
+
+ if ($state["close"] || ($state["client"] && isset($state["result"]["headers"]["Connection"]) && strtolower($state["result"]["headers"]["Connection"][0]) === "close")) fclose($state["fp"]);
+ else $state["result"]["fp"] = $state["fp"];
+
+ return $state["result"];
+ }
+ else
+ {
+ return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("Invalid 'type' in state tracker."), "errorcode" => "invalid_type"));
+ }
+ }
+
+ public static function RawFileSize($fileorname)
+ {
+ if (is_resource($fileorname)) $fp = $fileorname;
+ else
+ {
+ $fp = @fopen($fileorname, "rb");
+ if ($fp === false) return 0;
+ }
+
+ if (PHP_INT_SIZE < 8)
+ {
+ $pos = 0;
+ $size = 1073741824;
+ fseek($fp, 0, SEEK_SET);
+ while ($size > 1)
+ {
+ if (fseek($fp, $size, SEEK_CUR) === -1) break;
+
+ if (fgetc($fp) === false)
+ {
+ fseek($fp, -$size, SEEK_CUR);
+ $size = (int)($size / 2);
+ }
+ else
+ {
+ fseek($fp, -1, SEEK_CUR);
+ $pos += $size;
+ }
+ }
+
+ if ($size > 1)
+ {
+ // Unfortunately, fseek() failed for some reason. Going to have to do this the old-fashioned way.
+ do
+ {
+ $data = fread($fp, 10485760);
+ if ($data === false) $data = "";
+ $pos += strlen($data);
+ } while ($data !== "");
+ }
+ else
+ {
+ while (fgetc($fp) !== false) $pos++;
+ }
+ }
+ else
+ {
+ fseek($fp, 0, SEEK_END);
+ $pos = ftell($fp);
+ }
+
+ if (!is_resource($fileorname)) fclose($fp);
+
+ return $pos;
+ }
+
+ public static function RetrieveWebpage($url, $options = array())
+ {
+ $startts = microtime(true);
+ $timeout = (isset($options["timeout"]) ? $options["timeout"] : false);
+
+ if (!function_exists("stream_socket_client") && !function_exists("fsockopen")) return array("success" => false, "error" => self::HTTPTranslate("The functions 'stream_socket_client' and 'fsockopen' do not exist."), "errorcode" => "function_check");
+
+ // Process the URL.
+ $url = trim($url);
+ $url = self::ExtractURL($url);
+
+ if ($url["scheme"] != "http" && $url["scheme"] != "https") return array("success" => false, "error" => self::HTTPTranslate("RetrieveWebpage() only supports the 'http' and 'https' protocols."), "errorcode" => "protocol_check");
+
+ $secure = ($url["scheme"] == "https");
+ $async = (isset($options["async"]) ? $options["async"] : false);
+ $protocol = ($secure && !$async ? (isset($options["protocol"]) ? strtolower($options["protocol"]) : "ssl") : "tcp");
+ if (function_exists("stream_get_transports") && !in_array($protocol, stream_get_transports())) return array("success" => false, "error" => self::HTTPTranslate("The desired transport protocol '%s' is not installed.", $protocol), "errorcode" => "transport_not_installed");
+ $host = str_replace(" ", "-", self::HeaderValueCleanup($url["host"]));
+ if ($host == "") return array("success" => false, "error" => self::HTTPTranslate("Invalid URL."));
+ $port = ((int)$url["port"] ? (int)$url["port"] : ($secure ? 443 : 80));
+ $defaultport = ((!$secure && $port == 80) || ($secure && $port == 443));
+ $path = ($url["path"] == "" ? "/" : $url["path"]);
+ $query = $url["query"];
+ $username = $url["loginusername"];
+ $password = $url["loginpassword"];
+
+ // Cleanup input headers.
+ if (!isset($options["headers"])) $options["headers"] = array();
+ $options["headers"] = self::NormalizeHeaders($options["headers"]);
+ if (isset($options["rawheaders"])) self::MergeRawHeaders($options["headers"], $options["rawheaders"]);
+
+ // Process the proxy URL (if specified).
+ $useproxy = (isset($options["proxyurl"]) && trim($options["proxyurl"]) != "");
+ $proxysecure = false;
+ $proxyconnect = false;
+ $proxydata = "";
+ if ($useproxy)
+ {
+ $proxyurl = trim($options["proxyurl"]);
+ $proxyurl = self::ExtractURL($proxyurl);
+
+ $proxysecure = ($proxyurl["scheme"] == "https");
+ if ($proxysecure && $secure) return array("success" => false, "error" => self::HTTPTranslate("The PHP SSL sockets implementation does not support tunneled SSL/TLS connections over SSL/TLS."), "errorcode" => "multi_ssl_tunneling_not_supported");
+ $proxyprotocol = ($proxysecure && !$async ? (isset($options["proxyprotocol"]) ? strtolower($options["proxyprotocol"]) : "ssl") : "tcp");
+ if (function_exists("stream_get_transports") && !in_array($proxyprotocol, stream_get_transports())) return array("success" => false, "error" => self::HTTPTranslate("The desired transport proxy protocol '%s' is not installed.", $proxyprotocol), "errorcode" => "proxy_transport_not_installed");
+ $proxyhost = str_replace(" ", "-", self::HeaderValueCleanup($proxyurl["host"]));
+ if ($proxyhost === "") return array("success" => false, "error" => self::HTTPTranslate("The specified proxy URL is not a URL. Prefix 'proxyurl' with http:// or https://"), "errorcode" => "invalid_proxy_url");
+ $proxyport = ((int)$proxyurl["port"] ? (int)$proxyurl["port"] : ($proxysecure ? 443 : 80));
+ $proxypath = ($proxyurl["path"] == "" ? "/" : $proxyurl["path"]);
+ $proxyusername = $proxyurl["loginusername"];
+ $proxypassword = $proxyurl["loginpassword"];
+
+ // Open a tunnel instead of letting the proxy modify the request (HTTP CONNECT).
+ $proxyconnect = (isset($options["proxyconnect"]) && $options["proxyconnect"] ? $options["proxyconnect"] : false);
+ if ($proxyconnect)
+ {
+ $proxydata = "CONNECT " . $host . ":" . $port . " HTTP/1.1\r\n";
+ if (isset($options["headers"]["User-Agent"])) $proxydata .= "User-Agent: " . $options["headers"]["User-Agent"] . "\r\n";
+ $proxydata .= "Host: " . $host . ($defaultport ? "" : ":" . $port) . "\r\n";
+ $proxydata .= "Proxy-Connection: keep-alive\r\n";
+ if ($proxyusername != "") $proxydata .= "Proxy-Authorization: BASIC " . base64_encode($proxyusername . ":" . $proxypassword) . "\r\n";
+ if (!isset($options["proxyheaders"])) $options["proxyheaders"] = array();
+ $options["proxyheaders"] = self::NormalizeHeaders($options["proxyheaders"]);
+ if (isset($options["rawproxyheaders"])) self::MergeRawHeaders($options["proxyheaders"], $options["rawproxyheaders"]);
+
+ unset($options["proxyheaders"]["Accept-Encoding"]);
+ foreach ($options["proxyheaders"] as $name => $val)
+ {
+ if ($name != "Content-Type" && $name != "Content-Length" && $name != "Proxy-Connection" && $name != "Host") $proxydata .= $name . ": " . $val . "\r\n";
+ }
+
+ $proxydata .= "\r\n";
+ if (isset($options["debug_callback"]) && is_callable($options["debug_callback"])) call_user_func_array($options["debug_callback"], array("rawproxyheaders", $proxydata, &$options["debug_callback_opts"]));
+ }
+ }
+
+ // Process the method.
+ if (!isset($options["method"]))
+ {
+ if ((isset($options["write_body_callback"]) && is_callable($options["write_body_callback"])) || isset($options["body"])) $options["method"] = "PUT";
+ else if (isset($options["postvars"]) || (isset($options["files"]) && count($options["files"]))) $options["method"] = "POST";
+ else $options["method"] = "GET";
+ }
+ $options["method"] = preg_replace('/[^A-Z]/', "", strtoupper($options["method"]));
+
+ // Process the HTTP version.
+ if (!isset($options["httpver"])) $options["httpver"] = "1.1";
+ $options["httpver"] = preg_replace('/[^0-9.]/', "", $options["httpver"]);
+
+ // Process the request.
+ $data = $options["method"] . " ";
+ $data .= ($useproxy && !$proxyconnect ? $url["scheme"] . "://" . $host . ":" . $port : "") . $path . ($query != "" ? "?" . $query : "");
+ $data .= " HTTP/" . $options["httpver"] . "\r\n";
+
+ // Process the headers.
+ if ($useproxy && !$proxyconnect && $proxyusername != "") $data .= "Proxy-Authorization: BASIC " . base64_encode($proxyusername . ":" . $proxypassword) . "\r\n";
+ if ($username != "") $data .= "Authorization: BASIC " . base64_encode($username . ":" . $password) . "\r\n";
+ $ver = explode(".", $options["httpver"]);
+ if (isset($options["headers"]["Host"]))
+ {
+ $url2 = self::ExtractURL("http://" . $options["headers"]["Host"]);
+ $options["headers"]["Host"] = $url2["host"] . (isset($url2["port"]) && $url2["port"] != "" ? ":" . $url2["port"] : "");
+ }
+ if ((int)$ver[0] > 1 || ((int)$ver[0] == 1 && (int)$ver[1] >= 1))
+ {
+ if (!isset($options["headers"]["Host"])) $options["headers"]["Host"] = $host . ($defaultport ? "" : ":" . $port);
+ $data .= "Host: " . $options["headers"]["Host"] . "\r\n";
+ }
+
+ if (!isset($options["headers"]["Connection"])) $options["headers"]["Connection"] = "close";
+ $data .= "Connection: " . $options["headers"]["Connection"] . "\r\n";
+
+ foreach ($options["headers"] as $name => $val)
+ {
+ if ($name != "Content-Type" && $name != "Content-Length" && $name != "Connection" && $name != "Host") $data .= $name . ": " . $val . "\r\n";
+ }
+
+ if (isset($options["files"]) && !count($options["files"])) unset($options["files"]);
+
+ // Process the body.
+ $mime = "";
+ $body = "";
+ $bodysize = 0;
+ if (isset($options["write_body_callback"]) && is_callable($options["write_body_callback"]))
+ {
+ if (isset($options["headers"]["Content-Type"])) $data .= "Content-Type: " . $options["headers"]["Content-Type"] . "\r\n";
+
+ call_user_func_array($options["write_body_callback"], array(&$body, &$bodysize, &$options["write_body_callback_opts"]));
+ }
+ else if (isset($options["body"]))
+ {
+ if (isset($options["headers"]["Content-Type"])) $data .= "Content-Type: " . $options["headers"]["Content-Type"] . "\r\n";
+
+ $body = $options["body"];
+ $bodysize = strlen($body);
+ unset($options["body"]);
+ }
+ else if ((isset($options["files"]) && count($options["files"])) || (isset($options["headers"]["Content-Type"]) && stripos($options["headers"]["Content-Type"], "multipart/form-data") !== false))
+ {
+ $mime = "--------" . substr(sha1(uniqid(mt_rand(), true)), 0, 25);
+ $data .= "Content-Type: multipart/form-data; boundary=" . $mime . "\r\n";
+ if (isset($options["postvars"]))
+ {
+ foreach ($options["postvars"] as $name => $val)
+ {
+ $name = self::HeaderValueCleanup($name);
+ $name = str_replace("\"", "", $name);
+
+ if (!is_array($val))
+ {
+ if (is_string($val) || is_numeric($val)) $val = array($val);
+ else return array("success" => false, "error" => "A supplied 'postvars' value is an invalid type. Expected string, numeric, or array.", "errorcode" => "invalid_postvars_value", "info" => array("name" => $name, "val" => $val));
+ }
+
+ foreach ($val as $val2)
+ {
+ $body .= "--" . $mime . "\r\n";
+ $body .= "Content-Disposition: form-data; name=\"" . $name . "\"\r\n";
+ $body .= "\r\n";
+ $body .= $val2 . "\r\n";
+ }
+ }
+
+ unset($options["postvars"]);
+ }
+
+ $bodysize = strlen($body);
+
+ // Only count the amount of data to send.
+ if (!isset($options["files"])) $options["files"] = array();
+ foreach ($options["files"] as $num => $info)
+ {
+ $name = self::HeaderValueCleanup($info["name"]);
+ $name = str_replace("\"", "", $name);
+ $filename = self::FilenameSafe(self::ExtractFilename($info["filename"]));
+ $type = self::HeaderValueCleanup($info["type"]);
+
+ $body2 = "--" . $mime . "\r\n";
+ $body2 .= "Content-Disposition: form-data; name=\"" . $name . "\"; filename=\"" . $filename . "\"\r\n";
+ $body2 .= "Content-Type: " . $type . "\r\n";
+ $body2 .= "\r\n";
+
+ $info["filesize"] = (isset($info["datafile"]) ? self::RawFileSize($info["datafile"]) : strlen($info["data"]));
+ $bodysize += strlen($body2) + $info["filesize"] + 2;
+
+ $options["files"][$num] = $info;
+ }
+
+ $body2 = "--" . $mime . "--\r\n";
+ $bodysize += strlen($body2);
+ }
+ else
+ {
+ if (isset($options["postvars"]))
+ {
+ foreach ($options["postvars"] as $name => $val)
+ {
+ $name = self::HeaderValueCleanup($name);
+
+ if (!is_array($val))
+ {
+ if (is_string($val) || is_numeric($val)) $val = array($val);
+ else return array("success" => false, "error" => "A supplied 'postvars' value is an invalid type. Expected string, numeric, or array.", "errorcode" => "invalid_postvars_value", "info" => array("name" => $name, "val" => $val));
+ }
+
+ foreach ($val as $val2) $body .= ($body != "" ? "&" : "") . urlencode($name) . "=" . urlencode($val2);
+ }
+
+ unset($options["postvars"]);
+ }
+
+ if ($body != "") $data .= "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n";
+
+ $bodysize = strlen($body);
+ }
+ if (($bodysize === false && strlen($body) > 0) || ($bodysize !== false && $bodysize < strlen($body))) $bodysize = strlen($body);
+
+ // Finalize the headers.
+ if ($bodysize === false) $data .= "Transfer-Encoding: chunked\r\n";
+ else if ($bodysize > 0 || $body != "" || $options["method"] == "POST") $data .= "Content-Length: " . $bodysize . "\r\n";
+ $data .= "\r\n";
+ if (isset($options["debug_callback"]) && is_callable($options["debug_callback"])) call_user_func_array($options["debug_callback"], array("rawheaders", $data, &$options["debug_callback_opts"]));
+ $rawheadersize = strlen($data);
+
+ // Finalize the initial data to be sent.
+ $data .= $body;
+ if ($bodysize !== false) $bodysize -= strlen($body);
+ $body = "";
+ $result = array("success" => true, "rawsendsize" => 0, "rawsendheadersize" => $rawheadersize, "rawrecvsize" => 0, "rawrecvheadersize" => 0, "startts" => $startts);
+ $debug = (isset($options["debug"]) && $options["debug"]);
+ if ($debug)
+ {
+ $result["rawsend"] = "";
+ $result["rawrecv"] = "";
+ }
+
+ if ($timeout !== false && self::GetTimeLeft($startts, $timeout) == 0) return array("success" => false, "error" => self::HTTPTranslate("HTTP timeout exceeded."), "errorcode" => "timeout_exceeded");
+
+ // Connect to the target server.
+ $errornum = 0;
+ $errorstr = "";
+ if (isset($options["fp"]) && is_resource($options["fp"]))
+ {
+ $fp = $options["fp"];
+ unset($options["fp"]);
+
+ $useproxy = false;
+ $proxyconnect = false;
+ $proxydata = "";
+ }
+ else if ($useproxy)
+ {
+ if (!isset($options["proxyconnecttimeout"])) $options["proxyconnecttimeout"] = 10;
+ $timeleft = self::GetTimeLeft($startts, $timeout);
+ if ($timeleft !== false) $options["proxyconnecttimeout"] = min($options["proxyconnecttimeout"], $timeleft);
+ if (!function_exists("stream_socket_client"))
+ {
+ if ($debug) $fp = fsockopen($proxyprotocol . "://" . $proxyhost, $proxyport, $errornum, $errorstr, $options["proxyconnecttimeout"]);
+ else $fp = @fsockopen($proxyprotocol . "://" . $proxyhost, $proxyport, $errornum, $errorstr, $options["proxyconnecttimeout"]);
+ }
+ else
+ {
+ $context = @stream_context_create();
+ if (isset($options["source_ip"])) $context["socket"] = array("bindto" => $options["source_ip"] . ":0");
+ if ($proxysecure)
+ {
+ if (!isset($options["proxysslopts"]) || !is_array($options["proxysslopts"])) $options["proxysslopts"] = self::GetSafeSSLOpts();
+ self::ProcessSSLOptions($options, "proxysslopts", $host);
+ foreach ($options["proxysslopts"] as $key => $val) @stream_context_set_option($context, "ssl", $key, $val);
+ }
+ else if ($secure)
+ {
+ if (!isset($options["sslopts"]) || !is_array($options["sslopts"]))
+ {
+ $options["sslopts"] = self::GetSafeSSLOpts();
+ $options["sslopts"]["auto_peer_name"] = true;
+ }
+
+ self::ProcessSSLOptions($options, "sslopts", $host);
+ foreach ($options["sslopts"] as $key => $val) @stream_context_set_option($context, "ssl", $key, $val);
+ }
+
+ if ($debug) $fp = stream_socket_client($proxyprotocol . "://" . $proxyhost . ":" . $proxyport, $errornum, $errorstr, $options["proxyconnecttimeout"], ($async ? STREAM_CLIENT_ASYNC_CONNECT : STREAM_CLIENT_CONNECT), $context);
+ else $fp = @stream_socket_client($proxyprotocol . "://" . $proxyhost . ":" . $proxyport, $errornum, $errorstr, $options["proxyconnecttimeout"], ($async ? STREAM_CLIENT_ASYNC_CONNECT : STREAM_CLIENT_CONNECT), $context);
+ }
+
+ if ($fp === false) return array("success" => false, "error" => self::HTTPTranslate("Unable to establish a connection to '%s'.", ($proxysecure ? $proxyprotocol . "://" : "") . $proxyhost . ":" . $proxyport), "info" => $errorstr . " (" . $errornum . ")", "errorcode" => "proxy_connect");
+ }
+ else
+ {
+ if (!isset($options["connecttimeout"])) $options["connecttimeout"] = 10;
+ $timeleft = self::GetTimeLeft($startts, $timeout);
+ if ($timeleft !== false) $options["connecttimeout"] = min($options["connecttimeout"], $timeleft);
+ if (!function_exists("stream_socket_client"))
+ {
+ if ($debug) $fp = fsockopen($protocol . "://" . $host, $port, $errornum, $errorstr, $options["connecttimeout"]);
+ else $fp = @fsockopen($protocol . "://" . $host, $port, $errornum, $errorstr, $options["connecttimeout"]);
+ }
+ else
+ {
+ $context = @stream_context_create();
+ if (isset($options["source_ip"])) $context["socket"] = array("bindto" => $options["source_ip"] . ":0");
+ if ($secure)
+ {
+ if (!isset($options["sslopts"]) || !is_array($options["sslopts"]))
+ {
+ $options["sslopts"] = self::GetSafeSSLOpts();
+ $options["sslopts"]["auto_peer_name"] = true;
+ }
+
+ self::ProcessSSLOptions($options, "sslopts", $host);
+ foreach ($options["sslopts"] as $key => $val) @stream_context_set_option($context, "ssl", $key, $val);
+ }
+
+ if ($debug) $fp = stream_socket_client($protocol . "://" . $host . ":" . $port, $errornum, $errorstr, $options["connecttimeout"], ($async ? STREAM_CLIENT_ASYNC_CONNECT : STREAM_CLIENT_CONNECT), $context);
+ else $fp = @stream_socket_client($protocol . "://" . $host . ":" . $port, $errornum, $errorstr, $options["connecttimeout"], ($async ? STREAM_CLIENT_ASYNC_CONNECT : STREAM_CLIENT_CONNECT), $context);
+ }
+
+ if ($fp === false) return array("success" => false, "error" => self::HTTPTranslate("Unable to establish a connection to '%s'.", ($secure ? $protocol . "://" : "") . $host . ":" . $port), "info" => $errorstr . " (" . $errornum . ")", "errorcode" => "connect_failed");
+ }
+
+ if (function_exists("stream_set_blocking")) @stream_set_blocking($fp, ($async ? 0 : 1));
+
+ // Initialize the connection request state array.
+ $state = array(
+ "fp" => $fp,
+ "type" => "request",
+ "async" => $async,
+ "debug" => $debug,
+ "startts" => $startts,
+ "timeout" => $timeout,
+ "waituntil" => -1.0,
+ "mime" => $mime,
+ "data" => $data,
+ "bodysize" => $bodysize,
+ "chunked" => ($bodysize === false),
+ "secure" => $secure,
+ "useproxy" => $useproxy,
+ "proxysecure" => $proxysecure,
+ "proxyconnect" => $proxyconnect,
+ "proxydata" => $proxydata,
+ "currentfile" => false,
+
+ "state" => "connecting",
+
+ "options" => $options,
+ "result" => $result,
+ "close" => ($options["headers"]["Connection"] === "close"),
+ "nextread" => "",
+ "client" => true
+ );
+
+ // Return the state for async calls. Caller must call ProcessState().
+ if ($state["async"]) return array("success" => true, "state" => $state);
+
+ // Run through all of the valid states and return the result.
+ return self::ProcessState($state);
+ }
+ }
+?>
\ No newline at end of file
diff --git a/ms-windows/support/utf_utils.php b/ms-windows/support/utf_utils.php
new file mode 100644
index 0000000..c2d8819
--- /dev/null
+++ b/ms-windows/support/utf_utils.php
@@ -0,0 +1,559 @@
+= 0x0300 && $val <= 0x036F) || ($val >= 0x1DC0 && $val <= 0x1DFF) || ($val >= 0x20D0 && $val <= 0x20FF) || ($val >= 0xFE20 && $val <= 0xFE2F));
+ }
+
+ public static function Convert($data, $srctype, $desttype)
+ {
+ $arr = is_array($data);
+ if ($arr) $srctype = self::UTF32_ARRAY;
+ $x = 0;
+ $y = ($arr ? count($data) : strlen($data));
+ $result = ($desttype === self::UTF32_ARRAY ? array() : "");
+ if (!$arr && $srctype === self::UTF32_ARRAY) return $result;
+
+ $first = true;
+
+ if ($srctype === self::UTF8_BOM)
+ {
+ if (substr($data, 0, 3) === "\xEF\xBB\xBF") $x = 3;
+
+ $srctype = self::UTF8;
+ }
+
+ if ($srctype === self::UTF16_BOM)
+ {
+ if (substr($data, 0, 2) === "\xFE\xFF")
+ {
+ $srctype = self::UTF16_BE;
+ $x = 2;
+ }
+ else if (substr($data, 0, 2) === "\xFF\xFE")
+ {
+ $srctype = self::UTF16_LE;
+ $x = 2;
+ }
+ else
+ {
+ $srctype = self::UTF16_LE;
+ }
+ }
+
+ if ($srctype === self::UTF32_BOM)
+ {
+ if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
+ {
+ $srctype = self::UTF32_BE;
+ $x = 4;
+ }
+ else if (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
+ {
+ $srctype = self::UTF32_LE;
+ $x = 4;
+ }
+ else
+ {
+ $srctype = self::UTF32_LE;
+ }
+ }
+
+ while ($x < $y)
+ {
+ // Read the next valid code point.
+ $val = false;
+
+ switch ($srctype)
+ {
+ case self::UTF8:
+ {
+ $tempchr = ord($data[$x]);
+ if ($tempchr <= 0x7F)
+ {
+ $val = $tempchr;
+ $x++;
+ }
+ else if ($tempchr < 0xC2) $x++;
+ else
+ {
+ $left = $y - $x;
+ if ($left < 2) $x++;
+ else
+ {
+ $tempchr2 = ord($data[$x + 1]);
+
+ if (($tempchr >= 0xC2 && $tempchr <= 0xDF) && ($tempchr2 >= 0x80 && $tempchr2 <= 0xBF))
+ {
+ $val = (($tempchr & 0x1F) << 6) | ($tempchr2 & 0x3F);
+ $x += 2;
+ }
+ else if ($left < 3) $x++;
+ else
+ {
+ $tempchr3 = ord($data[$x + 2]);
+
+ if ($tempchr3 < 0x80 || $tempchr3 > 0xBF) $x++;
+ else
+ {
+ if (($tempchr == 0xE0 && ($tempchr2 >= 0xA0 && $tempchr2 <= 0xBF)) || ((($tempchr >= 0xE1 && $tempchr <= 0xEC) || $tempchr == 0xEE || $tempchr == 0xEF) && ($tempchr2 >= 0x80 && $tempchr2 <= 0xBF)) || ($tempchr == 0xED && ($tempchr2 >= 0x80 && $tempchr2 <= 0x9F)))
+ {
+ $val = (($tempchr & 0x0F) << 12) | (($tempchr2 & 0x3F) << 6) | ($tempchr3 & 0x3F);
+ $x += 3;
+ }
+ else if ($left < 4) $x++;
+ else
+ {
+ $tempchr4 = ord($data[$x + 3]);
+
+ if ($tempchr4 < 0x80 || $tempchr4 > 0xBF) $x++;
+ else if (($tempchr == 0xF0 && ($tempchr2 >= 0x90 && $tempchr2 <= 0xBF)) || (($tempchr >= 0xF1 && $tempchr <= 0xF3) && ($tempchr2 >= 0x80 && $tempchr2 <= 0xBF)) || ($tempchr == 0xF4 && ($tempchr2 >= 0x80 && $tempchr2 <= 0x8F)))
+ {
+ $val = (($tempchr & 0x07) << 18) | (($tempchr2 & 0x3F) << 12) | (($tempchr3 & 0x3F) << 6) | ($tempchr4 & 0x3F);
+ $x += 4;
+ }
+ else
+ {
+ $x++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ case self::UTF16_LE:
+ {
+ if ($x + 1 >= $y) $x = $y;
+ else
+ {
+ $val = unpack("v", substr($data, $x, 2))[1];
+ $x += 2;
+
+ if ($val >= 0xD800 && $val <= 0xDBFF)
+ {
+ if ($x + 1 >= $y)
+ {
+ $x = $y;
+ $val = false;
+ }
+ else
+ {
+ $val2 = unpack("v", substr($data, $x, 2))[1];
+
+ if ($val2 < 0xDC00 || $val2 > 0xDFFF) $val = false;
+ else
+ {
+ $val = ((($val - 0xD800) << 10) | ($val2 - 0xDC00)) + 0x10000;
+ $x += 2;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ case self::UTF16_BE:
+ {
+ if ($x + 1 >= $y) $x = $y;
+ else
+ {
+ $val = unpack("n", substr($data, $x, 2))[1];
+ $x += 2;
+
+ if ($val >= 0xD800 && $val <= 0xDBFF)
+ {
+ if ($x + 1 >= $y)
+ {
+ $x = $y;
+ $val = false;
+ }
+ else
+ {
+ $val2 = unpack("n", substr($data, $x, 2))[1];
+
+ if ($val2 < 0xDC00 || $val2 > 0xDFFF) $val = false;
+ else
+ {
+ $val = ((($val - 0xD800) << 10) | ($val2 - 0xDC00)) + 0x10000;
+ $x += 2;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ case self::UTF32_LE:
+ {
+ if ($x + 3 >= $y) $x = $y;
+ else
+ {
+ $val = unpack("V", substr($data, $x, 4))[1];
+ $x += 4;
+ }
+
+ break;
+ }
+ case self::UTF32_BE:
+ {
+ if ($x + 3 >= $y) $x = $y;
+ else
+ {
+ $val = unpack("N", substr($data, $x, 4))[1];
+ $x += 4;
+ }
+
+ break;
+ }
+ case self::UTF32_ARRAY:
+ {
+ $val = (int)$data[$x];
+ $x++;
+
+ break;
+ }
+ default: $x = $y; break;
+ }
+
+ // Make sure it is a valid Unicode value.
+ // 0xD800-0xDFFF are for UTF-16 surrogate pairs. Invalid characters.
+ // 0xFDD0-0xFDEF are non-characters.
+ // 0x*FFFE and 0x*FFFF are reserved.
+ // The largest possible character is 0x10FFFF.
+ // First character can't be a combining code point.
+ if ($val !== false && !($val < 0 || ($val >= 0xD800 && $val <= 0xDFFF) || ($val >= 0xFDD0 && $val <= 0xFDEF) || ($val & 0xFFFE) == 0xFFFE || $val > 0x10FFFF || ($first && self::IsCombiningCodePoint($val))))
+ {
+ if ($first)
+ {
+ if ($desttype === self::UTF8_BOM)
+ {
+ $result .= "\xEF\xBB\xBF";
+
+ $desttype = self::UTF8;
+ }
+
+ if ($desttype === self::UTF16_BOM)
+ {
+ $result .= "\xFF\xFE";
+
+ $desttype = self::UTF16_LE;
+ }
+
+ if ($srctype === self::UTF32_BOM)
+ {
+ $result .= "\xFF\xFE\x00\x00";
+
+ $desttype = self::UTF32_LE;
+ }
+
+ $first = false;
+ }
+
+ switch ($desttype)
+ {
+ case self::UTF8:
+ {
+ if ($val <= 0x7F) $result .= chr($val);
+ else if ($val <= 0x7FF) $result .= chr(0xC0 | ($val >> 6)) . chr(0x80 | ($val & 0x3F));
+ else if ($val <= 0xFFFF) $result .= chr(0xE0 | ($val >> 12)) . chr(0x80 | (($val >> 6) & 0x3F)) . chr(0x80 | ($val & 0x3F));
+ else if ($val <= 0x10FFFF) $result .= chr(0xF0 | ($val >> 18)) . chr(0x80 | (($val >> 12) & 0x3F)) . chr(0x80 | (($val >> 6) & 0x3F)) . chr(0x80 | ($val & 0x3F));
+
+ break;
+ }
+ case self::UTF16_LE:
+ {
+ if ($val <= 0xFFFF) $result .= pack("v", $val);
+ else
+ {
+ $val -= 0x10000;
+ $result .= pack("v", ((($val >> 10) & 0x3FF) + 0xD800));
+ $result .= pack("v", (($val & 0x3FF) + 0xDC00));
+ }
+
+ break;
+ }
+ case self::UTF16_BE:
+ {
+ if ($val <= 0xFFFF) $result .= pack("n", $val);
+ else
+ {
+ $val -= 0x10000;
+ $result .= pack("n", ((($val >> 10) & 0x3FF) + 0xD800));
+ $result .= pack("n", (($val & 0x3FF) + 0xDC00));
+ }
+
+ break;
+ }
+ case self::UTF32_LE:
+ {
+ $result .= pack("V", $val);
+
+ break;
+ }
+ case self::UTF32_BE:
+ {
+ $result .= pack("N", $val);
+
+ break;
+ }
+ case self::UTF32_ARRAY:
+ {
+ $result[] = $val;
+
+ break;
+ }
+ default: $x = $y; break;
+ }
+ }
+ }
+
+ return $result;
+ }
+
+
+ protected const PUNYCODE_BASE = 36;
+ protected const PUNYCODE_TMIN = 1;
+ protected const PUNYCODE_TMAX = 26;
+ protected const PUNYCODE_SKEW = 38;
+ protected const PUNYCODE_DAMP = 700;
+ protected const PUNYCODE_INITIAL_BIAS = 72;
+ protected const PUNYCODE_INITIAL_N = 0x80;
+ protected const PUNYCODE_DIGIT_MAP = "abcdefghijklmnopqrstuvwxyz0123456789";
+
+ public static function ConvertToPunycode($domain)
+ {
+ // Reject invalid domain name lengths.
+ if (strlen($domain) > 255) return false;
+
+ $parts = explode(".", $domain);
+
+ foreach ($parts as $num => $part)
+ {
+ // Reject invalid label lengths.
+ $y = strlen($part);
+ if ($y > 63) return false;
+
+ // Skip already encoded portions.
+ if (substr($part, 0, 4) === "xn--") continue;
+
+ // Convert UTF-8 to UTF-32 code points.
+ $data = self::Convert($part, self::UTF8, self::UTF32_ARRAY);
+
+ // Handle ASCII code points.
+ $part2 = "";
+ foreach ($data as $cp)
+ {
+ if ($cp <= 0x7F) $part2 .= strtolower(chr($cp));
+ }
+
+ $numhandled = strlen($part2);
+ $y = count($data);
+
+ if ($numhandled >= $y)
+ {
+ $parts[$num] = $part2;
+
+ continue;
+ }
+
+ if ($numhandled) $part2 .= "-";
+
+ $part2 = "xn--" . $part2;
+
+ if (strlen($part2) > 63) return false;
+
+ $bias = self::PUNYCODE_INITIAL_BIAS;
+ $n = self::PUNYCODE_INITIAL_N;
+ $delta = 0;
+ $first = true;
+
+ while ($numhandled < $y)
+ {
+ // Find the next largest unhandled code point.
+ $cp2 = 0x01000000;
+ foreach ($data as $cp)
+ {
+ if ($cp >= $n && $cp2 > $cp) $cp2 = $cp;
+ }
+
+ // Increase delta but prevent overflow.
+ $delta += ($cp2 - $n) * ($numhandled + 1);
+ if ($delta < 0) return false;
+ $n = $cp2;
+
+ foreach ($data as $cp)
+ {
+ if ($cp < $n)
+ {
+ $delta++;
+
+ if ($delta < 0) return false;
+ }
+ else if ($cp === $n)
+ {
+ // Calculate and encode a variable length integer from the delta.
+ $q = $delta;
+ $x = 0;
+ do
+ {
+ $x += self::PUNYCODE_BASE;
+
+ if ($x <= $bias) $t = self::PUNYCODE_TMIN;
+ else if ($x >= $bias + self::PUNYCODE_TMAX) $t = self::PUNYCODE_TMAX;
+ else $t = $x - $bias;
+
+ if ($q < $t) break;
+
+ $part2 .= self::PUNYCODE_DIGIT_MAP[$t + (($q - $t) % (self::PUNYCODE_BASE - $t))];
+
+ $q = (int)(($q - $t) / (self::PUNYCODE_BASE - $t));
+
+ if (strlen($part2) > 63) return false;
+ } while (1);
+
+ $part2 .= self::PUNYCODE_DIGIT_MAP[$q];
+ if (strlen($part2) > 63) return false;
+
+ // Adapt bias.
+ $numhandled++;
+ $bias = self::InternalPunycodeAdapt($delta, $numhandled, $first);
+ $delta = 0;
+ $first = false;
+ }
+ }
+
+ $delta++;
+ $n++;
+ }
+
+ $parts[$num] = $part2;
+ }
+
+ return implode(".", $parts);
+ }
+
+ public static function ConvertFromPunycode($domain)
+ {
+ // Reject invalid domain name lengths.
+ if (strlen($domain) > 255) return false;
+
+ $parts = explode(".", $domain);
+
+ foreach ($parts as $num => $part)
+ {
+ // Reject invalid label lengths.
+ $y = strlen($part);
+ if ($y > 63) return false;
+
+ // Skip unencoded portions.
+ if (substr($part, 0, 4) !== "xn--") continue;
+
+ $part = substr($part, 4);
+
+ // Convert UTF-8 to UTF-32 code points.
+ $data = self::Convert($part, self::UTF8, self::UTF32_ARRAY);
+
+ // Handle ASCII code points.
+ $hyphen = ord("-");
+ for ($x = count($data); $x && $data[$x - 1] !== $hyphen; $x--);
+ if (!$x) $data2 = array();
+ else
+ {
+ $data2 = array_splice($data, 0, $x - 1);
+
+ array_shift($data);
+ }
+
+ $numhandled = count($data2);
+
+ $bias = self::PUNYCODE_INITIAL_BIAS;
+ $n = self::PUNYCODE_INITIAL_N;
+ $delta = 0;
+ $first = true;
+
+ $pos = 0;
+ $y = count($data);
+ while ($pos < $y)
+ {
+ // Calculate and decode a delta from the variable length integer.
+ $olddelta = $delta;
+ $w = 1;
+ $x = 0;
+ do
+ {
+ $x += self::PUNYCODE_BASE;
+
+ $cp = $data[$pos];
+ $pos++;
+
+ if ($cp >= ord("a") && $cp <= ord("z")) $digit = $cp - ord("a");
+ else if ($cp >= ord("A") && $cp <= ord("Z")) $digit = $cp - ord("A");
+ else if ($cp >= ord("0") && $cp <= ord("9")) $digit = $cp - ord("0") + 26;
+ else return false;
+
+ $delta += $digit * $w;
+ if ($delta < 0) return false;
+
+ if ($x <= $bias) $t = self::PUNYCODE_TMIN;
+ else if ($x >= $bias + self::PUNYCODE_TMAX) $t = self::PUNYCODE_TMAX;
+ else $t = $x - $bias;
+
+ if ($digit < $t) break;
+
+ $w *= (self::PUNYCODE_BASE - $t);
+ if ($w < 0) return false;
+ } while (1);
+
+ // Adapt bias.
+ $numhandled++;
+ $bias = self::InternalPunycodeAdapt($delta - $olddelta, $numhandled, $first);
+ $first = false;
+
+ // Delta was supposed to wrap around from $numhandled to 0, incrementing $n each time, so fix that now.
+ $n += (int)($delta / $numhandled);
+ $delta %= $numhandled;
+
+ // Insert $n (the code point) at the delta position.
+ array_splice($data2, $delta, 0, array($n));
+ $delta++;
+ }
+
+ $parts[$num] = self::Convert($data2, self::UTF32_ARRAY, self::UTF8);
+ }
+
+ return implode(".", $parts);
+ }
+
+ // RFC3492 adapt() function.
+ protected static function InternalPunycodeAdapt($delta, $numpoints, $first)
+ {
+ $delta = ($first ? (int)($delta / self::PUNYCODE_DAMP) : $delta >> 1);
+ $delta += (int)($delta / $numpoints);
+
+ $y = self::PUNYCODE_BASE - self::PUNYCODE_TMIN;
+
+ $condval = (int)(($y * self::PUNYCODE_TMAX) / 2);
+ for ($x = 0; $delta > $condval; $x += self::PUNYCODE_BASE) $delta = (int)($delta / $y);
+
+ return (int)($x + ((($y + 1) * $delta) / ($delta + self::PUNYCODE_SKEW)));
+ }
+ }
+?>
\ No newline at end of file
diff --git a/ms-windows/support/web_browser.php b/ms-windows/support/web_browser.php
new file mode 100644
index 0000000..ff6eb8c
--- /dev/null
+++ b/ms-windows/support/web_browser.php
@@ -0,0 +1,1189 @@
+ResetState();
+ $this->SetState($prevstate);
+ $this->html = false;
+ }
+
+ public function ResetState()
+ {
+ $this->data = array(
+ "allowedprotocols" => array("http" => true, "https" => true),
+ "allowedredirprotocols" => array("http" => true, "https" => true),
+ "hostauths" => array(),
+ "cookies" => array(),
+ "referer" => "",
+ "autoreferer" => true,
+ "useragent" => "firefox",
+ "followlocation" => true,
+ "maxfollow" => 20,
+ "extractforms" => false,
+ "httpopts" => array(),
+ );
+ }
+
+ public function SetState($options = array())
+ {
+ $this->data = array_merge($this->data, $options);
+ }
+
+ public function GetState()
+ {
+ return $this->data;
+ }
+
+ public function ProcessState(&$state)
+ {
+ while ($state["state"] !== "done")
+ {
+ switch ($state["state"])
+ {
+ case "initialize":
+ {
+ if (!isset($this->data["allowedprotocols"][$state["urlinfo"]["scheme"]]) || !$this->data["allowedprotocols"][$state["urlinfo"]["scheme"]])
+ {
+ return array("success" => false, "error" => self::WBTranslate("Protocol '%s' is not allowed in '%s'.", $state["urlinfo"]["scheme"], $state["url"]), "errorcode" => "allowed_protocols");
+ }
+
+ $filename = HTTP::ExtractFilename($state["urlinfo"]["path"]);
+ $pos = strrpos($filename, ".");
+ $fileext = ($pos !== false ? strtolower(substr($filename, $pos + 1)) : "");
+
+ // Set up some standard headers.
+ $headers = array();
+ $profile = strtolower($state["profile"]);
+ $tempprofile = explode("-", $profile);
+ if (count($tempprofile) == 2)
+ {
+ $profile = $tempprofile[0];
+ $fileext = $tempprofile[1];
+ }
+ if (substr($profile, 0, 2) == "ie" || ($profile == "auto" && substr($this->data["useragent"], 0, 2) == "ie"))
+ {
+ if ($fileext == "css") $headers["Accept"] = "text/css";
+ else if ($fileext == "png" || $fileext == "jpg" || $fileext == "jpeg" || $fileext == "gif" || $fileext == "svg") $headers["Accept"] = "image/png, image/svg+xml, image/*;q=0.8, */*;q=0.5";
+ else if ($fileext == "js") $headers["Accept"] = "application/javascript, */*;q=0.8";
+ else if ($this->data["referer"] != "" || $fileext == "" || $fileext == "html" || $fileext == "xhtml" || $fileext == "xml") $headers["Accept"] = "text/html, application/xhtml+xml, */*";
+ else $headers["Accept"] = "*/*";
+
+ $headers["Accept-Language"] = "en-US";
+ $headers["User-Agent"] = HTTP::GetUserAgent(substr($profile, 0, 2) == "ie" ? $profile : $this->data["useragent"]);
+ }
+ else if ($profile == "firefox" || ($profile == "auto" && $this->data["useragent"] == "firefox"))
+ {
+ if ($fileext == "css") $headers["Accept"] = "text/css,*/*;q=0.1";
+ else if ($fileext == "png" || $fileext == "jpg" || $fileext == "jpeg" || $fileext == "gif" || $fileext == "svg") $headers["Accept"] = "image/png,image/*;q=0.8,*/*;q=0.5";
+ else if ($fileext == "js") $headers["Accept"] = "*/*";
+ else $headers["Accept"] = "text/html, application/xhtml+xml, */*";
+
+ $headers["Accept-Language"] = "en-us,en;q=0.5";
+ $headers["Cache-Control"] = "max-age=0";
+ $headers["User-Agent"] = HTTP::GetUserAgent("firefox");
+ }
+ else if ($profile == "opera" || ($profile == "auto" && $this->data["useragent"] == "opera"))
+ {
+ // Opera has the right idea: Just send the same thing regardless of the request type.
+ $headers["Accept"] = "text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1";
+ $headers["Accept-Language"] = "en-US,en;q=0.9";
+ $headers["Cache-Control"] = "no-cache";
+ $headers["User-Agent"] = HTTP::GetUserAgent("opera");
+ }
+ else if ($profile == "safari" || $profile == "edge" || $profile == "chrome" || ($profile == "auto" && ($this->data["useragent"] == "safari" || $this->data["useragent"] == "edge" || $this->data["useragent"] == "chrome")))
+ {
+ if ($fileext == "css") $headers["Accept"] = "text/css,*/*;q=0.1";
+ else if ($fileext == "png" || $fileext == "jpg" || $fileext == "jpeg" || $fileext == "gif" || $fileext == "svg" || $fileext == "js") $headers["Accept"] = "*/*";
+ else $headers["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
+
+ $headers["Accept-Charset"] = "ISO-8859-1,utf-8;q=0.7,*;q=0.3";
+ $headers["Accept-Language"] = "en-US,en;q=0.8";
+ $headers["User-Agent"] = HTTP::GetUserAgent($profile == "safari" || $profile == "chrome" ? $profile : $this->data["useragent"]);
+ }
+
+ if ($this->data["referer"] != "") $headers["Referer"] = $this->data["referer"];
+
+ // Generate the final headers array.
+ $headers = array_merge($headers, $state["httpopts"]["headers"], $state["tempoptions"]["headers"]);
+
+ // Calculate the host and reverse host and remove port information.
+ $host = (isset($headers["Host"]) ? $headers["Host"] : $state["urlinfo"]["host"]);
+ $pos = strpos($host, "]");
+ if (substr($host, 0, 1) == "[" && $pos !== false)
+ {
+ $host = substr($host, 0, $pos + 1);
+ }
+ else
+ {
+ $pos = strpos($host, ":");
+ if ($pos !== false) $host = substr($host, 0, $pos);
+ }
+ $dothost = $host;
+ $dothost = strtolower($dothost);
+ if (substr($dothost, 0, 1) != ".") $dothost = "." . $dothost;
+ $state["dothost"] = $dothost;
+
+ // Append Authorization header.
+ if (isset($headers["Authorization"])) $this->data["hostauths"][$host] = $headers["Authorization"];
+ else if (isset($this->data["hostauths"][$host])) $headers["Authorization"] = $this->data["hostauths"][$host];
+
+ // Append cookies and delete old, invalid cookies.
+ $secure = ($state["urlinfo"]["scheme"] == "https");
+ $cookiepath = $state["urlinfo"]["path"];
+ if ($cookiepath == "") $cookiepath = "/";
+ $pos = strrpos($cookiepath, "/");
+ if ($pos !== false) $cookiepath = substr($cookiepath, 0, $pos + 1);
+ $state["cookiepath"] = $cookiepath;
+ $cookies = array();
+ foreach ($this->data["cookies"] as $domain => $paths)
+ {
+ if (strlen($dothost) >= strlen($domain) && substr($dothost, -strlen($domain)) === $domain)
+ {
+ foreach ($paths as $path => $cookies2)
+ {
+ if (substr($cookiepath, 0, strlen($path)) == $path)
+ {
+ foreach ($cookies2 as $num => $info)
+ {
+ if (isset($info["expires_ts"]) && $this->GetExpiresTimestamp($info["expires_ts"]) < time()) unset($this->data["cookies"][$domain][$path][$num]);
+ else if ($secure || !isset($info["secure"])) $cookies[$info["name"]] = $info["value"];
+ }
+
+ if (!count($this->data["cookies"][$domain][$path])) unset($this->data["cookies"][$domain][$path]);
+ }
+ }
+
+ if (!count($this->data["cookies"][$domain])) unset($this->data["cookies"][$domain]);
+ }
+ }
+
+ $cookies2 = array();
+ foreach ($cookies as $name => $value) $cookies2[] = rawurlencode($name) . "=" . rawurlencode($value);
+ $headers["Cookie"] = implode("; ", $cookies2);
+ if ($headers["Cookie"] == "") unset($headers["Cookie"]);
+
+ // Generate the final options array.
+ $state["options"] = array_merge($state["httpopts"], $state["tempoptions"]);
+ $state["options"]["headers"] = $headers;
+ if ($state["timeout"] !== false) $state["options"]["timeout"] = HTTP::GetTimeLeft($state["startts"], $state["timeout"]);
+
+ // Let a callback handle any additional state changes.
+ if (isset($state["options"]["pre_retrievewebpage_callback"]) && is_callable($state["options"]["pre_retrievewebpage_callback"]) && !call_user_func_array($state["options"]["pre_retrievewebpage_callback"], array(&$state)))
+ {
+ return array("success" => false, "error" => self::WBTranslate("Pre-RetrieveWebpage callback returned with a failure condition for '%s'.", $state["url"]), "errorcode" => "pre_retrievewebpage_callback");
+ }
+
+ // Process the request.
+ $result = HTTP::RetrieveWebpage($state["url"], $state["options"]);
+ $result["url"] = $state["url"];
+ unset($state["options"]["files"]);
+ unset($state["options"]["body"]);
+ unset($state["tempoptions"]["headers"]["Content-Type"]);
+ $result["options"] = $state["options"];
+ $result["firstreqts"] = $state["startts"];
+ $result["numredirects"] = $state["numredirects"];
+ $result["redirectts"] = $state["redirectts"];
+ if (isset($result["rawsendsize"])) $state["totalrawsendsize"] += $result["rawsendsize"];
+ $result["totalrawsendsize"] = $state["totalrawsendsize"];
+ if (!$result["success"]) return array("success" => false, "error" => self::WBTranslate("Unable to retrieve content. %s", $result["error"]), "info" => $result, "state" => $state, "errorcode" => "retrievewebpage");
+
+ if (isset($state["options"]["async"]) && $state["options"]["async"])
+ {
+ $state["async"] = true;
+ $state["httpstate"] = $result["state"];
+
+ $state["state"] = "process_async";
+ }
+ else
+ {
+ $state["result"] = $result;
+
+ $state["state"] = "post_retrieval";
+ }
+
+ break;
+ }
+ case "process_async":
+ {
+ // Run a cycle of the HTTP state processor.
+ $result = HTTP::ProcessState($state["httpstate"]);
+ if (!$result["success"]) return $result;
+
+ $result["url"] = $state["url"];
+ $result["options"] = $state["options"];
+ unset($result["options"]["files"]);
+ unset($result["options"]["body"]);
+ $result["firstreqts"] = $state["startts"];
+ $result["numredirects"] = $state["numredirects"];
+ $result["redirectts"] = $state["redirectts"];
+ if (isset($result["rawsendsize"])) $state["totalrawsendsize"] += $result["rawsendsize"];
+ $result["totalrawsendsize"] = $state["totalrawsendsize"];
+
+ $state["httpstate"] = false;
+ $state["result"] = $result;
+
+ $state["state"] = "post_retrieval";
+
+ break;
+ }
+ case "post_retrieval":
+ {
+ // Set up structures for another round.
+ if ($this->data["autoreferer"]) $this->data["referer"] = $state["url"];
+ if (isset($state["result"]["headers"]["Location"]) && $this->data["followlocation"])
+ {
+ $state["redirectts"] = microtime(true);
+
+ unset($state["tempoptions"]["method"]);
+ unset($state["tempoptions"]["write_body_callback"]);
+ unset($state["tempoptions"]["body"]);
+ unset($state["tempoptions"]["postvars"]);
+ unset($state["tempoptions"]["files"]);
+
+ $state["tempoptions"]["headers"]["Referer"] = $state["url"];
+ $state["url"] = $state["result"]["headers"]["Location"][0];
+
+ // Generate an absolute URL.
+ if ($this->data["referer"] != "") $state["url"] = HTTP::ConvertRelativeToAbsoluteURL($this->data["referer"], $state["url"]);
+
+ $urlinfo2 = HTTP::ExtractURL($state["url"]);
+
+ if (!isset($this->data["allowedredirprotocols"][$urlinfo2["scheme"]]) || !$this->data["allowedredirprotocols"][$urlinfo2["scheme"]])
+ {
+ return array("success" => false, "error" => self::WBTranslate("Protocol '%s' is not allowed. Server attempted to redirect to '%s'.", $urlinfo2["scheme"], $state["url"]), "info" => $state["result"], "errorcode" => "allowed_redir_protocols");
+ }
+
+ if ($urlinfo2["host"] != $state["urlinfo"]["host"])
+ {
+ unset($state["tempoptions"]["headers"]["Host"]);
+ unset($state["httpopts"]["headers"]["Host"]);
+
+ unset($state["httpopts"]["headers"]["Authorization"]);
+ unset($state["tempoptions"]["headers"]["Authorization"]);
+ }
+
+ $state["urlinfo"] = $urlinfo2;
+ $state["numredirects"]++;
+ }
+
+ // Handle any 'Set-Cookie' headers.
+ if (isset($state["result"]["headers"]["Set-Cookie"]))
+ {
+ foreach ($state["result"]["headers"]["Set-Cookie"] as $cookie)
+ {
+ $items = explode(";", $cookie);
+ $item = trim(array_shift($items));
+ if ($item != "")
+ {
+ $cookie2 = array();
+ $pos = strpos($item, "=");
+ if ($pos === false)
+ {
+ $cookie2["name"] = urldecode($item);
+ $cookie2["value"] = "";
+ }
+ else
+ {
+ $cookie2["name"] = urldecode(substr($item, 0, $pos));
+ $cookie2["value"] = urldecode(substr($item, $pos + 1));
+ }
+
+ $cookie = array();
+ foreach ($items as $item)
+ {
+ $item = trim($item);
+ if ($item != "")
+ {
+ $pos = strpos($item, "=");
+ if ($pos === false) $cookie[strtolower(trim(urldecode($item)))] = "";
+ else $cookie[strtolower(trim(urldecode(substr($item, 0, $pos))))] = urldecode(substr($item, $pos + 1));
+ }
+ }
+ $cookie = array_merge($cookie, $cookie2);
+
+ if (isset($cookie["expires"]))
+ {
+ $ts = HTTP::GetDateTimestamp($cookie["expires"]);
+ $cookie["expires_ts"] = gmdate("Y-m-d H:i:s", ($ts === false ? time() - 24 * 60 * 60 : $ts));
+ }
+ else if (isset($cookie["max-age"]))
+ {
+ $cookie["expires_ts"] = gmdate("Y-m-d H:i:s", time() + (int)$cookie["max-age"]);
+ }
+ else
+ {
+ unset($cookie["expires_ts"]);
+ }
+
+ if (!isset($cookie["domain"])) $cookie["domain"] = $state["dothost"];
+ if (!isset($cookie["path"])) $cookie["path"] = $state["cookiepath"];
+
+ $this->SetCookie($cookie);
+ }
+ }
+ }
+
+ if ($state["numfollow"] > 0) $state["numfollow"]--;
+
+ // If this is a redirect, handle it by starting over.
+ if (isset($state["result"]["headers"]["Location"]) && $this->data["followlocation"] && $state["numfollow"])
+ {
+ $state["result"] = false;
+
+ $state["state"] = "initialize";
+ }
+ else
+ {
+ $state["result"]["numredirects"] = $state["numredirects"];
+ $state["result"]["redirectts"] = $state["redirectts"];
+
+ // Extract the forms from the page in a parsed format.
+ // Call WebBrowser::GenerateFormRequest() to prepare an actual request for Process().
+ if ($this->data["extractforms"]) $state["result"]["forms"] = $this->ExtractForms($state["result"]["url"], $state["result"]["body"], (isset($state["tempoptions"]["extractforms_hint"]) ? $state["tempoptions"]["extractforms_hint"] : false));
+
+ $state["state"] = "done";
+ }
+
+ break;
+ }
+ }
+ }
+
+ return $state["result"];
+ }
+
+ public function Process($url, $tempoptions = array())
+ {
+ $startts = microtime(true);
+ $redirectts = $startts;
+
+ // Handle older function call: Process($url, $profile, $tempoptions)
+ if (is_string($tempoptions))
+ {
+ $args = func_get_args();
+ if (count($args) < 3) $tempoptions = array();
+ else $tempoptions = $args[2];
+
+ $tempoptions["profile"] = $args[1];
+ }
+
+ $profile = (isset($tempoptions["profile"]) ? $tempoptions["profile"] : "auto");
+
+ if (isset($tempoptions["timeout"])) $timeout = $tempoptions["timeout"];
+ else if (isset($this->data["httpopts"]["timeout"])) $timeout = $this->data["httpopts"]["timeout"];
+ else $timeout = false;
+
+ // Deal with possible application hanging issues.
+ if (isset($tempoptions["streamtimeout"])) $streamtimeout = $tempoptions["streamtimeout"];
+ else if (isset($this->data["httpopts"]["streamtimeout"])) $streamtimeout = $this->data["httpopts"]["streamtimeout"];
+ else $streamtimeout = 300;
+ $tempoptions["streamtimeout"] = $streamtimeout;
+
+ if (!isset($this->data["httpopts"]["headers"])) $this->data["httpopts"]["headers"] = array();
+ $this->data["httpopts"]["headers"] = HTTP::NormalizeHeaders($this->data["httpopts"]["headers"]);
+ unset($this->data["httpopts"]["method"]);
+ unset($this->data["httpopts"]["write_body_callback"]);
+ unset($this->data["httpopts"]["body"]);
+ unset($this->data["httpopts"]["postvars"]);
+ unset($this->data["httpopts"]["files"]);
+
+ $httpopts = $this->data["httpopts"];
+ $numfollow = $this->data["maxfollow"];
+ $numredirects = 0;
+ $totalrawsendsize = 0;
+
+ if (!isset($tempoptions["headers"])) $tempoptions["headers"] = array();
+ $tempoptions["headers"] = HTTP::NormalizeHeaders($tempoptions["headers"]);
+ if (isset($tempoptions["headers"]["Referer"])) $this->data["referer"] = $tempoptions["headers"]["Referer"];
+
+ // If a referrer is specified, use it to generate an absolute URL.
+ if ($this->data["referer"] != "") $url = HTTP::ConvertRelativeToAbsoluteURL($this->data["referer"], $url);
+
+ $urlinfo = HTTP::ExtractURL($url);
+
+ // Initialize the process state array.
+ $state = array(
+ "async" => false,
+ "startts" => $startts,
+ "redirectts" => $redirectts,
+ "timeout" => $timeout,
+ "tempoptions" => $tempoptions,
+ "httpopts" => $httpopts,
+ "numfollow" => $numfollow,
+ "numredirects" => $numredirects,
+ "totalrawsendsize" => $totalrawsendsize,
+ "profile" => $profile,
+ "url" => $url,
+ "urlinfo" => $urlinfo,
+
+ "state" => "initialize",
+ "httpstate" => false,
+ "result" => false,
+ );
+
+ // Run at least one state cycle to properly initialize the state array.
+ $result = $this->ProcessState($state);
+
+ // Return the state for async calls. Caller must call ProcessState().
+ if ($state["async"]) return array("success" => true, "state" => $state);
+
+ return $result;
+ }
+
+ // Implements the correct MultiAsyncHelper responses for WebBrowser instances.
+ public function ProcessAsync__Handler($mode, &$data, $key, &$info)
+ {
+ switch ($mode)
+ {
+ case "init":
+ {
+ if ($info["init"]) $data = $info["keep"];
+ else
+ {
+ $info["result"] = $this->Process($info["url"], $info["tempoptions"]);
+ if (!$info["result"]["success"])
+ {
+ $info["keep"] = false;
+
+ if (is_callable($info["callback"])) call_user_func_array($info["callback"], array($key, $info["url"], $info["result"]));
+ }
+ else
+ {
+ $info["state"] = $info["result"]["state"];
+
+ // Move to the live queue.
+ $data = true;
+ }
+ }
+
+ break;
+ }
+ case "update":
+ case "read":
+ case "write":
+ {
+ if ($info["keep"])
+ {
+ $info["result"] = $this->ProcessState($info["state"]);
+ if ($info["result"]["success"] || $info["result"]["errorcode"] !== "no_data") $info["keep"] = false;
+
+ if (is_callable($info["callback"])) call_user_func_array($info["callback"], array($key, $info["url"], $info["result"]));
+
+ if ($mode === "update") $data = $info["keep"];
+ }
+
+ break;
+ }
+ case "readfps":
+ {
+ if ($info["state"]["httpstate"] !== false && HTTP::WantRead($info["state"]["httpstate"])) $data[$key] = $info["state"]["httpstate"]["fp"];
+
+ break;
+ }
+ case "writefps":
+ {
+ if ($info["state"]["httpstate"] !== false && HTTP::WantWrite($info["state"]["httpstate"])) $data[$key] = $info["state"]["httpstate"]["fp"];
+
+ break;
+ }
+ case "cleanup":
+ {
+ // When true, caller is removing. Otherwise, detaching from the queue.
+ if ($data === true)
+ {
+ if (isset($info["state"]))
+ {
+ if ($info["state"]["httpstate"] !== false) HTTP::ForceClose($info["state"]["httpstate"]);
+
+ unset($info["state"]);
+ }
+
+ $info["keep"] = false;
+ }
+
+ break;
+ }
+ }
+ }
+
+ public function ProcessAsync($helper, $key, $callback, $url, $tempoptions = array())
+ {
+ $tempoptions["async"] = true;
+
+ // Handle older function call: ProcessAsync($helper, $key, $callback, $url, $profile, $tempoptions)
+ if (is_string($tempoptions))
+ {
+ $args = func_get_args();
+ if (count($args) < 6) $tempoptions = array();
+ else $tempoptions = $args[5];
+
+ $tempoptions["profile"] = $args[4];
+ }
+
+ $profile = (isset($tempoptions["profile"]) ? $tempoptions["profile"] : "auto");
+
+ $info = array(
+ "init" => false,
+ "keep" => true,
+ "callback" => $callback,
+ "url" => $url,
+ "tempoptions" => $tempoptions,
+ "result" => false
+ );
+
+ $helper->Set($key, $info, array($this, "ProcessAsync__Handler"));
+
+ return array("success" => true);
+ }
+
+ public function ExtractForms($baseurl, $data, $hint = false)
+ {
+ $result = array();
+
+ $lasthint = "";
+ $hintmap = array();
+ if ($this->html === false)
+ {
+ if (!class_exists("simple_html_dom", false)) require_once str_replace("\\", "/", dirname(__FILE__)) . "/simple_html_dom.php";
+
+ $this->html = new simple_html_dom();
+ }
+ $this->html->load($data);
+ $rows = $this->html->find("label[for]");
+ foreach ($rows as $row)
+ {
+ $hintmap[trim($row->for)] = trim($row->plaintext);
+ }
+ $html5rows = $this->html->find("input[form],textarea[form],select[form],button[form],datalist[id]" . ($hint !== false ? "," . $hint : ""));
+ $rows = $this->html->find("form");
+ foreach ($rows as $row)
+ {
+ $info = array();
+ if (isset($row->id)) $info["id"] = trim($row->id);
+ if (isset($row->name)) $info["name"] = (string)$row->name;
+ $info["action"] = (isset($row->action) ? HTTP::ConvertRelativeToAbsoluteURL($baseurl, (string)$row->action) : $baseurl);
+ $info["method"] = (isset($row->method) && strtolower(trim($row->method)) == "post" ? "post" : "get");
+ if ($info["method"] == "post") $info["enctype"] = (isset($row->enctype) ? strtolower($row->enctype) : "application/x-www-form-urlencoded");
+ if (isset($row->{"accept-charset"})) $info["accept-charset"] = (string)$row->{"accept-charset"};
+
+ $fields = array();
+ $rows2 = $row->find("input,textarea,select,button" . ($hint !== false ? "," . $hint : ""));
+ foreach ($rows2 as $row2)
+ {
+ if (!isset($row2->form))
+ {
+ if (isset($row2->id) && $row2->id != "" && isset($hintmap[trim($row2->id)])) $lasthint = $hintmap[trim($row2->id)];
+
+ $this->ExtractFieldFromDOM($fields, $row2, $lasthint);
+ }
+ }
+
+ // Handle HTML5.
+ if (isset($info["id"]) && $info["id"] != "")
+ {
+ foreach ($html5rows as $row2)
+ {
+ if (strpos(" " . $info["id"] . " ", " " . $row2->form . " ") !== false)
+ {
+ if (isset($hintmap[$info["id"]])) $lasthint = $hintmap[$info["id"]];
+
+ $this->ExtractFieldFromDOM($fields, $row2, $lasthint);
+ }
+ }
+ }
+
+ $form = new WebBrowserForm();
+ $form->info = $info;
+ $form->fields = $fields;
+ $result[] = $form;
+ }
+
+ return $result;
+ }
+
+ private function ExtractFieldFromDOM(&$fields, $row, &$lasthint)
+ {
+ switch ($row->tag)
+ {
+ case "input":
+ {
+ if (!isset($row->name) && ($row->type === "submit" || $row->type === "image")) $row->name = "";
+
+ if (isset($row->name) && is_string($row->name))
+ {
+ $field = array(
+ "id" => (isset($row->id) ? (string)$row->id : false),
+ "type" => "input." . (isset($row->type) ? strtolower($row->type) : "text"),
+ "name" => $row->name,
+ "value" => (isset($row->value) ? html_entity_decode($row->value, ENT_COMPAT, "UTF-8") : "")
+ );
+ if ($field["type"] == "input.radio" || $field["type"] == "input.checkbox")
+ {
+ $field["checked"] = (isset($row->checked));
+
+ if ($field["value"] === "") $field["value"] = "on";
+ }
+
+ if (isset($row->placeholder)) $field["hint"] = trim($row->placeholder);
+ else if ($field["type"] == "input.submit" || $field["type"] == "input.image") $field["hint"] = $field["type"] . "|" . $field["value"];
+ else if ($lasthint !== "") $field["hint"] = $lasthint;
+
+ $fields[] = $field;
+
+ $lasthint = "";
+ }
+
+ break;
+ }
+ case "textarea":
+ {
+ if (isset($row->name) && is_string($row->name))
+ {
+ $field = array(
+ "id" => (isset($row->id) ? (string)$row->id : false),
+ "type" => "textarea",
+ "name" => $row->name,
+ "value" => html_entity_decode($row->innertext, ENT_COMPAT, "UTF-8")
+ );
+
+ if (isset($row->placeholder)) $field["hint"] = trim($row->placeholder);
+ else if ($lasthint !== "") $field["hint"] = $lasthint;
+
+ $fields[] = $field;
+
+ $lasthint = "";
+ }
+
+ break;
+ }
+ case "select":
+ {
+ if (isset($row->name) && is_string($row->name))
+ {
+ if (isset($row->multiple))
+ {
+ // Change the type into multiple checkboxes.
+ $rows = $row->find("option");
+ foreach ($rows as $row2)
+ {
+ $field = array(
+ "id" => (isset($row->id) ? (string)$row->id : false),
+ "type" => "input.checkbox",
+ "name" => $row->name,
+ "value" => (isset($row2->value) ? html_entity_decode($row2->value, ENT_COMPAT, "UTF-8") : ""),
+ "display" => (string)$row2->innertext
+ );
+ if ($lasthint !== "") $field["hint"] = $lasthint;
+
+ $fields[] = $field;
+ }
+ }
+ else
+ {
+ $val = false;
+ $options = array();
+ $rows = $row->find("option");
+ foreach ($rows as $row2)
+ {
+ $options[$row2->value] = (string)$row2->innertext;
+
+ if ($val === false && isset($row2->selected)) $val = html_entity_decode($row2->value, ENT_COMPAT, "UTF-8");
+ }
+ if ($val === false && count($options))
+ {
+ $val = array_keys($options);
+ $val = $val[0];
+ }
+ if ($val === false) $val = "";
+
+ $field = array(
+ "id" => (isset($row->id) ? (string)$row->id : false),
+ "type" => "select",
+ "name" => $row->name,
+ "value" => $val,
+ "options" => $options
+ );
+ if ($lasthint !== "") $field["hint"] = $lasthint;
+
+ $fields[] = $field;
+ }
+
+ $lasthint = "";
+ }
+
+ break;
+ }
+ case "button":
+ {
+ if (isset($row->name) && is_string($row->name))
+ {
+ $field = array(
+ "id" => (isset($row->id) ? (string)$row->id : false),
+ "type" => "button." . (isset($row->type) ? strtolower($row->type) : "submit"),
+ "name" => $row->name,
+ "value" => (isset($row->value) ? html_entity_decode($row->value, ENT_COMPAT, "UTF-8") : "")
+ );
+ $field["hint"] = (trim($row->plaintext) !== "" ? trim($row->plaintext) : "button|" . $field["value"]);
+
+ $fields[] = $field;
+
+ $lasthint = "";
+ }
+
+ break;
+ }
+ case "datalist":
+ {
+ // Do nothing since browsers don't actually enforce this tag's values.
+
+ break;
+ }
+ default:
+ {
+ // Hint for the next element.
+ $lasthint = (string)$row->plaintext;
+
+ break;
+ }
+ }
+ }
+
+ public static function InteractiveFormFill($forms, $showselected = false)
+ {
+ if (!is_array($forms)) $forms = array($forms);
+
+ if (!count($forms)) return false;
+
+ if (count($forms) == 1) $form = reset($forms);
+ else
+ {
+ echo self::WBTranslate("There are multiple forms available to fill out:\n");
+ foreach ($forms as $num => $form)
+ {
+ echo self::WBTranslate("\t%d:\n", $num + 1);
+ foreach ($form->info as $key => $val) echo self::WBTranslate("\t\t%s: %s\n", $key, $val);
+ echo self::WBTranslate("\t\tfields: %d\n", count($form->GetVisibleFields(false)));
+ echo self::WBTranslate("\t\tbuttons: %d\n", count($form->GetVisibleFields(true)) - count($form->GetVisibleFields(false)));
+ echo "\n";
+ }
+
+ do
+ {
+ echo self::WBTranslate("Select: ");
+
+ $num = (int)trim(fgets(STDIN)) - 1;
+ } while (!isset($forms[$num]));
+
+ $form = $forms[$num];
+ }
+
+ if ($showselected)
+ {
+ echo self::WBTranslate("Selected form:\n");
+ foreach ($form->info as $key => $val) echo self::WBTranslate("\t%s: %s\n", $key, $val);
+ echo "\n";
+ }
+
+ if (count($form->GetVisibleFields(false)))
+ {
+ echo self::WBTranslate("Select form fields by field number to edit a field. When ready to submit the form, leave 'Field number' empty.\n\n");
+
+ do
+ {
+ echo self::WBTranslate("Editable form fields:\n");
+ foreach ($form->fields as $num => $field)
+ {
+ if ($field["type"] == "input.hidden" || $field["type"] == "input.submit" || $field["type"] == "input.image" || $field["type"] == "input.button" || substr($field["type"], 0, 7) == "button.") continue;
+
+ echo self::WBTranslate("\t%d: %s - %s\n", $num + 1, $field["name"], (is_array($field["value"]) ? json_encode($field["value"], JSON_PRETTY_PRINT) : $field["value"]) . (($field["type"] == "input.radio" || $field["type"] == "input.checkbox") ? ($field["checked"] ? self::WBTranslate(" [Y]") : self::WBTranslate(" [N]")) : "") . (isset($field["hint"]) && $field["hint"] !== "" ? " [" . $field["hint"] . "]" : ""));
+ }
+ echo "\n";
+
+ do
+ {
+ echo self::WBTranslate("Field number: ");
+
+ $num = trim(fgets(STDIN));
+ if ($num === "") break;
+
+ $num = (int)$num - 1;
+ } while (!isset($form->fields[$num]) || $form->fields[$num]["type"] == "input.hidden" || $form->fields[$num]["type"] == "input.submit" || $form->fields[$num]["type"] == "input.image" || $form->fields[$num]["type"] == "input.button" || substr($form->fields[$num]["type"], 0, 7) == "button.");
+
+ if ($num === "")
+ {
+ echo "\n";
+
+ break;
+ }
+
+ $field = $form->fields[$num];
+ $prefix = (isset($field["hint"]) && $field["hint"] !== "" ? $field["hint"] . " | " : "") . $field["name"];
+
+ if ($field["type"] == "select")
+ {
+ echo self::WBTranslate("[%s] Options:\n", $prefix);
+ foreach ($field["options"] as $key => $val)
+ {
+ echo self::WBTranslate("\t%s: %s\n");
+ }
+
+ do
+ {
+ echo self::WBTranslate("[%s] Select: ", $prefix);
+
+ $select = rtrim(fgets(STDIN));
+ } while (!isset($field["options"][$select]));
+
+ $form->fields[$num]["value"] = $select;
+ }
+ else if ($field["type"] == "input.radio")
+ {
+ $form->SetFormValue($field["name"], $field["value"], true, "input.radio");
+ }
+ else if ($field["type"] == "input.checkbox")
+ {
+ $form->fields[$num]["checked"] = !$field["checked"];
+ }
+ else if ($field["type"] == "input.file")
+ {
+ do
+ {
+ echo self::WBTranslate("[%s] Filename: ", $prefix);
+
+ $filename = rtrim(fgets(STDIN));
+ } while ($filename !== "" && !file_exists($filename));
+
+ if ($filename === "") $form->fields[$num]["value"] = "";
+ else
+ {
+ $form->fields[$num]["value"] = array(
+ "filename" => $filename,
+ "type" => "application/octet-stream",
+ "datafile" => $filename
+ );
+ }
+ }
+ else
+ {
+ echo self::WBTranslate("[%s] New value: ", $prefix);
+
+ $form->fields[$num]["value"] = rtrim(fgets(STDIN));
+ }
+
+ echo "\n";
+
+ } while (1);
+ }
+
+ $submitoptions = array(array("name" => self::WBTranslate("Default action"), "value" => self::WBTranslate("Might not work"), "hint" => "Default action"));
+ foreach ($form->fields as $num => $field)
+ {
+ if ($field["type"] != "input.submit" && $field["type"] != "input.image" && $field["type"] != "input.button" && $field["type"] != "button.submit") continue;
+
+ $submitoptions[] = $field;
+ }
+
+ if (count($submitoptions) <= 2) $num = count($submitoptions) - 1;
+ else
+ {
+ echo self::WBTranslate("Available submit buttons:\n");
+ foreach ($submitoptions as $num => $field)
+ {
+ echo self::WBTranslate("\t%d: %s - %s\n", $num, $field["name"], $field["value"] . (isset($field["hint"]) && $field["hint"] !== "" ? " [" . $field["hint"] . "]" : ""));
+ }
+ echo "\n";
+
+ do
+ {
+ echo self::WBTranslate("Select: ");
+
+ $num = (int)fgets(STDIN);
+ } while (!isset($submitoptions[$num]));
+
+ echo "\n";
+ }
+
+ $result = $form->GenerateFormRequest(($num ? $submitoptions[$num]["name"] : false), ($num ? $submitoptions[$num]["value"] : false));
+
+ return $result;
+ }
+
+ public function GetCookies()
+ {
+ return $this->data["cookies"];
+ }
+
+ public function SetCookie($cookie)
+ {
+ if (!isset($cookie["domain"]) || !isset($cookie["path"]) || !isset($cookie["name"]) || !isset($cookie["value"])) return array("success" => false, "error" => self::WBTranslate("SetCookie() requires 'domain', 'path', 'name', and 'value' to be options."), "errorcode" => "missing_information");
+
+ $cookie["domain"] = strtolower($cookie["domain"]);
+ if (substr($cookie["domain"], 0, 1) != ".") $cookie["domain"] = "." . $cookie["domain"];
+
+ $cookie["path"] = str_replace("\\", "/", $cookie["path"]);
+ if (substr($cookie["path"], -1) != "/") $cookie["path"] = "/";
+
+ if (!isset($this->data["cookies"][$cookie["domain"]])) $this->data["cookies"][$cookie["domain"]] = array();
+ if (!isset($this->data["cookies"][$cookie["domain"]][$cookie["path"]])) $this->data["cookies"][$cookie["domain"]][$cookie["path"]] = array();
+ $this->data["cookies"][$cookie["domain"]][$cookie["path"]][$cookie["name"]] = $cookie;
+
+ return array("success" => true);
+ }
+
+ // Simulates closing a web browser.
+ public function DeleteSessionCookies()
+ {
+ foreach ($this->data["cookies"] as $domain => $paths)
+ {
+ foreach ($paths as $path => $cookies)
+ {
+ foreach ($cookies as $num => $info)
+ {
+ if (!isset($info["expires_ts"])) unset($this->data["cookies"][$domain][$path][$num]);
+ }
+
+ if (!count($this->data["cookies"][$domain][$path])) unset($this->data["cookies"][$domain][$path]);
+ }
+
+ if (!count($this->data["cookies"][$domain])) unset($this->data["cookies"][$domain]);
+ }
+ }
+
+ public function DeleteCookies($domainpattern, $pathpattern, $namepattern)
+ {
+ foreach ($this->data["cookies"] as $domain => $paths)
+ {
+ if ($domainpattern == "" || substr($domain, -strlen($domainpattern)) == $domainpattern)
+ {
+ foreach ($paths as $path => $cookies)
+ {
+ if ($pathpattern == "" || substr($path, 0, strlen($pathpattern)) == $pathpattern)
+ {
+ foreach ($cookies as $num => $info)
+ {
+ if ($namepattern == "" || strpos($info["name"], $namepattern) !== false) unset($this->data["cookies"][$domain][$path][$num]);
+ }
+
+ if (!count($this->data["cookies"][$domain][$path])) unset($this->data["cookies"][$domain][$path]);
+ }
+ }
+
+ if (!count($this->data["cookies"][$domain])) unset($this->data["cookies"][$domain]);
+ }
+ }
+ }
+
+ private function GetExpiresTimestamp($ts)
+ {
+ $year = (int)substr($ts, 0, 4);
+ $month = (int)substr($ts, 5, 2);
+ $day = (int)substr($ts, 8, 2);
+ $hour = (int)substr($ts, 11, 2);
+ $min = (int)substr($ts, 14, 2);
+ $sec = (int)substr($ts, 17, 2);
+
+ return gmmktime($hour, $min, $sec, $month, $day, $year);
+ }
+
+ public static function WBTranslate()
+ {
+ $args = func_get_args();
+ if (!count($args)) return "";
+
+ return call_user_func_array((defined("CS_TRANSLATE_FUNC") && function_exists(CS_TRANSLATE_FUNC) ? CS_TRANSLATE_FUNC : "sprintf"), $args);
+ }
+ }
+
+ class WebBrowserForm
+ {
+ public $info, $fields;
+
+ public function __construct()
+ {
+ $this->info = array();
+ $this->fields = array();
+ }
+
+ public function FindFormFields($name = false, $value = false, $type = false)
+ {
+ $fields = array();
+ foreach ($this->fields as $num => $field)
+ {
+ if (($type === false || $field["type"] === $type) && ($name === false || $field["name"] === $name) && ($value === false || $field["value"] === $value))
+ {
+ $fields[] = $field;
+ }
+ }
+
+ return $fields;
+ }
+
+ public function GetHintMap()
+ {
+ $result = array();
+ foreach ($this->fields as $num => $field)
+ {
+ if (isset($field["hint"])) $result[$field["hint"]] = $field["name"];
+ }
+
+ return $result;
+ }
+
+ public function GetVisibleFields($submit)
+ {
+ $result = array();
+ foreach ($this->fields as $num => $field)
+ {
+ if ($field["type"] == "input.hidden" || (!$submit && ($field["type"] == "input.submit" || $field["type"] == "input.image" || $field["type"] == "input.button" || substr($field["type"], 0, 7) == "button."))) continue;
+
+ $result[$num] = $field;
+ }
+
+ return $result;
+ }
+
+ public function GetFormValue($name, $checkval = false, $type = false)
+ {
+ $val = false;
+ foreach ($this->fields as $field)
+ {
+ if (($type === false || $field["type"] === $type) && $field["name"] === $name)
+ {
+ if (is_string($checkval))
+ {
+ if ($checkval === $field["value"])
+ {
+ if ($field["type"] == "input.radio" || $field["type"] == "input.checkbox") $val = $field["checked"];
+ else $val = $field["value"];
+ }
+ }
+ else if (($field["type"] != "input.radio" && $field["type"] != "input.checkbox") || $field["checked"])
+ {
+ $val = $field["value"];
+ }
+ }
+ }
+
+ return $val;
+ }
+
+ public function SetFormValue($name, $value, $checked = false, $type = false, $create = false)
+ {
+ $result = false;
+ foreach ($this->fields as $num => $field)
+ {
+ if (($type === false || $field["type"] === $type) && $field["name"] === $name)
+ {
+ if ($field["type"] == "input.radio")
+ {
+ $this->fields[$num]["checked"] = ($field["value"] === $value ? $checked : false);
+ $result = true;
+ }
+ else if ($field["type"] == "input.checkbox")
+ {
+ if ($field["value"] === $value) $this->fields[$num]["checked"] = $checked;
+ $result = true;
+ }
+ else if ($field["type"] != "select" || !isset($field["options"]) || isset($field["options"][$value]))
+ {
+ $this->fields[$num]["value"] = $value;
+ $result = true;
+ }
+ }
+ }
+
+ // Add the field if it doesn't exist.
+ if (!$result && $create)
+ {
+ $this->fields[] = array(
+ "id" => false,
+ "type" => ($type !== false ? $type : "input.text"),
+ "name" => $name,
+ "value" => $value,
+ "checked" => $checked
+ );
+ }
+
+ return $result;
+ }
+
+ public function GenerateFormRequest($submitname = false, $submitvalue = false)
+ {
+ $method = $this->info["method"];
+ $fields = array();
+ $files = array();
+ foreach ($this->fields as $field)
+ {
+ if ($field["type"] == "input.file")
+ {
+ if (is_array($field["value"]))
+ {
+ $field["value"]["name"] = $field["name"];
+ $files[] = $field["value"];
+ $method = "post";
+ }
+ }
+ else if ($field["type"] == "input.reset" || $field["type"] == "button.reset")
+ {
+ }
+ else if ($field["type"] == "input.submit" || $field["type"] == "input.image" || $field["type"] == "button.submit")
+ {
+ if (($submitname === false || $field["name"] === $submitname) && ($submitvalue === false || $field["value"] === $submitvalue))
+ {
+ if ($submitname !== "")
+ {
+ if (!isset($fields[$field["name"]])) $fields[$field["name"]] = array();
+ $fields[$field["name"]][] = $field["value"];
+ }
+
+ if ($field["type"] == "input.image")
+ {
+ if (!isset($fields["x"])) $fields["x"] = array();
+ $fields["x"][] = "1";
+
+ if (!isset($fields["y"])) $fields["y"] = array();
+ $fields["y"][] = "1";
+ }
+ }
+ }
+ else if (($field["type"] != "input.radio" && $field["type"] != "input.checkbox") || $field["checked"])
+ {
+ if (!isset($fields[$field["name"]])) $fields[$field["name"]] = array();
+ $fields[$field["name"]][] = $field["value"];
+ }
+ }
+
+ if ($method == "get")
+ {
+ $url = HTTP::ExtractURL($this->info["action"]);
+ unset($url["query"]);
+ $url["queryvars"] = $fields;
+ $result = array(
+ "url" => HTTP::CondenseURL($url),
+ "options" => array()
+ );
+ }
+ else
+ {
+ $result = array(
+ "url" => $this->info["action"],
+ "options" => array(
+ "postvars" => $fields,
+ "files" => $files
+ )
+ );
+ }
+
+ return $result;
+ }
+ }
+?>
\ No newline at end of file
diff --git a/ms-windows/templates/1.1.1/info.json b/ms-windows/templates/1.1.1/info.json
new file mode 100644
index 0000000..1d3f6d4
--- /dev/null
+++ b/ms-windows/templates/1.1.1/info.json
@@ -0,0 +1,170 @@
+{
+ "copyright": "Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.",
+ "copyright_notes": "Licensed under the OpenSSL license (the \"License\"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at https://www.openssl.org/source/license.html",
+ "name": "OpenSSL 1.1.1",
+ "download_type": "tar.gz",
+ "download_extract_path": "[[VERSION_DIR]]/source",
+ "download": "https://www.openssl.org/source/openssl-[[DOTTED_VERSION]].tar.gz",
+ "download_sha256_url": "https://www.openssl.org/source/openssl-[[DOTTED_VERSION]].tar.gz.sha256",
+ "architectures": [
+ {
+ "name": "Intel/AMD x86 (32-bit)",
+ "architecture": "x86",
+ "dependencies": [
+ {
+ "name": "Visual C++ compiler",
+ "purpose": "Main C compiler",
+ "verify": "cl.exe",
+ "verify_opts": "",
+ "required_output": "/Microsoft .* C\\/C\\+\\+ .* x86/",
+ "required_alert": "Incorrect architecture detected or invalid compiler. Expected Microsoft Visual C++ x86."
+ },
+ {
+ "name": "Visual C++ object linker",
+ "purpose": "Main object file linker",
+ "verify": "link.exe",
+ "verify_opts": "/?",
+ "required_output": "/Microsoft .* Incremental Linker/",
+ "required_alert": "Missing Microsoft Visual C++ object linker."
+ },
+ {
+ "name": "Visual C++ nmake",
+ "purpose": "Main makefile processing utility",
+ "verify": "nmake.exe",
+ "verify_opts": "/?",
+ "required_output": "/Microsoft .* Program Maintenance Utility/",
+ "required_alert": "Missing Microsoft nmake."
+ },
+ {
+ "name": "Strawberry Perl Portable",
+ "purpose": "Running perl Configure to generate makefiles and also MinGW dlltool to create export libraries",
+ "verify": "perl.exe",
+ "verify_opts": "-v",
+ "required_output": "/perl .* \\(v5[.]/",
+ "required_alert": "Perl 5 is required.",
+ "preferred_output": "/perl .* \\(v5[.]32[.]1\\)/",
+ "preferred_alert": "Perl v5.32.1 is preferred.",
+ "env_paths": ["[[DEPS_DIR]]/perl/perl/site/bin", "[[DEPS_DIR]]/perl/perl/bin"],
+ "env_extras": {"TERM": "dumb"},
+ "download_type": "zip",
+ "download_extract_path": "[[DEPS_DIR]]/perl",
+ "download_x86": "https://strawberryperl.com/download/5.32.1.1/strawberry-perl-5.32.1.1-32bit-portable.zip",
+ "download_x86_sha256": "d9c5711d12573a0f6d977792caa58364b1d46217521ae5c25cf5cc378a7c23c0",
+ "download_x64": "https://strawberryperl.com/download/5.32.1.1/strawberry-perl-5.32.1.1-64bit-portable.zip",
+ "download_x64_sha256": "692646105b0f5e058198a852dc52a48f1cebcaf676d63bbdeae12f4eaee9bf5c"
+ },
+ {
+ "name": "Netwide Assembler (NASM)",
+ "purpose": "Building optimized assembly code",
+ "verify": "nasm.exe",
+ "verify_opts": "-v",
+ "preferred_output": "/NASM/",
+ "preferred_alert": "NASM is required.",
+ "preferred_output": "/NASM .* 2[.]16[.]01/",
+ "preferred_alert": "NASM v2.16.01 is preferred.",
+ "env_paths": ["[[DEPS_DIR]]/nasm/nasm-2.16.01"],
+ "env_extras": {},
+ "download_type": "zip",
+ "download_extract_path": "[[DEPS_DIR]]/nasm",
+ "download_x86": "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win32/nasm-2.16.01-win32.zip",
+ "download_x86_sha256": "e289fa70c88594b092c916344bb8bfcd6896b604bfab284ab57b1372997c820c",
+ "download_x64": "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/nasm-2.16.01-win64.zip",
+ "download_x64_sha256": "029eed31faf0d2c5f95783294432cbea6c15bf633430f254bb3c1f195c67ca3a"
+ },
+ {
+ "name": "Inno Setup 5",
+ "purpose": "Compiling .iss template files into .exe installers (32-bit only)",
+ "verify": "[[DEPS_DIR]]/innosetup5/iscc.exe",
+ "verify_opts": "",
+ "required_output": "/Inno Setup 5/",
+ "required_alert": "Inno Setup 5 is required.",
+ "download_type": "exe",
+ "download_extract_path": "[[DEPS_DIR]]/innosetup5",
+ "download_install_opts": "/PORTABLE=1 /verysilent /currentuser \"/DIR=[[DEPS_DIR]]\\innosetup5\"",
+ "download": "https://files.jrsoftware.org/is/5/innosetup-5.6.1.exe",
+ "download_sha256": "96fd6a5eaab473c61a19affff89618764b940ee3f15837c2944a5595aed5fde6"
+ },
+ {
+ "name": "Wix Toolset",
+ "purpose": "Generating .msi installers from .exe installers",
+ "verify": "[[DEPS_DIR]]/wixtoolset/candle.exe",
+ "verify_opts": "",
+ "env_extras": {"WIX": "[[DEPS_DIR]]\\wixtoolset\\"},
+ "required_output": "/Windows Installer XML Toolset Compiler version 3[.]14/",
+ "required_alert": "Wix toolset 3.14 is required.",
+ "download_type": "zip",
+ "download_extract_path": "[[DEPS_DIR]]/wixtoolset",
+ "download": "https://wixtoolset.org/downloads/v3.14.0.6526/wix314-binaries.zip",
+ "download_sha256": "4c89898df3bcab13e12f7ca54399c35ad273475ad2cb6284611d00ae2d063c2c"
+ }
+ ],
+ "build": {
+ "configure_target": "VC-WIN32",
+ "configure_extra": "-D_USE_32BIT_TIME_T -D_WINSOCK_DEPRECATED_NO_WARNINGS -D_WIN32_WINNT=0x0501",
+ "patches": {
+ "/Zi ": "/Z7 ",
+ "/subsystem:console ": "/subsystem:console,5.01 ",
+ "CNF_LDFLAGS=": "CNF_LDFLAGS=/subsystem:console,5.01 "
+ }
+ },
+ "package": {
+ "mingw_dlltool": "[[DEPS_DIR]]/perl/c/bin/dlltool.exe",
+ "inno_setup_dir": "[[DEPS_DIR]]/innosetup5",
+ "wix_toolset_dir": "[[DEPS_DIR]]/wixtoolset",
+ "wix_toolset_target": ""
+ }
+ },
+ {
+ "name": "Intel/AMD x64 (64-bit)",
+ "architecture": "x64",
+ "dependencies": [
+ {
+ "name": "Visual C++ compiler",
+ "purpose": "Main C compiler",
+ "verify": "cl.exe",
+ "verify_opts": "",
+ "required_output": "/Microsoft .* C\\/C\\+\\+ .* x64/",
+ "required_alert": "Incorrect architecture detected or invalid compiler. Expected Microsoft Visual C++ x64."
+ },
+ {
+ "name": "Visual C++ object linker",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Visual C++ nmake",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Strawberry Perl Portable",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Netwide Assembler (NASM)",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Inno Setup 5",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Wix Toolset",
+ "expand_from": "x86"
+ }
+ ],
+ "build": {
+ "configure_target": "VC-WIN64A",
+ "configure_extra": "-D_WINSOCK_DEPRECATED_NO_WARNINGS -D_WIN32_WINNT=0x0502",
+ "patches": {
+ "/Zi ": "/Z7 ",
+ "/subsystem:console ": "/subsystem:console,5.02 ",
+ "CNF_LDFLAGS=": "CNF_LDFLAGS=/subsystem:console,5.02 "
+ }
+ },
+ "package": {
+ "inno_setup_dir": "[[DEPS_DIR]]/innosetup5",
+ "wix_toolset_dir": "[[DEPS_DIR]]/wixtoolset",
+ "wix_toolset_target": "-arch x64"
+ }
+ }
+ ]
+}
diff --git a/ms-windows/templates/1.1.1/x64/openssl-light.iss b/ms-windows/templates/1.1.1/x64/openssl-light.iss
new file mode 100644
index 0000000..c119105
--- /dev/null
+++ b/ms-windows/templates/1.1.1/x64/openssl-light.iss
@@ -0,0 +1,148 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL Light (64-bit)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] Light (64-bit)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={pf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-x64-light
+LicenseFile=license.txt
+PrivilegesRequired=admin
+Compression=bzip
+ArchitecturesAllowed=x64
+ArchitecturesInstallIn64BitMode=x64
+; Minimum version supported is Windows XP.
+MinVersion=5.1
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2017 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{sys}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2017 Redistributables (64-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/15/release/vc_redist.x64.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (IsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-1_1-x64.dll', ExpandConstant('{sys}') + '\libcrypto-1_1-x64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-1_1-x64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-1_1-x64.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-1_1-x64.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-1_1-x64.dll', ExpandConstant('{sys}') + '\libssl-1_1-x64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-1_1-x64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-1_1-x64.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-1_1-x64.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-1_1-x64.dll', ExpandConstant('{app}') + '\bin\libcrypto-1_1-x64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-1_1-x64.dll', ExpandConstant('{app}') + '\bin\libssl-1_1-x64.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{cf}\SSL"; Flags: recursesubdirs
+Source: "bin\PEM\*"; DestDir: "{app}\bin\PEM"; Flags: recursesubdirs
+Source: "bin\*.pl"; DestDir: "{app}\bin"
+Source: "bin\openssl.exe"; DestDir: "{app}\bin"
+Source: "bin\*.dll"; DestDir: "{app}\bin"
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-1_1-x64.dll"; DestDir: "{app}"
+Source: "libssl-1_1-x64.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (x64)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-1_1-x64.dll"
+Type: files; Name: "{app}\bin\libssl-1_1-x64.dll"
diff --git a/ms-windows/templates/1.1.1/x64/openssl-light.wxs b/ms-windows/templates/1.1.1/x64/openssl-light.wxs
new file mode 100644
index 0000000..b5ba9ab
--- /dev/null
+++ b/ms-windows/templates/1.1.1/x64/openssl-light.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/1.1.1/x64/openssl.iss b/ms-windows/templates/1.1.1/x64/openssl.iss
new file mode 100644
index 0000000..25f694f
--- /dev/null
+++ b/ms-windows/templates/1.1.1/x64/openssl.iss
@@ -0,0 +1,152 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL (64-bit)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] (64-bit)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={pf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-x64
+LicenseFile=license.txt
+PrivilegesRequired=admin
+Compression=bzip
+ArchitecturesAllowed=x64
+ArchitecturesInstallIn64BitMode=x64
+; Minimum version supported is Windows XP.
+MinVersion=5.1
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2017 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{sys}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2017 Redistributables (64-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/15/release/vc_redist.x64.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (IsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-1_1-x64.dll', ExpandConstant('{sys}') + '\libcrypto-1_1-x64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-1_1-x64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-1_1-x64.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-1_1-x64.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-1_1-x64.dll', ExpandConstant('{sys}') + '\libssl-1_1-x64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-1_1-x64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-1_1-x64.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-1_1-x64.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-1_1-x64.dll', ExpandConstant('{app}') + '\bin\libcrypto-1_1-x64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-1_1-x64.dll', ExpandConstant('{app}') + '\bin\libssl-1_1-x64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-1_1-x64.dll', ExpandConstant('{app}') + '\tests\libcrypto-1_1-x64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-1_1-x64.dll', ExpandConstant('{app}') + '\tests\libssl-1_1-x64.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{cf}\SSL"; Flags: recursesubdirs
+Source: "bin\*"; DestDir: "{app}\bin"; Flags: recursesubdirs
+Source: "bin_static\*"; DestDir: "{app}\bin_static"; Flags: recursesubdirs
+Source: "exp\*"; DestDir: "{app}\exp"; Flags: recursesubdirs
+Source: "lib\*"; DestDir: "{app}\lib"; Flags: recursesubdirs
+Source: "include\*"; DestDir: "{app}\include"; Flags: recursesubdirs
+Source: "tests\*"; DestDir: "{app}\tests"; Flags: recursesubdirs
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-1_1-x64.dll"; DestDir: "{app}"
+Source: "libssl-1_1-x64.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (x64)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-1_1-x64.dll"
+Type: files; Name: "{app}\bin\libssl-1_1-x64.dll"
diff --git a/ms-windows/templates/1.1.1/x64/openssl.wxs b/ms-windows/templates/1.1.1/x64/openssl.wxs
new file mode 100644
index 0000000..808c685
--- /dev/null
+++ b/ms-windows/templates/1.1.1/x64/openssl.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/1.1.1/x64/start.bat b/ms-windows/templates/1.1.1/x64/start.bat
new file mode 100644
index 0000000..1e52980
--- /dev/null
+++ b/ms-windows/templates/1.1.1/x64/start.bat
@@ -0,0 +1,21 @@
+@echo off
+
+rem * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+rem *
+rem * Licensed under the OpenSSL license (the "License"). You may not use
+rem * this file except in compliance with the License. You can obtain a copy
+rem * in the file LICENSE in the source distribution or at
+rem * https://www.openssl.org/source/license.html
+
+@set PATH=%PATH%;%~dp0bin
+
+title OpenSSL Command Prompt (Intel/AMD x64)
+echo OpenSSL Command Prompt (Intel/AMD x64)
+echo.
+openssl version -a
+echo.
+
+%SystemDrive%
+cd %UserProfile%
+
+cmd.exe /K
diff --git a/ms-windows/templates/1.1.1/x86/openssl-light.iss b/ms-windows/templates/1.1.1/x86/openssl-light.iss
new file mode 100644
index 0000000..96d9dcb
--- /dev/null
+++ b/ms-windows/templates/1.1.1/x86/openssl-light.iss
@@ -0,0 +1,146 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL Light (32-bit)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] Light (32-bit)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={pf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-x86-light
+LicenseFile=license.txt
+PrivilegesRequired=admin
+Compression=bzip
+; Minimum version supported is Windows XP.
+MinVersion=5.1
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2017 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{syswow64}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2017 Redistributables (32-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/15/release/vc_redist.x86.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (IsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-1_1.dll', ExpandConstant('{sys}') + '\libcrypto-1_1.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-1_1.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-1_1.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-1_1.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-1_1.dll', ExpandConstant('{sys}') + '\libssl-1_1.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-1_1.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-1_1.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-1_1.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-1_1.dll', ExpandConstant('{app}') + '\bin\libcrypto-1_1.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-1_1.dll', ExpandConstant('{app}') + '\bin\libssl-1_1.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{cf}\SSL"; Flags: recursesubdirs
+Source: "bin\PEM\*"; DestDir: "{app}\bin\PEM"; Flags: recursesubdirs
+Source: "bin\*.pl"; DestDir: "{app}\bin"
+Source: "bin\openssl.exe"; DestDir: "{app}\bin"
+Source: "bin\*.dll"; DestDir: "{app}\bin"
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-1_1.dll"; DestDir: "{app}"
+Source: "libssl-1_1.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (x86)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-1_1.dll"
+Type: files; Name: "{app}\bin\libssl-1_1.dll"
diff --git a/ms-windows/templates/1.1.1/x86/openssl-light.wxs b/ms-windows/templates/1.1.1/x86/openssl-light.wxs
new file mode 100644
index 0000000..2dc7e67
--- /dev/null
+++ b/ms-windows/templates/1.1.1/x86/openssl-light.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/1.1.1/x86/openssl.iss b/ms-windows/templates/1.1.1/x86/openssl.iss
new file mode 100644
index 0000000..e5ab5d9
--- /dev/null
+++ b/ms-windows/templates/1.1.1/x86/openssl.iss
@@ -0,0 +1,149 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL (32-bit)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] (32-bit)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={pf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-x86
+LicenseFile=license.txt
+PrivilegesRequired=admin
+Compression=bzip
+; Minimum version supported is Windows XP.
+MinVersion=5.1
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2017 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{syswow64}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2017 Redistributables (32-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/15/release/vc_redist.x86.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (IsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-1_1.dll', ExpandConstant('{sys}') + '\libcrypto-1_1.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-1_1.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-1_1.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-1_1.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-1_1.dll', ExpandConstant('{sys}') + '\libssl-1_1.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-1_1.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-1_1.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-1_1.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-1_1.dll', ExpandConstant('{app}') + '\bin\libcrypto-1_1.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-1_1.dll', ExpandConstant('{app}') + '\bin\libssl-1_1.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-1_1.dll', ExpandConstant('{app}') + '\tests\libcrypto-1_1.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-1_1.dll', ExpandConstant('{app}') + '\tests\libssl-1_1.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{cf}\SSL"; Flags: recursesubdirs
+Source: "bin\*"; DestDir: "{app}\bin"; Flags: recursesubdirs
+Source: "exp\*"; DestDir: "{app}\exp"; Flags: recursesubdirs
+Source: "lib\*"; DestDir: "{app}\lib"; Flags: recursesubdirs
+Source: "include\*"; DestDir: "{app}\include"; Flags: recursesubdirs
+Source: "tests\*"; DestDir: "{app}\tests"; Flags: recursesubdirs
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-1_1.dll"; DestDir: "{app}"
+Source: "libssl-1_1.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (x86)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-1_1.dll"
+Type: files; Name: "{app}\bin\libssl-1_1.dll"
diff --git a/ms-windows/templates/1.1.1/x86/openssl.wxs b/ms-windows/templates/1.1.1/x86/openssl.wxs
new file mode 100644
index 0000000..d1dab26
--- /dev/null
+++ b/ms-windows/templates/1.1.1/x86/openssl.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/1.1.1/x86/start.bat b/ms-windows/templates/1.1.1/x86/start.bat
new file mode 100644
index 0000000..b3995f5
--- /dev/null
+++ b/ms-windows/templates/1.1.1/x86/start.bat
@@ -0,0 +1,21 @@
+@echo off
+
+rem * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+rem *
+rem * Licensed under the OpenSSL license (the "License"). You may not use
+rem * this file except in compliance with the License. You can obtain a copy
+rem * in the file LICENSE in the source distribution or at
+rem * https://www.openssl.org/source/license.html
+
+@set PATH=%PATH%;%~dp0bin
+
+title OpenSSL Command Prompt (Intel/AMD x86)
+echo OpenSSL Command Prompt (Intel/AMD x86)
+echo.
+openssl version -a
+echo.
+
+%SystemDrive%
+cd %UserProfile%
+
+cmd.exe /K
diff --git a/ms-windows/templates/3.0/arm64/openssl-light.iss b/ms-windows/templates/3.0/arm64/openssl-light.iss
new file mode 100644
index 0000000..01750a5
--- /dev/null
+++ b/ms-windows/templates/3.0/arm64/openssl-light.iss
@@ -0,0 +1,149 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL Light (64-bit ARM)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] Light (64-bit ARM)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={commonpf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-arm64-light
+LicenseFile=license.txt
+SetupIconFile=compiler:SetupClassicIcon.ico
+PrivilegesRequired=admin
+Compression=bzip
+ArchitecturesAllowed=arm64
+ArchitecturesInstallIn64BitMode=arm64
+; Minimum version supported is Windows 10.
+MinVersion=10.0
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2019 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{sys}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2019 Redistributables (64-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/16/release/VC_redist.arm64.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (WizardIsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-3-arm64.dll', ExpandConstant('{sys}') + '\libcrypto-3-arm64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-3-arm64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-arm64.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-3-arm64.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-3-arm64.dll', ExpandConstant('{sys}') + '\libssl-3-arm64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-3-arm64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-arm64.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-3-arm64.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-arm64.dll', ExpandConstant('{app}') + '\bin\libcrypto-3-arm64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-arm64.dll', ExpandConstant('{app}') + '\bin\libssl-3-arm64.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{commoncf}\SSL"; Flags: recursesubdirs
+Source: "bin\PEM\*"; DestDir: "{app}\bin\PEM"; Flags: recursesubdirs
+Source: "bin\*.pl"; DestDir: "{app}\bin"
+Source: "bin\openssl.exe"; DestDir: "{app}\bin"
+Source: "bin\*.dll"; DestDir: "{app}\bin"
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-3-arm64.dll"; DestDir: "{app}"
+Source: "libssl-3-arm64.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (ARM64)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-3-arm64.dll"
+Type: files; Name: "{app}\bin\libssl-3-arm64.dll"
diff --git a/ms-windows/templates/3.0/arm64/openssl-light.wxs b/ms-windows/templates/3.0/arm64/openssl-light.wxs
new file mode 100644
index 0000000..67a6931
--- /dev/null
+++ b/ms-windows/templates/3.0/arm64/openssl-light.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/3.0/arm64/openssl.iss b/ms-windows/templates/3.0/arm64/openssl.iss
new file mode 100644
index 0000000..58253e6
--- /dev/null
+++ b/ms-windows/templates/3.0/arm64/openssl.iss
@@ -0,0 +1,153 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL (64-bit ARM)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] (64-bit ARM)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={commonpf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-arm64
+LicenseFile=license.txt
+SetupIconFile=compiler:SetupClassicIcon.ico
+PrivilegesRequired=admin
+Compression=bzip
+ArchitecturesAllowed=arm64
+ArchitecturesInstallIn64BitMode=arm64
+; Minimum version supported is Windows 10.
+MinVersion=10.0
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2019 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{sys}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2019 Redistributables (64-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/16/release/VC_redist.arm64.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (WizardIsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-3-arm64.dll', ExpandConstant('{sys}') + '\libcrypto-3-arm64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-3-arm64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-arm64.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-3-arm64.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-3-arm64.dll', ExpandConstant('{sys}') + '\libssl-3-arm64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-3-arm64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-arm64.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-3-arm64.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-arm64.dll', ExpandConstant('{app}') + '\bin\libcrypto-3-arm64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-arm64.dll', ExpandConstant('{app}') + '\bin\libssl-3-arm64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-arm64.dll', ExpandConstant('{app}') + '\tests\libcrypto-3-arm64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-arm64.dll', ExpandConstant('{app}') + '\tests\libssl-3-arm64.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{commoncf}\SSL"; Flags: recursesubdirs
+Source: "bin\*"; DestDir: "{app}\bin"; Flags: recursesubdirs
+Source: "bin_static\*"; DestDir: "{app}\bin_static"; Flags: recursesubdirs
+Source: "exp\*"; DestDir: "{app}\exp"; Flags: recursesubdirs
+Source: "lib\*"; DestDir: "{app}\lib"; Flags: recursesubdirs
+Source: "include\*"; DestDir: "{app}\include"; Flags: recursesubdirs
+Source: "tests\*"; DestDir: "{app}\tests"; Flags: recursesubdirs
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-3-arm64.dll"; DestDir: "{app}"
+Source: "libssl-3-arm64.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (ARM64)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-3-arm64.dll"
+Type: files; Name: "{app}\bin\libssl-3-arm64.dll"
diff --git a/ms-windows/templates/3.0/arm64/openssl.wxs b/ms-windows/templates/3.0/arm64/openssl.wxs
new file mode 100644
index 0000000..e95f596
--- /dev/null
+++ b/ms-windows/templates/3.0/arm64/openssl.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/3.0/arm64/start.bat b/ms-windows/templates/3.0/arm64/start.bat
new file mode 100644
index 0000000..2e99d32
--- /dev/null
+++ b/ms-windows/templates/3.0/arm64/start.bat
@@ -0,0 +1,21 @@
+@echo off
+
+rem * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+rem *
+rem * Licensed under the OpenSSL license (the "License"). You may not use
+rem * this file except in compliance with the License. You can obtain a copy
+rem * in the file LICENSE in the source distribution or at
+rem * https://www.openssl.org/source/license.html
+
+@set PATH=%PATH%;%~dp0bin
+
+title OpenSSL Command Prompt (ARM64)
+echo OpenSSL Command Prompt (ARM64)
+echo.
+openssl version -a
+echo.
+
+%SystemDrive%
+cd %UserProfile%
+
+cmd.exe /K
diff --git a/ms-windows/templates/3.0/info.json b/ms-windows/templates/3.0/info.json
new file mode 100644
index 0000000..67348d9
--- /dev/null
+++ b/ms-windows/templates/3.0/info.json
@@ -0,0 +1,229 @@
+{
+ "copyright": "Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.",
+ "copyright_notes": "Licensed under the OpenSSL license (the \"License\"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at https://www.openssl.org/source/license.html",
+ "name": "OpenSSL 3.0",
+ "download_type": "tar.gz",
+ "download_extract_path": "[[VERSION_DIR]]/source",
+ "download": "https://www.openssl.org/source/openssl-[[DOTTED_VERSION]].tar.gz",
+ "download_sha256_url": "https://www.openssl.org/source/openssl-[[DOTTED_VERSION]].tar.gz.sha256",
+ "architectures": [
+ {
+ "name": "Intel/AMD x86 (32-bit)",
+ "architecture": "x86",
+ "dependencies": [
+ {
+ "name": "Visual C++ compiler",
+ "purpose": "Main C compiler",
+ "verify": "cl.exe",
+ "verify_opts": "",
+ "required_output": "/Microsoft .* C\\/C\\+\\+ .* x86/",
+ "required_alert": "Incorrect architecture detected or invalid compiler. Expected Microsoft Visual C++ x86."
+ },
+ {
+ "name": "Visual C++ object linker",
+ "purpose": "Main object file linker",
+ "verify": "link.exe",
+ "verify_opts": "/?",
+ "required_output": "/Microsoft .* Incremental Linker/",
+ "required_alert": "Missing Microsoft Visual C++ object linker."
+ },
+ {
+ "name": "Visual C++ nmake",
+ "purpose": "Main makefile processing utility",
+ "verify": "nmake.exe",
+ "verify_opts": "/?",
+ "required_output": "/Microsoft .* Program Maintenance Utility/",
+ "required_alert": "Missing Microsoft nmake."
+ },
+ {
+ "name": "Strawberry Perl Portable",
+ "purpose": "Running perl Configure to generate makefiles and also MinGW dlltool to create export libraries",
+ "verify": "perl.exe",
+ "verify_opts": "-v",
+ "required_output": "/perl .* \\(v5[.]/",
+ "required_alert": "Perl 5 is required.",
+ "preferred_output": "/perl .* \\(v5[.]32[.]1\\)/",
+ "preferred_alert": "Perl v5.32.1 is preferred.",
+ "env_paths": ["[[DEPS_DIR]]/perl/perl/site/bin", "[[DEPS_DIR]]/perl/perl/bin"],
+ "env_extras": {"TERM": "dumb"},
+ "download_type": "zip",
+ "download_extract_path": "[[DEPS_DIR]]/perl",
+ "download_x86": "https://strawberryperl.com/download/5.32.1.1/strawberry-perl-5.32.1.1-32bit-portable.zip",
+ "download_x86_sha256": "d9c5711d12573a0f6d977792caa58364b1d46217521ae5c25cf5cc378a7c23c0",
+ "download_x64": "https://strawberryperl.com/download/5.32.1.1/strawberry-perl-5.32.1.1-64bit-portable.zip",
+ "download_x64_sha256": "692646105b0f5e058198a852dc52a48f1cebcaf676d63bbdeae12f4eaee9bf5c"
+ },
+ {
+ "name": "Netwide Assembler (NASM)",
+ "purpose": "Building optimized assembly code",
+ "verify": "nasm.exe",
+ "verify_opts": "-v",
+ "preferred_output": "/NASM/",
+ "preferred_alert": "NASM is required.",
+ "preferred_output": "/NASM .* 2[.]16[.]01/",
+ "preferred_alert": "NASM v2.16.01 is preferred.",
+ "env_paths": ["[[DEPS_DIR]]/nasm/nasm-2.16.01"],
+ "env_extras": {},
+ "download_type": "zip",
+ "download_extract_path": "[[DEPS_DIR]]/nasm",
+ "download_x86": "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win32/nasm-2.16.01-win32.zip",
+ "download_x86_sha256": "e289fa70c88594b092c916344bb8bfcd6896b604bfab284ab57b1372997c820c",
+ "download_x64": "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/nasm-2.16.01-win64.zip",
+ "download_x64_sha256": "029eed31faf0d2c5f95783294432cbea6c15bf633430f254bb3c1f195c67ca3a"
+ },
+ {
+ "name": "Inno Setup 5",
+ "purpose": "Compiling .iss template files into .exe installers (32-bit only)",
+ "verify": "[[DEPS_DIR]]/innosetup5/iscc.exe",
+ "verify_opts": "",
+ "required_output": "/Inno Setup 5/",
+ "required_alert": "Inno Setup 5 is required.",
+ "download_type": "exe",
+ "download_extract_path": "[[DEPS_DIR]]/innosetup5",
+ "download_install_opts": "/PORTABLE=1 /verysilent /currentuser \"/DIR=[[DEPS_DIR]]\\innosetup5\"",
+ "download": "https://files.jrsoftware.org/is/5/innosetup-5.6.1.exe",
+ "download_sha256": "96fd6a5eaab473c61a19affff89618764b940ee3f15837c2944a5595aed5fde6"
+ },
+ {
+ "name": "Wix Toolset",
+ "purpose": "Generating .msi installers from .exe installers",
+ "verify": "[[DEPS_DIR]]/wixtoolset/candle.exe",
+ "verify_opts": "",
+ "env_extras": {"WIX": "[[DEPS_DIR]]\\wixtoolset\\"},
+ "required_output": "/Windows Installer XML Toolset Compiler version 3[.]14/",
+ "required_alert": "Wix toolset 3.14 is required.",
+ "download_type": "zip",
+ "download_extract_path": "[[DEPS_DIR]]/wixtoolset",
+ "download": "https://wixtoolset.org/downloads/v3.14.0.6526/wix314-binaries.zip",
+ "download_sha256": "4c89898df3bcab13e12f7ca54399c35ad273475ad2cb6284611d00ae2d063c2c"
+ }
+ ],
+ "build": {
+ "configure_target": "VC-WIN32",
+ "configure_extra": "-D_USE_32BIT_TIME_T -D_WINSOCK_DEPRECATED_NO_WARNINGS -D_WIN32_WINNT=0x0501",
+ "patches": {
+ "/Zi ": "/Z7 ",
+ "/subsystem:console ": "/subsystem:console,5.01 ",
+ "CNF_LDFLAGS=": "CNF_LDFLAGS=/subsystem:console,5.01 "
+ }
+ },
+ "package": {
+ "mingw_dlltool": "[[DEPS_DIR]]/perl/c/bin/dlltool.exe",
+ "inno_setup_dir": "[[DEPS_DIR]]/innosetup5",
+ "wix_toolset_dir": "[[DEPS_DIR]]/wixtoolset",
+ "wix_toolset_target": ""
+ }
+ },
+ {
+ "name": "Intel/AMD x64 (64-bit)",
+ "architecture": "x64",
+ "dependencies": [
+ {
+ "name": "Visual C++ compiler",
+ "purpose": "Main C compiler",
+ "verify": "cl.exe",
+ "verify_opts": "",
+ "required_output": "/Microsoft .* C\\/C\\+\\+ .* x64/",
+ "required_alert": "Incorrect architecture detected or invalid compiler. Expected Microsoft Visual C++ x64."
+ },
+ {
+ "name": "Visual C++ object linker",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Visual C++ nmake",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Strawberry Perl Portable",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Netwide Assembler (NASM)",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Inno Setup 5",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Wix Toolset",
+ "expand_from": "x86"
+ }
+ ],
+ "build": {
+ "configure_target": "VC-WIN64A",
+ "configure_extra": "-D_WINSOCK_DEPRECATED_NO_WARNINGS -D_WIN32_WINNT=0x0502",
+ "patches": {
+ "/Zi ": "/Z7 ",
+ "/subsystem:console ": "/subsystem:console,5.02 ",
+ "CNF_LDFLAGS=": "CNF_LDFLAGS=/subsystem:console,5.02 "
+ }
+ },
+ "package": {
+ "inno_setup_dir": "[[DEPS_DIR]]/innosetup5",
+ "wix_toolset_dir": "[[DEPS_DIR]]/wixtoolset",
+ "wix_toolset_target": "-arch x64"
+ }
+ },
+ {
+ "name": "ARM64 (64-bit)",
+ "architecture": "arm64",
+ "dependencies": [
+ {
+ "name": "Visual C++ compiler",
+ "purpose": "Main C compiler",
+ "verify": "cl.exe",
+ "verify_opts": "",
+ "required_output": "/Microsoft .* C\\/C\\+\\+ .* ARM64/",
+ "required_alert": "Incorrect architecture detected or invalid compiler. Expected Microsoft Visual C++ ARM64."
+ },
+ {
+ "name": "Visual C++ object linker",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Visual C++ nmake",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Strawberry Perl Portable",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Netwide Assembler (NASM)",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Inno Setup 6",
+ "purpose": "Compiling .iss template files into .exe installers (64-bit only)",
+ "verify": "[[DEPS_DIR]]/innosetup6/iscc.exe",
+ "verify_opts": "",
+ "required_output": "/Inno Setup 6/",
+ "required_alert": "Inno Setup 6 is required.",
+ "download_type": "exe",
+ "download_extract_path": "[[DEPS_DIR]]/innosetup6",
+ "download_install_opts": "/PORTABLE=1 /verysilent /currentuser \"/DIR=[[DEPS_DIR]]\\innosetup6\"",
+ "download": "https://files.jrsoftware.org/is/6/innosetup-6.2.2.exe",
+ "download_sha256": "8117d10d00a2ad33a1390978ea3872861c330e087914410a6377b22c4c5b8563"
+ },
+ {
+ "name": "Wix Toolset",
+ "expand_from": "x86"
+ }
+ ],
+ "build": {
+ "configure_target": "VC-WIN64-ARM",
+ "configure_extra": "",
+ "patches": {
+ "/Zi ": "/Z7 "
+ }
+ },
+ "package": {
+ "inno_setup_dir": "[[DEPS_DIR]]/innosetup6",
+ "wix_toolset_dir": "[[DEPS_DIR]]/wixtoolset",
+ "wix_toolset_target": "-arch arm64"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ms-windows/templates/3.0/x64/openssl-light.iss b/ms-windows/templates/3.0/x64/openssl-light.iss
new file mode 100644
index 0000000..0d6734e
--- /dev/null
+++ b/ms-windows/templates/3.0/x64/openssl-light.iss
@@ -0,0 +1,149 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL Light (64-bit)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] Light (64-bit)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={pf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-x64-light
+LicenseFile=license.txt
+; SetupIconFile=compiler:SetupClassicIcon.ico
+PrivilegesRequired=admin
+Compression=bzip
+ArchitecturesAllowed=x64
+ArchitecturesInstallIn64BitMode=x64
+; Minimum version supported is Windows XP.
+MinVersion=5.1
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2019 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{sys}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2019 Redistributables (64-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/16/release/vc_redist.x64.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (IsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-3-x64.dll', ExpandConstant('{sys}') + '\libcrypto-3-x64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-3-x64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-x64.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-3-x64.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-3-x64.dll', ExpandConstant('{sys}') + '\libssl-3-x64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-3-x64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-x64.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-3-x64.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-x64.dll', ExpandConstant('{app}') + '\bin\libcrypto-3-x64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-x64.dll', ExpandConstant('{app}') + '\bin\libssl-3-x64.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{cf}\SSL"; Flags: recursesubdirs
+Source: "bin\PEM\*"; DestDir: "{app}\bin\PEM"; Flags: recursesubdirs
+Source: "bin\*.pl"; DestDir: "{app}\bin"
+Source: "bin\openssl.exe"; DestDir: "{app}\bin"
+Source: "bin\*.dll"; DestDir: "{app}\bin"
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-3-x64.dll"; DestDir: "{app}"
+Source: "libssl-3-x64.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (x64)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-3-x64.dll"
+Type: files; Name: "{app}\bin\libssl-3-x64.dll"
diff --git a/ms-windows/templates/3.0/x64/openssl-light.wxs b/ms-windows/templates/3.0/x64/openssl-light.wxs
new file mode 100644
index 0000000..d485b1c
--- /dev/null
+++ b/ms-windows/templates/3.0/x64/openssl-light.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/3.0/x64/openssl.iss b/ms-windows/templates/3.0/x64/openssl.iss
new file mode 100644
index 0000000..fb03528
--- /dev/null
+++ b/ms-windows/templates/3.0/x64/openssl.iss
@@ -0,0 +1,153 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL (64-bit)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] (64-bit)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={pf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-x64
+LicenseFile=license.txt
+; SetupIconFile=compiler:SetupClassicIcon.ico
+PrivilegesRequired=admin
+Compression=bzip
+ArchitecturesAllowed=x64
+ArchitecturesInstallIn64BitMode=x64
+; Minimum version supported is Windows XP.
+MinVersion=5.1
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2019 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{sys}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2019 Redistributables (64-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/16/release/vc_redist.x64.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (IsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-3-x64.dll', ExpandConstant('{sys}') + '\libcrypto-3-x64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-3-x64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-x64.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-3-x64.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-3-x64.dll', ExpandConstant('{sys}') + '\libssl-3-x64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-3-x64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-x64.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-3-x64.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-x64.dll', ExpandConstant('{app}') + '\bin\libcrypto-3-x64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-x64.dll', ExpandConstant('{app}') + '\bin\libssl-3-x64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-x64.dll', ExpandConstant('{app}') + '\tests\libcrypto-3-x64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-x64.dll', ExpandConstant('{app}') + '\tests\libssl-3-x64.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{cf}\SSL"; Flags: recursesubdirs
+Source: "bin\*"; DestDir: "{app}\bin"; Flags: recursesubdirs
+Source: "bin_static\*"; DestDir: "{app}\bin_static"; Flags: recursesubdirs
+Source: "exp\*"; DestDir: "{app}\exp"; Flags: recursesubdirs
+Source: "lib\*"; DestDir: "{app}\lib"; Flags: recursesubdirs
+Source: "include\*"; DestDir: "{app}\include"; Flags: recursesubdirs
+Source: "tests\*"; DestDir: "{app}\tests"; Flags: recursesubdirs
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-3-x64.dll"; DestDir: "{app}"
+Source: "libssl-3-x64.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (x64)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-3-x64.dll"
+Type: files; Name: "{app}\bin\libssl-3-x64.dll"
diff --git a/ms-windows/templates/3.0/x64/openssl.wxs b/ms-windows/templates/3.0/x64/openssl.wxs
new file mode 100644
index 0000000..47e9919
--- /dev/null
+++ b/ms-windows/templates/3.0/x64/openssl.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/3.0/x64/start.bat b/ms-windows/templates/3.0/x64/start.bat
new file mode 100644
index 0000000..1e52980
--- /dev/null
+++ b/ms-windows/templates/3.0/x64/start.bat
@@ -0,0 +1,21 @@
+@echo off
+
+rem * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+rem *
+rem * Licensed under the OpenSSL license (the "License"). You may not use
+rem * this file except in compliance with the License. You can obtain a copy
+rem * in the file LICENSE in the source distribution or at
+rem * https://www.openssl.org/source/license.html
+
+@set PATH=%PATH%;%~dp0bin
+
+title OpenSSL Command Prompt (Intel/AMD x64)
+echo OpenSSL Command Prompt (Intel/AMD x64)
+echo.
+openssl version -a
+echo.
+
+%SystemDrive%
+cd %UserProfile%
+
+cmd.exe /K
diff --git a/ms-windows/templates/3.0/x86/openssl-light.iss b/ms-windows/templates/3.0/x86/openssl-light.iss
new file mode 100644
index 0000000..56956d7
--- /dev/null
+++ b/ms-windows/templates/3.0/x86/openssl-light.iss
@@ -0,0 +1,147 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL Light (32-bit)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] Light (32-bit)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={pf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-x86-light
+LicenseFile=license.txt
+; SetupIconFile=compiler:SetupClassicIcon.ico
+PrivilegesRequired=admin
+Compression=bzip
+; Minimum version supported is Windows XP.
+MinVersion=5.1
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2019 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{syswow64}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2019 Redistributables (32-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/16/release/vc_redist.x86.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (IsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-3.dll', ExpandConstant('{sys}') + '\libcrypto-3.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-3.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-3.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-3.dll', ExpandConstant('{sys}') + '\libssl-3.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-3.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-3.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-3.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3.dll', ExpandConstant('{app}') + '\bin\libcrypto-3.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3.dll', ExpandConstant('{app}') + '\bin\libssl-3.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{cf}\SSL"; Flags: recursesubdirs
+Source: "bin\PEM\*"; DestDir: "{app}\bin\PEM"; Flags: recursesubdirs
+Source: "bin\*.pl"; DestDir: "{app}\bin"
+Source: "bin\openssl.exe"; DestDir: "{app}\bin"
+Source: "bin\*.dll"; DestDir: "{app}\bin"
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-3.dll"; DestDir: "{app}"
+Source: "libssl-3.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (x86)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-3.dll"
+Type: files; Name: "{app}\bin\libssl-3.dll"
diff --git a/ms-windows/templates/3.0/x86/openssl-light.wxs b/ms-windows/templates/3.0/x86/openssl-light.wxs
new file mode 100644
index 0000000..6fc781a
--- /dev/null
+++ b/ms-windows/templates/3.0/x86/openssl-light.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/3.0/x86/openssl.iss b/ms-windows/templates/3.0/x86/openssl.iss
new file mode 100644
index 0000000..6424a2a
--- /dev/null
+++ b/ms-windows/templates/3.0/x86/openssl.iss
@@ -0,0 +1,151 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL (32-bit)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] (32-bit)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={pf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-x86
+LicenseFile=license.txt
+; SetupIconFile=compiler:SetupClassicIcon.ico
+PrivilegesRequired=admin
+Compression=bzip
+; Minimum version supported is Windows XP.
+MinVersion=5.1
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2019 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{syswow64}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2019 Redistributables (32-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/16/release/vc_redist.x86.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (IsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-3.dll', ExpandConstant('{sys}') + '\libcrypto-3.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-3.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-3.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-3.dll', ExpandConstant('{sys}') + '\libssl-3.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-3.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-3.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-3.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3.dll', ExpandConstant('{app}') + '\bin\libcrypto-3.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3.dll', ExpandConstant('{app}') + '\bin\libssl-3.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3.dll', ExpandConstant('{app}') + '\tests\libcrypto-3.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3.dll', ExpandConstant('{app}') + '\tests\libssl-3.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{cf}\SSL"; Flags: recursesubdirs
+Source: "bin\*"; DestDir: "{app}\bin"; Flags: recursesubdirs
+Source: "bin_static\*"; DestDir: "{app}\bin_static"; Flags: recursesubdirs
+Source: "exp\*"; DestDir: "{app}\exp"; Flags: recursesubdirs
+Source: "lib\*"; DestDir: "{app}\lib"; Flags: recursesubdirs
+Source: "include\*"; DestDir: "{app}\include"; Flags: recursesubdirs
+Source: "tests\*"; DestDir: "{app}\tests"; Flags: recursesubdirs
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-3.dll"; DestDir: "{app}"
+Source: "libssl-3.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (x86)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-3.dll"
+Type: files; Name: "{app}\bin\libssl-3.dll"
diff --git a/ms-windows/templates/3.0/x86/openssl.wxs b/ms-windows/templates/3.0/x86/openssl.wxs
new file mode 100644
index 0000000..7aa241e
--- /dev/null
+++ b/ms-windows/templates/3.0/x86/openssl.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/3.0/x86/start.bat b/ms-windows/templates/3.0/x86/start.bat
new file mode 100644
index 0000000..b3995f5
--- /dev/null
+++ b/ms-windows/templates/3.0/x86/start.bat
@@ -0,0 +1,21 @@
+@echo off
+
+rem * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+rem *
+rem * Licensed under the OpenSSL license (the "License"). You may not use
+rem * this file except in compliance with the License. You can obtain a copy
+rem * in the file LICENSE in the source distribution or at
+rem * https://www.openssl.org/source/license.html
+
+@set PATH=%PATH%;%~dp0bin
+
+title OpenSSL Command Prompt (Intel/AMD x86)
+echo OpenSSL Command Prompt (Intel/AMD x86)
+echo.
+openssl version -a
+echo.
+
+%SystemDrive%
+cd %UserProfile%
+
+cmd.exe /K
diff --git a/ms-windows/templates/3.1/arm64/openssl-light.iss b/ms-windows/templates/3.1/arm64/openssl-light.iss
new file mode 100644
index 0000000..01750a5
--- /dev/null
+++ b/ms-windows/templates/3.1/arm64/openssl-light.iss
@@ -0,0 +1,149 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL Light (64-bit ARM)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] Light (64-bit ARM)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={commonpf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-arm64-light
+LicenseFile=license.txt
+SetupIconFile=compiler:SetupClassicIcon.ico
+PrivilegesRequired=admin
+Compression=bzip
+ArchitecturesAllowed=arm64
+ArchitecturesInstallIn64BitMode=arm64
+; Minimum version supported is Windows 10.
+MinVersion=10.0
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2019 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{sys}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2019 Redistributables (64-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/16/release/VC_redist.arm64.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (WizardIsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-3-arm64.dll', ExpandConstant('{sys}') + '\libcrypto-3-arm64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-3-arm64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-arm64.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-3-arm64.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-3-arm64.dll', ExpandConstant('{sys}') + '\libssl-3-arm64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-3-arm64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-arm64.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-3-arm64.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-arm64.dll', ExpandConstant('{app}') + '\bin\libcrypto-3-arm64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-arm64.dll', ExpandConstant('{app}') + '\bin\libssl-3-arm64.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{commoncf}\SSL"; Flags: recursesubdirs
+Source: "bin\PEM\*"; DestDir: "{app}\bin\PEM"; Flags: recursesubdirs
+Source: "bin\*.pl"; DestDir: "{app}\bin"
+Source: "bin\openssl.exe"; DestDir: "{app}\bin"
+Source: "bin\*.dll"; DestDir: "{app}\bin"
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-3-arm64.dll"; DestDir: "{app}"
+Source: "libssl-3-arm64.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (ARM64)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-3-arm64.dll"
+Type: files; Name: "{app}\bin\libssl-3-arm64.dll"
diff --git a/ms-windows/templates/3.1/arm64/openssl-light.wxs b/ms-windows/templates/3.1/arm64/openssl-light.wxs
new file mode 100644
index 0000000..67a6931
--- /dev/null
+++ b/ms-windows/templates/3.1/arm64/openssl-light.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/3.1/arm64/openssl.iss b/ms-windows/templates/3.1/arm64/openssl.iss
new file mode 100644
index 0000000..58253e6
--- /dev/null
+++ b/ms-windows/templates/3.1/arm64/openssl.iss
@@ -0,0 +1,153 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL (64-bit ARM)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] (64-bit ARM)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={commonpf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-arm64
+LicenseFile=license.txt
+SetupIconFile=compiler:SetupClassicIcon.ico
+PrivilegesRequired=admin
+Compression=bzip
+ArchitecturesAllowed=arm64
+ArchitecturesInstallIn64BitMode=arm64
+; Minimum version supported is Windows 10.
+MinVersion=10.0
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2019 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{sys}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2019 Redistributables (64-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/16/release/VC_redist.arm64.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (WizardIsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-3-arm64.dll', ExpandConstant('{sys}') + '\libcrypto-3-arm64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-3-arm64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-arm64.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-3-arm64.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-3-arm64.dll', ExpandConstant('{sys}') + '\libssl-3-arm64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-3-arm64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-arm64.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-3-arm64.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-arm64.dll', ExpandConstant('{app}') + '\bin\libcrypto-3-arm64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-arm64.dll', ExpandConstant('{app}') + '\bin\libssl-3-arm64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-arm64.dll', ExpandConstant('{app}') + '\tests\libcrypto-3-arm64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-arm64.dll', ExpandConstant('{app}') + '\tests\libssl-3-arm64.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{commoncf}\SSL"; Flags: recursesubdirs
+Source: "bin\*"; DestDir: "{app}\bin"; Flags: recursesubdirs
+Source: "bin_static\*"; DestDir: "{app}\bin_static"; Flags: recursesubdirs
+Source: "exp\*"; DestDir: "{app}\exp"; Flags: recursesubdirs
+Source: "lib\*"; DestDir: "{app}\lib"; Flags: recursesubdirs
+Source: "include\*"; DestDir: "{app}\include"; Flags: recursesubdirs
+Source: "tests\*"; DestDir: "{app}\tests"; Flags: recursesubdirs
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-3-arm64.dll"; DestDir: "{app}"
+Source: "libssl-3-arm64.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (ARM64)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-3-arm64.dll"
+Type: files; Name: "{app}\bin\libssl-3-arm64.dll"
diff --git a/ms-windows/templates/3.1/arm64/openssl.wxs b/ms-windows/templates/3.1/arm64/openssl.wxs
new file mode 100644
index 0000000..e95f596
--- /dev/null
+++ b/ms-windows/templates/3.1/arm64/openssl.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/3.1/arm64/start.bat b/ms-windows/templates/3.1/arm64/start.bat
new file mode 100644
index 0000000..2e99d32
--- /dev/null
+++ b/ms-windows/templates/3.1/arm64/start.bat
@@ -0,0 +1,21 @@
+@echo off
+
+rem * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+rem *
+rem * Licensed under the OpenSSL license (the "License"). You may not use
+rem * this file except in compliance with the License. You can obtain a copy
+rem * in the file LICENSE in the source distribution or at
+rem * https://www.openssl.org/source/license.html
+
+@set PATH=%PATH%;%~dp0bin
+
+title OpenSSL Command Prompt (ARM64)
+echo OpenSSL Command Prompt (ARM64)
+echo.
+openssl version -a
+echo.
+
+%SystemDrive%
+cd %UserProfile%
+
+cmd.exe /K
diff --git a/ms-windows/templates/3.1/info.json b/ms-windows/templates/3.1/info.json
new file mode 100644
index 0000000..3c3f72c
--- /dev/null
+++ b/ms-windows/templates/3.1/info.json
@@ -0,0 +1,229 @@
+{
+ "copyright": "Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.",
+ "copyright_notes": "Licensed under the OpenSSL license (the \"License\"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at https://www.openssl.org/source/license.html",
+ "name": "OpenSSL 3.1",
+ "download_type": "tar.gz",
+ "download_extract_path": "[[VERSION_DIR]]/source",
+ "download": "https://www.openssl.org/source/openssl-[[DOTTED_VERSION]].tar.gz",
+ "download_sha256_url": "https://www.openssl.org/source/openssl-[[DOTTED_VERSION]].tar.gz.sha256",
+ "architectures": [
+ {
+ "name": "Intel/AMD x86 (32-bit)",
+ "architecture": "x86",
+ "dependencies": [
+ {
+ "name": "Visual C++ compiler",
+ "purpose": "Main C compiler",
+ "verify": "cl.exe",
+ "verify_opts": "",
+ "required_output": "/Microsoft .* C\\/C\\+\\+ .* x86/",
+ "required_alert": "Incorrect architecture detected or invalid compiler. Expected Microsoft Visual C++ x86."
+ },
+ {
+ "name": "Visual C++ object linker",
+ "purpose": "Main object file linker",
+ "verify": "link.exe",
+ "verify_opts": "/?",
+ "required_output": "/Microsoft .* Incremental Linker/",
+ "required_alert": "Missing Microsoft Visual C++ object linker."
+ },
+ {
+ "name": "Visual C++ nmake",
+ "purpose": "Main makefile processing utility",
+ "verify": "nmake.exe",
+ "verify_opts": "/?",
+ "required_output": "/Microsoft .* Program Maintenance Utility/",
+ "required_alert": "Missing Microsoft nmake."
+ },
+ {
+ "name": "Strawberry Perl Portable",
+ "purpose": "Running perl Configure to generate makefiles and also MinGW dlltool to create export libraries",
+ "verify": "perl.exe",
+ "verify_opts": "-v",
+ "required_output": "/perl .* \\(v5[.]/",
+ "required_alert": "Perl 5 is required.",
+ "preferred_output": "/perl .* \\(v5[.]32[.]1\\)/",
+ "preferred_alert": "Perl v5.32.1 is preferred.",
+ "env_paths": ["[[DEPS_DIR]]/perl/perl/site/bin", "[[DEPS_DIR]]/perl/perl/bin"],
+ "env_extras": {"TERM": "dumb"},
+ "download_type": "zip",
+ "download_extract_path": "[[DEPS_DIR]]/perl",
+ "download_x86": "https://strawberryperl.com/download/5.32.1.1/strawberry-perl-5.32.1.1-32bit-portable.zip",
+ "download_x86_sha256": "d9c5711d12573a0f6d977792caa58364b1d46217521ae5c25cf5cc378a7c23c0",
+ "download_x64": "https://strawberryperl.com/download/5.32.1.1/strawberry-perl-5.32.1.1-64bit-portable.zip",
+ "download_x64_sha256": "692646105b0f5e058198a852dc52a48f1cebcaf676d63bbdeae12f4eaee9bf5c"
+ },
+ {
+ "name": "Netwide Assembler (NASM)",
+ "purpose": "Building optimized assembly code",
+ "verify": "nasm.exe",
+ "verify_opts": "-v",
+ "preferred_output": "/NASM/",
+ "preferred_alert": "NASM is required.",
+ "preferred_output": "/NASM .* 2[.]16[.]01/",
+ "preferred_alert": "NASM v2.16.01 is preferred.",
+ "env_paths": ["[[DEPS_DIR]]/nasm/nasm-2.16.01"],
+ "env_extras": {},
+ "download_type": "zip",
+ "download_extract_path": "[[DEPS_DIR]]/nasm",
+ "download_x86": "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win32/nasm-2.16.01-win32.zip",
+ "download_x86_sha256": "e289fa70c88594b092c916344bb8bfcd6896b604bfab284ab57b1372997c820c",
+ "download_x64": "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/nasm-2.16.01-win64.zip",
+ "download_x64_sha256": "029eed31faf0d2c5f95783294432cbea6c15bf633430f254bb3c1f195c67ca3a"
+ },
+ {
+ "name": "Inno Setup 5",
+ "purpose": "Compiling .iss template files into .exe installers (32-bit only)",
+ "verify": "[[DEPS_DIR]]/innosetup5/iscc.exe",
+ "verify_opts": "",
+ "required_output": "/Inno Setup 5/",
+ "required_alert": "Inno Setup 5 is required.",
+ "download_type": "exe",
+ "download_extract_path": "[[DEPS_DIR]]/innosetup5",
+ "download_install_opts": "/PORTABLE=1 /verysilent /currentuser \"/DIR=[[DEPS_DIR]]\\innosetup5\"",
+ "download": "https://files.jrsoftware.org/is/5/innosetup-5.6.1.exe",
+ "download_sha256": "96fd6a5eaab473c61a19affff89618764b940ee3f15837c2944a5595aed5fde6"
+ },
+ {
+ "name": "Wix Toolset",
+ "purpose": "Generating .msi installers from .exe installers",
+ "verify": "[[DEPS_DIR]]/wixtoolset/candle.exe",
+ "verify_opts": "",
+ "env_extras": {"WIX": "[[DEPS_DIR]]\\wixtoolset\\"},
+ "required_output": "/Windows Installer XML Toolset Compiler version 3[.]14/",
+ "required_alert": "Wix toolset 3.14 is required.",
+ "download_type": "zip",
+ "download_extract_path": "[[DEPS_DIR]]/wixtoolset",
+ "download": "https://wixtoolset.org/downloads/v3.14.0.6526/wix314-binaries.zip",
+ "download_sha256": "4c89898df3bcab13e12f7ca54399c35ad273475ad2cb6284611d00ae2d063c2c"
+ }
+ ],
+ "build": {
+ "configure_target": "VC-WIN32",
+ "configure_extra": "-D_USE_32BIT_TIME_T -D_WINSOCK_DEPRECATED_NO_WARNINGS -D_WIN32_WINNT=0x0501",
+ "patches": {
+ "/Zi ": "/Z7 ",
+ "/subsystem:console ": "/subsystem:console,5.01 ",
+ "CNF_LDFLAGS=": "CNF_LDFLAGS=/subsystem:console,5.01 "
+ }
+ },
+ "package": {
+ "mingw_dlltool": "[[DEPS_DIR]]/perl/c/bin/dlltool.exe",
+ "inno_setup_dir": "[[DEPS_DIR]]/innosetup5",
+ "wix_toolset_dir": "[[DEPS_DIR]]/wixtoolset",
+ "wix_toolset_target": ""
+ }
+ },
+ {
+ "name": "Intel/AMD x64 (64-bit)",
+ "architecture": "x64",
+ "dependencies": [
+ {
+ "name": "Visual C++ compiler",
+ "purpose": "Main C compiler",
+ "verify": "cl.exe",
+ "verify_opts": "",
+ "required_output": "/Microsoft .* C\\/C\\+\\+ .* x64/",
+ "required_alert": "Incorrect architecture detected or invalid compiler. Expected Microsoft Visual C++ x64."
+ },
+ {
+ "name": "Visual C++ object linker",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Visual C++ nmake",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Strawberry Perl Portable",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Netwide Assembler (NASM)",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Inno Setup 5",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Wix Toolset",
+ "expand_from": "x86"
+ }
+ ],
+ "build": {
+ "configure_target": "VC-WIN64A",
+ "configure_extra": "-D_WINSOCK_DEPRECATED_NO_WARNINGS -D_WIN32_WINNT=0x0502",
+ "patches": {
+ "/Zi ": "/Z7 ",
+ "/subsystem:console ": "/subsystem:console,5.02 ",
+ "CNF_LDFLAGS=": "CNF_LDFLAGS=/subsystem:console,5.02 "
+ }
+ },
+ "package": {
+ "inno_setup_dir": "[[DEPS_DIR]]/innosetup5",
+ "wix_toolset_dir": "[[DEPS_DIR]]/wixtoolset",
+ "wix_toolset_target": "-arch x64"
+ }
+ },
+ {
+ "name": "ARM64 (64-bit)",
+ "architecture": "arm64",
+ "dependencies": [
+ {
+ "name": "Visual C++ compiler",
+ "purpose": "Main C compiler",
+ "verify": "cl.exe",
+ "verify_opts": "",
+ "required_output": "/Microsoft .* C\\/C\\+\\+ .* ARM64/",
+ "required_alert": "Incorrect architecture detected or invalid compiler. Expected Microsoft Visual C++ ARM64."
+ },
+ {
+ "name": "Visual C++ object linker",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Visual C++ nmake",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Strawberry Perl Portable",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Netwide Assembler (NASM)",
+ "expand_from": "x86"
+ },
+ {
+ "name": "Inno Setup 6",
+ "purpose": "Compiling .iss template files into .exe installers (64-bit only)",
+ "verify": "[[DEPS_DIR]]/innosetup6/iscc.exe",
+ "verify_opts": "",
+ "required_output": "/Inno Setup 6/",
+ "required_alert": "Inno Setup 6 is required.",
+ "download_type": "exe",
+ "download_extract_path": "[[DEPS_DIR]]/innosetup6",
+ "download_install_opts": "/PORTABLE=1 /verysilent /currentuser \"/DIR=[[DEPS_DIR]]\\innosetup6\"",
+ "download": "https://files.jrsoftware.org/is/6/innosetup-6.2.2.exe",
+ "download_sha256": "8117d10d00a2ad33a1390978ea3872861c330e087914410a6377b22c4c5b8563"
+ },
+ {
+ "name": "Wix Toolset",
+ "expand_from": "x86"
+ }
+ ],
+ "build": {
+ "configure_target": "VC-WIN64-ARM",
+ "configure_extra": "",
+ "patches": {
+ "/Zi ": "/Z7 "
+ }
+ },
+ "package": {
+ "inno_setup_dir": "[[DEPS_DIR]]/innosetup6",
+ "wix_toolset_dir": "[[DEPS_DIR]]/wixtoolset",
+ "wix_toolset_target": "-arch arm64"
+ }
+ }
+ ]
+}
diff --git a/ms-windows/templates/3.1/x64/openssl-light.iss b/ms-windows/templates/3.1/x64/openssl-light.iss
new file mode 100644
index 0000000..0d6734e
--- /dev/null
+++ b/ms-windows/templates/3.1/x64/openssl-light.iss
@@ -0,0 +1,149 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL Light (64-bit)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] Light (64-bit)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={pf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-x64-light
+LicenseFile=license.txt
+; SetupIconFile=compiler:SetupClassicIcon.ico
+PrivilegesRequired=admin
+Compression=bzip
+ArchitecturesAllowed=x64
+ArchitecturesInstallIn64BitMode=x64
+; Minimum version supported is Windows XP.
+MinVersion=5.1
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2019 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{sys}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2019 Redistributables (64-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/16/release/vc_redist.x64.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (IsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-3-x64.dll', ExpandConstant('{sys}') + '\libcrypto-3-x64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-3-x64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-x64.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-3-x64.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-3-x64.dll', ExpandConstant('{sys}') + '\libssl-3-x64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-3-x64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-x64.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-3-x64.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-x64.dll', ExpandConstant('{app}') + '\bin\libcrypto-3-x64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-x64.dll', ExpandConstant('{app}') + '\bin\libssl-3-x64.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{cf}\SSL"; Flags: recursesubdirs
+Source: "bin\PEM\*"; DestDir: "{app}\bin\PEM"; Flags: recursesubdirs
+Source: "bin\*.pl"; DestDir: "{app}\bin"
+Source: "bin\openssl.exe"; DestDir: "{app}\bin"
+Source: "bin\*.dll"; DestDir: "{app}\bin"
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-3-x64.dll"; DestDir: "{app}"
+Source: "libssl-3-x64.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (x64)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-3-x64.dll"
+Type: files; Name: "{app}\bin\libssl-3-x64.dll"
diff --git a/ms-windows/templates/3.1/x64/openssl-light.wxs b/ms-windows/templates/3.1/x64/openssl-light.wxs
new file mode 100644
index 0000000..d485b1c
--- /dev/null
+++ b/ms-windows/templates/3.1/x64/openssl-light.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/3.1/x64/openssl.iss b/ms-windows/templates/3.1/x64/openssl.iss
new file mode 100644
index 0000000..fb03528
--- /dev/null
+++ b/ms-windows/templates/3.1/x64/openssl.iss
@@ -0,0 +1,153 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL (64-bit)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] (64-bit)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={pf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-x64
+LicenseFile=license.txt
+; SetupIconFile=compiler:SetupClassicIcon.ico
+PrivilegesRequired=admin
+Compression=bzip
+ArchitecturesAllowed=x64
+ArchitecturesInstallIn64BitMode=x64
+; Minimum version supported is Windows XP.
+MinVersion=5.1
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2019 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{sys}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2019 Redistributables (64-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/16/release/vc_redist.x64.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (IsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-3-x64.dll', ExpandConstant('{sys}') + '\libcrypto-3-x64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-3-x64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-x64.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-3-x64.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-3-x64.dll', ExpandConstant('{sys}') + '\libssl-3-x64.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-3-x64.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-x64.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-3-x64.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-x64.dll', ExpandConstant('{app}') + '\bin\libcrypto-3-x64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-x64.dll', ExpandConstant('{app}') + '\bin\libssl-3-x64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3-x64.dll', ExpandConstant('{app}') + '\tests\libcrypto-3-x64.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3-x64.dll', ExpandConstant('{app}') + '\tests\libssl-3-x64.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{cf}\SSL"; Flags: recursesubdirs
+Source: "bin\*"; DestDir: "{app}\bin"; Flags: recursesubdirs
+Source: "bin_static\*"; DestDir: "{app}\bin_static"; Flags: recursesubdirs
+Source: "exp\*"; DestDir: "{app}\exp"; Flags: recursesubdirs
+Source: "lib\*"; DestDir: "{app}\lib"; Flags: recursesubdirs
+Source: "include\*"; DestDir: "{app}\include"; Flags: recursesubdirs
+Source: "tests\*"; DestDir: "{app}\tests"; Flags: recursesubdirs
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-3-x64.dll"; DestDir: "{app}"
+Source: "libssl-3-x64.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (x64)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-3-x64.dll"
+Type: files; Name: "{app}\bin\libssl-3-x64.dll"
diff --git a/ms-windows/templates/3.1/x64/openssl.wxs b/ms-windows/templates/3.1/x64/openssl.wxs
new file mode 100644
index 0000000..47e9919
--- /dev/null
+++ b/ms-windows/templates/3.1/x64/openssl.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/3.1/x64/start.bat b/ms-windows/templates/3.1/x64/start.bat
new file mode 100644
index 0000000..1e52980
--- /dev/null
+++ b/ms-windows/templates/3.1/x64/start.bat
@@ -0,0 +1,21 @@
+@echo off
+
+rem * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+rem *
+rem * Licensed under the OpenSSL license (the "License"). You may not use
+rem * this file except in compliance with the License. You can obtain a copy
+rem * in the file LICENSE in the source distribution or at
+rem * https://www.openssl.org/source/license.html
+
+@set PATH=%PATH%;%~dp0bin
+
+title OpenSSL Command Prompt (Intel/AMD x64)
+echo OpenSSL Command Prompt (Intel/AMD x64)
+echo.
+openssl version -a
+echo.
+
+%SystemDrive%
+cd %UserProfile%
+
+cmd.exe /K
diff --git a/ms-windows/templates/3.1/x86/openssl-light.iss b/ms-windows/templates/3.1/x86/openssl-light.iss
new file mode 100644
index 0000000..56956d7
--- /dev/null
+++ b/ms-windows/templates/3.1/x86/openssl-light.iss
@@ -0,0 +1,147 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL Light (32-bit)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] Light (32-bit)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={pf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-x86-light
+LicenseFile=license.txt
+; SetupIconFile=compiler:SetupClassicIcon.ico
+PrivilegesRequired=admin
+Compression=bzip
+; Minimum version supported is Windows XP.
+MinVersion=5.1
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2019 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{syswow64}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2019 Redistributables (32-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/16/release/vc_redist.x86.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (IsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-3.dll', ExpandConstant('{sys}') + '\libcrypto-3.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-3.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-3.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-3.dll', ExpandConstant('{sys}') + '\libssl-3.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-3.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-3.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-3.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3.dll', ExpandConstant('{app}') + '\bin\libcrypto-3.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3.dll', ExpandConstant('{app}') + '\bin\libssl-3.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{cf}\SSL"; Flags: recursesubdirs
+Source: "bin\PEM\*"; DestDir: "{app}\bin\PEM"; Flags: recursesubdirs
+Source: "bin\*.pl"; DestDir: "{app}\bin"
+Source: "bin\openssl.exe"; DestDir: "{app}\bin"
+Source: "bin\*.dll"; DestDir: "{app}\bin"
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-3.dll"; DestDir: "{app}"
+Source: "libssl-3.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (x86)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-3.dll"
+Type: files; Name: "{app}\bin\libssl-3.dll"
diff --git a/ms-windows/templates/3.1/x86/openssl-light.wxs b/ms-windows/templates/3.1/x86/openssl-light.wxs
new file mode 100644
index 0000000..6fc781a
--- /dev/null
+++ b/ms-windows/templates/3.1/x86/openssl-light.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/3.1/x86/openssl.iss b/ms-windows/templates/3.1/x86/openssl.iss
new file mode 100644
index 0000000..6424a2a
--- /dev/null
+++ b/ms-windows/templates/3.1/x86/openssl.iss
@@ -0,0 +1,151 @@
+; Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+;
+; Licensed under the OpenSSL license (the "License"). You may not use
+; this file except in compliance with the License. You can obtain a copy
+; in the file LICENSE in the source distribution or at
+; https://www.openssl.org/source/license.html
+
+[Setup]
+AppName=OpenSSL (32-bit)
+AppVersion=[[DOTTED_VERSION]]
+AppVerName=OpenSSL [[DOTTED_VERSION]] (32-bit)
+AppPublisher=OpenSSL Foundation
+AppPublisherURL=https://www.openssl.org
+AppSupportURL=https://github.com/openssl/installer
+AppUpdatesURL=https://www.openssl.org
+VersionInfoVersion=[[WINDOWS_DOTTED_VERSION]]
+DefaultDirName={pf}\OpenSSL
+DisableDirPage=no
+DefaultGroupName=OpenSSL
+SourceDir=[[INSTALLER_SOURCE_DIR]]
+OutputBaseFilename=OpenSSL-[[DOTTED_VERSION]]-x86
+LicenseFile=license.txt
+; SetupIconFile=compiler:SetupClassicIcon.ico
+PrivilegesRequired=admin
+Compression=bzip
+; Minimum version supported is Windows XP.
+MinVersion=5.1
+CreateUninstallRegKey=not IsMSI
+
+[Code]
+// Determine whether or not the installer is being called from the WiX wrapper.
+function IsMSI(): Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ Result := True;
+ end;
+ end;
+end;
+
+// Sets a static registry key as per the input. Lets the MSI wrapper do its thing later.
+procedure PrepareMSIUninstall();
+var
+ x: Integer;
+ subkey: String;
+begin
+ for x := 1 to ParamCount do
+ begin
+ if CompareText(Copy(ParamStr(x), 1, 5), '/MSI=') = 0 then
+ begin
+ subkey := 'SOFTWARE\Inno Setup MSIs\' + Copy(ParamStr(x), 6, Length(ParamStr(x)) - 5);
+ RegDeleteKeyIncludingSubkeys(HKLM, subkey);
+ RegWriteStringValue(HKLM, subkey, '', ExpandConstant('{uninstallexe}'));
+ end;
+ end;
+end;
+
+function InitializeSetup() : Boolean;
+var
+ MsgResult : Integer;
+ ErrCode: integer;
+begin
+ // Deal with the VC++ 2019 Redistributable issue.
+ if ((NOT FileExists(ExpandConstant('{syswow64}') + '\vcruntime140.dll'))) then begin
+ MsgResult := SuppressibleMsgBox('The OpenSSL installation setup has detected that the following critical component is missing:'#10'Microsoft Visual C++ 2019 Redistributables (32-bit)'#10#10'OpenSSL will not function properly without this component.'#10'Download the required redistributables now?', mbError, MB_YESNOCANCEL, IDNO);
+ if (MsgResult = IDCANCEL) then exit;
+
+ if (MsgResult = IDYES) then begin
+ ShellExecAsOriginalUser('open', 'https://aka.ms/vs/16/release/vc_redist.x86.exe', '', '', SW_SHOW, ewNoWait, ErrCode);
+ end;
+ end;
+
+ Result := True;
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ IsCopied : Boolean;
+ MsgResult : Integer;
+begin
+ if (CurStep = ssPostInstall) then begin
+ // Copy files to the system directory if the task was selected.
+ if (IsTaskSelected('copytosystem')) then begin
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libcrypto-3.dll', ExpandConstant('{sys}') + '\libcrypto-3.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libcrypto-3.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3.dll', ExpandConstant('{app}') + '\tmpeay32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpeay32.dll', ExpandConstant('{sys}') + '\libcrypto-3.dll');
+ end;
+
+ MsgResult := IDCANCEL;
+ repeat
+ IsCopied := FileCopy(ExpandConstant('{app}') + '\libssl-3.dll', ExpandConstant('{sys}') + '\libssl-3.dll', False);
+ if (NOT IsCopied) then MsgResult := SuppressibleMsgBox('Unable to copy libssl-3.dll to ' + ExpandConstant('{sys}') + '.'#10'Please close any applications that may be using this OpenSSL component and click Retry to try again.'#10'Clicking Cancel will register the file to be moved during the next reboot.'#10#10'If you click Cancel, OpenSSL may not function properly until the computer is rebooted.', mbError, MB_RETRYCANCEL, IDCANCEL);
+ until ((IsCopied) OR (MsgResult = IDCANCEL));
+ if (NOT IsCopied) then begin
+ FileCopy(ExpandConstant('{app}') + '\libssl-3.dll', ExpandConstant('{app}') + '\tmpssl32.dll', False);
+ RestartReplace(ExpandConstant('{app}') + '\tmpssl32.dll', ExpandConstant('{sys}') + '\libssl-3.dll');
+ end;
+ end
+ else begin
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3.dll', ExpandConstant('{app}') + '\bin\libcrypto-3.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3.dll', ExpandConstant('{app}') + '\bin\libssl-3.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libcrypto-3.dll', ExpandConstant('{app}') + '\tests\libcrypto-3.dll', False);
+ FileCopy(ExpandConstant('{app}') + '\libssl-3.dll', ExpandConstant('{app}') + '\tests\libssl-3.dll', False);
+ end;
+ end;
+end;
+
+[Tasks]
+Name: copytosystem; Description: "The Windows &system directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive
+Name: copytobin; Description: "The OpenSSL &binaries (/bin) directory"; GroupDescription: "Copy OpenSSL DLLs to:"; Flags: exclusive unchecked
+
+[Files]
+Source: "conf\*"; DestDir: "{cf}\SSL"; Flags: recursesubdirs
+Source: "bin\*"; DestDir: "{app}\bin"; Flags: recursesubdirs
+Source: "bin_static\*"; DestDir: "{app}\bin_static"; Flags: recursesubdirs
+Source: "exp\*"; DestDir: "{app}\exp"; Flags: recursesubdirs
+Source: "lib\*"; DestDir: "{app}\lib"; Flags: recursesubdirs
+Source: "include\*"; DestDir: "{app}\include"; Flags: recursesubdirs
+Source: "tests\*"; DestDir: "{app}\tests"; Flags: recursesubdirs
+Source: "text\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "tools\*"; DestDir: "{app}"; Flags: recursesubdirs
+Source: "libcrypto-3.dll"; DestDir: "{app}"
+Source: "libssl-3.dll"; DestDir: "{app}"
+Source: "start.bat"; DestDir: "{app}"
+
+[Icons]
+Name: "{group}\OpenSSL Command Prompt (x86)"; Filename: "{app}\start.bat"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Website"; Filename: "https://www.openssl.org/"; WorkingDir: "{app}"
+Name: "{group}\OpenSSL Documentation"; Filename: "https://www.openssl.org/docs/"; WorkingDir: "{app}"
+Name: "{group}\Uninstall OpenSSL"; Filename: "{uninstallexe}"; Check: not IsMSI
+
+[Registry]
+Root: HKLM; Subkey: "SOFTWARE\Inno Setup MSIs"; Check: IsMSI; AfterInstall: PrepareMSIUninstall
+
+[Run]
+Filename: "https://github.com/sponsors/openssl"; Description: "Become a sponsor of the OpenSSL project"; WorkingDir: "{app}"; Flags: shellexec postinstall nowait skipifsilent unchecked
+
+[UninstallDelete]
+Type: files; Name: "{app}\bin\libcrypto-3.dll"
+Type: files; Name: "{app}\bin\libssl-3.dll"
diff --git a/ms-windows/templates/3.1/x86/openssl.wxs b/ms-windows/templates/3.1/x86/openssl.wxs
new file mode 100644
index 0000000..7aa241e
--- /dev/null
+++ b/ms-windows/templates/3.1/x86/openssl.wxs
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UILevel=2 AND REMOVE AND UNINSTALLINNOSETUP
+ (UILevel=3 OR UILevel=4) AND REMOVE AND UNINSTALLINNOSETUP
+ UILevel=5 AND REMOVE AND UNINSTALLINNOSETUP
+
+ UILevel=2 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ (UILevel=3 OR UILevel=4) AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+ UILevel=5 AND (NOT Installed OR UPGRADINGPRODUCTCODE)
+
+
+
+
+
+
+
+
+
+
diff --git a/ms-windows/templates/3.1/x86/start.bat b/ms-windows/templates/3.1/x86/start.bat
new file mode 100644
index 0000000..b3995f5
--- /dev/null
+++ b/ms-windows/templates/3.1/x86/start.bat
@@ -0,0 +1,21 @@
+@echo off
+
+rem * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+rem *
+rem * Licensed under the OpenSSL license (the "License"). You may not use
+rem * this file except in compliance with the License. You can obtain a copy
+rem * in the file LICENSE in the source distribution or at
+rem * https://www.openssl.org/source/license.html
+
+@set PATH=%PATH%;%~dp0bin
+
+title OpenSSL Command Prompt (Intel/AMD x86)
+echo OpenSSL Command Prompt (Intel/AMD x86)
+echo.
+openssl version -a
+echo.
+
+%SystemDrive%
+cd %UserProfile%
+
+cmd.exe /K