public static List <LogInfo> CopyOrExpand(EngineState s, CodeCommand cmd) { List <LogInfo> logs = new List <LogInfo>(); Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_CopyOrExpand)); CodeInfo_CopyOrExpand info = cmd.Info as CodeInfo_CopyOrExpand; string srcFile = StringEscaper.Preprocess(s, info.SrcFile); string destPath = StringEscaper.Preprocess(s, info.DestPath); // Path Security Check if (StringEscaper.PathSecurityCheck(destPath, out string errorMsg) == false) { logs.Add(new LogInfo(LogState.Error, errorMsg)); return(logs); } // Check srcFile contains wildcard if (srcFile.IndexOfAny(new char[] { '*', '?' }) == -1) { // No Wildcard InternalCopyOrExpand(s, logs, info, srcFile, destPath); } else { // With Wildcard string srcDirToFind = FileHelper.GetDirNameEx(srcFile); string[] files = FileHelper.GetFilesEx(srcDirToFind, Path.GetFileName(srcFile)); if (0 < files.Length) { // One or more file will be copied logs.Add(new LogInfo(LogState.Success, $"[{srcFile}] will be copied to [{destPath}]", cmd)); for (int i = 0; i < files.Length; i++) { string f = files[i]; InternalCopyOrExpand(s, logs, info, f, destPath); } logs.Add(new LogInfo(LogState.Success, $"[{files.Length}] files copied", cmd)); } else { // No file will be copied logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Warning, $"Files match wildcard [{srcFile}] not found", cmd)); } } return(logs); }
public static List <LogInfo> CopyOrExpand(EngineState s, CodeCommand cmd) { List <LogInfo> logs = new List <LogInfo>(); CodeInfo_CopyOrExpand info = cmd.Info.Cast <CodeInfo_CopyOrExpand>(); #region Event Handlers void ReportExpandProgress(object sender, ProgressEventArgs e) { s.MainViewModel.BuildCommandProgressValue = e.PercentDone; s.MainViewModel.BuildCommandProgressText = $"Expanding... ({e.PercentDone}%)"; } #endregion string srcFile = StringEscaper.Preprocess(s, info.SrcFile); string destPath = StringEscaper.Preprocess(s, info.DestPath); Debug.Assert(srcFile != null, $"{nameof(srcFile)} != null"); Debug.Assert(destPath != null, $"{nameof(destPath)} != null"); // Path Security Check if (!StringEscaper.PathSecurityCheck(destPath, out string errorMsg)) { return(LogInfo.LogErrorMessage(logs, errorMsg)); } string srcFileName = Path.GetFileName(srcFile); string srcFileExt = Path.GetExtension(srcFile); if (!Directory.Exists(destPath)) { if (File.Exists(destPath)) { if (info.Preserve) { logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Overwrite, $"File [{destPath}] already exists and will not be overwritten")); return(logs); } logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Overwrite, $"File [{destPath}] already exists and will be overwritten")); } } // Get destFullPath. It should be a file. string destDir; string destFullPath; if (Directory.Exists(destPath)) { destDir = destPath; destFullPath = Path.Combine(destPath, srcFileName); } else // Move to new name { destDir = FileHelper.GetDirNameEx(destPath); destFullPath = destPath; } Directory.CreateDirectory(destDir); // Check wildcard // WinBuilder082 behavior // - Some files are matched with wildcard : Reports success, but no files are copied. // - No files are matched with wildcard : Reports error. string wildcard = Path.GetFileName(srcFile); if (wildcard.IndexOfAny(new char[] { '*', '?' }) != -1) { logs.Add(new LogInfo(LogState.Warning, "CopyOrExpand does not support filename with wildcard")); return(logs); } // Copy or Expand srcFile. if (File.Exists(srcFile)) { // SrcFile is uncompressed, just copy! File.Copy(srcFile, destFullPath, !info.Preserve); logs.Add(new LogInfo(LogState.Success, $"[{srcFile}] copied to [{destPath}]")); } else { // Extract Cabinet from _ (Ex) EXPLORER.EX_ -> EXPLORER.EXE // Terminate if a file does not have equivalent cabinet file if (srcFileExt.Length == ".".Length) { return(logs); } string srcCabExt = srcFileExt.Substring(0, srcFileExt.Length - 1) + "_"; string srcCab = srcFile.Substring(0, srcFile.Length - srcCabExt.Length) + srcCabExt; if (File.Exists(srcCab)) { // Turn on report progress only if file is larger than 1MB FileInfo fi = new FileInfo(srcCab); bool reportProgress = 1024 * 1024 <= fi.Length; using (SevenZipExtractor extractor = new SevenZipExtractor(srcCab)) { if (extractor.Format != InArchiveFormat.Cab) { return(LogInfo.LogErrorMessage(logs, $"[{srcCab}] is not a cabinet archive")); } string[] archiveFileNames = extractor.ArchiveFileNames.ToArray(); if (archiveFileNames.Length != 1) { return(LogInfo.LogErrorMessage(logs, $"Cabinet [{srcCab}] should contain only a single file")); } if (!archiveFileNames.Contains(srcFileName, StringComparer.OrdinalIgnoreCase)) { return(LogInfo.LogErrorMessage(logs, $"Failed to extract [{srcFileName}] from [{srcCab}]")); } if (reportProgress) { extractor.Extracting += ReportExpandProgress; // Use "Expanding" instead of "CopyOrExpanding" s.MainViewModel.SetBuildCommandProgress("CopyOrExpand Progress"); } try { using (FileStream fs = new FileStream(destFullPath, FileMode.Create)) { extractor.ExtractFile(srcFileName, fs); } logs.Add(new LogInfo(LogState.Success, $"[{srcCab}] extracted to [{destFullPath}]")); } finally { extractor.Extracting -= ReportExpandProgress; // Use "Expanding" instead of "CopyOrExpanding" s.MainViewModel.ResetBuildCommandProgress(); } } } else { // Error logs.Add(new LogInfo(LogState.Error, $"The file [{srcFile}] or [{Path.GetFileName(srcCab)}] could not be found")); } } return(logs); }
private static void InternalCopyOrExpand(EngineState s, List <LogInfo> logs, CodeInfo_CopyOrExpand info, string srcFile, string destPath) { string srcFileName = Path.GetFileName(srcFile); bool destIsDir = Directory.Exists(destPath); bool destIsFile = File.Exists(destPath); if (!destIsDir) { if (destIsFile) { if (info.Preserve) { logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Warning, $"Cannot overwrite [{destPath}]")); return; } else { logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Warning, $"[{destPath}] will be overwritten")); } } } if (File.Exists(srcFile)) { // SrcFile is uncompressed, just copy! string destFullPath = destPath; if (destIsDir) { destFullPath = Path.Combine(destPath, srcFileName); } else if (!destIsFile) { Directory.CreateDirectory(FileHelper.GetDirNameEx(destPath)); } File.Copy(srcFile, destFullPath, !info.Preserve); logs.Add(new LogInfo(LogState.Success, $"[{srcFile}] copied to [{destPath}]")); } else { // Extract Cabinet from _ (Ex) EXPLORER.EX_ -> EXPLORER.EXE string destDir; if (destIsDir) { destDir = destPath; } else { destDir = Path.GetDirectoryName(destPath); } string srcCab = srcFile.Substring(0, srcFile.Length - 1) + "_"; if (File.Exists(srcCab)) { // Get Temp Dir string tempDir; { string tempDirName = Path.GetTempFileName(); File.Delete(tempDirName); tempDir = Path.Combine(Path.GetTempPath(), tempDirName); } Directory.CreateDirectory(tempDir); try { bool result; using (FileStream fs = new FileStream(srcCab, FileMode.Open, FileAccess.Read, FileShare.Read)) using (CabExtract cab = new CabExtract(fs)) { result = cab.ExtractAll(tempDir, out List <string> fileList); if (2 < fileList.Count) { // WB082 behavior : Expand/CopyOrExpand only supports single-file cabinet logs.Add(new LogInfo(LogState.Error, $"Cabinet [{srcFileName}] should contain single file")); return; } } if (result) { // Extract Success string tempFullPath = Path.Combine(tempDir, srcFileName); if (File.Exists(tempFullPath)) { string destFullPath; if (destIsDir) { destFullPath = Path.Combine(destDir, srcFileName); } else // Move to new name { destFullPath = Path.Combine(destDir, Path.GetFileName(destPath)); } if (File.Exists(destFullPath)) { logs.Add(new LogInfo(LogState.Warning, $"File [{destFullPath}] already exists, will be overwritten")); } try { if (!Directory.Exists(Path.GetDirectoryName(destFullPath))) { Directory.CreateDirectory(Path.GetDirectoryName(destFullPath)); } File.Copy(tempFullPath, destFullPath, true); logs.Add(new LogInfo(LogState.Success, $"[{srcFileName}] from [{srcCab}] extracted to [{destFullPath}]")); } finally { File.Delete(tempFullPath); } } else { // Unable to find srcFile logs.Add(new LogInfo(LogState.Error, $"Cabinet [{srcFileName}] does not contains [{Path.GetFileName(destPath)}]")); } } else { // Extract Fail logs.Add(new LogInfo(LogState.Error, $"Failed to extract [{srcCab}]")); } } finally { Directory.Delete(tempDir, true); } } else { // Error logs.Add(new LogInfo(LogState.Error, $"[{srcFile}] nor [{srcCab}] not found")); } } }