Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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"));
                }
            }
        }