Commit: b1704f17dd71abd5d4b8064019f5ecd9fcd9e9d5 Author: Holly Li (WIPRO LIMITED) <v-hu...@microsoft.com> Mon, 15 Apr 2019 17:22:44 -0700 Committer: Anatol Belski <a...@php.net> Tue, 30 Apr 2019 12:18:19 +0200 Parents: b423a5d0587eb4f97f67f2fc1434d4b99f37ba05 Branches: master
Link: http://git.php.net/?p=pftt2.git;a=commitdiff;h=b1704f17dd71abd5d4b8064019f5ecd9fcd9e9d5 Log: Issue #3, Implement pftt setup, step 1 use zip non-install package for MySQL installation support download/install VC16 remove code for sql installer which will never be used rename from VC16 to VS16 Bugs: https://bugs.php.net/3 Changed paths: M .gitignore M src/com/mostc/pftt/host/Host.java M src/com/mostc/pftt/main/PfttMain.java M src/com/mostc/pftt/model/core/EBuildBranch.java M src/com/mostc/pftt/model/core/PhpBuild.java M src/com/mostc/pftt/util/DownloadUtil.java M src/com/mostc/pftt/util/HostEnvUtil.java
diff --git a/.gitignore b/.gitignore index 638851d..80b9c7c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,8 @@ src/com/sshtools/* hostkeys.txt ssh_server.jar cache/working/* +cache/dep/* jre/* -/build/ +job_work/* +.metadata/* +pftt_release.zip \ No newline at end of file diff --git a/src/com/mostc/pftt/host/Host.java b/src/com/mostc/pftt/host/Host.java index edecc47..93657ed 100644 --- a/src/com/mostc/pftt/host/Host.java +++ b/src/com/mostc/pftt/host/Host.java @@ -25,6 +25,8 @@ public abstract class Host { /** should always have a timeout... should NOT let something run forever */ public static final int FOUR_HOURS = ONE_HOUR * 4; public static final int ONE_MINUTE = 60; + public static final int TEN_MINUTES = ONE_MINUTE * 10; + public static final int TWENTY_MINUTES = TEN_MINUTES * 2; protected static final int NO_TIMEOUT = 0; /** put PATH in the ENV vars you pass to #exec and it will automatically add that * value to the system's PATH (takes care of merging it for you, so it won't be completely overridden) diff --git a/src/com/mostc/pftt/main/PfttMain.java b/src/com/mostc/pftt/main/PfttMain.java index 941163e..c28e7db 100644 --- a/src/com/mostc/pftt/main/PfttMain.java +++ b/src/com/mostc/pftt/main/PfttMain.java @@ -501,6 +501,14 @@ public class PfttMain { return config==null?ScenarioSet.getDefaultScenarioSets():config.getScenarioSets(layer); } + private PhpBuild setupBuild; + protected void ensureLocalhostSetup(PhpBuild build) throws Exception { + if (setupBuild==build) + return; + HostEnvUtil.setupHostEnv(fs, host, cm, build); + setupBuild = build; + } + private PhpBuild prepared; protected void ensureLocalhostPrepared(PhpBuild build) throws Exception { if (prepared==build) @@ -1978,6 +1986,9 @@ public class PfttMain { checkUAC(is_uac, true, config, cm, EScenarioSetPermutationLayer.PRODUCTION_OR_ALL_UP_TEST); + // setup host environment + p.ensureLocalhostSetup(build); + // setup all scenarios PhpIni ini; ScenarioSetSetup setup = null; diff --git a/src/com/mostc/pftt/model/core/EBuildBranch.java b/src/com/mostc/pftt/model/core/EBuildBranch.java index 7edd966..f6ccf64 100644 --- a/src/com/mostc/pftt/model/core/EBuildBranch.java +++ b/src/com/mostc/pftt/model/core/EBuildBranch.java @@ -69,6 +69,18 @@ public enum EBuildBranch { return null; // could be X86 or X64 } }, + PHP_7_4 { + @Override + public ECPUArch getCPUArch() { + return null; // could be X86 or X64 + } + }, + PHP_8_0 { + @Override + public ECPUArch getCPUArch() { + return null; // could be X86 or X64 + } + }, STR_SIZE_AND_INT64 { @Override public ECPUArch getCPUArch() { diff --git a/src/com/mostc/pftt/model/core/PhpBuild.java b/src/com/mostc/pftt/model/core/PhpBuild.java index f0161b5..036999c 100644 --- a/src/com/mostc/pftt/model/core/PhpBuild.java +++ b/src/com/mostc/pftt/model/core/PhpBuild.java @@ -517,6 +517,15 @@ public class PhpBuild extends SAPIManager { case 3: branch = EBuildBranch.PHP_7_3; break; + case 4: + branch = EBuildBranch.PHP_7_4; + break; + } + } else if (major == 8) { + switch(minor) { + case 0: + branch = EBuildBranch.PHP_8_0; + break; } } diff --git a/src/com/mostc/pftt/util/DownloadUtil.java b/src/com/mostc/pftt/util/DownloadUtil.java index 880648d..0e7a545 100644 --- a/src/com/mostc/pftt/util/DownloadUtil.java +++ b/src/com/mostc/pftt/util/DownloadUtil.java @@ -1,14 +1,17 @@ package com.mostc.pftt.util; +import java.io.File; import java.io.FileOutputStream; import java.net.Socket; import java.net.URL; import org.apache.http.ConnectionReuseStrategy; +import org.apache.http.Header; import org.apache.http.HttpHost; import org.apache.http.HttpRequestInterceptor; import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; +import org.apache.http.StatusLine; import org.apache.http.impl.DefaultConnectionReuseStrategy; import org.apache.http.impl.DefaultHttpClientConnection; import org.apache.http.message.BasicHttpRequest; @@ -46,6 +49,52 @@ public class DownloadUtil { public static boolean downloadAndUnzip(ConsoleManager cm, Host host, URL remote_url, String local_dir) { String local_file_zip = host.mCreateTempName("Download", ".zip"); + if(!downloadFile(cm, remote_url, local_file_zip)) + { + return false; + } + + // decompress local_file_zip + try { + host.mCreateDirs(local_dir); + + System.out.println("PFTT: release_get: decompressing "+local_file_zip+"..."); + + return host.unzip(cm, local_file_zip, local_dir); + } catch ( Exception ex ) { + cm.addGlobalException(EPrintType.CANT_CONTINUE, DownloadUtil.class, "downloadAndUnzip", ex, ""); + return false; + } + } // end public static boolean downloadAndUnzip + + public static boolean downloadFile(ConsoleManager cm, String remote_url, String local_file_name) { + try { + cm.println(EPrintType.CLUE, DownloadUtil.class, "Downloading from ["+remote_url.toString()+"] as ["+local_file_name+"]"); + return downloadFile(cm, new URL(remote_url), local_file_name); + } catch ( Exception ex ) { + cm.addGlobalException(EPrintType.CANT_CONTINUE, DownloadUtil.class, "downloadFile", ex, ""); + return false; + } + } + + private static final int MAX_REDIRECT = 5; + /** + * @param cm + * @param remote_url + * @param local_file_name + */ + public static boolean downloadFile(ConsoleManager cm, URL remote_url, String local_file_name) + { + return downloadFile(cm, remote_url, local_file_name, 0); + } + + private static boolean downloadFile(ConsoleManager cm, URL remote_url, String local_file_name, int redirect) { + if(redirect > MAX_REDIRECT) + { + cm.println(EPrintType.CANT_CONTINUE, DownloadUtil.class, "Exceeding maximal redirects" + MAX_REDIRECT + " for downloading [" + remote_url + "]"); + return false; + } + HttpParams params = new SyncBasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, "UTF-8"); @@ -84,35 +133,57 @@ public class DownloadUtil { response.setParams(params); httpexecutor.postProcess(response, httpproc, context); - FileOutputStream out_file = new FileOutputStream(local_file_zip); + StatusLine statusLine = response.getStatusLine(); + int statusCode = statusLine.getStatusCode(); + if( statusCode != 200) + { + switch(statusCode) + { + // Handling redirects + case 301: // 301 Moved Permanently + case 302: // 302 Found or originally temporary redirect + case 303: // 303 see other + case 307: // 307 temporary redirect + case 308: // 308 permanent redirect + Header[] locations = response.getHeaders("Location"); + for(int i = 0; i < locations.length; i++) + { + String redirectedUrl = locations[i].getValue(); + cm.println(EPrintType.CLUE, DownloadUtil.class, "Redirecting from ["+remote_url.toString()+"] to ["+redirectedUrl+"], redirect count =" + redirect++); + if(downloadFile(cm, new URL(redirectedUrl), local_file_name, redirect)) + { + return true; + } + } + break; + } + + throw new Exception("Error downloading file from [" + remote_url + "] with status " + statusLine.toString()); + + } + + File local_file = new File(local_file_name); + // create parent directories if not exists + local_file.getParentFile().mkdirs(); + + FileOutputStream out_file = new FileOutputStream(local_file_name); IOUtil.copy(response.getEntity().getContent(), out_file, IOUtil.UNLIMITED); out_file.close(); + return true; } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.CANT_CONTINUE, DownloadUtil.class, "downloadAndUnzip", ex, "error downloading file: "+remote_url); + cm.addGlobalException(EPrintType.CANT_CONTINUE, DownloadUtil.class, "downloadFile", ex, "error downloading file: "+remote_url); return false; } finally { if ( response == null || !connStrategy.keepAlive(response, context)) { try { conn.close(); } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.CANT_CONTINUE, DownloadUtil.class, "downloadAndUnzip", ex, ""); + cm.addGlobalException(EPrintType.CANT_CONTINUE, DownloadUtil.class, "downloadFile", ex, ""); } } } - - // decompress local_file_zip - try { - host.mCreateDirs(local_dir); - - System.out.println("PFTT: release_get: decompressing "+local_file_zip+"..."); - - return host.unzip(cm, local_file_zip, local_dir); - } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.CANT_CONTINUE, DownloadUtil.class, "downloadAndUnzip", ex, ""); - return false; - } - } // end public static boolean downloadAndUnzip + } } // end public class DownloadUtil diff --git a/src/com/mostc/pftt/util/HostEnvUtil.java b/src/com/mostc/pftt/util/HostEnvUtil.java index 98d0e52..6410b7e 100644 --- a/src/com/mostc/pftt/util/HostEnvUtil.java +++ b/src/com/mostc/pftt/util/HostEnvUtil.java @@ -1,6 +1,10 @@ package com.mostc.pftt.util; +import java.io.File; import java.io.IOException; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.nio.file.*; import com.github.mattficken.io.StringUtil; import com.mostc.pftt.host.ExecOutput; @@ -9,7 +13,17 @@ import com.mostc.pftt.host.LocalHost; import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.EPrintType; +import com.mostc.pftt.results.LocalConsoleManager; import com.mostc.pftt.scenario.FileSystemScenario; +import com.mostc.pftt.scenario.LocalFileSystemScenario; +import com.sun.corba.se.impl.orbutil.closure.Future; +import com.sun.jna.Memory; +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.VerRsrc.VS_FIXEDFILEINFO; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.PointerByReference; + +import groovy.lang.Tuple; /** Utilities for setting up the test environment and convenience settings on Hosts * @@ -18,6 +32,70 @@ import com.mostc.pftt.scenario.FileSystemScenario; */ public final class HostEnvUtil { + + static final String Link_VC9_Redist_X86 + = "https://download.microsoft.com/download/1/1/1/1116b75a-9ec3-481a-a3c8-1777b5381140/vcredist_x86.exe"; + static final String Link_VC10_Redist_X86 + = "https://download.microsoft.com/download/5/B/C/5BC5DBB3-652D-4DCE-B14A-475AB85EEF6E/vcredist_x86.exe"; + static final String Link_VC10_Redist_X64 + = "https://download.microsoft.com/download/3/2/2/3224B87F-CFA0-4E70-BDA3-3DE650EFEBA5/vcredist_x64.exe"; + static final String Link_VC11_Redist_X86 + = "https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe"; + static final String Link_VC11_Redist_X64 + = "https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe"; + static final String Link_VC14_Redist_X86 + = "https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x86.exe"; + static final String Link_VC14_Redist_X64 + = "https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe"; + static final String Link_VC15_Redist_X86 + = "https://aka.ms/vs/15/release/VC_redist.x86.exe"; + static final String Link_VC15_Redist_X64 + = "https://aka.ms/vs/15/release/VC_redist.x64.exe"; + static final String Link_VS16_Redist_X86 + = "https://aka.ms/vs/16/release/VC_redist.x86.exe"; + static final String Link_VS16_Redist_X64 + = "https://aka.ms/vs/16/release/VC_redist.x64.exe"; + static final String Link_Mysql_Win32_5_7_25 + = "https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.25-win32.zip"; + + + static final String Dir_Cache_Dep = LocalHost.getLocalPfttDir() + "\\cache\\dep"; + static final String Dir_Cache_Dep_VCRedist = Dir_Cache_Dep + "\\VCRedist"; + static final String Dir_Cache_Dep_Mysql = Dir_Cache_Dep + "\\MySql"; + static final String File_VC9_Redist_X86 = Dir_Cache_Dep_VCRedist + "\\vc9_redist_x86.exe"; + static final String File_VC10_Redist_X86 = Dir_Cache_Dep_VCRedist + "\\vc10_redist_x86.exe"; + static final String File_VC10_Redist_X64 = Dir_Cache_Dep_VCRedist + "\\vc10_redist_x64.exe"; + static final String File_VC11_Redist_X86 = Dir_Cache_Dep_VCRedist + "\\vc11_redist_x86.exe"; + static final String File_VC11_Redist_X64 = Dir_Cache_Dep_VCRedist + "\\vc11_redist_x64.exe"; + static final String File_VC12_Redist_X86 = Dir_Cache_Dep_VCRedist + "\\vc12_redist_x86.exe"; + static final String File_VC12_Redist_X64 = Dir_Cache_Dep_VCRedist + "\\vc12_redist_x64.exe"; + static final String File_VC14_Redist_X86 = Dir_Cache_Dep_VCRedist + "\\vc14_redist_x86.exe"; + static final String File_VC14_Redist_X64 = Dir_Cache_Dep_VCRedist + "\\vc14_redist_x64.exe"; + static final String File_VC15_Redist_X86 = Dir_Cache_Dep_VCRedist + "\\vc15_redist_x86.exe"; + static final String File_VC15_Redist_X64 = Dir_Cache_Dep_VCRedist + "\\vc15_redist_x64.exe"; + static final String File_VS16_Redist_X86 = Dir_Cache_Dep_VCRedist + "\\vc_vs16_redist_x86.exe"; + static final String File_VS16_Redist_X64 = Dir_Cache_Dep_VCRedist + "\\vc_vs16_redist_x64.exe"; + + static final String Dir_Mysql = "C:\\MySQL"; + static final String Dir_Mysql_5_7 = Dir_Mysql + "\\mysql-5.7.25-win32"; + static final String Dir_Mysql_5_7_bin = Dir_Mysql_5_7 + "\\bin"; + static final String Exe_Mysql_5_7_mysqld = Dir_Mysql_5_7_bin + "\\mysqld.exe"; + static final String Exe_Mysql_5_7_mysql = Dir_Mysql_5_7_bin + "\\mysql.exe"; + + static final String Dir_WinSxS = "\\WinSxS"; + static final String WinSxS_VC9_Fragment = "VC9"; + + static final String Dir_System32 = "\\system32"; + static final String Dir_SysWOW64 = "\\SysWOW64"; + static final String Sys_Dll_VC10_Redist_X86 = Dir_System32 + "\\msvcr100.dll"; + static final String Sys_Dll_VC10_Redist_X64 = Dir_SysWOW64 + "\\msvcr100.dll"; + static final String Sys_Dll_VC11_Redist_X86 = Dir_System32 + "\\msvcr110.dll"; + static final String Sys_Dll_VC11_Redist_X64 = Dir_SysWOW64 + "\\msvcr110.dll"; + static final String Sys_Dll_VC12_Redist_X86 = Dir_System32 + "\\msvcr120.dll"; + static final String Sys_Dll_VC12_Redist_X64 = Dir_SysWOW64 + "\\msvcr120.dll"; + // Note: VC15 and VC16 will have the same dll name with VC14, but different version to be backward compatible + static final String Sys_Dll_VC14Plus_Redist_X86 = Dir_System32 + "\\vcruntime140.dll"; + static final String Sys_Dll_VC14Plus_Redist_X64 = Dir_SysWOW64 + "\\vcruntime140.dll"; public static void prepareHostEnv(FileSystemScenario fs, AHost host, ConsoleManager cm, PhpBuild build, boolean enable_debug_prompt) throws Exception { if (host.isWindows()) { @@ -120,15 +198,85 @@ public final class HostEnvUtil { // share PHP-SDK over network. this also will share C$, G$, etc... //host.execElevated(cm, HostEnvUtil.class, "NET SHARE PHP_SDK="+host.getJobWorkDir()+" /Grant:"+host.getUsername()+",Full", AHost.ONE_MINUTE); } - + installVCRuntime(fs, host, cm, build); + + installAndConfigureMySql(fs, host, cm); + cm.println(EPrintType.COMPLETED_OPERATION, HostEnvUtil.class, "Windows host prepared to run PHP."); } // end public static void prepareWindows + private static void installAndConfigureMySql(FileSystemScenario fs, AHost host, ConsoleManager cm) throws IllegalStateException, IOException, Exception { + + if(!fs.exists(Exe_Mysql_5_7_mysqld)) + { + cm.println(EPrintType.WARNING, HostEnvUtil.class, "MySql 5.7.25.0 is not downloaded, should run setup command first..."); + return; + } + + ExecOutput op = host.execOut("sc.exe query MySQL", AHost.TEN_MINUTES); + + if(op.output.contains("RUNNING")) + { + cm.println(EPrintType.WARNING, HostEnvUtil.class, "MySql service is already running."); + return; + } + + if(op.output.contains("EnumQueryServicesStatus:OpenService FAILED")) + { + // creating data directly for MySQL service + cm.println(EPrintType.IN_PROGRESS, HostEnvUtil.class, "Creating data folder for MySql Server 5.7.25.0"); + String data_dir = Dir_Mysql_5_7 + "\\data"; + createDirectoryIfNotExists(fs, cm, data_dir); + + // Install the MySQL service + cm.println(EPrintType.IN_PROGRESS, HostEnvUtil.class, "Installing MySQL as a windows service"); + // mysqld.exe --install + host.execOut("\"" + Exe_Mysql_5_7_mysqld + "\" --install", AHost.TEN_MINUTES); + + // initialize the MySQL service + cm.println(EPrintType.IN_PROGRESS, HostEnvUtil.class, "Initializing MySQL service"); + // mysqld.exe --initialize-insecure + ExecOutput output = host.execOut("\"" + Exe_Mysql_5_7_mysqld + "\" --initialize-insecure", AHost.TEN_MINUTES); + cm.println(EPrintType.CLUE, HostEnvUtil.class, output.output); + } + + // Start the MySQL service + cm.println(EPrintType.IN_PROGRESS, HostEnvUtil.class, "Starting MySQL service"); + // start MySQL service using sc.exe + // sc start MySQL + host.execOut("sc.exe start MySQL", AHost.TEN_MINUTES); + + // Create database "test" if not exist + // mysql -u root -e "create database if not exists test" + cm.println(EPrintType.IN_PROGRESS, HostEnvUtil.class, "Creating test database on MySQL server"); + host.execOut("\"" + Exe_Mysql_5_7_mysql + "\" -u root -e \"create database if not exists test\"", AHost.TEN_MINUTES); + } + + /** + * @param fs + * @param cm + * @param dir_path + */ + private static void createDirectoryIfNotExists(FileSystemScenario fs, ConsoleManager cm, String dir_path) { + if(!fs.exists(dir_path)) + { + File data_dir_file = new File(dir_path); + // attempt to create the directory here + boolean successful = data_dir_file.mkdirs(); + if (!successful) + { + cm.println(EPrintType.WARNING, HostEnvUtil.class, "Failed create directory " + dir_path); + return; + } + } + } + /** PHP on Windows requires Microsoft's VC Runtime to be installed. This method ensures that the correct version is installed. * * PHP 5.3 and 5.4 require the VC9 x86 Runtime * PHP 5.5+ require the VC11 x86 Runtime + * PHP 7.0+ require the VC14 x86 Runtime * * Windows 8+ already has the VC9 x86 Runtime * @@ -143,49 +291,204 @@ public final class HostEnvUtil { if (!host.isWindows()) { return; } - + switch (build.getVersionBranch(cm, host)) { case PHP_5_3: case PHP_5_4: installVCRT9(cm, fs, host); break; - case PHP_7_0: - case PHP_Master: - // TODO install VC14 CRT case PHP_5_5: case PHP_5_6: - default: - installVCRT9(cm, fs, host); // just in case - installVCRT(cm, fs, host, "VC10 x86", "msvcr100.dll", "vc10_redist_x86.exe"); - installVCRT(cm, fs, host, "VC11 x86", "msvcr110.dll", "vc11_redist_x86.exe"); + installVCRT(cm, fs, host, "VC10 x86", File_VC10_Redist_X86, Sys_Dll_VC10_Redist_X86); + installVCRT(cm, fs, host, "VC11 x86", File_VC11_Redist_X86, Sys_Dll_VC11_Redist_X86); + if (build.isX64()) { + installVCRT(cm, fs, host, "VC10 x64", File_VC10_Redist_X64, Sys_Dll_VC10_Redist_X64); + installVCRT(cm, fs, host, "VC11 x64", File_VC11_Redist_X64, Sys_Dll_VC11_Redist_X64); + } + break; + case PHP_7_0: + case PHP_7_1: + installVCRT14(cm, fs, host, "VC14 x86", File_VC14_Redist_X86, Sys_Dll_VC14Plus_Redist_X86); + if (build.isX64()) { + installVCRT14(cm, fs, host, "VC14 x64", File_VC14_Redist_X64, Sys_Dll_VC14Plus_Redist_X64); + } + break; + case PHP_7_2: + case PHP_7_3: + installVCRT15(cm, fs, host, "VC15 x86", File_VC15_Redist_X86, Sys_Dll_VC14Plus_Redist_X86); + if (build.isX64()) { + installVCRT15(cm, fs, host, "VC15 x64", File_VC15_Redist_X64, Sys_Dll_VC14Plus_Redist_X64); + } + break; + case PHP_7_4: + case PHP_8_0: + case PHP_Master: + default: + installVCRT16(cm, fs, host, "VS16 x86", File_VS16_Redist_X86, Sys_Dll_VC14Plus_Redist_X86); if (build.isX64()) { - installVCRT(cm, fs, host, "VC10 x64", "msvcr100.dll", "vc10_redist_x64.exe"); - installVCRT(cm, fs, host, "VC11 x64", "msvcr110.dll", "vc11_redist_x64.exe"); + installVCRT16(cm, fs, host, "VS16 x64", File_VS16_Redist_X64, Sys_Dll_VC14Plus_Redist_X64); } break; } // end switch } // end public static void installVCRuntime - protected static void installVCRT9(ConsoleManager cm, FileSystemScenario fs, AHost host) throws IllegalStateException, IOException, Exception { + + protected static boolean installedVCRT9(AHost host) + { // with VC9 (and before), checking WinSXS directory is the only way to tell - if (host.mDirContainsFragment(host.getSystemRoot()+"\\WinSxS", "VC9")) { + return host.mDirContainsFragment(host.getSystemRoot() + Dir_WinSxS, WinSxS_VC9_Fragment); + } + + + protected static void installVCRT9(ConsoleManager cm, FileSystemScenario fs, AHost host) throws IllegalStateException, IOException, Exception { + + if (installedVCRT9(host)) { cm.println(EPrintType.CLUE, HostEnvUtil.class, "VC9 Runtime already installed"); } else { doInstallVCRT(cm, fs, host, "VC9", "vc9_redist_x86.exe"); } } - - protected static void installVCRT(ConsoleManager cm, FileSystemScenario fs, AHost host, String name, String dll_name, String filename) throws IllegalStateException, IOException, Exception { + + protected static void installVCRT(ConsoleManager cm, FileSystemScenario fs, AHost host, String name, String installerFile, String sysDllFile) + throws IllegalStateException, IOException, Exception { // starting with VCRT10, checking the registry is the only way to tell - if (fs.exists(host.getSystemRoot()+"\\system32\\"+dll_name)) { + if (fs.exists(host.getSystemRoot() + sysDllFile)) { + cm.println(EPrintType.CLUE, HostEnvUtil.class, name+" Runtime already installed"); + } else { + doInstallVCRT(cm, fs, host, name, installerFile); + } + } + + protected static void installVCRT14(ConsoleManager cm, FileSystemScenario fs, AHost host, String name, String installerFile, String sysDllFile) + throws IllegalStateException, IOException, Exception { + + String dllFullName = host.getSystemRoot() + sysDllFile; + if(installedVCRT14(fs, dllFullName)) { + cm.println(EPrintType.CLUE, HostEnvUtil.class, name+" Runtime already installed"); + } + else { + doInstallVCRT(cm, fs, host, name, installerFile); + } + } + + protected static void installVCRT15(ConsoleManager cm, FileSystemScenario fs, AHost host, String name, String installerFile, String sysDllFile) + throws IllegalStateException, IOException, Exception { + + String dllFullName = host.getSystemRoot() + sysDllFile; + if(installedVCRT15(fs, dllFullName)) { + cm.println(EPrintType.CLUE, HostEnvUtil.class, name+" Runtime already installed"); + } + else { + doInstallVCRT(cm, fs, host, name, installerFile); + } + } + + protected static void installVCRT16(ConsoleManager cm, FileSystemScenario fs, AHost host, String name, String installerFile, String sysDllFile) + throws IllegalStateException, IOException, Exception { + + if(installedVCRT16(fs, host.getSystemRoot() + sysDllFile)) { cm.println(EPrintType.CLUE, HostEnvUtil.class, name+" Runtime already installed"); } else { - doInstallVCRT(cm, fs, host, name, filename); + doInstallVCRT(cm, fs, host, name, installerFile); + } + } + + // checking if VCRT15 is installed by existing of the vcruntime140.dll and the file version + private static boolean installedVCRT14(FileSystemScenario fs, String dllFile) + { + if(!fs.exists(dllFile)) + { + return false; + } + + int[] fileVersion = getVC14Version(fs, dllFile); + if(fileVersion.length != 4) + { + return false; } + + // VC14 Runtime dll file version: 14.0.23026.0 + return fileVersion[0] == 14 && fileVersion[1] > 0; } - protected static void doInstallVCRT(ConsoleManager cm, FileSystemScenario fs, AHost host, String name, String filename) throws IllegalStateException, IOException, Exception { - String local_file = LocalHost.getLocalPfttDir()+"/cache/dep/VCRedist/"+filename; + // checking if VCRT15 is installed by existing of the vcruntime140.dll and the file version + private static boolean installedVCRT15(FileSystemScenario fs, String dllFile) + { + if(!fs.exists(dllFile)) + { + return false; + } + + int[] fileVersion = getVC14Version(fs, dllFile); + if(fileVersion.length != 4) + { + return false; + } + + // VC15 Runtime dll file version: 14.16.27027.1 + return fileVersion[0] == 14 && fileVersion[1] >= 16; + } + + // checking if VCRT15 is installed by existing of the vcruntime140.dll and the file version + private static boolean installedVCRT16(FileSystemScenario fs, String dllFile) + { + if(!fs.exists(dllFile)) + { + return false; + } + + int[] fileVersion = getVC14Version(fs, dllFile); + if(fileVersion.length != 4) + { + return false; + } + + // VC16 Runtime dll file version: 14.20.27508.1 + return fileVersion[0] == 14 && fileVersion[1] >= 20; + } + + // checking if VCRT15 is installed by existing of the vcruntime140.dll and the file version + private static int[] getVC14Version(FileSystemScenario fs, String dllFile) + { + if(!fs.exists(dllFile)) + { + return new int[0]; + } + + IntByReference dwDummy = new IntByReference(); + dwDummy.setValue(0); + + int versionlength = + com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfoSize( + dllFile, dwDummy); + + byte[] bufferarray = new byte[versionlength]; + Pointer lpData = new Memory(bufferarray.length); + PointerByReference lplpBuffer = new PointerByReference(); + IntByReference puLen = new IntByReference(); + + boolean fileInfoResult = + com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfo( + dllFile, 0, versionlength, lpData); + + boolean verQueryVal = + com.sun.jna.platform.win32.Version.INSTANCE.VerQueryValue( + lpData, "\\", lplpBuffer, puLen); + + VS_FIXEDFILEINFO lplpBufStructure = new VS_FIXEDFILEINFO(lplpBuffer.getValue()); + lplpBufStructure.read(); + + int v1 = (lplpBufStructure.dwFileVersionMS).intValue() >> 16; + int v2 = (lplpBufStructure.dwFileVersionMS).intValue() & 0xffff; + int v3 = (lplpBufStructure.dwFileVersionLS).intValue() >> 16; + int v4 = (lplpBufStructure.dwFileVersionLS).intValue() & 0xffff; + + return new int[] {v1, v2, v3, v4}; + } + + + protected static void doInstallVCRT(ConsoleManager cm, FileSystemScenario fs, AHost host, String name, String installerFile) throws IllegalStateException, IOException, Exception { + String local_file = LocalHost.getLocalPfttDir() + installerFile; String remote_file = local_file; if (host.isRemote()) { remote_file = fs.mktempname(HostEnvUtil.class, ".exe"); @@ -194,7 +497,7 @@ public final class HostEnvUtil { host.upload(local_file, remote_file); } cm.println(EPrintType.IN_PROGRESS, HostEnvUtil.class, "Installing "+name+" Runtime"); - host.execElevated(cm, HostEnvUtil.class, remote_file+" /Q /NORESTART", AHost.FOUR_HOURS); + host.execElevated(cm, HostEnvUtil.class, remote_file+" /Q /NORESTART", AHost.TEN_MINUTES); if (remote_file!=null) fs.delete(remote_file); } @@ -250,7 +553,165 @@ public final class HostEnvUtil { public static boolean regDel(ConsoleManager cm, AHost host, String key, String value_name) throws Exception { return host.execElevated(cm, HostEnvUtil.class, "REG DELETE \""+key+"\" /v "+value_name + " /f", AHost.ONE_MINUTE); } + + public static void setupHostEnv(FileSystemScenario fs, LocalHost host, LocalConsoleManager cm, PhpBuild build) + throws IllegalStateException, IOException, Exception { + if (host.isWindows()) { + setupWindows(fs, host, cm, build); + } else { + // TODO: setup none windows environment + } + } + + private static void setupWindows(FileSystemScenario fs, LocalHost host, LocalConsoleManager cm, PhpBuild build) + throws IllegalStateException, IOException, Exception { + + downloadVCRuntimeByBuild(fs, host, cm, build); + + downloadMySQL5(fs, host, cm); + + cm.println(EPrintType.COMPLETED_OPERATION, HostEnvUtil.class, "Windows host setup to run PHP."); + } + + private static void downloadMySQL5(FileSystemScenario fs, LocalHost host, LocalConsoleManager cm) { + + if(!fs.exists(Exe_Mysql_5_7_mysqld)) + { + // download MySQL and unzip + createDirectoryIfNotExists(fs, cm, Dir_Mysql); + DownloadUtil.downloadAndUnzip(cm, host, Link_Mysql_Win32_5_7_25, Dir_Mysql); + } + else + { + cm.println(EPrintType.CLUE, HostEnvUtil.class, "MySQL 5.7.25 is already downloaded."); + } + } + + private static void downloadVCRuntimeByBuild(FileSystemScenario fs, LocalHost host, LocalConsoleManager cm, + PhpBuild build) + throws IllegalStateException, IOException, Exception { + if (!host.isWindows()) { + return; + } + + String system_dir = host.getSystemRoot(); + switch (build.getVersionBranch(cm, host)) { + case PHP_5_3: + case PHP_5_4: + downloadVCRuntime9(fs, host, cm); + break; + case PHP_5_5: + case PHP_5_6: + downloadVCRuntime(fs, cm, "VC10 x86", Link_VC10_Redist_X86, File_VC10_Redist_X86, system_dir + Sys_Dll_VC10_Redist_X86); + downloadVCRuntime(fs, cm, "VC11 x86", Link_VC11_Redist_X86, File_VC11_Redist_X86, system_dir + Sys_Dll_VC11_Redist_X86); + if (build.isX64()) { + downloadVCRuntime(fs, cm, "VC10 x64", Link_VC10_Redist_X64, File_VC10_Redist_X64, system_dir + Sys_Dll_VC10_Redist_X64); + downloadVCRuntime(fs, cm, "VC11 x64", Link_VC11_Redist_X64, File_VC11_Redist_X64, system_dir + Sys_Dll_VC11_Redist_X64); + } + break; + case PHP_7_0: + case PHP_7_1: + downloadVC14Runtime(fs, cm, "VC14 x86", Link_VC14_Redist_X86, File_VC14_Redist_X86, system_dir + Sys_Dll_VC14Plus_Redist_X86); + if (build.isX64()) { + downloadVC14Runtime(fs, cm, "VC14 x64", Link_VC14_Redist_X64, File_VC14_Redist_X64, system_dir + Sys_Dll_VC14Plus_Redist_X64); + } + break; + case PHP_7_2: + case PHP_7_3: + downloadVC15Runtime(fs, cm, "VC15 x86", Link_VC15_Redist_X86, File_VC15_Redist_X86, system_dir + Sys_Dll_VC14Plus_Redist_X86); + if (build.isX64()) { + downloadVC15Runtime(fs, cm, "VC15 x64", Link_VC15_Redist_X64, File_VC15_Redist_X64, system_dir + Sys_Dll_VC14Plus_Redist_X64); + } + break; + case PHP_7_4: + case PHP_8_0: + case PHP_Master: + default: + downloadVC16Runtime(fs, cm, "VS16 x86", Link_VS16_Redist_X86, File_VS16_Redist_X86, system_dir + Sys_Dll_VC14Plus_Redist_X86); + if (build.isX64()) { + downloadVC16Runtime(fs, cm, "VS16 x64", Link_VS16_Redist_X64, File_VS16_Redist_X64, system_dir + Sys_Dll_VC14Plus_Redist_X64); + } + break; + } // end switch + } + private static void downloadVCRuntime9(FileSystemScenario fs, LocalHost host, LocalConsoleManager cm) + { + if (installedVCRT9(host)) { + cm.println(EPrintType.CLUE, HostEnvUtil.class, "VC9 Runtime already installed, skip downloading."); + } + else + { + String pftt_dir = LocalHost.getLocalPfttDir(); + downloadFile(fs, cm, "VC9 Runtime", Link_VC9_Redist_X86, pftt_dir + File_VC9_Redist_X86); + } + } + + private static void downloadVC14Runtime(FileSystemScenario fs, LocalConsoleManager cm, + String name, String remote_url, String installer_file, String dll_file) + { + if(installedVCRT14(fs, dll_file)) + { + cm.println(EPrintType.CLUE, HostEnvUtil.class, name + " Runtime already installed, skip downloading."); + } + else + { + downloadFile(fs, cm, name, remote_url, installer_file); + } + } + + private static void downloadVC15Runtime(FileSystemScenario fs, LocalConsoleManager cm, + String name, String remote_url, String installer_file, String dll_file) + { + if(installedVCRT15(fs, dll_file)) + { + cm.println(EPrintType.CLUE, HostEnvUtil.class, name + " Runtime already installed, skip downloading."); + } + else + { + downloadFile(fs, cm, name, remote_url, installer_file); + } + } + + + private static void downloadVC16Runtime(FileSystemScenario fs, LocalConsoleManager cm, + String name, String remote_url, String installer_file, String dll_file) + { + if(installedVCRT16(fs, dll_file)) + { + cm.println(EPrintType.CLUE, HostEnvUtil.class, name + " Runtime already installed, skip downloading."); + } + else + { + downloadFile(fs, cm, name, remote_url, installer_file); + } + } + + private static void downloadVCRuntime(FileSystemScenario fs, LocalConsoleManager cm, + String name, String remote_url, String installer_file, String dll_file) + { + if(fs.exists(dll_file)) + { + cm.println(EPrintType.CLUE, HostEnvUtil.class, name + " Runtime already installed, skip downloading."); + } + else + { + downloadFile(fs, cm, name, remote_url, installer_file); + } + } + + private static void downloadFile(FileSystemScenario fs, LocalConsoleManager cm, + String name, String remote_url, String local_file) + { + if(fs.exists(local_file)) + { + cm.println(EPrintType.CLUE, HostEnvUtil.class, name + " Installer [" + local_file + "] already downloaded."); + } + else + { + DownloadUtil.downloadFile(cm, remote_url, local_file); + } + } private HostEnvUtil() {}