Example #1
0
        public void RenameFolder()
        {
            EngineState s = EngineTests.CreateEngineState();
            string      originScriptPath = Path.Combine(StringEscaper.Preprocess(s, "%TestBench%"), "EncodedFile", "ExtractFileTests.script");

            // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local
            void Template(string oldFolderName, string newFolderName, bool result)
            {
                string destDir    = FileHelper.GetTempDir();
                string destScript = Path.Combine(destDir, "RenameFolderTest.script");

                try
                {
                    File.Copy(originScriptPath, destScript, true);

                    Script sc = s.Project.LoadScriptRuntime(destScript, new LoadScriptRuntimeOptions());

                    Dictionary <string, string> fileDict = null;
                    if (result)
                    {
                        fileDict = sc.Sections[oldFolderName].IniDict;
                    }

                    string errMsg;
                    (sc, errMsg) = EncodedFile.RenameFolder(sc, oldFolderName, newFolderName);

                    if (errMsg != null)
                    {
                        Assert.IsFalse(result);
                        return;
                    }
                    Assert.IsTrue(result);

                    Assert.IsFalse(sc.Sections.ContainsKey(oldFolderName));
                    Assert.IsTrue(sc.Sections.ContainsKey(newFolderName));
                    Assert.IsFalse(IniReadWriter.ContainsSection(destScript, oldFolderName));
                    Assert.IsTrue(IniReadWriter.ContainsSection(destScript, newFolderName));

                    string[] folders = sc.Sections[EncodedFolders].Lines;
                    Assert.IsFalse(folders.Contains(oldFolderName, StringComparer.OrdinalIgnoreCase));
                    Assert.IsTrue(folders.Contains(newFolderName, StringComparer.OrdinalIgnoreCase));

                    foreach (string fileName in fileDict.Keys)
                    {
                        Assert.IsFalse(sc.Sections.ContainsKey(GetSectionName(oldFolderName, fileName)));
                        Assert.IsTrue(sc.Sections.ContainsKey(GetSectionName(newFolderName, fileName)));
                    }
                }
                finally
                {
                    if (Directory.Exists(destDir))
                    {
                        Directory.Delete(destDir, true);
                    }
                }
            }

            Template("FolderExample", "RenamedExample", true);
            Template("BannerImage", "BannerRenamed", true);
            Template(AuthorEncoded, "Hello", false);
            Template(InterfaceEncoded, "World", false);
            Template("FolderExample", AuthorEncoded, false);
            Template("BannerImage", InterfaceEncoded, false);
            Template("ShouldFail", "ShouldNotRename", false);
        }
Example #2
0
        public static void Loop(EngineState s, CodeCommand cmd)
        {
            Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_Loop));
            CodeInfo_Loop info = cmd.Info as CodeInfo_Loop;

            if (info.Break)
            {
                if (s.LoopRunning)
                {
                    s.LoopRunning = false;
                    s.Logger.Build_Write(s, new LogInfo(LogState.Info, "Breaking Loop", cmd, s.CurDepth));
                }
                else
                {
                    s.Logger.Build_Write(s, new LogInfo(LogState.Error, "Loop is not running", cmd, s.CurDepth));
                }
            }
            else
            {
                string startIdxStr = StringEscaper.Preprocess(s, info.StartIdx);
                if (NumberHelper.ParseInt64(startIdxStr, out long startIdx) == false)
                {
                    throw new ExecuteException($"Argument [{startIdxStr}] is not a valid integer");
                }
                string endIdxStr = StringEscaper.Preprocess(s, info.EndIdx);
                if (NumberHelper.ParseInt64(endIdxStr, out long endIdx) == false)
                {
                    throw new ExecuteException($"Argument [{endIdxStr}] is not a valid integer");
                }
                long loopCount = endIdx - startIdx + 1;

                // Prepare Loop
                string        pluginFile  = StringEscaper.Preprocess(s, info.PluginFile);
                string        sectionName = StringEscaper.Preprocess(s, info.SectionName);
                List <string> paramList   = StringEscaper.Preprocess(s, info.Parameters);

                Plugin p = Engine.GetPluginInstance(s, cmd, s.CurrentPlugin.FullPath, pluginFile, out bool inCurrentPlugin);

                // Does section exists?
                if (!p.Sections.ContainsKey(sectionName))
                {
                    throw new ExecuteException($"[{pluginFile}] does not have section [{sectionName}]");
                }

                string logMessage;
                if (inCurrentPlugin)
                {
                    logMessage = $"Loop Section [{sectionName}] [{loopCount}] times";
                }
                else
                {
                    logMessage = $"Loop [{p.Title}]'s Section [{sectionName}] [{loopCount}] times";
                }
                s.Logger.Build_Write(s, new LogInfo(LogState.Info, logMessage, cmd, s.CurDepth));

                // Section Parameter
                Dictionary <int, string> paramDict = new Dictionary <int, string>();
                for (int i = 0; i < paramList.Count; i++)
                {
                    paramDict[i + 1] = paramList[i];
                }

                // Loop it
                SectionAddress nextAddr = new SectionAddress(p, p.Sections[sectionName]);
                for (s.LoopCounter = startIdx; s.LoopCounter <= endIdx; s.LoopCounter++)
                { // Counter Variable is [#c]
                    s.Logger.Build_Write(s, new LogInfo(LogState.Info, $"Entering Loop [{s.LoopCounter}/{loopCount}]", cmd, s.CurDepth));
                    s.Logger.LogSectionParameter(s, s.CurDepth, paramDict, cmd);

                    int depthBackup = s.CurDepth;
                    s.LoopRunning = true;
                    Engine.RunSection(s, nextAddr, paramDict, s.CurDepth + 1, true);
                    if (s.LoopRunning == false) // Loop,Break
                    {
                        break;
                    }
                    s.LoopRunning = false;
                    s.CurDepth    = depthBackup;

                    s.Logger.Build_Write(s, new LogInfo(LogState.Info, $"End of Loop [{s.LoopCounter}/{loopCount}]", cmd, s.CurDepth));
                }
            }
        }
Example #3
0
        public static List <LogInfo> RegRead(EngineState s, CodeCommand cmd)
        { // RegRead,<HKey>,<KeyPath>,<ValueName>,<DestVar>
            List <LogInfo> logs = new List <LogInfo>();

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

            string keyPath   = StringEscaper.Preprocess(s, info.KeyPath);
            string valueName = StringEscaper.Preprocess(s, info.ValueName);

            string hKeyStr = RegistryHelper.RegKeyToString(info.HKey);

            if (hKeyStr == null)
            {
                throw new InternalException("Internal Logic Error");
            }
            string fullKeyPath = $"{hKeyStr}\\{keyPath}";

            string valueDataStr;

            using (RegistryKey subKey = info.HKey.OpenSubKey(keyPath, false))
            {
                object valueData = subKey.GetValue(valueName, null, RegistryValueOptions.DoNotExpandEnvironmentNames);
                if (valueData == null)
                {
                    logs.Add(new LogInfo(LogState.Error, $"Cannot read registry key [{fullKeyPath}]"));
                    return(logs);
                }

                RegistryValueKind kind = subKey.GetValueKind(valueName);
                switch (kind)
                {
                case RegistryValueKind.None:
                    throw new ExecuteException($"Cannot read empty value [{fullKeyPath}\\{valueName}]");

                case RegistryValueKind.String:
                case RegistryValueKind.ExpandString:
                    valueDataStr = (string)valueData;
                    break;

                case RegistryValueKind.Binary:
                    valueDataStr = StringEscaper.PackRegBinary((byte[])valueData);
                    break;

                case RegistryValueKind.DWord:
                    valueDataStr = ((uint)(int)valueData).ToString();
                    break;

                case RegistryValueKind.MultiString:
                    valueDataStr = StringEscaper.PackRegMultiString((string[])valueData);
                    break;

                case RegistryValueKind.QWord:
                    valueDataStr = ((ulong)(long)valueData).ToString();
                    break;

                default:
                    logs.Add(new LogInfo(LogState.Error, $"Unsupported registry value type [0x{((int) kind).ToString("0:X")}]"));
                    return(logs);
                }
            }

            logs.Add(new LogInfo(LogState.Success, $"Registry value [{fullKeyPath}\\{valueName}]'s data is [{valueDataStr}]"));
            List <LogInfo> varLogs = Variables.SetVariable(s, info.DestVar, valueDataStr);

            logs.AddRange(varLogs);

            return(logs);
        }
Example #4
0
        public static List <LogInfo> SystemCmd(EngineState s, CodeCommand cmd)
        {
            List <LogInfo> logs = new List <LogInfo>();

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

            SystemType type = info.Type;

            switch (type)
            {
            case SystemType.Cursor:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo_Cursor));
                SystemInfo_Cursor subInfo = info.SubInfo as SystemInfo_Cursor;

                string iconStr = StringEscaper.Preprocess(s, subInfo.IconKind);

                if (iconStr.Equals("WAIT", StringComparison.OrdinalIgnoreCase))
                {
                    Application.Current?.Dispatcher.Invoke(() =>
                        {
                            System.Windows.Input.Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
                        });
                    logs.Add(new LogInfo(LogState.Success, "Mouse cursor icon set to [Wait]"));
                }
                else if (iconStr.Equals("NORMAL", StringComparison.OrdinalIgnoreCase))
                {
                    Application.Current?.Dispatcher.Invoke(() =>
                        {
                            System.Windows.Input.Mouse.OverrideCursor = null;
                        });
                    logs.Add(new LogInfo(LogState.Success, "Mouse cursor icon set to [Normal]"));
                }
                else
                {
                    logs.Add(new LogInfo(LogState.Error, $"Wrong mouse cursor icon [{iconStr}]"));
                }
            }
            break;

            case SystemType.ErrorOff:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo_ErrorOff));
                SystemInfo_ErrorOff subInfo = info.SubInfo as SystemInfo_ErrorOff;

                string linesStr = StringEscaper.Preprocess(s, subInfo.Lines);
                if (!NumberHelper.ParseInt32(linesStr, out int lines))
                {
                    throw new ExecuteException($"[{linesStr}] is not a valid integer");
                }
                if (lines <= 0)
                {
                    throw new ExecuteException($"[{linesStr}] must be positive integer");
                }

                // +1 to not count ErrorOff itself
                s.ErrorOffSection      = cmd.Addr.Section;
                s.ErrorOffStartLineIdx = cmd.LineIdx + 1;
                s.ErrorOffLineCount    = lines;

                logs.Add(new LogInfo(LogState.Success, $"Error is off for [{lines}] lines"));
            }
            break;

            case SystemType.GetEnv:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo_GetEnv));
                SystemInfo_GetEnv subInfo = info.SubInfo as SystemInfo_GetEnv;

                string envVarName  = StringEscaper.Preprocess(s, subInfo.EnvVarName);
                string envVarValue = Environment.GetEnvironmentVariable(envVarName);
                if (envVarValue == null)         // Failure
                {
                    logs.Add(new LogInfo(LogState.Ignore, $"Cannot get environment variable [%{envVarName}%]'s value"));
                    envVarValue = string.Empty;
                }

                logs.Add(new LogInfo(LogState.Success, $"Environment variable [{envVarName}]'s value is [{envVarValue}]"));
                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, envVarValue);
                logs.AddRange(varLogs);
            }
            break;

            case SystemType.GetFreeDrive:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo_GetFreeDrive));
                SystemInfo_GetFreeDrive subInfo = info.SubInfo as SystemInfo_GetFreeDrive;

                DriveInfo[] drives         = DriveInfo.GetDrives();
                string      letters        = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                char        lastFreeLetter = letters.Except(drives.Select(d => d.Name[0])).LastOrDefault();

                if (lastFreeLetter != '\0')         // Success
                {
                    logs.Add(new LogInfo(LogState.Success, $"Last free drive letter is [{lastFreeLetter}]"));
                    List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, lastFreeLetter.ToString());
                    logs.AddRange(varLogs);
                }
                else         // No Free Drives
                {
                    // TODO: Is it correct WB082 behavior?
                    logs.Add(new LogInfo(LogState.Ignore, "No free drive letter"));
                    List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, string.Empty);
                    logs.AddRange(varLogs);
                }
            }
            break;

            case SystemType.GetFreeSpace:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo_GetFreeSpace));
                SystemInfo_GetFreeSpace subInfo = info.SubInfo as SystemInfo_GetFreeSpace;

                string path = StringEscaper.Preprocess(s, subInfo.Path);

                FileInfo  f           = new FileInfo(path);
                DriveInfo drive       = new DriveInfo(f.Directory.Root.FullName);
                long      freeSpaceMB = drive.TotalFreeSpace / (1024 * 1024);    // B to MB

                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, freeSpaceMB.ToString());
                logs.AddRange(varLogs);
            }
            break;

            case SystemType.IsAdmin:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo_IsAdmin));
                SystemInfo_IsAdmin subInfo = info.SubInfo as SystemInfo_IsAdmin;

                bool isAdmin;
                using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
                {
                    WindowsPrincipal principal = new WindowsPrincipal(identity);
                    isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
                }

                if (isAdmin)
                {
                    logs.Add(new LogInfo(LogState.Success, "PEBakery is running as Administrator"));
                }
                else
                {
                    logs.Add(new LogInfo(LogState.Success, "PEBakery is not running as Administrator"));
                }

                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, isAdmin.ToString());
                logs.AddRange(varLogs);
            }
            break;

            case SystemType.OnBuildExit:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo_OnBuildExit));
                SystemInfo_OnBuildExit subInfo = info.SubInfo as SystemInfo_OnBuildExit;

                s.OnBuildExit = subInfo.Cmd;

                logs.Add(new LogInfo(LogState.Success, "OnBuildExit callback registered"));
            }
            break;

            case SystemType.OnScriptExit:
            case SystemType.OnPluginExit:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo_OnPluginExit));
                SystemInfo_OnPluginExit subInfo = info.SubInfo as SystemInfo_OnPluginExit;

                s.OnPluginExit = subInfo.Cmd;

                logs.Add(new LogInfo(LogState.Success, "OnPluginExit callback registered"));
            }
            break;

            case SystemType.RefreshInterface:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo_RefreshInterface));
                SystemInfo_RefreshInterface subInfo = info.SubInfo as SystemInfo_RefreshInterface;

                AutoResetEvent resetEvent = null;
                Application.Current?.Dispatcher.Invoke(() =>
                    {
                        MainWindow w = (Application.Current.MainWindow as MainWindow);
                        resetEvent   = w.StartReloadPluginWorker();
                    });
                if (resetEvent != null)
                {
                    resetEvent.WaitOne();
                }

                logs.Add(new LogInfo(LogState.Success, $"Rerendered plugin [{cmd.Addr.Plugin.Title}]"));
            }
            break;

            case SystemType.RescanScripts:
            case SystemType.LoadAll:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo_LoadAll));
                SystemInfo_LoadAll subInfo = info.SubInfo as SystemInfo_LoadAll;

                // Reload Project
                AutoResetEvent resetEvent = null;
                Application.Current?.Dispatcher.Invoke(() =>
                    {
                        MainWindow w = (Application.Current.MainWindow as MainWindow);
                        resetEvent   = w.StartLoadWorker(true);
                    });
                if (resetEvent != null)
                {
                    resetEvent.WaitOne();
                }

                logs.Add(new LogInfo(LogState.Success, $"Reload project [{cmd.Addr.Plugin.Project.ProjectName}]"));
            }
            break;

            case SystemType.Load:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo_Load));
                SystemInfo_Load subInfo = info.SubInfo as SystemInfo_Load;

                string       filePath     = StringEscaper.Preprocess(s, subInfo.FilePath);
                SearchOption searchOption = SearchOption.TopDirectoryOnly;
                if (subInfo.NoRec)
                {
                    searchOption = SearchOption.AllDirectories;
                }

                // Check wildcard
                string wildcard         = Path.GetFileName(filePath);
                bool   containsWildcard = (wildcard.IndexOfAny(new char[] { '*', '?' }) != -1);

                string[] files;
                if (containsWildcard)
                {         // With wildcard
                    files = FileHelper.GetFilesEx(FileHelper.GetDirNameEx(filePath), wildcard, searchOption);
                    if (files.Length == 0)
                    {
                        logs.Add(new LogInfo(LogState.Error, $"Plugin [{filePath}] does not exist"));
                        return(logs);
                    }
                }
                else
                {         // No wildcard
                    if (!File.Exists(filePath))
                    {
                        logs.Add(new LogInfo(LogState.Error, $"Plugin [{filePath}] does not exist"));
                        return(logs);
                    }

                    files = new string[1] {
                        filePath
                    };
                }

                int successCount = 0;
                foreach (string f in files)
                {
                    string pFullPath = Path.GetFullPath(f);

                    // Does this file already exists in project.AllPlugins?
                    Project project = cmd.Addr.Project;
                    if (project.ContainsPluginByFullPath(pFullPath))
                    {         // Project Tree conatins this plugin, so just refresh it
                        // RefreshPlugin -> Update Project.AllPlugins
                        // TODO: Update EngineState.Plugins?
                        Plugin p = Engine.GetPluginInstance(s, cmd, cmd.Addr.Plugin.FullPath, pFullPath, out bool inCurrentPlugin);
                        p = s.Project.RefreshPlugin(p);
                        if (p == null)
                        {
                            logs.Add(new LogInfo(LogState.Error, $"Unable to refresh plugin [{pFullPath}]"));
                            continue;
                        }

                        // Update MainWindow and redraw Plugin
                        Application.Current?.Dispatcher.Invoke(() =>
                            {
                                MainWindow w = (Application.Current.MainWindow as MainWindow);

                                w.UpdatePluginTree(project, false);
                                if (p.Equals(w.CurMainTree.Plugin))
                                {
                                    w.CurMainTree.Plugin = p;
                                    w.DrawPlugin(w.CurMainTree.Plugin);
                                }
                            });

                        logs.Add(new LogInfo(LogState.Success, $"Refreshed plugin [{f}]"));
                        successCount += 1;
                    }
                    else
                    {         // Add plugins into Project.AllPlugins
                        Plugin p = cmd.Addr.Project.LoadPluginMonkeyPatch(pFullPath, true, false);
                        if (p == null)
                        {
                            logs.Add(new LogInfo(LogState.Error, $"Unable to load plugin [{pFullPath}]"));
                            continue;
                        }

                        // Update MainWindow.MainTree and redraw Plugin
                        Application.Current?.Dispatcher.Invoke(() =>
                            {
                                MainWindow w = (Application.Current.MainWindow as MainWindow);

                                w.UpdatePluginTree(project, false);
                                if (p.Equals(w.CurMainTree.Plugin))
                                {
                                    w.CurMainTree.Plugin = p;
                                    w.DrawPlugin(w.CurMainTree.Plugin);
                                }
                            });

                        logs.Add(new LogInfo(LogState.Success, $"Loaded plugin [{f}], added to plugin tree"));
                        successCount += 1;
                    }
                }

                if (1 < files.Length)
                {
                    logs.Add(new LogInfo(LogState.Success, $"Refresh or loaded [{successCount}] plugins"));
                }
            }
            break;

            case SystemType.SaveLog:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo_SaveLog));
                SystemInfo_SaveLog subInfo = info.SubInfo as SystemInfo_SaveLog;

                string destPath     = StringEscaper.Preprocess(s, subInfo.DestPath);
                string logFormatStr = StringEscaper.Preprocess(s, subInfo.LogFormat);

                LogExportType logFormat = Logger.ParseLogExportType(logFormatStr);

                if (s.DisableLogger == false)
                {         // When logger is disabled, s.BuildId is invalid.
                    s.Logger.Build_Write(s, new LogInfo(LogState.Success, $"Exported Build Logs to [{destPath}]", cmd, s.CurDepth));
                    s.Logger.ExportBuildLog(logFormat, destPath, s.BuildId);
                }
            }
            break;

            case SystemType.SetLocal:
            {         // SetLocal
                // No SystemInfo
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo));

                Engine.EnableSetLocal(s, cmd.Addr.Section);

                logs.Add(new LogInfo(LogState.Success, "Local variables are isolated"));
            }
            break;

            case SystemType.EndLocal:
            {         // EndLocal
                // No CodeInfo
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo));

                Engine.DisableSetLocal(s, cmd.Addr.Section);

                logs.Add(new LogInfo(LogState.Success, "Local variables are no longer isolated"));
            }
            break;

            // WB082 Compatibility Shim
            case SystemType.HasUAC:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo_HasUAC));
                SystemInfo_HasUAC subInfo = info.SubInfo as SystemInfo_HasUAC;

                logs.Add(new LogInfo(LogState.Warning, $"[System,HasUAC] is deprecated"));

                // Deprecated, WB082 Compability Shim
                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, "True");
                logs.AddRange(varLogs);
            }
            break;

            case SystemType.FileRedirect:     // Do nothing
                logs.Add(new LogInfo(LogState.Ignore, $"[System,FileRedirect] is not necessary in PEBakery"));
                break;

            case SystemType.RegRedirect:     // Do nothing
                logs.Add(new LogInfo(LogState.Ignore, $"[System,RegRedirect] is not necessary in PEBakery"));
                break;

            case SystemType.RebuildVars:
            {         // Reset Variables to clean state
                s.Variables.ResetVariables(VarsType.Fixed);
                s.Variables.ResetVariables(VarsType.Global);
                s.Variables.ResetVariables(VarsType.Local);

                // Load Global Variables
                List <LogInfo> varLogs;
                varLogs = s.Variables.LoadDefaultGlobalVariables();
                logs.AddRange(LogInfo.AddDepth(varLogs, s.CurDepth + 1));

                // Load Per-Plugin Variables
                varLogs = s.Variables.LoadDefaultPluginVariables(cmd.Addr.Plugin);
                logs.AddRange(LogInfo.AddDepth(varLogs, s.CurDepth + 1));

                // Load Per-Plugin Macro
                s.Macro.ResetLocalMacros();
                varLogs = s.Macro.LoadLocalMacroDict(cmd.Addr.Plugin, false);
                logs.AddRange(LogInfo.AddDepth(varLogs, s.CurDepth + 1));

                logs.Add(new LogInfo(LogState.Success, $"Variables are reset to default state"));
            }
            break;

            default:     // Error
                throw new InvalidCodeCommandException($"Wrong SystemType [{type}]");
            }

            return(logs);
        }
Example #5
0
        public static List <LogInfo> Compress(EngineState s, CodeCommand cmd)
        { // Compress,<ArchiveType>,<SrcPath>,<DestArchive>,[CompressLevel],[UTF8|UTF16|UTF16BE|ANSI]
            List <LogInfo> logs = new List <LogInfo>();

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

            ArchiveCompressFormat arcType = info.Format;
            string srcPath     = StringEscaper.Preprocess(s, info.SrcPath);
            string destArchive = StringEscaper.Preprocess(s, info.DestArchive);

            ArchiveHelper.CompressLevel compLevel = ArchiveHelper.CompressLevel.Normal;
            if (info.CompressLevel != null)
            {
                compLevel = (ArchiveHelper.CompressLevel)info.CompressLevel;
            }

            Encoding encoding = info.Encoding;

            if (info.Encoding == null)
            {
                encoding = Encoding.UTF8;
            }

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

            if (Directory.Exists(destArchive))
            {
                logs.Add(new LogInfo(LogState.Error, $"[{destArchive}] should be a file, not a directory"));
                return(logs);
            }
            else
            {
                if (File.Exists(destArchive))
                {
                    logs.Add(new LogInfo(LogState.Warning, $"File [{destArchive}] will be overwritten"));
                }
            }

            if (!Directory.Exists(srcPath) && !File.Exists(srcPath))
            {
                logs.Add(new LogInfo(LogState.Error, $"Cannot find [{srcPath}]"));
                return(logs);
            }

            bool success;

            switch (arcType)
            {
            case ArchiveCompressFormat.Zip:
                success = ArchiveHelper.CompressManagedZip(srcPath, destArchive, compLevel, encoding);
                break;

            default:
                logs.Add(new LogInfo(LogState.Error, $"Compressing to [{arcType}] format is not supported"));
                return(logs);
            }
            if (success)
            {
                logs.Add(new LogInfo(LogState.Success, $"[{srcPath}] compressed to [{destArchive}]"));
            }
            else
            {
                logs.Add(new LogInfo(LogState.Error, $"Compressing [{srcPath}] failed"));
            }

            return(logs);
        }
Example #6
0
        public static List <LogInfo> Math(EngineState s, CodeCommand cmd)
        {
            List <LogInfo> logs = new List <LogInfo>();

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

            MathType type = info.Type;

            switch (type)
            {
            case MathType.Add:
            case MathType.Sub:
            case MathType.Mul:
            case MathType.Div:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(MathInfo_Arithmetic));
                MathInfo_Arithmetic subInfo = info.SubInfo as MathInfo_Arithmetic;

                string srcStr1 = StringEscaper.Preprocess(s, subInfo.Src1);
                string srcStr2 = StringEscaper.Preprocess(s, subInfo.Src2);

                if (!NumberHelper.ParseDecimal(srcStr1, out decimal src1))
                {
                    throw new ExecuteException($"[{srcStr1}] is not a valid integer");
                }
                if (!NumberHelper.ParseDecimal(srcStr2, out decimal src2))
                {
                    throw new ExecuteException($"[{srcStr2}] is not a valid integer");
                }

                decimal destInt;
                if (type == MathType.Add)
                {
                    destInt = src1 + src2;
                }
                else if (type == MathType.Sub)
                {
                    destInt = src1 - src2;
                }
                else if (type == MathType.Mul)
                {
                    destInt = src1 * src2;
                }
                else if (type == MathType.Div)
                {
                    destInt = src1 / src2;
                }
                else
                {
                    throw new InternalException($"Internal Logic Error");
                }

                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, destInt.ToString()));
            }
            break;

            case MathType.IntDiv:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(MathInfo_IntDiv));
                MathInfo_IntDiv subInfo = info.SubInfo as MathInfo_IntDiv;

                string srcStr1 = StringEscaper.Preprocess(s, subInfo.Src1);
                string srcStr2 = StringEscaper.Preprocess(s, subInfo.Src2);

                if (srcStr1.StartsWith("-", StringComparison.Ordinal) ||
                    srcStr2.StartsWith("-", StringComparison.Ordinal))
                {         // Signed
                    if (!NumberHelper.ParseInt64(srcStr1, out long src1))
                    {
                        throw new ExecuteException($"[{srcStr1}] is not a valid integer");
                    }
                    if (!NumberHelper.ParseInt64(srcStr2, out long src2))
                    {
                        throw new ExecuteException($"[{srcStr2}] is not a valid integer");
                    }

                    long q = src1 / src2;
                    long r = src1 % src2;

                    logs.AddRange(Variables.SetVariable(s, subInfo.QuotientVar, q.ToString()));
                    logs.AddRange(Variables.SetVariable(s, subInfo.RemainderVar, r.ToString()));
                }
                else
                {         // Unsigned
                    if (!NumberHelper.ParseUInt64(srcStr1, out ulong src1))
                    {
                        throw new ExecuteException($"[{srcStr1}] is not a valid integer");
                    }
                    if (!NumberHelper.ParseUInt64(srcStr2, out ulong src2))
                    {
                        throw new ExecuteException($"[{srcStr2}] is not a valid integer");
                    }

                    ulong q = src1 / src2;
                    ulong r = src1 % src2;

                    logs.AddRange(Variables.SetVariable(s, subInfo.QuotientVar, q.ToString()));
                    logs.AddRange(Variables.SetVariable(s, subInfo.RemainderVar, r.ToString()));
                }
            }
            break;

            case MathType.Neg:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(MathInfo_Neg));
                MathInfo_Neg subInfo = info.SubInfo as MathInfo_Neg;

                string srcStr = StringEscaper.Preprocess(s, subInfo.Src);
                if (!NumberHelper.ParseDecimal(srcStr, out decimal src))
                {
                    throw new ExecuteException($"[{srcStr}] is not a valid integer");
                }

                decimal destInt = (src * -1);
                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, destInt.ToString()));
            }
            break;

            case MathType.ToSign:
            case MathType.ToUnsign:
            {
                // Math,IntSign,<DestVar>,<Src>,[8|16|32|64]
                // Math,IntUnsign,<DestVar>,<Src>,[8|16|32|64]

                Debug.Assert(info.SubInfo.GetType() == typeof(MathInfo_IntegerSignedness));
                MathInfo_IntegerSignedness subInfo = info.SubInfo as MathInfo_IntegerSignedness;

                string srcStr = StringEscaper.Preprocess(s, subInfo.Src);

                string destStr;
                if (info.Type == MathType.ToSign)
                {         // Unsigned int to signed int
                    switch (subInfo.Size)
                    {
                    case 8:
                    {
                        if (!NumberHelper.ParseUInt8(srcStr, out byte src))
                        {
                            throw new ExecuteException($"[{srcStr}] is not a valid integer");
                        }

                        destStr = ((sbyte)src).ToString();
                    }
                    break;

                    case 16:
                    {
                        if (!NumberHelper.ParseUInt16(srcStr, out ushort src))
                        {
                            throw new ExecuteException($"[{srcStr}] is not a valid integer");
                        }

                        destStr = ((short)src).ToString();
                    }
                    break;

                    case 32:
                    {
                        if (!NumberHelper.ParseUInt32(srcStr, out uint src))
                        {
                            throw new ExecuteException($"[{srcStr}] is not a valid integer");
                        }

                        destStr = ((int)src).ToString();
                    }
                    break;

                    case 64:
                    {
                        if (!NumberHelper.ParseUInt64(srcStr, out ulong src))
                        {
                            throw new ExecuteException($"[{srcStr}] is not a valid integer");
                        }

                        destStr = ((long)src).ToString();
                    }
                    break;

                    default:
                        throw new InternalException($"Internal Logic Error");
                    }
                }
                else
                {         // Signed int to unsigned int
                    switch (subInfo.Size)
                    {
                    case 8:
                    {
                        if (!NumberHelper.ParseInt8(srcStr, out sbyte src))
                        {
                            throw new ExecuteException($"[{srcStr}] is not a valid integer");
                        }

                        destStr = ((byte)src).ToString();
                    }
                    break;

                    case 16:
                    {
                        if (!NumberHelper.ParseInt16(srcStr, out short src))
                        {
                            throw new ExecuteException($"[{srcStr}] is not a valid integer");
                        }

                        destStr = ((ushort)src).ToString();
                    }
                    break;

                    case 32:
                    {
                        if (!NumberHelper.ParseInt32(srcStr, out int src))
                        {
                            throw new ExecuteException($"[{srcStr}] is not a valid integer");
                        }

                        destStr = ((uint)src).ToString();
                    }
                    break;

                    case 64:
                    {
                        if (!NumberHelper.ParseInt64(srcStr, out long src))
                        {
                            throw new ExecuteException($"[{srcStr}] is not a valid integer");
                        }

                        destStr = ((ulong)src).ToString();
                    }
                    break;

                    default:
                        throw new InternalException($"Internal Logic Error");
                    }
                }

                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, destStr));
            }
            break;

            case MathType.BoolAnd:
            case MathType.BoolOr:
            case MathType.BoolXor:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(MathInfo_BoolLogicOper));
                MathInfo_BoolLogicOper subInfo = info.SubInfo as MathInfo_BoolLogicOper;

                string srcStr1 = StringEscaper.Preprocess(s, subInfo.Src1);
                string srcStr2 = StringEscaper.Preprocess(s, subInfo.Src2);

                bool src1 = false;
                if (srcStr1.Equals("True", StringComparison.OrdinalIgnoreCase))
                {
                    src1 = true;
                }
                else if (!srcStr1.Equals("False", StringComparison.OrdinalIgnoreCase))
                {
                    throw new ExecuteException($"[{srcStr1}] is not valid boolean value");
                }

                bool src2 = false;
                if (srcStr2.Equals("True", StringComparison.OrdinalIgnoreCase))
                {
                    src2 = true;
                }
                else if (!srcStr2.Equals("False", StringComparison.OrdinalIgnoreCase))
                {
                    throw new ExecuteException($"[{srcStr2}] is not valid boolean value");
                }

                bool dest;
                if (type == MathType.BoolAnd)
                {
                    dest = src1 && src2;
                }
                else if (type == MathType.BoolOr)
                {
                    dest = src1 || src2;
                }
                else if (type == MathType.BoolXor)
                {
                    dest = src1 ^ src2;
                }
                else
                {
                    throw new InternalException($"Internal Logic Error");
                }

                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, dest.ToString()));
            }
            break;

            case MathType.BoolNot:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(MathInfo_BoolNot));
                MathInfo_BoolNot subInfo = info.SubInfo as MathInfo_BoolNot;

                bool   src    = false;
                string srcStr = StringEscaper.Preprocess(s, subInfo.Src);
                if (srcStr.Equals("True", StringComparison.OrdinalIgnoreCase))
                {
                    src = true;
                }
                else if (!srcStr.Equals("False", StringComparison.OrdinalIgnoreCase))
                {
                    throw new ExecuteException($"[{srcStr}] is not valid boolean value");
                }

                bool dest = !src;
                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, dest.ToString()));
            }
            break;

            case MathType.BitAnd:
            case MathType.BitOr:
            case MathType.BitXor:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(MathInfo_BitLogicOper));
                MathInfo_BitLogicOper subInfo = info.SubInfo as MathInfo_BitLogicOper;

                string srcStr1 = StringEscaper.Preprocess(s, subInfo.Src1);
                string srcStr2 = StringEscaper.Preprocess(s, subInfo.Src2);

                if (!NumberHelper.ParseUInt64(srcStr1, out ulong src1))
                {
                    throw new ExecuteException($"[{srcStr1}] is not a valid integer");
                }
                if (!NumberHelper.ParseUInt64(srcStr2, out ulong src2))
                {
                    throw new ExecuteException($"[{srcStr2}] is not a valid integer");
                }

                ulong dest;
                if (type == MathType.BitAnd)
                {
                    dest = src1 & src2;
                }
                else if (type == MathType.BitOr)
                {
                    dest = src1 | src2;
                }
                else if (type == MathType.BitXor)
                {
                    dest = src1 ^ src2;
                }
                else
                {
                    throw new InternalException($"Internal Logic Error");
                }

                string destStr = dest.ToString();
                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, destStr));
            }
            break;

            case MathType.BitNot:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(MathInfo_BitNot));
                MathInfo_BitNot subInfo = info.SubInfo as MathInfo_BitNot;

                string srcStr = StringEscaper.Preprocess(s, subInfo.Src);
                string destStr;

                switch (subInfo.Size)
                {
                case 8:
                {
                    if (!NumberHelper.ParseUInt8(srcStr, out byte src))
                    {
                        throw new ExecuteException($"[{srcStr}] is not a valid integer");
                    }

                    destStr = ((byte)(~src)).ToString();
                }
                break;

                case 16:
                {
                    if (!NumberHelper.ParseUInt16(srcStr, out ushort src))
                    {
                        throw new ExecuteException($"[{srcStr}] is not a valid integer");
                    }

                    destStr = ((ushort)(~src)).ToString();
                }
                break;

                case 32:
                {
                    if (!NumberHelper.ParseUInt32(srcStr, out uint src))
                    {
                        throw new ExecuteException($"[{srcStr}] is not a valid integer");
                    }

                    destStr = ((uint)(~src)).ToString();
                }
                break;

                case 64:
                {
                    if (!NumberHelper.ParseUInt64(srcStr, out ulong src))
                    {
                        throw new ExecuteException($"[{srcStr}] is not a valid integer");
                    }

                    destStr = ((ulong)(~src)).ToString();
                }
                break;

                default:
                    throw new InternalException($"Internal Logic Error");
                }

                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, destStr));
            }
            break;

            case MathType.BitShift:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(MathInfo_BitShift));
                MathInfo_BitShift subInfo = info.SubInfo as MathInfo_BitShift;

                string srcStr = StringEscaper.Preprocess(s, subInfo.Src);

                string shiftStr = StringEscaper.Preprocess(s, subInfo.Shift);
                if (!NumberHelper.ParseInt32(shiftStr, out int shift))
                {
                    throw new ExecuteException($"[{shiftStr}] is not a valid integer");
                }

                string leftRightStr = StringEscaper.Preprocess(s, subInfo.LeftRight);
                bool   isLeft       = false;
                if (leftRightStr.Equals("Left", StringComparison.OrdinalIgnoreCase))
                {
                    isLeft = true;
                }
                else if (!leftRightStr.Equals("Right", StringComparison.OrdinalIgnoreCase))
                {
                    throw new ExecuteException($"[{leftRightStr}] must be one of [Left, Right]");
                }

                string destStr;
                switch (subInfo.Size)
                {
                case 8:
                {
                    if (!NumberHelper.ParseUInt8(srcStr, out byte src))
                    {
                        throw new ExecuteException($"[{srcStr}] is not a valid integer");
                    }

                    byte dest;
                    if (isLeft)
                    {
                        dest = (byte)(src << shift);
                    }
                    else
                    {
                        dest = (byte)(src >> shift);
                    }
                    destStr = dest.ToString();
                }
                break;

                case 16:
                {
                    if (!NumberHelper.ParseUInt16(srcStr, out ushort src))
                    {
                        throw new ExecuteException($"[{srcStr}] is not a valid integer");
                    }

                    ushort dest;
                    if (isLeft)
                    {
                        dest = (ushort)(src << shift);
                    }
                    else
                    {
                        dest = (ushort)(src >> shift);
                    }
                    destStr = dest.ToString();
                }
                break;

                case 32:
                {
                    if (!NumberHelper.ParseUInt32(srcStr, out uint src))
                    {
                        throw new ExecuteException($"[{srcStr}] is not a valid integer");
                    }

                    uint dest;
                    if (isLeft)
                    {
                        dest = (uint)(src << shift);
                    }
                    else
                    {
                        dest = (uint)(src >> shift);
                    }
                    destStr = dest.ToString();
                }
                break;

                case 64:
                {
                    if (!NumberHelper.ParseUInt64(srcStr, out ulong src))
                    {
                        throw new ExecuteException($"[{srcStr}] is not a valid integer");
                    }

                    ulong dest;
                    if (isLeft)
                    {
                        dest = (ulong)(src << shift);
                    }
                    else
                    {
                        dest = (ulong)(src >> shift);
                    }
                    destStr = dest.ToString();
                }
                break;

                default:
                    throw new InternalException($"Internal Logic Error");
                }

                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, destStr));
            }
            break;

            case MathType.Ceil:
            case MathType.Floor:
            case MathType.Round:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(MathInfo_CeilFloorRound));
                MathInfo_CeilFloorRound subInfo = info.SubInfo as MathInfo_CeilFloorRound;

                string srcStr = StringEscaper.Preprocess(s, subInfo.Src);
                if (!NumberHelper.ParseInt64(srcStr, out long srcInt))
                {
                    throw new ExecuteException($"[{srcStr}] is not a valid integer");
                }

                string unitStr = StringEscaper.Preprocess(s, subInfo.Unit);
                // Is roundToStr number?
                if (!NumberHelper.ParseInt64(unitStr, out long unit))
                {
                    throw new ExecuteException($"[{unitStr}] is not a valid integer");
                }
                if (unit < 0)
                {
                    throw new ExecuteException($"[{unit}] must be positive integer");
                }

                long destInt;
                long remainder = srcInt % unit;
                if (type == MathType.Ceil)
                {
                    destInt = srcInt - remainder + unit;
                }
                else if (type == MathType.Floor)
                {
                    destInt = srcInt - remainder;
                }
                else         // if (type == StrFormatType.Round)
                {
                    if ((unit - 1) / 2 < remainder)
                    {
                        destInt = srcInt - remainder + unit;
                    }
                    else
                    {
                        destInt = srcInt - remainder;
                    }
                }

                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, destInt.ToString());
                logs.AddRange(varLogs);
            }
            break;

            case MathType.Abs:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(MathInfo_Abs));
                MathInfo_Abs subInfo = info.SubInfo as MathInfo_Abs;

                string srcStr = StringEscaper.Preprocess(s, subInfo.Src);
                if (!NumberHelper.ParseDecimal(srcStr, out decimal src))
                {
                    throw new ExecuteException($"[{srcStr}] is not a valid integer");
                }

                decimal dest = System.Math.Abs(src);
                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, dest.ToString()));
            }
            break;

            case MathType.Pow:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(MathInfo_Pow));
                MathInfo_Pow subInfo = info.SubInfo as MathInfo_Pow;

                string baseStr = StringEscaper.Preprocess(s, subInfo.Base);
                if (!NumberHelper.ParseDecimal(baseStr, out decimal _base))
                {
                    throw new ExecuteException($"[{baseStr}] is not a valid integer");
                }

                string powerStr = StringEscaper.Preprocess(s, subInfo.Power);
                if (!NumberHelper.ParseUInt32(powerStr, out uint power))
                {
                    throw new ExecuteException($"[{baseStr}] is not a postivie integer");
                }

                decimal dest = NumberHelper.DecimalPower(_base, power);
                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, dest.ToString()));
            }
            break;

            default:     // Error
                throw new InvalidCodeCommandException($"Wrong MathType [{type}]");
            }

            return(logs);
        }
Example #7
0
        public static List <LogInfo> WebGet(EngineState s, CodeCommand cmd)
        { // WebGet,<URL>,<DestPath>,[HashType],[HashDigest]
            List <LogInfo> logs = new List <LogInfo>();

            CodeInfo_WebGet info = cmd.Info.Cast <CodeInfo_WebGet>();

            string url      = StringEscaper.Preprocess(s, info.URL);
            string destPath = StringEscaper.Preprocess(s, info.DestPath);
            int    timeOut  = 10;

            if (info.TimeOut != null)
            {
                string timeOutStr = StringEscaper.Preprocess(s, info.TimeOut);
                if (!NumberHelper.ParseInt32(timeOutStr, out timeOut))
                {
                    return(LogInfo.LogErrorMessage(logs, $"TimeOut [{timeOutStr}] is not a valid positive integer"));
                }
                if (timeOut <= 0)
                {
                    return(LogInfo.LogErrorMessage(logs, $"TimeOut [{timeOutStr}] is not a valid positive integer"));
                }
            }

            // Check PathSecurity in destPath
            if (!StringEscaper.PathSecurityCheck(destPath, out string pathErrorMsg))
            {
                return(LogInfo.LogErrorMessage(logs, pathErrorMsg));
            }

            Uri    uri = new Uri(url);
            string destFile;

            if (Directory.Exists(destPath))
            {
                destFile = Path.Combine(destPath, Path.GetFileName(uri.LocalPath));
            }
            else // downloadTo is file
            {
                if (File.Exists(destPath))
                {
                    if (cmd.Type == CodeType.WebGetIfNotExist)
                    {
                        logs.Add(new LogInfo(LogState.Ignore, $"File [{destPath}] already exists"));
                        return(logs);
                    }

                    logs.Add(new LogInfo(LogState.Overwrite, $"File [{destPath}] will be overwritten"));
                }
                else
                {
                    Directory.CreateDirectory(FileHelper.GetDirNameEx(destPath));
                }
                destFile = destPath;
            }

            string destFileExt = Path.GetExtension(destFile);

            s.MainViewModel.SetBuildCommandProgress("WebGet Progress");
            try
            {
                if (info.HashType == HashHelper.HashType.None)
                { // Standard WebGet
                    string tempPath = FileHelper.GetTempFile(destFileExt);

                    HttpFileDownloader        downloader = new HttpFileDownloader(s.MainViewModel, timeOut, s.CustomUserAgent);
                    HttpFileDownloader.Report report;
                    try
                    {
                        CancellationTokenSource ct = new CancellationTokenSource();
                        s.CancelWebGet = ct;

                        Task <HttpFileDownloader.Report> task = downloader.Download(url, tempPath, ct.Token);
                        task.Wait(ct.Token);

                        report = task.Result;
                    }
                    catch (Exception e)
                    {
                        report = new HttpFileDownloader.Report(false, 0, Logger.LogExceptionMessage(e));
                    }
                    finally
                    {
                        s.CancelWebGet = null;
                    }

                    int statusCode = report.StatusCode;
                    if (report.Result)
                    {
                        FileHelper.FileReplaceEx(tempPath, destFile);
                        logs.Add(new LogInfo(LogState.Success, $"[{destFile}] downloaded from [{url}]"));
                    }
                    else
                    {
                        LogState state = info.NoErrFlag ? LogState.Warning : LogState.Error;
                        logs.Add(new LogInfo(state, $"Error occured while downloading [{url}]"));
                        logs.Add(new LogInfo(LogState.Info, report.ErrorMsg));
                        if (statusCode == 0)
                        {
                            logs.Add(new LogInfo(LogState.Info, "Request failed, no response received."));
                        }
                        else
                        {
                            logs.Add(new LogInfo(LogState.Info, $"Response returned HTTP status code [{statusCode}]"));
                        }
                    }

                    // PEBakery extension -> Report exit code via #r
                    if (!s.CompatDisableExtendedSectionParams)
                    {
                        s.ReturnValue = statusCode.ToString();
                        if (statusCode < 100)
                        {
                            logs.Add(new LogInfo(LogState.Success, $"Returned [{statusCode}] into [#r]"));
                        }
                        else
                        {
                            logs.Add(new LogInfo(LogState.Success, $"Returned HTTP status code [{statusCode}] to [#r]"));
                        }
                    }
                }
                else
                { // Validate downloaded file with hash
                    Debug.Assert(info.HashDigest != null);

                    string tempPath = FileHelper.GetTempFile(destFileExt);

                    HttpFileDownloader        downloader = new HttpFileDownloader(s.MainViewModel, timeOut, s.CustomUserAgent);
                    HttpFileDownloader.Report report;
                    try
                    {
                        CancellationTokenSource ct = new CancellationTokenSource();
                        s.CancelWebGet = ct;

                        Task <HttpFileDownloader.Report> task = downloader.Download(url, tempPath, ct.Token);
                        task.Wait(ct.Token);

                        report = task.Result;
                    }
                    catch (Exception e)
                    {
                        report = new HttpFileDownloader.Report(false, 0, Logger.LogExceptionMessage(e));
                    }
                    finally
                    {
                        s.CancelWebGet = null;
                    }

                    int statusCode = report.StatusCode;
                    if (report.Result)
                    { // Success -> Check hash
                        string hashDigest = StringEscaper.Preprocess(s, info.HashDigest);
                        if (hashDigest.Length != 2 * HashHelper.GetHashByteLen(info.HashType))
                        {
                            return(LogInfo.LogErrorMessage(logs, $"Hash digest [{hashDigest}] is not [{info.HashType}]"));
                        }

                        string downDigest;
                        using (FileStream fs = new FileStream(tempPath, FileMode.Open, FileAccess.Read))
                        {
                            byte[] digest = HashHelper.GetHash(info.HashType, fs);
                            downDigest = StringHelper.ToHexStr(digest);
                        }

                        if (hashDigest.Equals(downDigest, StringComparison.OrdinalIgnoreCase)) // Success
                        {
                            FileHelper.FileReplaceEx(tempPath, destFile);
                            logs.Add(new LogInfo(LogState.Success, $"[{destFile}] downloaded from [{url}] and verified "));
                        }
                        else
                        {
                            statusCode = 1; // 1 means hash mismatch
                            logs.Add(new LogInfo(LogState.Error, $"Downloaded file from [{url}] was corrupted"));
                        }
                    }
                    else
                    { // Failure -> Log error message
                        LogState state = info.NoErrFlag ? LogState.Warning : LogState.Error;
                        logs.Add(new LogInfo(state, $"Error occured while downloading [{url}]"));
                        logs.Add(new LogInfo(LogState.Info, report.ErrorMsg));
                        if (statusCode == 0)
                        {
                            logs.Add(new LogInfo(LogState.Info, "Request failed, no response received."));
                        }
                        else
                        {
                            logs.Add(new LogInfo(LogState.Info, $"Response returned HTTP Status Code [{statusCode}]"));
                        }
                    }

                    // PEBakery extension -> Report exit code via #r
                    if (!s.CompatDisableExtendedSectionParams)
                    {
                        s.ReturnValue = statusCode.ToString();
                        if (statusCode < 100)
                        {
                            logs.Add(new LogInfo(LogState.Success, $"Returned [{statusCode}] into [#r]"));
                        }
                        else
                        {
                            logs.Add(new LogInfo(LogState.Success, $"Returned HTTP status code [{statusCode}] to [#r]"));
                        }
                    }
                }
            }
            finally
            {
                s.MainViewModel.ResetBuildCommandProgress();
            }

            return(logs);
        }
Example #8
0
        public static List <LogInfo> ExtractAndRun(EngineState s, CodeCommand cmd)
        {
            List <LogInfo> logs = new List <LogInfo>();

            CodeInfo_ExtractAndRun info = cmd.Info.Cast <CodeInfo_ExtractAndRun>();

            string scriptFile = StringEscaper.Preprocess(s, info.ScriptFile);
            string dirName    = StringEscaper.Preprocess(s, info.DirName);
            string fileName   = StringEscaper.Preprocess(s, info.FileName);

            Script sc = Engine.GetScriptInstance(s, s.CurrentScript.RealPath, scriptFile, out _);

            // Check if encoded file exist
            if (!EncodedFile.ContainsFile(sc, dirName, fileName))
            {
                return(LogInfo.LogErrorMessage(logs, $"Encoded file [{dirName}\\{fileName}] not found in script [{sc.RealPath}]."));
            }

            string tempDir  = FileHelper.GetTempDir();
            string tempPath = Path.Combine(tempDir, fileName);

            s.MainViewModel.SetBuildCommandProgress("ExtractAndRun Progress", 1);
            try
            {
                object             progressLock = new object();
                IProgress <double> progress     = new Progress <double>(x =>
                {
                    lock (progressLock)
                    {
                        s.MainViewModel.BuildCommandProgressValue = x;
                        if (x < EncodedFile.Base64ReportFactor)
                        { // [Stage 1] Base64
                            s.MainViewModel.BuildCommandProgressText = $"Reading \"{fileName}\" from script\r\n({x * 100:0.0}%)";
                        }
                        else
                        { // [Stage 2] Decompress
                            s.MainViewModel.BuildCommandProgressText = $"Decompressing \"{fileName}\"\r\n({x * 100:0.0}%)";
                        }
                    }
                });

                using (FileStream fs = new FileStream(tempPath, FileMode.Create, FileAccess.Write))
                {
                    EncodedFile.ExtractFile(sc, dirName, info.FileName, fs, progress);
                }
            }
            finally
            {
                s.MainViewModel.ResetBuildCommandProgress();
            }

            string _params = null;

            using (Process proc = new Process())
            {
                proc.EnableRaisingEvents = true;
                proc.StartInfo           = new ProcessStartInfo
                {
                    FileName        = tempPath,
                    UseShellExecute = true,
                };

                if (!string.IsNullOrEmpty(info.Params))
                {
                    _params = StringEscaper.Preprocess(s, info.Params);
                    proc.StartInfo.Arguments = _params;
                }

                proc.Exited += (object sender, EventArgs e) =>
                {
                    if (Directory.Exists(tempDir))
                    {
                        Directory.Delete(tempDir, true);
                    }

                    // ReSharper disable once AccessToDisposedClosure
                    proc.Dispose();
                };

                proc.Start();
            }

            if (_params == null)
            {
                logs.Add(new LogInfo(LogState.Success, $"Extracted and executed [{fileName}]"));
            }
            else
            {
                logs.Add(new LogInfo(LogState.Success, $"Extracted and executed [{fileName} {_params}]"));
            }

            return(logs);
        }
Example #9
0
        public static List <LogInfo> ExtractAllFiles(EngineState s, CodeCommand cmd)
        {
            List <LogInfo> logs = new List <LogInfo>();

            CodeInfo_ExtractAllFiles info = cmd.Info.Cast <CodeInfo_ExtractAllFiles>();

            string scriptFile = StringEscaper.Preprocess(s, info.ScriptFile);
            string dirName    = StringEscaper.Preprocess(s, info.DirName);
            string destDir    = StringEscaper.Preprocess(s, info.DestDir);

            Script sc = Engine.GetScriptInstance(s, s.CurrentScript.RealPath, scriptFile, out _);

            // Check if encoded file exist
            if (!EncodedFile.ContainsFolder(sc, dirName))
            {
                return(LogInfo.LogErrorMessage(logs, $"Encoded folder [{dirName}] not found in script [{sc.RealPath}]."));
            }

            // Filter dest path
            if (!StringEscaper.PathSecurityCheck(destDir, out string errorMsg))
            {
                return(LogInfo.LogErrorMessage(logs, errorMsg));
            }

            string[] dirs = sc.Sections[ScriptSection.Names.EncodedFolders].Lines;
            if (!dirs.Any(d => d.Equals(dirName, StringComparison.OrdinalIgnoreCase)))
            {
                return(LogInfo.LogErrorMessage(logs, $"Directory [{dirName}] not exists in [{scriptFile}]"));
            }

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

            string[] lines = sc.Sections[dirName].Lines;
            Dictionary <string, string> fileDict = IniReadWriter.ParseIniLinesIniStyle(lines);
            int fileCount = fileDict.Count;

            s.MainViewModel.SetBuildCommandProgress("ExtractAndRun Progress", fileCount);
            try
            {
                int i = 0;
                foreach (string file in fileDict.Keys)
                {
                    object             progressLock = new object();
                    IProgress <double> progress     = new Progress <double>(x =>
                    {
                        lock (progressLock)
                        {
                            s.MainViewModel.BuildCommandProgressText  = $"Decompressing \"{file}\"\r\n({(x + i) * 100 / fileCount:0.0}%)";
                            s.MainViewModel.BuildCommandProgressValue = x + i;
                        }
                    });

                    using (FileStream fs = new FileStream(Path.Combine(destDir, file), FileMode.Create, FileAccess.Write))
                    {
                        EncodedFile.ExtractFile(sc, dirName, file, fs, progress);
                    }

                    i += 1;
                }
            }
            finally
            {
                s.MainViewModel.ResetBuildCommandProgress();
            }

            logs.Add(new LogInfo(LogState.Success, $"Encoded folder [{dirName}] was extracted to [{destDir}]"));

            return(logs);
        }
Example #10
0
        public static List <LogInfo> DirCopy(EngineState s, CodeCommand cmd)
        {
            List <LogInfo> logs = new List <LogInfo>();

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

            string srcDir  = StringEscaper.Preprocess(s, info.SrcDir);
            string destDir = StringEscaper.Preprocess(s, info.DestDir);

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

            // DestPath must be directory
            if (File.Exists(destDir))
            {
                logs.Add(new LogInfo(LogState.Error, $"Cannot overwrite file [{destDir}] with directory [{srcDir}]"));
                return(logs);
            }

            // Check srcDir contains wildcard
            string wildcard = Path.GetFileName(srcDir);

            if (wildcard.IndexOfAny(new char[] { '*', '?' }) == -1)
            { // No Wildcard
                string destFullPath = Path.Combine(destDir, Path.GetFileName(srcDir));
                if (Directory.Exists(destFullPath))
                {
                    logs.Add(new LogInfo(LogState.Ignore, $"Directory [{destFullPath}] will be overwritten with [{srcDir}]"));
                }
                else
                {
                    Directory.CreateDirectory(destFullPath);
                }

                FileHelper.DirectoryCopy(srcDir, destFullPath, true, true, null);
                logs.Add(new LogInfo(LogState.Success, $"Directory [{srcDir}] copied to [{destFullPath}]", cmd));
            }
            else
            { // With Wildcard
                if (Directory.Exists(destDir))
                {
                    logs.Add(new LogInfo(LogState.Ignore, $"Directory [{destDir}] will be overwritten with [{srcDir}]"));
                }
                else
                {
                    Directory.CreateDirectory(destDir);
                }

                string srcParentDir = Path.GetDirectoryName(srcDir);

                DirectoryInfo dirInfo = new DirectoryInfo(srcParentDir);
                if (!dirInfo.Exists)
                {
                    throw new DirectoryNotFoundException($"Source directory does not exist or cannot be found: {srcDir}");
                }

                if (s.CompatDirCopyBug)
                { // Simulate WB082's [DirCopy,%SrcDir%\*,%DestDir%] filecopy bug
                    foreach (FileInfo f in dirInfo.GetFiles(wildcard))
                    {
                        File.Copy(f.FullName, Path.Combine(destDir, f.Name), true);
                    }
                }

                // Copy first sublevel directory with wildcard
                // Note that wildcard will not be applied to subdirectory copy
                foreach (DirectoryInfo subDir in dirInfo.GetDirectories(wildcard))
                {
                    FileHelper.DirectoryCopy(subDir.FullName, Path.Combine(destDir, subDir.Name), true, true, null);
                }

                logs.Add(new LogInfo(LogState.Success, $"Directory [{srcDir}] copied to [{destDir}]", cmd));
            }

            return(logs);
        }
Example #11
0
        public static List <LogInfo> FileCopy(EngineState s, CodeCommand cmd)
        {
            List <LogInfo> logs = new List <LogInfo>();

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

            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 destPath is directory
            bool destPathExists = false;
            bool destPathIsDir  = false;

            if (Directory.Exists(destPath))
            {
                destPathExists = true;
                destPathIsDir  = true;
            }
            else if (File.Exists(destPath))
            {
                destPathExists = true;
            }

            // Check srcFileName contains wildcard
            string wildcard = Path.GetFileName(srcFile);

            if (wildcard.IndexOfAny(new char[] { '*', '?' }) == -1)
            {                      // No Wildcard
                if (destPathIsDir) // DestPath exists, and it is directory
                {
                    Directory.CreateDirectory(destPath);
                    string destFullPath = Path.Combine(destPath, Path.GetFileName(srcFile));
                    if (File.Exists(destFullPath))
                    {
                        if (info.Preserve)
                        {
                            logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Overwrite, $"Cannot overwrite file [{destFullPath}]", cmd));
                            return(logs);
                        }
                        else
                        {
                            logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Overwrite, $"File [{destFullPath}] will be overwritten", cmd));
                        }
                    }

                    File.Copy(srcFile, destFullPath, true);
                    logs.Add(new LogInfo(LogState.Success, $"[{srcFile}] copied to [{destFullPath}]", cmd));
                }
                else // DestPath not exist, or it is a file
                {
                    Directory.CreateDirectory(FileHelper.GetDirNameEx(destPath));
                    if (destPathExists)
                    {
                        if (info.Preserve)
                        {
                            logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Overwrite, $"Cannot overwrite file [{destPath}]", cmd));
                            return(logs);
                        }
                        else
                        {
                            logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Overwrite, $"File [{destPath}] will be overwritten", cmd));
                        }
                    }

                    File.Copy(srcFile, destPath, true);
                    logs.Add(new LogInfo(LogState.Success, $"[{srcFile}] copied to [{destPath}]", cmd));
                }
            }
            else
            { // With Wildcard
                // Use FileHelper.GetDirNameEx to prevent ArgumentException of Directory.GetFiles
                string srcDirToFind = Path.GetFullPath(FileHelper.GetDirNameEx(srcFile));

                string[] files;
                if (info.NoRec)
                {
                    files = FileHelper.GetFilesEx(srcDirToFind, wildcard);
                }
                else
                {
                    files = FileHelper.GetFilesEx(srcDirToFind, wildcard, SearchOption.AllDirectories);
                }

                if (0 < files.Length)
                { // One or more file will be copied
                    logs.Add(new LogInfo(LogState.Success, $"[{srcFile}] will be copied to [{destPath}]", cmd));

                    if (destPathIsDir || !destPathExists)
                    {
                        for (int i = 0; i < files.Length; i++)
                        {
                            string f            = files[i];
                            string destFullPath = Path.Combine(destPath, f.Substring(srcDirToFind.Length + 1));

                            if (File.Exists(destFullPath))
                            {
                                if (info.Preserve)
                                {
                                    logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Overwrite, $"Cannot overwrite [{destFullPath}]", cmd));
                                    continue;
                                }
                                else
                                {
                                    logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Overwrite, $"[{destFullPath}] will be overwritten", cmd));
                                }
                            }

                            Directory.CreateDirectory(Path.GetDirectoryName(destFullPath));
                            File.Copy(f, destFullPath, true);

                            logs.Add(new LogInfo(LogState.Success, $"[{f}] copied to [{destFullPath}]", cmd));
                        }

                        logs.Add(new LogInfo(LogState.Success, $"[{files.Length}] files copied", cmd));
                    }
                    else
                    {
                        logs.Add(new LogInfo(LogState.Error, "<DestPath> must be directory when using wildcard in <SrcFile>", cmd));
                        return(logs);
                    }
                }
                else
                { // No file will be copied
                    logs.Add(new LogInfo(LogState.Ignore, $"Files matching wildcard [{srcFile}] not found", cmd));
                }
            }

            return(logs);
        }
Example #12
0
        public static List <LogInfo> FileRename(EngineState s, CodeCommand cmd)
        {
            List <LogInfo> logs = new List <LogInfo>();

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

            string srcPath  = StringEscaper.Preprocess(s, info.SrcPath);
            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);
            }

            if (File.Exists(srcPath) == false)
            {
                // Check if srcPath is directory
                if (Directory.Exists(srcPath))
                {
                    if (s.CompatFileRenameCanMoveDir)
                    {
                        if (Directory.Exists(destPath))
                        {
                            string destFullPath = Path.Combine(destPath, Path.GetFileName(srcPath));

                            Directory.Move(srcPath, destFullPath);
                            logs.Add(new LogInfo(LogState.Success, $"Directory [{srcPath}] moved to [{destFullPath}]"));
                            return(logs);
                        }
                        else
                        {
                            Directory.Move(srcPath, destPath);
                            logs.Add(new LogInfo(LogState.Success, $"Directory [{srcPath}] moved to [{destPath}]"));
                            return(logs);
                        }
                    }
                    else
                    {
                        logs.Add(new LogInfo(LogState.Error, $"[{srcPath}] is a directory, not a file"));
                        return(logs);
                    }
                }
                else
                {
                    logs.Add(new LogInfo(LogState.Error, $"File [{srcPath}] does not exist"));
                    return(logs);
                }
            }

            File.SetAttributes(srcPath, FileAttributes.Normal);
            File.Move(srcPath, destPath);
            if (cmd.Type == CodeType.FileRename)
            {
                logs.Add(new LogInfo(LogState.Success, $"File [{srcPath}] renamed to [{destPath}]"));
            }
            else
            {
                logs.Add(new LogInfo(LogState.Success, $"File [{srcPath}] moved to [{destPath}]"));
            }

            return(logs);
        }
Example #13
0
        public static List <LogInfo> FileDelete(EngineState s, CodeCommand cmd)
        {
            List <LogInfo> logs = new List <LogInfo>();

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

            string filePath = StringEscaper.Preprocess(s, info.FilePath);

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

            // Check srcFileName contains wildcard
            string wildcard = Path.GetFileName(filePath);

            if (wildcard.IndexOfAny(new char[] { '*', '?' }) == -1)
            {     // No Wildcard
                if (File.Exists(filePath))
                { // Delete File
                    File.SetAttributes(filePath, FileAttributes.Normal);
                    File.Delete(filePath);

                    logs.Add(new LogInfo(LogState.Success, $"Deleted file [{filePath}]"));
                }
                else
                {
                    logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Warning, $"File [{filePath}] not exists"));
                }
            }
            else
            { // With Wildcard
                // Use FileHelper.GetDirNameEx to prevent ArgumentException of Directory.GetFiles
                string srcDirToFind = FileHelper.GetDirNameEx(filePath);
                if (Directory.Exists(srcDirToFind) == false)
                {
                    logs.Add(new LogInfo(LogState.Error, $"Cannot find path [{srcDirToFind}]"));
                    return(logs);
                }

                string[] files;
                if (info.NoRec)
                {
                    files = FileHelper.GetFilesEx(srcDirToFind, wildcard);
                }
                else
                {
                    files = FileHelper.GetFilesEx(srcDirToFind, wildcard, SearchOption.AllDirectories);
                }

                if (0 < files.Length)
                { // One or more file will be deleted
                    foreach (string f in files)
                    {
                        File.SetAttributes(f, FileAttributes.Normal);
                        File.Delete(f);
                        logs.Add(new LogInfo(LogState.Success, $"File [{f}] deleted"));
                    }

                    logs.Add(new LogInfo(LogState.Success, $"[{files.Length}] files deleted"));
                }
                else
                { // No file will be deleted
                    logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Warning, $"Files match wildcard [{filePath}] not found"));
                }
            }

            return(logs);
        }
Example #14
0
        public static List <LogInfo> SystemCmd(EngineState s, CodeCommand cmd)
        {
            List <LogInfo>  logs = new List <LogInfo>(1);
            CodeInfo_System info = cmd.Info.Cast <CodeInfo_System>();

            SystemType type = info.Type;

            switch (type)
            {
            case SystemType.Cursor:
            {
                SystemInfo_Cursor subInfo = info.SubInfo.Cast <SystemInfo_Cursor>();

                string iconStr = StringEscaper.Preprocess(s, subInfo.State);

                if (iconStr.Equals("WAIT", StringComparison.OrdinalIgnoreCase))
                {
                    Application.Current?.Dispatcher?.Invoke(() =>
                        {
                            System.Windows.Input.Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
                        });
                    s.CursorWait = true;
                    logs.Add(new LogInfo(LogState.Success, "Mouse cursor icon set to [Wait]"));
                }
                else if (iconStr.Equals("NORMAL", StringComparison.OrdinalIgnoreCase))
                {
                    Application.Current?.Dispatcher?.Invoke(() =>
                        {
                            System.Windows.Input.Mouse.OverrideCursor = null;
                        });
                    s.CursorWait = false;
                    logs.Add(new LogInfo(LogState.Success, "Mouse cursor icon set to [Normal]"));
                }
                else
                {
                    logs.Add(new LogInfo(LogState.Error, $"[{iconStr}] is not a valid mouse cursor icon"));
                }
            }
            break;

            case SystemType.ErrorOff:
            {
                SystemInfo_ErrorOff subInfo = info.SubInfo.Cast <SystemInfo_ErrorOff>();

                string linesStr = StringEscaper.Preprocess(s, subInfo.Lines);
                if (!NumberHelper.ParseInt32(linesStr, out int lines))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{linesStr}] is not a positive integer"));
                }
                if (lines <= 0)
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{linesStr}] is not a positive integer"));
                }

                if (s.ErrorOff == null)
                {
                    // Enable s.ErrorOff
                    // Write to s.ErrorOffWaitingRegister instead of s.ErrorOff, to prevent muting error of [System,ErrorOff] itself.
                    EngineLocalState ls = s.PeekLocalState();
                    if (s.ErrorOffDepthMinusOne)
                    {
                        ls = ls.UpdateDepth(ls.Depth - 1);
                    }

                    ErrorOffState newState = new ErrorOffState
                    {
                        LocalState   = ls,
                        StartLineIdx = cmd.LineIdx,
                        LineCount    = lines,
                    };

                    s.ErrorOffWaitingRegister = newState;
                    s.ErrorOffDepthMinusOne   = false;
                    logs.Add(new LogInfo(LogState.Success, $"Error and warning logs will be muted for [{lines}] lines"));
                }
                else
                {         // If s.ErrorOff is already enabled, do nothing. Ex) Nested ErrorOff
                    logs.Add(new LogInfo(LogState.Ignore, "ErrorOff is already enabled"));
                }
            }
            break;

            case SystemType.GetEnv:
            {
                SystemInfo_GetEnv subInfo = info.SubInfo.Cast <SystemInfo_GetEnv>();

                string envVarName  = StringEscaper.Preprocess(s, subInfo.EnvVar);
                string envVarValue = Environment.GetEnvironmentVariable(envVarName);
                if (envVarValue == null)         // Failure
                {
                    logs.Add(new LogInfo(LogState.Ignore, $"Cannot get environment variable [%{envVarName}%]'s value"));
                    envVarValue = string.Empty;
                }

                logs.Add(new LogInfo(LogState.Success, $"Environment variable [{envVarName}]'s value is [{envVarValue}]"));
                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, envVarValue);
                logs.AddRange(varLogs);
            }
            break;

            case SystemType.GetFreeDrive:
            {
                SystemInfo_GetFreeDrive subInfo = info.SubInfo.Cast <SystemInfo_GetFreeDrive>();

                DriveInfo[] drives = DriveInfo.GetDrives();
                // ReSharper disable once StringLiteralTypo
                const string letters        = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                char         lastFreeLetter = letters.Except(drives.Select(d => d.Name[0])).LastOrDefault();

                if (lastFreeLetter != '\0')         // Success
                {
                    logs.Add(new LogInfo(LogState.Success, $"Last free drive letter is [{lastFreeLetter}]"));
                    List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, lastFreeLetter.ToString(CultureInfo.InvariantCulture));
                    logs.AddRange(varLogs);
                }
                else         // No Free Drives
                {
                    // TODO: Is it correct WB082 behavior?
                    logs.Add(new LogInfo(LogState.Ignore, "No free drive letter"));
                    List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, string.Empty);
                    logs.AddRange(varLogs);
                }
            }
            break;

            case SystemType.GetFreeSpace:
            {
                SystemInfo_GetFreeSpace subInfo = info.SubInfo.Cast <SystemInfo_GetFreeSpace>();

                string path = StringEscaper.Preprocess(s, subInfo.Path);

                DriveInfo drive             = new DriveInfo(Path.GetPathRoot(path));
                long      freeSpaceMegaByte = drive.TotalFreeSpace / (1024 * 1024);    // B to MB

                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, freeSpaceMegaByte.ToString(CultureInfo.InvariantCulture));
                logs.AddRange(varLogs);
            }
            break;

            case SystemType.IsAdmin:
            {
                SystemInfo_IsAdmin subInfo = info.SubInfo.Cast <SystemInfo_IsAdmin>();

                bool isAdmin;
                using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
                {
                    WindowsPrincipal principal = new WindowsPrincipal(identity);
                    isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
                }

                if (isAdmin)
                {
                    logs.Add(new LogInfo(LogState.Success, "PEBakery is running as Administrator"));
                }
                else
                {
                    logs.Add(new LogInfo(LogState.Success, "PEBakery is not running as Administrator"));
                }

                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, isAdmin.ToString(CultureInfo.InvariantCulture));
                logs.AddRange(varLogs);
            }
            break;

            case SystemType.OnBuildExit:
            {
                SystemInfo_OnBuildExit subInfo = info.SubInfo.Cast <SystemInfo_OnBuildExit>();

                s.OnBuildExit = subInfo.Cmd;

                logs.Add(new LogInfo(LogState.Success, "OnBuildExit callback registered"));
            }
            break;

            case SystemType.OnScriptExit:
            {
                SystemInfo_OnScriptExit subInfo = info.SubInfo.Cast <SystemInfo_OnScriptExit>();

                s.OnScriptExit = subInfo.Cmd;

                logs.Add(new LogInfo(LogState.Success, "OnScriptExit callback registered"));
            }
            break;

            case SystemType.RefreshInterface:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo), "Invalid CodeInfo");

                s.MainViewModel.StartRefreshScript().Wait();

                logs.Add(new LogInfo(LogState.Success, $"Re-rendered script [{cmd.Section.Script.Title}]"));
            }
            break;

            case SystemType.RescanScripts:
            case SystemType.RefreshAllScripts:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo), "Invalid CodeInfo");

                // Refresh Project
                s.MainViewModel.StartLoadingProjects(true, true).Wait();

                logs.Add(new LogInfo(LogState.Success, $"Reload project [{cmd.Section.Script.Project.ProjectName}]"));
            }
            break;

            case SystemType.LoadNewScript:
            {
                SystemInfo_LoadNewScript subInfo = info.SubInfo.Cast <SystemInfo_LoadNewScript>();

                string       srcFilePath  = StringEscaper.Preprocess(s, subInfo.SrcFilePath);
                string       destTreeDir  = StringEscaper.Preprocess(s, subInfo.DestTreeDir);
                SearchOption searchOption = SearchOption.AllDirectories;
                if (subInfo.NoRecFlag)
                {
                    searchOption = SearchOption.TopDirectoryOnly;
                }

                Debug.Assert(srcFilePath != null, "Internal Logic Error at CommandSystem.LoadNewScript");

                // Check wildcard
                string wildcard         = Path.GetFileName(srcFilePath);
                bool   containsWildcard = wildcard.IndexOfAny(new[] { '*', '?' }) != -1;

                string[] files;
                if (containsWildcard)
                {         // With wildcard
                    files = FileHelper.GetFilesEx(FileHelper.GetDirNameEx(srcFilePath), wildcard, searchOption);
                    if (files.Length == 0)
                    {
                        return(LogInfo.LogErrorMessage(logs, $"Script [{srcFilePath}] does not exist"));
                    }
                }
                else
                {         // No wildcard
                    if (!File.Exists(srcFilePath))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"Script [{srcFilePath}] does not exist"));
                    }

                    files = new string[] { srcFilePath };
                }
                List <Script> newScripts = new List <Script>(files.Length);

                string srcDirPath = Path.GetDirectoryName(srcFilePath);
                Debug.Assert(srcDirPath != null, $"{nameof(srcDirPath)} is null (CommandSystem.LoadNewScript)");

                (string realPath, string treePath)[] fileTuples = files
Example #15
0
        public static List <LogInfo> Set(EngineState s, CodeCommand cmd)
        {
            CodeInfo_Set info = cmd.Info.Cast <CodeInfo_Set>();

            Variables.VarKeyType varType = Variables.DetectType(info.VarKey);
            if (varType == Variables.VarKeyType.None)
            {
                // Check Macro
                if (Regex.Match(info.VarKey, Macro.MacroNameRegex,
                                RegexOptions.Compiled | RegexOptions.CultureInvariant).Success) // Macro Name Validation
                {
                    string macroCommand = StringEscaper.Preprocess(s, info.VarValue);

                    if (macroCommand.Equals("NIL", StringComparison.OrdinalIgnoreCase))
                    {
                        macroCommand = null;
                    }

                    LogInfo log = s.Macro.SetMacro(info.VarKey, macroCommand, cmd.Section, info.Permanent, false);
                    return(new List <LogInfo>(1)
                    {
                        log
                    });
                }
            }

            // [WB082 Behavior] -> Enabled if s.CompatAllowSetModifyInterface == true
            // If PERMANENT was used but the key exists in interface command, the value will not be written to script.project but in interface.
            // Need to investigate where the logs are saved in this case.
            switch (info.Permanent)
            {
            case true:
            {
                // Check if interface contains VarKey
                List <LogInfo> logs = new List <LogInfo>();

                if (Variables.DetectType(info.VarKey) != Variables.VarKeyType.Variable)
                {
                    goto case false;
                }

                #region Set interface control's value (Compat)
                if (s.CompatAllowSetModifyInterface)
                {
                    string varKey     = Variables.TrimPercentMark(info.VarKey);
                    string finalValue = StringEscaper.Preprocess(s, info.VarValue);

                    Script        sc    = cmd.Section.Script;
                    ScriptSection iface = sc.GetInterfaceSection(out _);
                    if (iface == null)
                    {
                        goto case false;
                    }

                    (List <UIControl> uiCtrls, _) = UIParser.ParseStatements(iface.Lines, iface);
                    UIControl uiCtrl = uiCtrls.Find(x => x.Key.Equals(varKey, StringComparison.OrdinalIgnoreCase));
                    if (uiCtrl == null)
                    {
                        goto case false;
                    }

                    bool valid = uiCtrl.SetValue(finalValue, false, out List <LogInfo> varLogs);
                    logs.AddRange(varLogs);

                    if (valid)
                    {
                        // Update uiCtrl into file
                        uiCtrl.Update();

                        // Also update local variables
                        logs.AddRange(Variables.SetVariable(s, info.VarKey, info.VarValue, false, false));
                        return(logs);
                    }
                }

                goto case false;
                #endregion
            }

            case false:
            default:
                return(Variables.SetVariable(s, info.VarKey, info.VarValue, info.Global, info.Permanent));
            }
        }
Example #16
0
        public static List <LogInfo> Encode(EngineState s, CodeCommand cmd)
        {
            List <LogInfo> logs = new List <LogInfo>();

            CodeInfo_Encode info = cmd.Info.Cast <CodeInfo_Encode>();

            string scriptFile = StringEscaper.Preprocess(s, info.ScriptFile);
            string dirName    = StringEscaper.Preprocess(s, info.DirName);
            string filePath   = StringEscaper.Preprocess(s, info.FilePath);

            EncodeMode mode = EncodeMode.ZLib;

            if (info.Compression != null)
            {
                string encodeModeStr = StringEscaper.Preprocess(s, info.Compression);
                if (encodeModeStr.Equals("None", StringComparison.OrdinalIgnoreCase))
                {
                    mode = EncodeMode.Raw;
                }
                else if (encodeModeStr.Equals("Deflate", StringComparison.OrdinalIgnoreCase))
                {
                    mode = EncodeMode.ZLib;
                }
                else if (encodeModeStr.Equals("LZMA2", StringComparison.OrdinalIgnoreCase))
                {
                    mode = EncodeMode.XZ;
                }
                else
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{encodeModeStr}] is invalid compression"));
                }
            }

            Script sc = Engine.GetScriptInstance(s, s.CurrentScript.RealPath, scriptFile, out _);

            // Check srcFileName contains wildcard
            if (filePath.IndexOfAny(new char[] { '*', '?' }) == -1)
            { // No Wildcard
                s.MainViewModel.SetBuildCommandProgress("Encode Progress", 1);
                try
                {
                    object             progressLock = new object();
                    IProgress <double> progress     = new Progress <double>(x =>
                    {
                        lock (progressLock)
                        {
                            s.MainViewModel.BuildCommandProgressValue = x;
                            if (x < EncodedFile.CompReportFactor) // [Stage 1] Compress
                            {
                                s.MainViewModel.BuildCommandProgressText = $"Compressing \"{filePath}\"\r\n({x * 100:0.0}%)";
                            }
                            else // [Stage 2] Base64
                            {
                                s.MainViewModel.BuildCommandProgressText = $"Writing \"{filePath}\" to script\r\n({x * 100:0.0}%)";
                            }
                        }
                    });

                    EncodedFile.AttachFile(sc, dirName, Path.GetFileName(filePath), filePath, mode, progress);

                    logs.Add(new LogInfo(LogState.Success, $"[{filePath}] was encoded into [{sc.RealPath}]", cmd));
                }
                finally
                {
                    s.MainViewModel.ResetBuildCommandProgress();
                }
            }
            else
            { // With Wildcard
                // Use FileHelper.GetDirNameEx to prevent ArgumentException of Directory.GetFiles
                string   srcDirToFind = FileHelper.GetDirNameEx(filePath);
                string[] files        = Directory.GetFiles(srcDirToFind, Path.GetFileName(filePath));

                // No file will be compressed
                if (files.Length == 0)
                {
                    logs.Add(new LogInfo(LogState.Warning, $"Files matching wildcard [{filePath}] were not found", cmd));
                    return(logs);
                }

                s.MainViewModel.SetBuildCommandProgress("Encode Progress", files.Length);
                try
                {
                    int                i            = 0;
                    object             progressLock = new object();
                    IProgress <double> progress     = new Progress <double>(x =>
                    {
                        lock (progressLock)
                        {
                            s.MainViewModel.BuildCommandProgressText  = $"Attaching {filePath}...\r\n({(x + i) * 100:0.0}%)";
                            s.MainViewModel.BuildCommandProgressValue = x + i;
                        }
                    });

                    // One or more file will be copied
                    logs.Add(new LogInfo(LogState.Success, $"[{filePath}] will be encoded into [{sc.RealPath}]", cmd));
                    foreach (string f in files)
                    {
                        EncodedFile.AttachFile(sc, dirName, Path.GetFileName(f), f, mode, progress);
                        logs.Add(new LogInfo(LogState.Success, $"[{f}] encoded ({i + 1}/{files.Length})", cmd));

                        i += 1;
                    }

                    logs.Add(new LogInfo(LogState.Success, $"[{files.Length}] files copied", cmd));
                }
                finally
                {
                    s.MainViewModel.ResetBuildCommandProgress();
                }
            }

            return(logs);
        }
Example #17
0
        public static List <LogInfo> Set(EngineState s, CodeCommand cmd)
        {
            Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_Set));
            CodeInfo_Set info = cmd.Info as CodeInfo_Set;

            Variables.VarKeyType varType = Variables.DetermineType(info.VarKey);
            if (varType == Variables.VarKeyType.None)
            {
                // Check Macro
                if (Regex.Match(info.VarKey, Macro.MacroNameRegex, RegexOptions.Compiled).Success) // Macro Name Validation
                {
                    string macroCommand = StringEscaper.Preprocess(s, info.VarValue);

                    if (macroCommand.Equals("NIL", StringComparison.OrdinalIgnoreCase))
                    {
                        macroCommand = null;
                    }

                    LogInfo log = s.Macro.SetMacro(info.VarKey, macroCommand, cmd.Addr, info.Permanent, false);
                    return(new List <LogInfo>(1)
                    {
                        log
                    });
                }
            }

            // [WB082 Behavior]
            // If PERMANENT was used but the key exists in interface command, the value will not be written to script.project but in interface.
            // Need to investigate where the logs are saved in this case.
            switch (info.Permanent)
            {
            case true:
            {         // Check if interface contains VarKey
                List <LogInfo> logs = new List <LogInfo>();

                if (Variables.DetermineType(info.VarKey) != Variables.VarKeyType.Variable)
                {
                    goto case false;
                }

                string varKey     = Variables.TrimPercentMark(info.VarKey);
                string finalValue = StringEscaper.Preprocess(s, info.VarValue);

                #region Set UI
                Plugin        p     = cmd.Addr.Plugin;
                PluginSection iface = p.GetInterface(out string sectionName);
                if (iface == null)
                {
                    goto case false;
                }

                List <UICommand> uiCmds = iface.GetUICodes(true);
                UICommand        uiCmd  = uiCmds.Find(x => x.Key.Equals(varKey, StringComparison.OrdinalIgnoreCase));
                if (uiCmd == null)
                {
                    goto case false;
                }

                bool match = uiCmd.SetValue(finalValue, false, out List <LogInfo> varLogs);
                logs.AddRange(varLogs);

                if (match)
                {
                    uiCmd.Update();

                    logs.AddRange(Variables.SetVariable(s, info.VarKey, info.VarValue, false, false));
                    return(logs);
                }
                else
                {
                    goto case false;
                }
                #endregion
            }

            case false:
            default:
                return(Variables.SetVariable(s, info.VarKey, info.VarValue, info.Global, info.Permanent));
            }
        }
Example #18
0
        /*
         * WB082 Behavior
         * ExtractFile : DestDir must be Directory, create if not exists.
         * Ex) (...),README.txt,%BaseDir%\Temp\Hello
         *   -> No Hello : Create directory "Hello" and extract files into new directory.
         *   -> Hello is a file : Failure
         *   -> Hello is a directory : Extract files into directory.
         *
         * ExtractAllFiles
         * Ex) (...),Fonts,%BaseDir%\Temp\Hello
         *   -> No Hello : Failure
         *   -> Hello is a file : Failure
         *   -> Hello is a directory : Extract files into directory.
         *
         * PEBakery Behavior
         * ExtractFile/ExtractAllFiles : DestDir must be Directory, create if not exists.
         * Ex) (...),README.txt,%BaseDir%\Temp\Hello
         *   -> No Hello : Create directory "Hello" and extract files into new directory.
         *   -> Hello is a file : Failure
         *   -> Hello is a directory : Extract files into directory.
         */

        public static List <LogInfo> ExtractFile(EngineState s, CodeCommand cmd)
        {
            List <LogInfo> logs = new List <LogInfo>();

            CodeInfo_ExtractFile info = cmd.Info.Cast <CodeInfo_ExtractFile>();

            string scriptFile = StringEscaper.Preprocess(s, info.ScriptFile);
            string dirName    = StringEscaper.Preprocess(s, info.DirName);
            string fileName   = StringEscaper.Preprocess(s, info.FileName);
            string destDir    = StringEscaper.Preprocess(s, info.DestDir); // Should be directory name

            Script sc = Engine.GetScriptInstance(s, s.CurrentScript.RealPath, scriptFile, out _);

            // Check if encoded file exist
            if (!EncodedFile.ContainsFile(sc, dirName, fileName))
            {
                return(LogInfo.LogErrorMessage(logs, $"Encoded file [{dirName}\\{fileName}] not found in script [{sc.RealPath}]."));
            }

            // Filter dest path
            if (!StringEscaper.PathSecurityCheck(destDir, out string errorMsg))
            {
                return(LogInfo.LogErrorMessage(logs, errorMsg));
            }

            if (!Directory.Exists(destDir)) // DestDir already exists
            {
                if (File.Exists(destDir))   // Error, cannot proceed
                {
                    return(LogInfo.LogErrorMessage(logs, $"File [{destDir}] is not a directory."));
                }

                Directory.CreateDirectory(destDir);
            }

            s.MainViewModel.SetBuildCommandProgress("ExtractFile Progress", 1);
            try
            {
                object             progressLock = new object();
                IProgress <double> progress     = new Progress <double>(x =>
                {
                    lock (progressLock)
                    {
                        s.MainViewModel.BuildCommandProgressValue = x;
                        if (x < EncodedFile.Base64ReportFactor)
                        { // [Stage 1] Base64
                            s.MainViewModel.BuildCommandProgressText = $"Reading \"{fileName}\" from script\r\n({x * 100:0.0}%)";
                        }
                        else
                        { // [Stage 2] Decompress
                            s.MainViewModel.BuildCommandProgressText = $"Decompressing \"{fileName}\"\r\n({x * 100:0.0}%)";
                        }
                    }
                });

                string destPath = Path.Combine(destDir, fileName);
                using (FileStream fs = new FileStream(destPath, FileMode.Create, FileAccess.Write))
                {
                    EncodedFile.ExtractFile(sc, dirName, fileName, fs, progress);
                }
            }
            finally
            {
                s.MainViewModel.ResetBuildCommandProgress();
            }

            logs.Add(new LogInfo(LogState.Success, $"Encoded file [{fileName}] was extracted to [{destDir}]"));

            return(logs);
        }
Example #19
0
        /// <summary>
        /// PEBakery uses 1-based index for concated list
        /// </summary>
        /// <param name="s"></param>
        /// <param name="cmd"></param>
        /// <returns></returns>
        public static List <LogInfo> List(EngineState s, CodeCommand cmd)
        {
            List <LogInfo> logs = new List <LogInfo>();
            CodeInfo_List  info = cmd.Info.Cast <CodeInfo_List>();

            string listStr = string.Empty;
            string listVar = info.SubInfo.ListVar;

            if (Variables.ContainsKey(s, listVar) == true)
            {
                listStr = StringEscaper.Preprocess(s, listVar);
            }

            ListType type      = info.Type;
            string   delimiter = "|";

            switch (type)
            {
            case ListType.Get:
            {
                ListInfo_Get subInfo = info.SubInfo.Cast <ListInfo_Get>();

                string indexStr = StringEscaper.Preprocess(s, subInfo.Index);

                if (!NumberHelper.ParseInt32(indexStr, out int index))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{indexStr}] is not a valid positive integer"));
                }
                if (index <= 0)
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{indexStr}] is not a valid positive integer"));
                }

                if (subInfo.Delim != null)
                {
                    delimiter = StringEscaper.Preprocess(s, subInfo.Delim);
                }

                List <string> list    = StringEscaper.UnpackListStr(listStr, delimiter);
                string        destStr = list[index - 1];

                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, destStr);
                logs.AddRange(varLogs);
            }
            break;

            case ListType.Set:
            {
                ListInfo_Set subInfo = info.SubInfo.Cast <ListInfo_Set>();

                string indexStr = StringEscaper.Preprocess(s, subInfo.Index);
                string item     = StringEscaper.Preprocess(s, subInfo.Item);

                if (!NumberHelper.ParseInt32(indexStr, out int index))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{indexStr}] is not a valid positive integer"));
                }
                if (index <= 0)
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{indexStr}] is not a valid positive integer"));
                }

                if (subInfo.Delim != null)
                {
                    delimiter = StringEscaper.Preprocess(s, subInfo.Delim);
                }

                List <string> list = StringEscaper.UnpackListStr(listStr, delimiter);
                list[index - 1] = item;

                listStr = StringEscaper.PackListStr(list, delimiter);
                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.ListVar, listStr);
                logs.AddRange(varLogs);
            }
            break;

            case ListType.Append:
            {
                ListInfo_Append subInfo = info.SubInfo.Cast <ListInfo_Append>();

                string item = StringEscaper.Preprocess(s, subInfo.Item);

                if (subInfo.Delim != null)
                {
                    delimiter = StringEscaper.Preprocess(s, subInfo.Delim);
                }

                List <string> list = StringEscaper.UnpackListStr(listStr, delimiter);
                list.Add(item);

                listStr = StringEscaper.PackListStr(list, delimiter);
                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.ListVar, listStr);
                logs.AddRange(varLogs);
            }
            break;

            case ListType.Insert:
            {
                ListInfo_Insert subInfo = info.SubInfo.Cast <ListInfo_Insert>();

                string indexStr = StringEscaper.Preprocess(s, subInfo.Index);
                string item     = StringEscaper.Preprocess(s, subInfo.Item);

                if (!NumberHelper.ParseInt32(indexStr, out int index))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{indexStr}] is not a valid positive integer"));
                }
                if (index <= 0)
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{indexStr}] is not a valid positive integer"));
                }

                if (subInfo.Delim != null)
                {
                    delimiter = StringEscaper.Preprocess(s, subInfo.Delim);
                }

                List <string> list = StringEscaper.UnpackListStr(listStr, delimiter);
                list.Insert(index - 1, item);

                listStr = StringEscaper.PackListStr(list, delimiter);
                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.ListVar, listStr);
                logs.AddRange(varLogs);
            }
            break;

            case ListType.Remove:
            case ListType.RemoveX:
            {
                ListInfo_Remove subInfo = info.SubInfo.Cast <ListInfo_Remove>();

                string item = StringEscaper.Preprocess(s, subInfo.Item);

                if (subInfo.Delim != null)
                {
                    delimiter = StringEscaper.Preprocess(s, subInfo.Delim);
                }

                List <string>    list = StringEscaper.UnpackListStr(listStr, delimiter);
                StringComparison comp;
                switch (type)
                {
                case ListType.Remove:
                    comp = StringComparison.OrdinalIgnoreCase;
                    break;

                case ListType.RemoveX:
                    comp = StringComparison.Ordinal;
                    break;

                default:
                    throw new InternalException("Internal Logic Error at CommandList");
                }

                int deletedItemCount = list.RemoveAll(x => x.Equals(item, comp));
                if (0 < deletedItemCount)
                {
                    logs.Add(new LogInfo(LogState.Success, $"[{deletedItemCount}] items were deleted"));
                    listStr = StringEscaper.PackListStr(list, delimiter);
                    List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.ListVar, listStr);
                    logs.AddRange(varLogs);
                }
                else
                {
                    logs.Add(new LogInfo(LogState.Ignore, "No items were deleted"));
                }
            }
            break;

            case ListType.RemoveAt:
            {
                ListInfo_RemoveAt subInfo = info.SubInfo.Cast <ListInfo_RemoveAt>();

                string indexStr = StringEscaper.Preprocess(s, subInfo.Index);

                if (subInfo.Delim != null)
                {
                    delimiter = StringEscaper.Preprocess(s, subInfo.Delim);
                }

                if (!NumberHelper.ParseInt32(indexStr, out int index))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{indexStr}] is not a valid positive integer"));
                }
                if (index <= 0)
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{indexStr}] is not a valid positive integer"));
                }

                List <string> list = StringEscaper.UnpackListStr(listStr, delimiter);
                list.RemoveAt(index - 1);

                listStr = StringEscaper.PackListStr(list, delimiter);
                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.ListVar, listStr);
                logs.AddRange(varLogs);
            }
            break;

            case ListType.Count:
            {
                ListInfo_Count subInfo = info.SubInfo.Cast <ListInfo_Count>();

                if (subInfo.Delim != null)
                {
                    delimiter = StringEscaper.Preprocess(s, subInfo.Delim);
                }

                List <string> list    = StringEscaper.UnpackListStr(listStr, delimiter);
                int           destInt = list.Count;

                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, destInt.ToString());
                logs.AddRange(varLogs);
            }
            break;

            case ListType.Pos:
            case ListType.PosX:
            case ListType.LastPos:
            case ListType.LastPosX:
            {
                ListInfo_Pos subInfo = info.SubInfo.Cast <ListInfo_Pos>();

                string item = StringEscaper.Preprocess(s, subInfo.Item);

                if (subInfo.Delim != null)
                {
                    delimiter = StringEscaper.Preprocess(s, subInfo.Delim);
                }

                List <string> list = StringEscaper.UnpackListStr(listStr, delimiter);
                int           destInt;
                switch (type)
                {
                case ListType.Pos:
                    destInt = list.FindIndex(x => x.Equals(item, StringComparison.OrdinalIgnoreCase));
                    break;

                case ListType.PosX:
                    destInt = list.FindIndex(x => x.Equals(item, StringComparison.Ordinal));
                    break;

                case ListType.LastPos:
                    destInt = list.FindLastIndex(x => x.Equals(item, StringComparison.OrdinalIgnoreCase));
                    break;

                case ListType.LastPosX:
                    destInt = list.FindLastIndex(x => x.Equals(item, StringComparison.Ordinal));
                    break;

                default:
                    throw new InternalException("Internal Logic Error at CommandList");
                }
                destInt += 1;

                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, destInt.ToString());
                logs.AddRange(varLogs);
            }
            break;

            case ListType.Sort:
            case ListType.SortX:
            case ListType.SortN:
            case ListType.SortNX:
            {
                ListInfo_Sort subInfo = info.SubInfo.Cast <ListInfo_Sort>();

                string order = StringEscaper.Preprocess(s, subInfo.Order);

                if (subInfo.Delim != null)
                {
                    delimiter = StringEscaper.Preprocess(s, subInfo.Delim);
                }

                bool reverse;
                if (order.Equals("ASC", StringComparison.OrdinalIgnoreCase))
                {
                    reverse = false;
                }
                else if (order.Equals("DESC", StringComparison.OrdinalIgnoreCase))
                {
                    reverse = true;
                }
                else
                {
                    return(LogInfo.LogErrorMessage(logs, "Order must be [ASC] or [DESC]"));
                }

                List <string> list = StringEscaper.UnpackListStr(listStr, delimiter);
                switch (type)
                {
                case ListType.Sort:
                    list = list
                           .OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
                           .ThenBy(x => x, StringComparer.Ordinal)
                           .ToList();
                    break;

                case ListType.SortX:
                    list.Sort(StringComparer.Ordinal);
                    break;

                case ListType.SortN:
                    list = list
                           .OrderBy(x => x, StringComparer.OrdinalIgnoreCase.WithNaturalSort())
                           .ThenBy(x => x, StringComparer.Ordinal.WithNaturalSort())
                           .ToList();
                    break;

                case ListType.SortNX:
                    list.Sort(StringComparer.Ordinal.WithNaturalSort());
                    break;

                default:
                    throw new InternalException("Internal Logic Error at CommandList");
                }

                if (reverse)
                {
                    list.Reverse();
                }

                listStr = StringEscaper.PackListStr(list, delimiter);
                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.ListVar, listStr);
                logs.AddRange(varLogs);
            }
            break;

            default:     // Error
                throw new InternalException("Internal Logic Error at CommandList");
            }

            return(logs);
        }
Example #20
0
        public void FileDelete()
        {
            EngineState s       = EngineTests.CreateEngineState();
            string      destDir = FileHelper.GetTempDir();

            void SingleTemplate(string rawCode, string fileName, ErrorCheck check = ErrorCheck.Success)
            {
                string dirPath = StringEscaper.Preprocess(s, Path.Combine("%TestBench%", "CommandFile"));

                string srcDir = Path.Combine(dirPath, SrcDirFile);

                string destFullPath = Path.Combine(destDir, fileName);

                if (Directory.Exists(destDir))
                {
                    Directory.Delete(destDir, true);
                }
                FileHelper.DirCopy(srcDir, destDir, new DirCopyOptions
                {
                    CopySubDirs = true,
                    Overwrite   = true,
                });
                try
                {
                    EngineTests.Eval(s, rawCode, CodeType.FileDelete, check);

                    if (check == ErrorCheck.Success)
                    {
                        Assert.IsFalse(File.Exists(destFullPath));
                    }
                }
                finally
                {
                    if (Directory.Exists(destDir))
                    {
                        Directory.Delete(destDir, true);
                    }
                }
            }

            void MultiTemplate(string rawCode, string wildCard, ErrorCheck check = ErrorCheck.Success, bool recursive = true)
            {
                string dirPath      = StringEscaper.Preprocess(s, Path.Combine("%TestBench%", "CommandFile"));
                string srcDir       = Path.Combine(dirPath, SrcDirFile);
                string destFullPath = Path.Combine(destDir, wildCard);

                if (Directory.Exists(destDir))
                {
                    Directory.Delete(destDir, true);
                }
                FileHelper.DirCopy(srcDir, destDir, new DirCopyOptions
                {
                    CopySubDirs = true,
                    Overwrite   = true,
                });
                try
                {
                    string[] destFiles;
                    if (recursive)
                    {
                        destFiles = Directory.GetFiles(destDir, wildCard, SearchOption.AllDirectories);
                    }
                    else
                    {
                        destFiles = Directory.GetFiles(destDir, wildCard);
                    }

                    EngineTests.Eval(s, rawCode, CodeType.FileDelete, check);

                    if (check == ErrorCheck.Success)
                    {
                        for (int i = 0; i < destFiles.Length; i++)
                        {
                            Assert.IsFalse(File.Exists(destFullPath));
                        }
                    }
                }
                finally
                {
                    if (Directory.Exists(destDir))
                    {
                        Directory.Delete(destDir, true);
                    }
                }
            }

            SingleTemplate($@"FileDelete,{destDir}\A.txt", "A.txt");
            SingleTemplate($@"FileDelete,{destDir}\H.txt", "H.txt", ErrorCheck.Warning);
            SingleTemplate($@"FileDelete,{destDir}\H.txt,NOWARN", "H.txt", ErrorCheck.Success);
            MultiTemplate($@"FileDelete,{destDir}\*.ini", "*.ini", ErrorCheck.Success);
            MultiTemplate($@"FileDelete,{destDir}\*.ini,NOREC", "*.ini", ErrorCheck.Success, false);
        }
Example #21
0
        public static List <LogInfo> ShellExecute(EngineState s, CodeCommand cmd)
        {
            List <LogInfo> logs = new List <LogInfo>();

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

            string verb     = StringEscaper.Preprocess(s, info.Action);
            string filePath = StringEscaper.Preprocess(s, info.FilePath);

            // Must not check existance of filePath with File.Exists()!
            // Because of PATH envrionment variable, it prevents call of system executables.
            // Ex) cmd.exe does not exist in %BaseDir%, but in System32 directory.

            StringBuilder b = new StringBuilder(filePath);

            using (Process proc = new Process())
            {
                proc.StartInfo = new ProcessStartInfo(filePath);
                if (!string.IsNullOrEmpty(info.Params))
                {
                    string parameters = StringEscaper.Preprocess(s, info.Params);
                    proc.StartInfo.Arguments = parameters;
                    b.Append(" ");
                    b.Append(parameters);
                }

                string pathVarBackup = null;
                if (info.WorkDir != null)
                {
                    string workDir = StringEscaper.Preprocess(s, info.WorkDir);
                    proc.StartInfo.WorkingDirectory = workDir;

                    // Set PATH environment variable (only for this process)
                    pathVarBackup = Environment.GetEnvironmentVariable("PATH");
                    Environment.SetEnvironmentVariable("PATH", workDir + ";" + pathVarBackup);
                }

                bool          redirectStandardStream = false;
                Stopwatch     watch   = Stopwatch.StartNew();
                StringBuilder bConOut = new StringBuilder();
                try
                {
                    if (verb.Equals("Open", StringComparison.OrdinalIgnoreCase))
                    {
                        proc.StartInfo.UseShellExecute = true;
                    }
                    else if (verb.Equals("Hide", StringComparison.OrdinalIgnoreCase))
                    {
                        proc.StartInfo.UseShellExecute = false;
                        proc.StartInfo.WindowStyle     = ProcessWindowStyle.Hidden;
                        proc.StartInfo.CreateNoWindow  = true;

                        // Redirecting standard stream without reading can full buffer, which leads to hang
                        if (MainViewModel.DisplayShellExecuteConOut && cmd.Type != CodeType.ShellExecuteEx)
                        {
                            redirectStandardStream = true;

                            proc.StartInfo.RedirectStandardOutput = true;
                            proc.OutputDataReceived += (object sender, DataReceivedEventArgs e) =>
                            {
                                if (e.Data != null)
                                {
                                    bConOut.AppendLine(e.Data);
                                    s.MainViewModel.BuildConOutRedirect = bConOut.ToString();
                                }
                            };

                            proc.StartInfo.RedirectStandardError = true;
                            proc.ErrorDataReceived += (object sender, DataReceivedEventArgs e) =>
                            {
                                if (e.Data != null)
                                {
                                    bConOut.AppendLine(e.Data);
                                    s.MainViewModel.BuildConOutRedirect = bConOut.ToString();
                                }
                            };

                            // Without this, XCOPY.exe of Windows 7 will not work properly.
                            // https://stackoverflow.com/questions/14218642/xcopy-does-not-work-with-useshellexecute-false
                            proc.StartInfo.RedirectStandardInput = true;

                            s.MainViewModel.BuildConOutRedirectShow = true;
                        }
                    }
                    else if (verb.Equals("Min", StringComparison.OrdinalIgnoreCase))
                    {
                        proc.StartInfo.UseShellExecute = true;
                        proc.StartInfo.WindowStyle     = ProcessWindowStyle.Minimized;
                    }
                    else
                    {
                        proc.StartInfo.Verb            = verb;
                        proc.StartInfo.UseShellExecute = true;
                    }

                    // Register process instance in EngineState, and run it
                    s.RunningSubProcess = proc;
                    proc.Exited        += (object sender, EventArgs e) =>
                    {
                        s.RunningSubProcess = null;
                        if (redirectStandardStream)
                        {
                            s.MainViewModel.BuildConOutRedirect = bConOut.ToString();
                            watch.Stop();
                        }
                    };
                    proc.Start();

                    if (cmd.Type == CodeType.ShellExecuteSlow)
                    {
                        proc.PriorityClass = ProcessPriorityClass.BelowNormal;
                    }

                    if (redirectStandardStream)
                    {
                        proc.BeginOutputReadLine();
                        proc.BeginErrorReadLine();
                    }

                    long tookTime = (long)watch.Elapsed.TotalSeconds;
                    switch (cmd.Type)
                    {
                    case CodeType.ShellExecute:
                    case CodeType.ShellExecuteSlow:
                        proc.WaitForExit();
                        logs.Add(new LogInfo(LogState.Success, $"Executed [{b}], returned exit code [{proc.ExitCode}], took [{tookTime}s]"));
                        break;

                    case CodeType.ShellExecuteEx:
                        logs.Add(new LogInfo(LogState.Success, $"Executed [{b}]"));
                        break;

                    case CodeType.ShellExecuteDelete:
                        proc.WaitForExit();
                        File.Delete(filePath);
                        logs.Add(new LogInfo(LogState.Success, $"Executed and deleted [{b}], returned exit code [{proc.ExitCode}], took [{tookTime}s]"));
                        break;

                    default:
                        throw new InternalException($"Internal Error! Invalid CodeType [{cmd.Type}]. Please report to issue tracker.");
                    }

                    if (cmd.Type != CodeType.ShellExecuteEx)
                    {
                        string exitOutVar;
                        if (info.ExitOutVar == null)
                        {
                            exitOutVar = "%ExitCode%"; // WB082 behavior -> even if info.ExitOutVar is not specified, it will save value to %ExitCode%
                        }
                        else
                        {
                            exitOutVar = info.ExitOutVar;
                        }

                        LogInfo log = Variables.SetVariable(s, exitOutVar, proc.ExitCode.ToString()).First();

                        if (log.State == LogState.Success)
                        {
                            logs.Add(new LogInfo(LogState.Success, $"Exit code [{proc.ExitCode}] saved into variable [{exitOutVar}]"));
                        }
                        else if (log.State == LogState.Error)
                        {
                            logs.Add(log);
                        }
                        else
                        {
                            throw new InternalException($"Internal Error! Invalid LogType [{log.State}]. Please report to issue tracker.");
                        }

                        if (redirectStandardStream)
                        {
                            string conout = bConOut.ToString().Trim();
                            if (0 < conout.Length)
                            {
                                if (conout.IndexOf('\n') == -1) // No NewLine
                                {
                                    logs.Add(new LogInfo(LogState.Success, $"[Console Output] {conout}"));
                                }
                                else // With NewLine
                                {
                                    logs.Add(new LogInfo(LogState.Success, $"[Console Output]\r\n{conout}\r\n"));
                                }
                            }
                        }
                    }
                }
                finally
                {
                    // Restore PATH environment variable
                    if (pathVarBackup != null)
                    {
                        Environment.SetEnvironmentVariable("PATH", pathVarBackup);
                    }

                    if (redirectStandardStream)
                    {
                        s.MainViewModel.BuildConOutRedirect     = string.Empty;
                        s.MainViewModel.BuildConOutRedirectShow = false;
                    }
                }
            }

            return(logs);
        }
Example #22
0
        public void DirCopy()
        {
            EngineState s         = EngineTests.CreateEngineState();
            string      pbDirPath = Path.Combine("%TestBench%", "CommandFile");
            string      pbSrcDir  = Path.Combine(pbDirPath, SrcDirDir);
            string      destDir   = FileHelper.GetTempDir();

            void Template(string rawCode, string dirName, ErrorCheck check = ErrorCheck.Success, bool wbBug = false)
            {
                string dirPath = StringEscaper.Preprocess(s, Path.Combine("%TestBench%", "CommandFile"));
                string srcDir  = Path.Combine(dirPath, SrcDirDir);

                string srcFullPath  = Path.Combine(srcDir, dirName);
                string destFullPath = Path.Combine(destDir, dirName);

                if (Directory.Exists(destDir))
                {
                    Directory.Delete(destDir, true);
                }
                try
                {
                    EngineTests.Eval(s, rawCode, CodeType.DirCopy, check);

                    if (check == ErrorCheck.Success)
                    {
                        string wildcard = null;
                        if (dirName.IndexOfAny(new char[] { '*', '?' }) != -1)
                        {
                            wildcard = dirName;
                        }

                        if (wildcard == null)
                        {
                            Assert.IsTrue(Directory.Exists(destFullPath));

                            string[] srcDirs  = Directory.GetFiles(srcFullPath, "*", SearchOption.AllDirectories);
                            string[] destDirs = Directory.GetFiles(destFullPath, "*", SearchOption.AllDirectories);

                            Assert.IsTrue(srcDirs.Length == destDirs.Length);

                            for (int i = 0; i < srcDirs.Length; i++)
                            {
                                Assert.IsTrue(srcDirs[i].Substring(srcDir.Length).Equals(destDirs[i].Substring(destDir.Length), StringComparison.Ordinal));
                            }
                        }
                        else
                        {
                            if (wbBug)
                            {
                                string[] firstSrcFiles  = Directory.GetFiles(srcDir, wildcard);
                                string[] firstDestFiles = Directory.GetFiles(destDir, wildcard);
                                Assert.IsTrue(firstDestFiles.Length == firstSrcFiles.Length);
                            }
                            else
                            {
                                string[] firstDestFiles = Directory.GetFiles(destDir, wildcard);
                                Assert.IsTrue(firstDestFiles.Length == 0);
                            }

                            string[] firstSrcDirs  = Directory.GetDirectories(srcDir, wildcard);
                            string[] firstDestDirs = Directory.GetDirectories(destDir, wildcard);
                            Assert.IsTrue(firstSrcDirs.Length == firstDestDirs.Length);

                            for (int i = 0; i < firstSrcDirs.Length; i++)
                            {
                                string[] srcDirs  = Directory.GetFiles(firstSrcDirs[i], "*", SearchOption.AllDirectories);
                                string[] destDirs = Directory.GetFiles(firstDestDirs[i], "*", SearchOption.AllDirectories);
                                Assert.IsTrue(srcDirs.Length == destDirs.Length);
                                Assert.IsTrue(srcDirs[i].Substring(srcDir.Length).Equals(destDirs[i].Substring(destDir.Length), StringComparison.Ordinal));
                            }
                        }
                    }
                }
                finally
                {
                    if (Directory.Exists(destDir))
                    {
                        Directory.Delete(destDir, true);
                    }
                }
            }

            Template($@"DirCopy,{pbSrcDir}\ABCD,{destDir}", "ABCD");
            Template($@"DirCopy,{pbSrcDir}\ABDE,{destDir}", "ABDE");
            Template($@"DirCopy,{pbSrcDir}\AB*,{destDir}", "AB*");
            Template($@"DirCopy,{pbSrcDir}\*,{destDir}", "*");

            s.CompatDirCopyBug = true;
            Template($@"DirCopy,{pbSrcDir}\*,{destDir}", "*", ErrorCheck.Success, true);
        }
Example #23
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);
        }
Example #24
0
        public void FileCopy()
        {
            EngineState s = EngineTests.CreateEngineState();

            string pbDirPath = Path.Combine("%TestBench%", "CommandFile");
            string pbSrcDir  = Path.Combine(pbDirPath, SrcDirFile);
            string destDir   = FileHelper.GetTempDir();

            void SingleTemplate(string rawCode, string srcFileName, string destFileName,
                                ErrorCheck check = ErrorCheck.Success, bool preserve = false, bool ignoreCompare = false)
            {
                if (destFileName == null)
                {
                    destFileName = srcFileName;
                }

                string dirPath = StringEscaper.Preprocess(s, Path.Combine("%TestBench%", "CommandFile"));
                string srcDir  = Path.Combine(dirPath, SrcDirFile);

                string srcFullPath  = Path.Combine(srcDir, srcFileName);
                string destFullPath = Path.Combine(destDir, destFileName);

                if (Directory.Exists(destDir))
                {
                    Directory.Delete(destDir, true);
                }
                Directory.CreateDirectory(destDir);
                try
                {
                    if (preserve)
                    {
                        File.Create(destFullPath).Close();
                    }

                    EngineTests.Eval(s, rawCode, CodeType.FileCopy, check);

                    if (check == ErrorCheck.Success && !ignoreCompare)
                    {
                        Assert.IsTrue(File.Exists(destFullPath));

                        using (FileStream srcStream = new FileStream(srcFullPath, FileMode.Open, FileAccess.Read, FileShare.Read))
                            using (FileStream destStream = new FileStream(destFullPath, FileMode.Open, FileAccess.Read, FileShare.Read))
                            {
                                byte[] srcDigest  = HashHelper.GetHash(HashHelper.HashType.SHA256, srcStream);
                                byte[] destDigest = HashHelper.GetHash(HashHelper.HashType.SHA256, destStream);
                                Assert.IsTrue(srcDigest.SequenceEqual(destDigest));
                            }
                    }
                }
                finally
                {
                    if (Directory.Exists(destDir))
                    {
                        Directory.Delete(destDir, true);
                    }
                }
            }

            void MultiTemplate(string rawCode, string srcFileWildCard, bool recursive, ErrorCheck check = ErrorCheck.Success)
            {
                string dirPath = StringEscaper.Preprocess(s, Path.Combine("%TestBench%", "CommandFile"));
                string srcDir  = Path.Combine(dirPath, SrcDirFile);

                if (Directory.Exists(destDir))
                {
                    Directory.Delete(destDir, true);
                }
                Directory.CreateDirectory(destDir);
                try
                {
                    EngineTests.Eval(s, rawCode, CodeType.FileCopy, check);

                    if (check == ErrorCheck.Success)
                    {
                        string[] srcFiles;
                        string[] destFiles;
                        if (recursive)
                        {
                            srcFiles  = Directory.GetFiles(srcDir, srcFileWildCard, SearchOption.AllDirectories);
                            destFiles = Directory.GetFiles(destDir, srcFileWildCard, SearchOption.AllDirectories);
                        }
                        else
                        {
                            srcFiles  = Directory.GetFiles(srcDir, srcFileWildCard);
                            destFiles = Directory.GetFiles(destDir, srcFileWildCard);
                        }

                        Assert.IsTrue(srcFiles.Length == destFiles.Length);

                        for (int i = 0; i < srcFiles.Length; i++)
                        {
                            using (FileStream srcStream = new FileStream(srcFiles[i], FileMode.Open, FileAccess.Read, FileShare.Read))
                                using (FileStream destStream = new FileStream(destFiles[i], FileMode.Open, FileAccess.Read, FileShare.Read))
                                {
                                    byte[] srcDigest  = HashHelper.GetHash(HashHelper.HashType.SHA256, srcStream);
                                    byte[] destDigest = HashHelper.GetHash(HashHelper.HashType.SHA256, destStream);
                                    Assert.IsTrue(srcDigest.SequenceEqual(destDigest));
                                }
                        }
                    }
                }
                finally
                {
                    if (Directory.Exists(destDir))
                    {
                        Directory.Delete(destDir, true);
                    }
                }
            }

            SingleTemplate($@"FileCopy,{pbSrcDir}\A.txt,{destDir}", "A.txt", null);
            SingleTemplate($@"FileCopy,{pbSrcDir}\A.txt,{destDir}\B.txt", "A.txt", "B.txt");
            SingleTemplate($@"FileCopy,{pbSrcDir}\Z\Y.ini,{destDir}", Path.Combine("Z", "Y.ini"), "Y.ini");
            MultiTemplate($@"FileCopy,{pbSrcDir}\*.txt,{destDir}", "*.txt", true);
            MultiTemplate($@"FileCopy,{pbSrcDir}\*.ini,{destDir},NOREC", "*.ini", false);
            // Check https://github.com/pebakery/pebakery/issues/150
            MultiTemplate($@"FileCopy,{pbSrcDir}\\*.txt,{destDir}", "*.txt", true);
            MultiTemplate($@"FileCopy,{pbSrcDir}\\*.ini,{destDir},NOREC", "*.ini", false);

            SingleTemplate($@"FileCopy,{pbSrcDir}\P.txt,{destDir}", "P.txt", null, ErrorCheck.RuntimeError);
            SingleTemplate($@"FileCopy,{pbSrcDir}\C.txt,{destDir}", "C.txt", null, ErrorCheck.Overwrite, true);
            SingleTemplate($@"FileCopy,{pbSrcDir}\C.txt,{destDir},NOWARN", "C.txt", null, ErrorCheck.Success, true);
            SingleTemplate($@"FileCopy,{pbSrcDir}\C.txt,{destDir},PRESERVE", "C.txt", null, ErrorCheck.Overwrite, true);
            SingleTemplate($@"FileCopy,{pbSrcDir}\C.txt,{destDir},PRESERVE,NOWARN", "C.txt", null, ErrorCheck.Success, true, true);

            SingleTemplate($@"FileCopy,{pbSrcDir}\A.txt,{destDir}\NonExistDir\", "A.txt", null, ErrorCheck.Warning, false, false);
        }
Example #25
0
        /// <summary>
        /// Render FileBox control.
        /// Return true if failed.
        /// </summary>
        /// <param name="canvas">Parent canvas</param>
        /// <param name="uiCmd">UICommand</param>
        public static void RenderFileBox(RenderInfo r, UICommand uiCmd, Variables variables)
        {
            // It took time to find WB082 textbox control's y coord is of textbox's, not textlabel's.
            Debug.Assert(uiCmd.Info.GetType() == typeof(UIInfo_FileBox));
            UIInfo_FileBox info = uiCmd.Info as UIInfo_FileBox;

            TextBox box = new TextBox()
            {
                Text     = uiCmd.Text,
                FontSize = CalcFontPointScale(),
                VerticalContentAlignment = VerticalAlignment.Center,
            };

            box.TextChanged += (object sender, TextChangedEventArgs e) =>
            {
                TextBox tBox = sender as TextBox;
                uiCmd.Text = tBox.Text;
                uiCmd.Update();
            };
            SetToolTip(box, info.ToolTip);

            Button button = new Button()
            {
                FontSize = CalcFontPointScale(),
                Content  = ImageHelper.GetMaterialIcon(PackIconMaterialKind.FolderUpload, 0),
            };

            SetToolTip(button, info.ToolTip);

            button.Click += (object sender, RoutedEventArgs e) =>
            {
                Button bt = sender as Button;

                if (info.IsFile)
                { // File
                    string currentPath = StringEscaper.Preprocess(variables, uiCmd.Text);
                    if (File.Exists(currentPath))
                    {
                        currentPath = Path.GetDirectoryName(currentPath);
                    }
                    else
                    {
                        currentPath = string.Empty;
                    }

                    Microsoft.Win32.OpenFileDialog dialog = new Microsoft.Win32.OpenFileDialog()
                    {
                        Filter           = "All Files|*.*",
                        InitialDirectory = currentPath,
                    };
                    if (dialog.ShowDialog() == true)
                    {
                        box.Text = dialog.FileName;
                    }
                }
                else
                { // Directory
                    System.Windows.Forms.FolderBrowserDialog dialog = new System.Windows.Forms.FolderBrowserDialog();

                    string currentPath = StringEscaper.Preprocess(variables, uiCmd.Text);
                    if (Directory.Exists(currentPath))
                    {
                        dialog.SelectedPath = currentPath;
                    }

                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                        {
                            box.Text = dialog.SelectedPath;
                            if (!dialog.SelectedPath.EndsWith("\\", StringComparison.Ordinal))
                            {
                                box.Text += "\\";
                            }
                        }
                    });
                }
            };

            double margin  = 5;
            Rect   boxRect = new Rect(uiCmd.Rect.Left, uiCmd.Rect.Top, uiCmd.Rect.Width - (uiCmd.Rect.Height + margin), uiCmd.Rect.Height);
            Rect   btnRect = new Rect(boxRect.Right + margin, uiCmd.Rect.Top, uiCmd.Rect.Height, uiCmd.Rect.Height);

            DrawToCanvas(r, box, boxRect);
            DrawToCanvas(r, button, btnRect);
        }
Example #26
0
        public void PathMove()
        {
            EngineState s       = EngineTests.CreateEngineState();
            string      destDir = FileHelper.GetTempDir();

            void FileTemplate(string rawCode, string srcFileName, string destFileName, ErrorCheck check = ErrorCheck.Success)
            {
                string dirPath      = StringEscaper.Preprocess(s, Path.Combine("%TestBench%", "CommandFile"));
                string srcDir       = Path.Combine(dirPath, SrcDirFile);
                string srcFullPath  = Path.Combine(destDir, srcFileName);
                string destFullPath = Path.Combine(destDir, destFileName);

                if (Directory.Exists(destDir))
                {
                    Directory.Delete(destDir, true);
                }
                FileHelper.DirCopy(srcDir, destDir, new DirCopyOptions
                {
                    CopySubDirs = true,
                    Overwrite   = true,
                });
                try
                {
                    EngineTests.Eval(s, rawCode, CodeType.PathMove, check);

                    if (check == ErrorCheck.Success)
                    {
                        Assert.IsFalse(File.Exists(srcFullPath));
                        Assert.IsTrue(File.Exists(destFullPath));
                    }
                }
                finally
                {
                    if (Directory.Exists(destDir))
                    {
                        Directory.Delete(destDir, true);
                    }
                }
            }

            void DirTemplate(string rawCode, string srcFileName, string destFileName, ErrorCheck check = ErrorCheck.Success)
            {
                string dirPath      = StringEscaper.Preprocess(s, Path.Combine("%TestBench%", "CommandFile"));
                string srcDir       = Path.Combine(dirPath, SrcDirDir);
                string srcFullPath  = Path.Combine(destDir, srcFileName);
                string destFullPath = Path.Combine(destDir, destFileName);

                if (Directory.Exists(destDir))
                {
                    Directory.Delete(destDir, true);
                }
                FileHelper.DirCopy(srcDir, destDir, new DirCopyOptions
                {
                    CopySubDirs = true,
                    Overwrite   = true,
                });
                try
                {
                    EngineTests.Eval(s, rawCode, CodeType.PathMove, check);

                    if (check == ErrorCheck.Success)
                    {
                        Assert.IsFalse(Directory.Exists(srcFullPath));
                        Assert.IsTrue(Directory.Exists(destFullPath));
                    }
                }
                finally
                {
                    if (Directory.Exists(destDir))
                    {
                        Directory.Delete(destDir, true);
                    }
                }
            }

            FileTemplate($@"PathMove,{destDir}\A.txt,{destDir}\R.txt", "A.txt", "R.txt");
            DirTemplate($@"PathMove,{destDir}\ABCD,{destDir}\XYZ", "ABCD", "XYZ");
        }
Example #27
0
        public static void RunExec(EngineState s, CodeCommand cmd, bool preserveCurParams, bool forceLog, bool callback)
        {
            Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_RunExec));
            CodeInfo_RunExec info = cmd.Info as CodeInfo_RunExec;

            string        pluginFile  = StringEscaper.Preprocess(s, info.PluginFile);
            string        sectionName = StringEscaper.Preprocess(s, info.SectionName);
            List <string> paramList   = StringEscaper.Preprocess(s, info.Parameters);

            Plugin p = Engine.GetPluginInstance(s, cmd, s.CurrentPlugin.FullPath, pluginFile, out bool inCurrentPlugin);

            // Does section exists?
            if (!p.Sections.ContainsKey(sectionName))
            {
                throw new ExecuteException($"[{pluginFile}] does not have section [{sectionName}]");
            }

            // Section Parameter
            Dictionary <int, string> paramDict = new Dictionary <int, string>();

            if (preserveCurParams)
            {
                paramDict = s.CurSectionParams;
            }
            else
            {
                for (int i = 0; i < paramList.Count; i++)
                {
                    paramDict[i + 1] = paramList[i];
                }
            }

            // Branch to new section
            SectionAddress nextAddr = new SectionAddress(p, p.Sections[sectionName]);

            s.Logger.LogStartOfSection(s, nextAddr, s.CurDepth, inCurrentPlugin, paramDict, cmd, forceLog);

            Dictionary <string, string>      localVars   = null;
            Dictionary <string, string>      fixedVars   = null;
            Dictionary <string, CodeCommand> localMacros = null;

            if (cmd.Type == CodeType.Exec)
            {
                // Backup Varaibles and Macros
                localVars   = s.Variables.GetVarDict(VarsType.Local);
                fixedVars   = s.Variables.GetVarDict(VarsType.Fixed);
                localMacros = s.Macro.LocalDict;

                // Load Per-Plugin Variables
                s.Variables.ResetVariables(VarsType.Local);
                List <LogInfo> varLogs = s.Variables.LoadDefaultPluginVariables(p);
                s.Logger.Build_Write(s, LogInfo.AddDepth(varLogs, s.CurDepth + 1));

                // Load Per-Plugin Macro
                s.Macro.ResetLocalMacros();
                List <LogInfo> macroLogs = s.Macro.LoadLocalMacroDict(p, false);
                s.Logger.Build_Write(s, LogInfo.AddDepth(macroLogs, s.CurDepth + 1));
            }

            // Run Section
            int depthBackup = s.CurDepth;
            int errorOffStartLineIdxBackup = s.ErrorOffStartLineIdx;
            int erroroffCountBackup        = s.ErrorOffLineCount;

            Engine.RunSection(s, nextAddr, paramDict, s.CurDepth + 1, callback);

            if (cmd.Type == CodeType.Exec)
            {
                // Restore Variables
                s.Variables.SetVarDict(VarsType.Local, localVars);
                s.Variables.SetVarDict(VarsType.Fixed, fixedVars);

                // Restore Local Macros
                s.Macro.SetLocalMacros(localMacros);
            }

            s.CurDepth             = depthBackup;
            s.ErrorOffStartLineIdx = errorOffStartLineIdxBackup;
            s.ErrorOffLineCount    = erroroffCountBackup;
            s.Logger.LogEndOfSection(s, nextAddr, s.CurDepth, inCurrentPlugin, cmd, forceLog);
        }
Example #28
0
        public static List <LogInfo> Math(EngineState s, CodeCommand cmd)
        {
            List <LogInfo> logs = new List <LogInfo>();

            CodeInfo_Math info = cmd.Info.Cast <CodeInfo_Math>();

            MathType type = info.Type;

            switch (type)
            {
            case MathType.Add:
            case MathType.Sub:
            case MathType.Mul:
            case MathType.Div:
            {
                MathInfo_Arithmetic subInfo = info.SubInfo.Cast <MathInfo_Arithmetic>();

                string srcStr1 = StringEscaper.Preprocess(s, subInfo.Src1);
                string srcStr2 = StringEscaper.Preprocess(s, subInfo.Src2);

                if (!NumberHelper.ParseDecimal(srcStr1, out decimal src1))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{srcStr1}] is not a valid integer"));
                }
                if (!NumberHelper.ParseDecimal(srcStr2, out decimal src2))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{srcStr2}] is not a valid integer"));
                }

                decimal destInt;
                switch (type)
                {
                case MathType.Add:
                    destInt = src1 + src2;
                    break;

                case MathType.Sub:
                    destInt = src1 - src2;
                    break;

                case MathType.Mul:
                    destInt = src1 * src2;
                    break;

                case MathType.Div:
                    destInt = src1 / src2;
                    break;

                default:
                    throw new InternalException("Internal Logic Error at Math,Arithmetic");
                }

                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, destInt.ToString(CultureInfo.InvariantCulture)));
            }
            break;

            case MathType.IntDiv:
            {
                MathInfo_IntDiv subInfo = info.SubInfo.Cast <MathInfo_IntDiv>();

                string srcStr1 = StringEscaper.Preprocess(s, subInfo.Src1);
                string srcStr2 = StringEscaper.Preprocess(s, subInfo.Src2);

                if (srcStr1.StartsWith("-", StringComparison.Ordinal) ||
                    srcStr2.StartsWith("-", StringComparison.Ordinal))
                {         // Signed
                    if (!NumberHelper.ParseInt64(srcStr1, out long src1))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{srcStr1}] is not a valid integer"));
                    }
                    if (!NumberHelper.ParseInt64(srcStr2, out long src2))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{srcStr2}] is not a valid integer"));
                    }

                    long q = src1 / src2;
                    long r = src1 % src2;

                    logs.AddRange(Variables.SetVariable(s, subInfo.QuotientVar, q.ToString()));
                    logs.AddRange(Variables.SetVariable(s, subInfo.RemainderVar, r.ToString()));
                }
                else
                {         // Unsigned
                    if (!NumberHelper.ParseUInt64(srcStr1, out ulong src1))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{srcStr1}] is not a valid integer"));
                    }
                    if (!NumberHelper.ParseUInt64(srcStr2, out ulong src2))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{srcStr2}] is not a valid integer"));
                    }

                    ulong q = src1 / src2;
                    ulong r = src1 % src2;

                    logs.AddRange(Variables.SetVariable(s, subInfo.QuotientVar, q.ToString()));
                    logs.AddRange(Variables.SetVariable(s, subInfo.RemainderVar, r.ToString()));
                }
            }
            break;

            case MathType.Neg:
            {
                MathInfo_Neg subInfo = info.SubInfo.Cast <MathInfo_Neg>();

                string srcStr = StringEscaper.Preprocess(s, subInfo.Src);
                if (!NumberHelper.ParseDecimal(srcStr, out decimal src))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                }

                decimal destInt = src * -1;
                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, destInt.ToString(CultureInfo.InvariantCulture)));
            }
            break;

            case MathType.ToSign:
            case MathType.ToUnsign:
            {
                // Math,IntSign,<DestVar>,<Src>,<BitSize>
                // Math,IntUnsign,<DestVar>,<Src>,<BitSize>
                MathInfo_IntegerSignedness subInfo = info.SubInfo.Cast <MathInfo_IntegerSignedness>();

                string srcStr     = StringEscaper.Preprocess(s, subInfo.Src);
                string bitSizeStr = StringEscaper.Preprocess(s, subInfo.BitSize);
                string errorMsg   = ParseAndCheckBitSize(bitSizeStr, out int bitSize);
                if (errorMsg != null)
                {
                    return(LogInfo.LogErrorMessage(logs, errorMsg));
                }

                string destStr;
                if (info.Type == MathType.ToSign)
                {         // Unsigned int to signed int
                    switch (bitSize)
                    {
                    case 8:
                    {
                        if (!NumberHelper.ParseUInt8(srcStr, out byte src))
                        {
                            return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                        }

                        destStr = ((sbyte)src).ToString();
                    }
                    break;

                    case 16:
                    {
                        if (!NumberHelper.ParseUInt16(srcStr, out ushort src))
                        {
                            return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                        }

                        destStr = ((short)src).ToString();
                    }
                    break;

                    case 32:
                    {
                        if (!NumberHelper.ParseUInt32(srcStr, out uint src))
                        {
                            return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                        }

                        destStr = ((int)src).ToString();
                    }
                    break;

                    case 64:
                    {
                        if (!NumberHelper.ParseUInt64(srcStr, out ulong src))
                        {
                            return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                        }

                        destStr = ((long)src).ToString();
                    }
                    break;

                    default:
                        throw new InternalException("Internal Logic Error at Math,ToSign");
                    }
                }
                else
                {         // Signed int to unsigned int
                    switch (bitSize)
                    {
                    case 8:
                    {
                        if (!NumberHelper.ParseInt8(srcStr, out sbyte src))
                        {
                            return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                        }

                        destStr = ((byte)src).ToString();
                    }
                    break;

                    case 16:
                    {
                        if (!NumberHelper.ParseInt16(srcStr, out short src))
                        {
                            return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                        }

                        destStr = ((ushort)src).ToString();
                    }
                    break;

                    case 32:
                    {
                        if (!NumberHelper.ParseInt32(srcStr, out int src))
                        {
                            return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                        }

                        destStr = ((uint)src).ToString();
                    }
                    break;

                    case 64:
                    {
                        if (!NumberHelper.ParseInt64(srcStr, out long src))
                        {
                            return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                        }

                        destStr = ((ulong)src).ToString();
                    }
                    break;

                    default:
                        throw new InternalException("Internal Logic Error at Math,ToUnsign");
                    }
                }

                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, destStr));
            }
            break;

            case MathType.BoolAnd:
            case MathType.BoolOr:
            case MathType.BoolXor:
            {
                MathInfo_BoolLogicOperation subInfo = info.SubInfo.Cast <MathInfo_BoolLogicOperation>();

                string srcStr1 = StringEscaper.Preprocess(s, subInfo.Src1);
                string srcStr2 = StringEscaper.Preprocess(s, subInfo.Src2);

                bool src1;
                if (NumberHelper.ParseInt64(srcStr1, out long srcInt1))         // C-Style Boolean
                {
                    src1 = srcInt1 != 0;
                }
                else if (srcStr1.Equals("True", StringComparison.OrdinalIgnoreCase))
                {
                    src1 = true;
                }
                else if (srcStr1.Equals("False", StringComparison.OrdinalIgnoreCase))
                {
                    src1 = false;
                }
                else
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{srcStr1}] is not valid boolean value"));
                }

                bool src2;
                if (NumberHelper.ParseInt64(srcStr2, out long srcInt2))         // C-Style Boolean
                {
                    src2 = srcInt2 != 0;
                }
                else if (srcStr2.Equals("True", StringComparison.OrdinalIgnoreCase))
                {
                    src2 = true;
                }
                else if (srcStr2.Equals("False", StringComparison.OrdinalIgnoreCase))
                {
                    src2 = false;
                }
                else
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{srcStr2}] is not valid boolean value"));
                }

                bool dest;
                switch (type)
                {
                case MathType.BoolAnd:
                    dest = src1 && src2;
                    break;

                case MathType.BoolOr:
                    dest = src1 || src2;
                    break;

                case MathType.BoolXor:
                    dest = src1 ^ src2;
                    break;

                default:
                    throw new InternalException("Internal Logic Error at Math,BoolLogicOper");
                }

                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, dest.ToString()));
            }
            break;

            case MathType.BoolNot:
            {
                MathInfo_BoolNot subInfo = info.SubInfo.Cast <MathInfo_BoolNot>();

                bool   src;
                string srcStr = StringEscaper.Preprocess(s, subInfo.Src);
                if (NumberHelper.ParseInt64(srcStr, out long srcInt))         // C-Style Boolean
                {
                    src = srcInt != 0;
                }
                else if (srcStr.Equals("True", StringComparison.OrdinalIgnoreCase))
                {
                    src = true;
                }
                else if (srcStr.Equals("False", StringComparison.OrdinalIgnoreCase))
                {
                    src = false;
                }
                else
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not valid boolean value"));
                }

                bool dest = !src;
                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, dest.ToString()));
            }
            break;

            case MathType.BitAnd:
            case MathType.BitOr:
            case MathType.BitXor:
            {
                MathInfo_BitLogicOperation subInfo = info.SubInfo.Cast <MathInfo_BitLogicOperation>();

                string srcStr1 = StringEscaper.Preprocess(s, subInfo.Src1);
                string srcStr2 = StringEscaper.Preprocess(s, subInfo.Src2);

                if (!NumberHelper.ParseUInt64(srcStr1, out ulong src1))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{srcStr1}] is not a valid integer"));
                }
                if (!NumberHelper.ParseUInt64(srcStr2, out ulong src2))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{srcStr2}] is not a valid integer"));
                }

                ulong dest;
                switch (type)
                {
                case MathType.BitAnd:
                    dest = src1 & src2;
                    break;

                case MathType.BitOr:
                    dest = src1 | src2;
                    break;

                case MathType.BitXor:
                    dest = src1 ^ src2;
                    break;

                default:
                    throw new InternalException("Internal Logic Error at Math,BitLogicOper");
                }

                string destStr = dest.ToString();
                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, destStr));
            }
            break;

            case MathType.BitNot:
            {
                MathInfo_BitNot subInfo = info.SubInfo.Cast <MathInfo_BitNot>();

                string srcStr     = StringEscaper.Preprocess(s, subInfo.Src);
                string bitSizeStr = StringEscaper.Preprocess(s, subInfo.BitSize);
                string errorMsg   = ParseAndCheckBitSize(bitSizeStr, out int bitSize);
                if (errorMsg != null)
                {
                    return(LogInfo.LogErrorMessage(logs, errorMsg));
                }

                string destStr;
                switch (bitSize)
                {
                case 8:
                {
                    if (!NumberHelper.ParseUInt8(srcStr, out byte src))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                    }

                    destStr = ((byte)~src).ToString();
                }
                break;

                case 16:
                {
                    if (!NumberHelper.ParseUInt16(srcStr, out ushort src))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                    }

                    destStr = ((ushort)~src).ToString();
                }
                break;

                case 32:
                {
                    if (!NumberHelper.ParseUInt32(srcStr, out uint src))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                    }

                    destStr = (~src).ToString();
                }
                break;

                case 64:
                {
                    if (!NumberHelper.ParseUInt64(srcStr, out ulong src))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                    }

                    destStr = (~src).ToString();
                }
                break;

                default:
                    throw new InternalException("Internal Logic Error at Math,BitNot");
                }

                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, destStr));
            }
            break;

            case MathType.BitShift:
            {
                MathInfo_BitShift subInfo = info.SubInfo.Cast <MathInfo_BitShift>();

                string srcStr = StringEscaper.Preprocess(s, subInfo.Src);

                string shiftStr = StringEscaper.Preprocess(s, subInfo.Shift);
                if (!NumberHelper.ParseInt32(shiftStr, out int shift))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{shiftStr}] is not a valid integer"));
                }

                string directionStr = StringEscaper.Preprocess(s, subInfo.Direction);
                bool   isLeft       = false;
                if (directionStr.Equals("Left", StringComparison.OrdinalIgnoreCase))
                {
                    isLeft = true;
                }
                else if (!directionStr.Equals("Right", StringComparison.OrdinalIgnoreCase))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{directionStr}] must be one of [Left, Right]"));
                }

                string bitSizeStr = StringEscaper.Preprocess(s, subInfo.BitSize);
                string errorMsg   = ParseAndCheckBitSize(bitSizeStr, out int bitSize);
                if (errorMsg != null)
                {
                    return(LogInfo.LogErrorMessage(logs, errorMsg));
                }

                string destStr;
                switch (bitSize)
                {
                case 8:
                {
                    if (!NumberHelper.ParseUInt8(srcStr, out byte src))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                    }

                    byte dest;
                    if (isLeft)
                    {
                        dest = (byte)(src << shift);
                    }
                    else
                    {
                        dest = (byte)(src >> shift);
                    }
                    destStr = dest.ToString();
                }
                break;

                case 16:
                {
                    if (!NumberHelper.ParseUInt16(srcStr, out ushort src))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                    }

                    ushort dest;
                    if (isLeft)
                    {
                        dest = (ushort)(src << shift);
                    }
                    else
                    {
                        dest = (ushort)(src >> shift);
                    }
                    destStr = dest.ToString();
                }
                break;

                case 32:
                {
                    if (!NumberHelper.ParseUInt32(srcStr, out uint src))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                    }

                    uint dest;
                    if (isLeft)
                    {
                        dest = src << shift;
                    }
                    else
                    {
                        dest = src >> shift;
                    }
                    destStr = dest.ToString();
                }
                break;

                case 64:
                {
                    if (!NumberHelper.ParseUInt64(srcStr, out ulong src))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                    }

                    ulong dest;
                    if (isLeft)
                    {
                        dest = src << shift;
                    }
                    else
                    {
                        dest = src >> shift;
                    }
                    destStr = dest.ToString();
                }
                break;

                default:
                    throw new InternalException("Internal Logic Error at Math,BitShift");
                }

                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, destStr));
            }
            break;

            case MathType.Ceil:
            case MathType.Floor:
            case MathType.Round:
            {
                MathInfo_CeilFloorRound subInfo = info.SubInfo.Cast <MathInfo_CeilFloorRound>();

                string srcStr = StringEscaper.Preprocess(s, subInfo.Src);
                if (!NumberHelper.ParseInt64(srcStr, out long srcInt))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                }

                string unitStr = StringEscaper.Preprocess(s, subInfo.Unit);
                // Is roundToStr number?
                if (!NumberHelper.ParseInt64(unitStr, out long unit))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{unitStr}] is not a valid integer"));
                }
                if (unit < 0)
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{unit}] must be positive integer"));
                }

                long destInt;
                long remainder = srcInt % unit;
                switch (type)
                {
                case MathType.Ceil:
                    destInt = srcInt - remainder + unit;
                    break;

                case MathType.Floor:
                    destInt = srcInt - remainder;
                    break;

                case MathType.Round:
                    if ((unit - 1) / 2 < remainder)
                    {
                        destInt = srcInt - remainder + unit;
                    }
                    else
                    {
                        destInt = srcInt - remainder;
                    }
                    break;

                default:
                    throw new InternalException($"Internal Logic Error at Math,{info.Type}");
                }

                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, destInt.ToString());
                logs.AddRange(varLogs);
            }
            break;

            case MathType.Abs:
            {
                MathInfo_Abs subInfo = info.SubInfo.Cast <MathInfo_Abs>();

                string srcStr = StringEscaper.Preprocess(s, subInfo.Src);
                if (!NumberHelper.ParseDecimal(srcStr, out decimal src))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{srcStr}] is not a valid integer"));
                }

                decimal dest = System.Math.Abs(src);
                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, dest.ToString(CultureInfo.InvariantCulture)));
            }
            break;

            case MathType.Pow:
            {
                MathInfo_Pow subInfo = info.SubInfo.Cast <MathInfo_Pow>();

                string baseStr = StringEscaper.Preprocess(s, subInfo.Base);
                if (!NumberHelper.ParseDecimal(baseStr, out decimal _base))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{baseStr}] is not a valid integer"));
                }

                string powerStr = StringEscaper.Preprocess(s, subInfo.Power);
                if (!NumberHelper.ParseUInt32(powerStr, out uint power))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{baseStr}] is not a postivie integer"));
                }

                decimal dest = NumberHelper.DecimalPower(_base, power);
                logs.AddRange(Variables.SetVariable(s, subInfo.DestVar, dest.ToString(CultureInfo.InvariantCulture)));
            }
            break;

            case MathType.Hex:
            case MathType.Dec:
            {
                MathInfo_HexDec subInfo = info.SubInfo.Cast <MathInfo_HexDec>();

                string intStr     = StringEscaper.Preprocess(s, subInfo.Src);
                string bitSizeStr = StringEscaper.Preprocess(s, subInfo.BitSize);
                string errorMsg   = ParseAndCheckBitSize(bitSizeStr, out int bitSize);
                if (errorMsg != null)
                {
                    return(LogInfo.LogErrorMessage(logs, errorMsg));
                }

                string dest;
                switch (bitSize)
                {
                case 8:
                    if (!NumberHelper.ParseSignedAsUInt8(intStr, out byte u8))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{intStr}] is not a valid 8bit integer"));
                    }
                    dest = info.Type == MathType.Hex ? $"0x{u8:X2}" : u8.ToString();
                    break;

                case 16:
                    if (!NumberHelper.ParseSignedAsUInt16(intStr, out ushort u16))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{intStr}] is not a valid 16bit integer"));
                    }
                    dest = info.Type == MathType.Hex ? $"0x{u16:X4}" : u16.ToString();
                    break;

                case 32:
                    if (!NumberHelper.ParseSignedAsUInt32(intStr, out uint u32))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{intStr}] is not a valid 32bit integer"));
                    }
                    dest = info.Type == MathType.Hex ? $"0x{u32:X8}" : u32.ToString();
                    break;

                case 64:
                    if (!NumberHelper.ParseSignedAsUInt64(intStr, out ulong u64))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{intStr}] is not a valid 64bit integer"));
                    }
                    dest = info.Type == MathType.Hex ? $"0x{u64:X16}" : u64.ToString();
                    break;

                default:
                    throw new InternalException($"Internal Logic Error at Math,{info.Type}");
                }

                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, dest);
                logs.AddRange(varLogs);
            }
            break;

            case MathType.Rand:
            {
                MathInfo_Rand subInfo = info.SubInfo.Cast <MathInfo_Rand>();

                int min = 0;
                if (subInfo.Min != null)
                {
                    string minStr = StringEscaper.Preprocess(s, subInfo.Min);
                    if (!NumberHelper.ParseInt32(minStr, out min))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{minStr}] is not a valid integer"));
                    }
                    if (min < 0)
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{min}] must be positive integer"));
                    }
                }

                int max = 65536;
                if (subInfo.Max != null)
                {
                    string maxStr = StringEscaper.Preprocess(s, subInfo.Max);
                    if (!NumberHelper.ParseInt32(maxStr, out max))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{maxStr}] is not a valid integer"));
                    }
                    if (max < 0)
                    {
                        return(LogInfo.LogErrorMessage(logs, $"[{max}] must be positive integer"));
                    }
                    if (max <= min)
                    {
                        return(LogInfo.LogErrorMessage(logs, "Maximum bounds must be larger than minimum value"));
                    }
                }

                int destInt = s.Random.Next() % (max - min) + min;

                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, destInt.ToString());
                logs.AddRange(varLogs);
            }
            break;

            default:     // Error
                throw new InternalException("Internal Logic Error at CommandMath.Math");
            }

            return(logs);
        }
Example #29
0
        public static List <LogInfo> RegWrite(EngineState s, CodeCommand cmd)
        { // RegWrite,<HKey>,<ValueType>,<KeyPath>,<ValueName>,<ValueData>,[OptionalData]
            List <LogInfo> logs = new List <LogInfo>();

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

            string keyPath   = StringEscaper.Preprocess(s, info.KeyPath);
            string valueName = null;

            if (info.ValueName != null)
            {
                valueName = StringEscaper.Preprocess(s, info.ValueName);
            }

            if (info.HKey == null)
            {
                throw new InternalException("Internal Logic Error");
            }
            string hKeyStr = RegistryHelper.RegKeyToString(info.HKey);

            string fullKeyPath   = $"{hKeyStr}\\{keyPath}";
            string fullValuePath = $"{hKeyStr}\\{keyPath}\\{valueName}";

            using (RegistryKey subKey = info.HKey.CreateSubKey(keyPath, true))
            {
                if (valueName == null)
                {
                    logs.Add(new LogInfo(LogState.Success, $"Registry subkey [{fullKeyPath}] created"));
                    return(logs);
                }

                object checkData = subKey.GetValue(valueName);
                if (checkData != null)
                {
                    logs.Add(new LogInfo(info.NoWarn ? LogState.Ignore : LogState.Overwrite, $"Registry value [{fullValuePath}] already exists"));
                }

                switch (info.ValueType)
                {
                case RegistryValueKind.None:
                {
                    subKey.SetValue(valueName, new byte[0], RegistryValueKind.None);
                    logs.Add(new LogInfo(LogState.Success, $"Registry value [{fullValuePath}] set to REG_NONE"));
                }
                break;

                case RegistryValueKind.String:
                {
                    string valueData = StringEscaper.Preprocess(s, info.ValueData);
                    subKey.SetValue(valueName, valueData, RegistryValueKind.String);
                    logs.Add(new LogInfo(LogState.Success, $"Registry value [{fullValuePath}] set to REG_SZ [{valueData}]"));
                }
                break;

                case RegistryValueKind.ExpandString:
                {
                    string valueData = StringEscaper.Preprocess(s, info.ValueData);
                    subKey.SetValue(valueName, valueData, RegistryValueKind.ExpandString);
                    logs.Add(new LogInfo(LogState.Success, $"Registry value [{fullValuePath}] set to REG_EXPAND_SZ [{valueData}]"));
                }
                break;

                case RegistryValueKind.MultiString:
                {
                    string[] multiStrs = StringEscaper.Preprocess(s, info.ValueDatas).ToArray();
                    subKey.SetValue(valueName, multiStrs, RegistryValueKind.MultiString);
                    string valueData = StringEscaper.PackRegMultiBinary(multiStrs);
                    logs.Add(new LogInfo(LogState.Success, $"Registry value [{fullValuePath}] set to REG_MULTI_SZ [{valueData}]"));
                }
                break;

                case RegistryValueKind.Binary:
                {
                    if (info.ValueData == null)
                    {         // Use info.ValueDatas
                        string[] binStrs   = StringEscaper.Preprocess(s, info.ValueDatas).ToArray();
                        string   valueData = StringEscaper.PackRegBinary(binStrs);
                        if (!StringEscaper.UnpackRegBinary(binStrs, out byte[] binData))
Example #30
0
        public void ReadAllFilesInfo()
        {
            // ReSharper disable once InconsistentNaming
            const string FolderExample = "FolderExample";

            EngineState s = EngineTests.CreateEngineState();
            string      pbOriginScript = Path.Combine("%TestBench%", "EncodedFile", "ExtractFileTests.script");
            string      originScript   = StringEscaper.Preprocess(s, pbOriginScript);

            Script sc = s.Project.LoadScriptRuntime(originScript, new LoadScriptRuntimeOptions());

            // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local
            void Template(bool inspectEncodedSize, Dictionary <string, List <EncodedFileInfo> > compDict)
            {
                ReadFileInfoOptions opts = new ReadFileInfoOptions
                {
                    InspectEncodeMode = inspectEncodedSize,
                };
                ResultReport <Dictionary <string, List <EncodedFileInfo> > > report = EncodedFile.ReadAllFilesInfo(sc, opts);

                Assert.IsTrue(report.Success);
                Dictionary <string, List <EncodedFileInfo> > infoDict = report.Result;

                Assert.AreEqual(compDict.Count, infoDict.Count);
                foreach (var kv in compDict)
                {
                    Assert.IsTrue(infoDict.ContainsKey(kv.Key));
                    Assert.AreEqual(kv.Value.Count, infoDict[kv.Key].Count);
                    foreach (EncodedFileInfo fileInfo in kv.Value)
                    {
                        Assert.IsTrue(infoDict[kv.Key].Contains(fileInfo));
                    }
                }
            }

            Dictionary <string, List <EncodedFileInfo> > compDetailDict = new Dictionary <string, List <EncodedFileInfo> >
            {
                ["FolderExample"] = new List <EncodedFileInfo>
                {
                    new EncodedFileInfo
                    {
                        FolderName  = FolderExample,
                        FileName    = "Type1.jpg",
                        RawSize     = 7683,
                        EncodedSize = 10244,
                        EncodeMode  = EncodeMode.ZLib
                    },
                    new EncodedFileInfo
                    {
                        FolderName  = FolderExample,
                        FileName    = "Type2.7z",
                        RawSize     = 1631,
                        EncodedSize = 2175,
                        EncodeMode  = EncodeMode.Raw
                    },
                    new EncodedFileInfo
                    {
                        FolderName  = FolderExample,
                        FileName    = "Type3.pdf",
                        RawSize     = 88692,
                        EncodedSize = 102908,
                        EncodeMode  = EncodeMode.XZ
                    }
                },
                ["FolderRun"] = new List <EncodedFileInfo>
                {
                    new EncodedFileInfo
                    {
                        FolderName  = "FolderRun",
                        FileName    = "TestBatch.cmd",
                        RawSize     = 34,
                        EncodedSize = 144,
                        EncodeMode  = EncodeMode.Raw
                    }
                },
                ["BannerImage"] = new List <EncodedFileInfo>
                {
                    new EncodedFileInfo
                    {
                        FolderName  = "BannerImage",
                        FileName    = "Banner.bmp",
                        RawSize     = 17626,
                        EncodedSize = 23502,
                        EncodeMode  = EncodeMode.ZLib
                    },
                    new EncodedFileInfo
                    {
                        FolderName  = "BannerImage",
                        FileName    = "Banner.svg",
                        RawSize     = 4715,
                        EncodedSize = 6287,
                        EncodeMode  = EncodeMode.ZLib
                    },
                }
            };

            Dictionary <string, List <EncodedFileInfo> > compNoDetailDict = new Dictionary <string, List <EncodedFileInfo> >();

            foreach (var kv in compDetailDict)
            {
                compNoDetailDict[kv.Key] = new List <EncodedFileInfo>();
                foreach (EncodedFileInfo info in kv.Value)
                {
                    EncodedFileInfo clone = info.Clone() as EncodedFileInfo;
                    Assert.IsTrue(clone != null);

                    clone.EncodeMode = null;

                    compNoDetailDict[kv.Key].Add(clone);
                }
            }

            Template(true, compDetailDict);
            Template(false, compNoDetailDict);
        }