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); }
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)); } } }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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
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)); } }
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); }
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)); } }
/* * 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); }
/// <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); }
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); }
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); }
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); }
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); }
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); }
/// <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); }
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"); }
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); }
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); }
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))
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); }