Ejemplo n.º 1
0
        public static List <LogInfo> Expand(EngineState s, CodeCommand cmd)
        {
            List <LogInfo>  logs           = new List <LogInfo>();
            CodeInfo_Expand info           = cmd.Info.Cast <CodeInfo_Expand>();
            List <string>   extractedFiles = new List <string>();

            #region Event Handlers
            void ReportExpandProgress(object sender, ProgressEventArgs e)
            {
                s.MainViewModel.BuildCommandProgressValue = e.PercentDone;
                s.MainViewModel.BuildCommandProgressText  = $"Expanding... ({e.PercentDone}%)";
            }

            object trackLock = new object();
            void TrackExtractedFile(object sender, FileInfoEventArgs e)
            {
                lock (trackLock)
                    extractedFiles.Add(e.FileInfo.FileName);
            }

            #endregion

            string srcCab     = StringEscaper.Preprocess(s, info.SrcCab);
            string destDir    = StringEscaper.Preprocess(s, info.DestDir);
            string singleFile = null;
            if (info.SingleFile != null)
            {
                singleFile = StringEscaper.Preprocess(s, info.SingleFile);
            }

            // Path Security Check
            if (!StringEscaper.PathSecurityCheck(destDir, out string errorMsg))
            {
                return(LogInfo.LogErrorMessage(logs, errorMsg));
            }

            if (!Directory.Exists(destDir))
            {
                if (File.Exists(destDir))
                {
                    return(LogInfo.LogErrorMessage(logs, $"Path [{destDir}] is a file, not a directory"));
                }
                Directory.CreateDirectory(destDir);
            }

            // Does srcCab exist?
            if (!File.Exists(srcCab))
            {
                return(LogInfo.LogErrorMessage(logs, $"Cannot find [{srcCab}]"));
            }

            // Turn on report progress only if file is larger than 1MB
            FileInfo fi             = new FileInfo(srcCab);
            bool     reportProgress = 1024 * 1024 <= fi.Length;

            if (singleFile == null)
            { // No singleFile operand, extract all
                using (SevenZipExtractor extractor = new SevenZipExtractor(srcCab))
                {
                    if (extractor.Format != InArchiveFormat.Cab)
                    {
                        return(LogInfo.LogErrorMessage(logs, "Expand command must be used with cabinet archive"));
                    }

                    if (reportProgress)
                    {
                        extractor.FileExtractionFinished += TrackExtractedFile;
                        extractor.Extracting             += ReportExpandProgress;
                        s.MainViewModel.SetBuildCommandProgress("Expand Progress");
                    }
                    try
                    {
                        extractor.ExtractArchive(destDir);
                        foreach (string file in extractedFiles)
                        {
                            logs.Add(new LogInfo(LogState.Success, $"[{file}] extracted"));
                        }
                        logs.Add(new LogInfo(LogState.Success, $"[{extractedFiles.Count}] files from [{srcCab}] extracted to [{destDir}]"));
                    }
                    finally
                    {
                        if (reportProgress)
                        {
                            extractor.FileExtractionFinished -= TrackExtractedFile;
                            extractor.Extracting             -= ReportExpandProgress;
                            s.MainViewModel.ResetBuildCommandProgress();
                        }
                    }
                }
            }
            else
            { // singleFile specified, extract only that file
                string destPath = Path.Combine(destDir, singleFile);
                if (File.Exists(destPath))
                {     // Check PRESERVE, NOWARN
                    if (info.Preserve)
                    { // Do nothing
                        logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Overwrite, $"[{destPath}] already exists, skipping extract from [{srcCab}]"));
                        return(logs);
                    }

                    logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Overwrite, $"[{destPath}] will be overwritten"));
                }

                using (SevenZipExtractor extractor = new SevenZipExtractor(srcCab))
                {
                    if (extractor.Format != InArchiveFormat.Cab)
                    {
                        return(LogInfo.LogErrorMessage(logs, "Expand command must be used with cabinet archive"));
                    }

                    if (reportProgress)
                    {
                        extractor.Extracting += ReportExpandProgress;
                        s.MainViewModel.SetBuildCommandProgress("Expand Progress");
                    }

                    string[] archiveFileNames = extractor.ArchiveFileNames.ToArray();
                    if (archiveFileNames.Contains(singleFile, StringComparer.OrdinalIgnoreCase))
                    {
                        try
                        {
                            string destFile = Path.Combine(destDir, singleFile);
                            using (FileStream fs = new FileStream(destFile, FileMode.Create))
                            {
                                extractor.ExtractFile(singleFile, fs);
                            }
                            logs.Add(new LogInfo(LogState.Success, $"[{singleFile}] from [{srcCab}] extracted to [{destPath}]"));
                        }
                        finally
                        {
                            if (reportProgress)
                            {
                                extractor.Extracting -= ReportExpandProgress;
                                s.MainViewModel.ResetBuildCommandProgress();
                            }
                        }
                    }
                    else
                    { // Unable to find specified file
                        logs.Add(new LogInfo(LogState.Error, $"Failed to extract [{singleFile}] from [{srcCab}]"));
                    }
                }
            }

            return(logs);
        }
Ejemplo n.º 2
0
        public static List <LogInfo> Expand(EngineState s, CodeCommand cmd)
        {
            List <LogInfo> logs = new List <LogInfo>();

            Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_Expand));
            CodeInfo_Expand info = cmd.Info as CodeInfo_Expand;

            string srcCab     = StringEscaper.Preprocess(s, info.SrcCab);
            string destDir    = StringEscaper.Preprocess(s, info.DestDir);
            string singleFile = null;

            if (info.SingleFile != null)
            {
                singleFile = StringEscaper.Preprocess(s, info.SingleFile);
            }

            // Path Security Check
            if (StringEscaper.PathSecurityCheck(destDir, out string errorMsg) == false)
            {
                logs.Add(new LogInfo(LogState.Error, errorMsg));
                return(logs);
            }

            if (!Directory.Exists(destDir))
            {
                if (File.Exists(destDir))
                {
                    logs.Add(new LogInfo(LogState.Error, $"Path [{destDir}] is file, not a directory"));
                    return(logs);
                }
                Directory.CreateDirectory(destDir);
            }

            if (singleFile == null)
            {                                                                              // No singleFile operand, extract all
                if (ArchiveHelper.ExtractCab(srcCab, destDir, out List <string> doneList)) // Success
                {
                    foreach (string done in doneList)
                    {
                        logs.Add(new LogInfo(LogState.Success, $"[{done}] extracted"));
                    }
                    logs.Add(new LogInfo(LogState.Success, $"[{doneList.Count}] files from [{srcCab}] extracted to [{destDir}]"));
                }
                else // Failure
                {
                    logs.Add(new LogInfo(LogState.Error, $"Failed to extract [{srcCab}]"));
                }
            }
            else
            { // singleFile specified, extract only that singleFile
                string destPath = Path.Combine(destDir, singleFile);
                if (File.Exists(destPath))
                {     // Check PRESERVE, NOWARN
                    if (info.Preserve)
                    { // Do nothing
                        logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Warning, $"[{destPath}] already exists, cannot extract from [{srcCab}]"));
                        return(logs);
                    }
                    else
                    {
                        logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Warning, $"[{destPath}] will be overwritten"));
                    }
                }

                if (ArchiveHelper.ExtractCab(srcCab, destDir, singleFile)) // Success
                {
                    logs.Add(new LogInfo(LogState.Success, $"[{singleFile}] from [{srcCab}] extracted to [{destPath}]"));
                }
                else // Failure
                {
                    logs.Add(new LogInfo(LogState.Error, $"Failed to extract [{singleFile}] from [{srcCab}]"));
                }
            }

            return(logs);
        }