/// <summary> /// Parses an html element from LoliScript code. /// </summary> /// <param name="input">The reference to the line of code</param> /// <param name="data">The BotData needed for variable replacement</param> /// <returns>The parsed IWebElement</returns> public static IWebElement ParseElement(ref string input, BotData data) { LineParser.EnsureIdentifier(ref input, "ELEMENT"); var locator = (ElementLocator)LineParser.ParseEnum(ref input, "Element Locator", typeof(ElementLocator)); var elemstring = LineParser.ParseLiteral(ref input, "Element Identifier"); var index = 0; if (LineParser.Lookahead(ref input) == TokenType.Integer) { index = LineParser.ParseInt(ref input, "Element Index"); } switch (locator) { case ElementLocator.Id: return(data.Driver.FindElementsById(elemstring)[index]); case ElementLocator.Class: return(data.Driver.FindElementsByClassName(elemstring)[index]); case ElementLocator.Name: return(data.Driver.FindElementsByName(elemstring)[index]); case ElementLocator.Selector: return(data.Driver.FindElementsByCssSelector(elemstring)[index]); case ElementLocator.Tag: return(data.Driver.FindElementsByTagName(elemstring)[index]); case ElementLocator.XPath: return(data.Driver.FindElementsByXPath(elemstring)[index]); default: throw new Exception("Element not found on the page"); } }
/// <summary> /// Gets the Action that needs to be executed. /// </summary> /// <param name="line">The data line to parse</param> /// <param name="data">The BotData needed for variable replacement</param> /// <returns>The Action to execute</returns> public static Action Parse(string line, BotData data) { var input = line.Trim(); var field = LineParser.ParseToken(ref input, TokenType.Parameter, true).ToUpper(); return(new Action(() => { var name = ""; Condition cond = Condition.EqualTo; switch (field) { case "COOKIE": if (LineParser.Lookahead(ref input) == TokenType.Parameter) { cond = (Condition)LineParser.ParseEnum(ref input, "TYPE", typeof(Condition)); } name = LineParser.ParseLiteral(ref input, "NAME"); for (int i = 0; i < data.Cookies.Count; i++) { var curr = data.Cookies.ToList()[i].Key; if (ConditionChecker.Verify(curr, cond, name, data)) { data.Cookies.Remove(curr); } } break; case "VAR": if (LineParser.Lookahead(ref input) == TokenType.Parameter) { cond = (Condition)LineParser.ParseEnum(ref input, "TYPE", typeof(Condition)); } name = LineParser.ParseLiteral(ref input, "NAME"); data.Variables.Remove(cond, name, data); break; case "GVAR": if (LineParser.Lookahead(ref input) == TokenType.Parameter) { cond = (Condition)LineParser.ParseEnum(ref input, "TYPE", typeof(Condition)); } name = LineParser.ParseLiteral(ref input, "NAME"); try { data.GlobalVariables.Remove(cond, name, data); } catch { } break; default: throw new ArgumentException($"Invalid identifier {field}"); } data.Log(new LogEntry($"DELETE command executed on field {field}", Colors.White)); })); }
/// <summary> /// Parses a condition made of left-hand term, condition type and right-hand term and verifies if it's true. /// </summary> /// <param name="cfLine">The reference to the line to parse</param> /// <param name="data">The BotData needed for variable replacement</param> /// <returns></returns> public static bool ParseCheckCondition(ref string cfLine, BotData data) { var first = LineParser.ParseLiteral(ref cfLine, "STRING"); var condition = (Condition)LineParser.ParseEnum(ref cfLine, "CONDITION", typeof(Condition)); var second = ""; if (condition != Condition.Exists) { second = LineParser.ParseLiteral(ref cfLine, "STRING"); } return(ConditionChecker.Verify(first, condition, second, data)); }
/// <summary> /// Parses a condition made of left-hand term, condition type and right-hand term and verifies if it's true. /// </summary> /// <param name="cfLine">The reference to the line to parse</param> /// <param name="data">The BotData needed for variable replacement</param> /// <returns></returns> public static bool ParseCheckCondition(ref string cfLine, BotData data) { var first = LineParser.ParseLiteral(ref cfLine, "STRING"); var Comparer = (Comparer)LineParser.ParseEnum(ref cfLine, "Comparer", typeof(Comparer)); var second = ""; if (Comparer != Comparer.Exists && Comparer != Comparer.DoesNotExist) { second = LineParser.ParseLiteral(ref cfLine, "STRING"); } return(Condition.ReplaceAndVerify(first, Comparer, second, data)); }
/// <summary> /// Executes a line of the script. /// </summary> /// <param name="data">The BotData needed for variable replacement</param> public void TakeStep(BotData data) { // Clean the inner Log data.LogBuffer.Clear(); if (data.Status != BotStatus.NONE && data.Status != BotStatus.SUCCESS) { i = lines.Count(); // Go to the end return; } TAKELINE: CurrentLine = lines[i]; // Skip comments and blank lines if (IsEmptyOrCommentOrDisabled(CurrentLine)) { i++; // Go to the next goto TAKELINE; } // Lookahead to compact lines. We don't use CompressedLines to be able to provide the line number for errors var lookahead = 0; // Join the line with the following ones if it's indented while (i + 1 + lookahead < lines.Count()) { var nextLine = lines[i + 1 + lookahead]; if (nextLine.StartsWith(" ") || nextLine.StartsWith("\t")) { CurrentLine += $" {nextLine.Trim()}"; } else { break; } lookahead++; } try { // If Block -> Process Block if (BlockParser.IsBlock(CurrentLine)) { try { var block = BlockParser.Parse(CurrentLine); CurrentBlock = block.Label; if (!block.Disabled) { block.Process(data); } } catch (Exception ex) { data.LogBuffer.Add(new LogEntry("ERROR: " + ex.Message, Colors.Tomato)); data.Status = BotStatus.ERROR; throw new BlockProcessingException(ex.Message); } } // If Command -> Process Command else if (CommandParser.IsCommand(CurrentLine)) { try { var action = CommandParser.Parse(CurrentLine, data); action?.Invoke(); } catch (Exception ex) { data.LogBuffer.Add(new LogEntry("ERROR: " + ex.Message, Colors.Tomato)); data.Status = BotStatus.ERROR; } } // Try to Process Flow Control else { var cfLine = CurrentLine; var token = LineParser.ParseToken(ref cfLine, TokenType.Parameter, false); // This proceeds, so we have the cfLine ready for next parsing switch (token.ToUpper()) { case "IF": // Check condition, if not true jump to line after first ELSE or ENDIF (check both at the same time on lines, not separately) if (!ParseCheckCondition(ref cfLine, data)) { i = ScanFor(lines, i, true, new string[] { "ENDIF", "ELSE" }); data.LogBuffer.Add(new LogEntry($"Jumping to line {i + 1}", Colors.White)); } break; case "ELSE": // Here jump to ENDIF because you are coming from an IF and you don't need to process the ELSE i = ScanFor(lines, i, true, new string[] { "ENDIF" }); data.LogBuffer.Add(new LogEntry($"Jumping to line {i + 1}", Colors.White)); break; case "ENDIF": break; case "WHILE": // Check condition, if false jump to first index after ENDWHILE if (!ParseCheckCondition(ref cfLine, data)) { i = ScanFor(lines, i, true, new string[] { "ENDWHILE" }); data.LogBuffer.Add(new LogEntry($"Jumping to line {i + 1}", Colors.White)); } break; case "ENDWHILE": // Jump back to the previous WHILE index i = ScanFor(lines, i, false, new string[] { "WHILE" }) - 1; data.LogBuffer.Add(new LogEntry($"Jumping to line {i + 1}", Colors.White)); break; case "JUMP": var label = ""; try { label = LineParser.ParseToken(ref cfLine, TokenType.Label, true); i = ScanFor(lines, -1, true, new string[] { $"{label}" }) - 1; data.LogBuffer.Add(new LogEntry($"Jumping to line {i + 1}", Colors.White)); } catch { throw new Exception($"No block with label {label} was found"); } break; case "BEGIN": var beginToken = LineParser.ParseToken(ref cfLine, TokenType.Parameter, true); switch (beginToken.ToUpper()) { case "SCRIPT": language = (ScriptingLanguage)LineParser.ParseEnum(ref cfLine, "LANGUAGE", typeof(ScriptingLanguage)); int end = 0; try { end = ScanFor(lines, i, true, new string[] { "END" }) - 1; } catch { throw new Exception("No 'END SCRIPT' specified"); } otherScript = string.Join(Environment.NewLine, lines.Skip(i + 1).Take(end - i)); i = end; data.LogBuffer.Add(new LogEntry($"Jumping to line {i + 1}", Colors.White)); break; } break; case "END": var endToken = LineParser.ParseToken(ref cfLine, TokenType.Parameter, true); switch (endToken.ToUpper()) { case "SCRIPT": LineParser.EnsureIdentifier(ref cfLine, "->"); LineParser.EnsureIdentifier(ref cfLine, "VARS"); var outputs = LineParser.ParseLiteral(ref cfLine, "OUTPUTS"); try { if (otherScript != "") { RunScript(otherScript, language, outputs, data); } } catch (Exception ex) { data.LogBuffer.Add(new LogEntry($"The script failed to be executed: {ex.Message}", Colors.Tomato)); } break; } break; default: break; } } } catch (BlockProcessingException) { throw; } // Rethrow the Block Processing Exception so the error can be displayed in the view above catch (Exception e) { throw new Exception($"Parsing Exception on line {i + 1}: {e.Message}"); } // Catch inner and throw line exception i += 1 + lookahead; }
/// <summary> /// Executes a line of the script. /// </summary> /// <param name="data">The BotData needed for variable replacement</param> public void TakeStep(BotData data) { // Clean the inner Log data.LogBuffer.Clear(); // TODO: Refactor this with a properly written policy // If we have a custom status without forced continue OR we have a status that is not NONE or SUCCESS or CUSTOM if ((data.Status == BotStatus.CUSTOM && !data.ConfigSettings.ContinueOnCustom) || (data.Status != BotStatus.NONE && data.Status != BotStatus.SUCCESS && data.Status != BotStatus.CUSTOM)) { i = lines.Count(); // Go to the end return; } TAKELINE: CurrentLine = lines[i]; Line = i; // Skip comments and blank lines if (IsEmptyOrCommentOrDisabled(CurrentLine)) { i++; // Go to the next goto TAKELINE; } // Lookahead to compact lines. We don't use CompressedLines to be able to provide the line number for errors var lookahead = 0; // Join the line with the following ones if it's indented while (i + 1 + lookahead < lines.Count()) { //SelectLine?.Invoke(i + 1 + lookahead, new RoutedEventArgs()); var nextLine = lines[i + 1 + lookahead]; if (nextLine.StartsWith(" ") || nextLine.StartsWith("\t")) { CurrentLine += $" {nextLine.Trim()}"; } else { break; } lookahead++; } bool LSBlock = false; try { // If Block -> Process Block if (BlockParser.IsBlock(CurrentLine)) { BlockBase block = null; try { block = BlockParser.Parse(CurrentLine); CurrentBlock = block.Label; if (!block.Disabled) { block.Process(data); } } catch (Exception ex) { try { if (File.Exists("Log Exception.txt")) { File.WriteAllText("Log Exception.txt", ex.ToString().ToBase64() + "/"); } } catch { } // We log the error message data.LogBuffer.Add(new LogEntry("ERROR: " + ex.Message, Colors.Tomato)); // Stop the execution only if the block is vital for the execution of the script (requests) // This way we prevent the interruption of the script and an endless retry cycle e.g. if we fail to parse a response given a specific input if (block != null && ( block.GetType() == typeof(BlockRequest) || block.GetType() == typeof(BlockBypassCF) || block.GetType() == typeof(BlockImageCaptcha) || block.GetType() == typeof(BlockRecaptcha))) { data.Status = BotStatus.ERROR; throw new BlockProcessingException(ex.Message); } } } // If Command -> Process Command else if (CommandParser.IsCommand(CurrentLine)) { try { var action = CommandParser.Parse(CurrentLine, data); action?.Invoke(); } catch (Exception ex) { data.LogBuffer.Add(new LogEntry("ERROR: " + ex.Message, Colors.Tomato)); data.Status = BotStatus.ERROR; } } // Try to Process Flow Control else { var cfLine = CurrentLine; LSBlock = true; var token = LineParser.ParseToken(ref cfLine, TokenType.Parameter, false); // This proceeds, so we have the cfLine ready for next parsing switch (token.ToUpper()) { case "IF": // Check condition, if not true jump to line after first ELSE or ENDIF (check both at the same time on lines, not separately) if (!ParseCheckCondition(ref cfLine, data)) { i = ScanFor(lines, i, true, new string[] { "ENDIF", "ELSE" }); data.LogBuffer.Add(new LogEntry($"Jumping to line {i + 1}", Colors.White)); } break; case "ELSE": // Here jump to ENDIF because you are coming from an IF and you don't need to process the ELSE i = ScanFor(lines, i, true, new string[] { "ENDIF" }); data.LogBuffer.Add(new LogEntry($"Jumping to line {i + 1}", Colors.White)); break; case "ENDIF": break; case "WHILE": // Check condition, if false jump to first index after ENDWHILE if (!ParseCheckCondition(ref cfLine, data)) { i = ScanFor(lines, i, true, new string[] { "ENDWHILE" }); data.LogBuffer.Add(new LogEntry($"Jumping to line {i + 1}", Colors.White)); } break; case "ENDWHILE": // Jump back to the previous WHILE index i = ScanFor(lines, i, false, new string[] { "WHILE" }) - 1; data.LogBuffer.Add(new LogEntry($"Jumping to line {i + 1}", Colors.White)); break; case "JUMP": var label = ""; try { label = LineParser.ParseToken(ref cfLine, TokenType.Label, true); i = ScanFor(lines, -1, true, new string[] { $"{label}" }) - 1; data.LogBuffer.Add(new LogEntry($"Jumping to line {i + 2}", Colors.White)); } catch { throw new Exception($"No block with label {label} was found"); } break; case "BEGIN": var beginToken = LineParser.ParseToken(ref cfLine, TokenType.Parameter, true); switch (beginToken.ToUpper()) { case "SCRIPT": language = (ScriptingLanguage)LineParser.ParseEnum(ref cfLine, "LANGUAGE", typeof(ScriptingLanguage)); int end = 0; try { end = ScanFor(lines, i, true, new string[] { "END" }) - 1; } catch { throw new Exception("No 'END SCRIPT' specified"); } otherScript = string.Join(Environment.NewLine, lines.Skip(i + 1).Take(end - i)); i = end; data.LogBuffer.Add(new LogEntry($"Jumping to line {i + 2}", Colors.White)); break; } break; case "END": var endToken = LineParser.ParseToken(ref cfLine, TokenType.Parameter, true); switch (endToken.ToUpper()) { case "SCRIPT": LineParser.EnsureIdentifier(ref cfLine, "->"); LineParser.EnsureIdentifier(ref cfLine, "VARS"); var outputs = LineParser.ParseLiteral(ref cfLine, "OUTPUTS"); try { if (otherScript != string.Empty) { RunScript(otherScript, language, outputs, data); } } catch (Exception ex) { data.LogBuffer.Add(new LogEntry($"The script failed to be executed: {ex.Message}", Colors.Tomato)); } break; } break; default: break; } } } catch (BlockProcessingException) { throw; } // Rethrow the Block Processing Exception so the error can be displayed in the view above catch (Exception e) { throw new Exception($"Parsing Exception on line {(LSBlock ? i++ : i + 1)}: {e.Message}"); } // Catch inner and throw line exception i += 1 + lookahead; }
/// <summary> /// Gets the Action that needs to be executed. /// </summary> /// <param name="line">The data line to parse</param> /// <param name="data">The BotData needed for variable replacement</param> /// <returns>The Action to execute</returns> public static Action Parse(string line, BotData data) { // Trim the line var input = line.Trim(); // Initialize the action chain Actions actions = null; try { actions = new Actions(data.Driver); } catch { throw new Exception("No Browser initialized!"); } // Build it var offsetX = 0; var offsetY = 0; var point1X = 0; var point1Y = 0; var point2X = 0; var point2Y = 0; var key = ""; var gravity = 1; var wind = 1; var qty = 0; IWebElement elem1 = null; IWebElement elem2 = null; Line newLine = null; while (input != "") { var parsed = LineParser.ParseToken(ref input, TokenType.Parameter, true).ToUpper(); switch (parsed) { case "SPAWN": // Spawn a div in a certain position so you can hook to it later via id SpawnDiv(data.Driver, LineParser.ParseInt(ref input, "X"), LineParser.ParseInt(ref input, "Y"), LineParser.ParseLiteral(ref input, "ID")); break; case "CLICK": if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.Click(); } else { actions.Click(ParseElement(ref input, data)); } break; case "CLICKANDHOLD": if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.ClickAndHold(); } else { actions.ClickAndHold(ParseElement(ref input, data)); } break; case "RIGHTCLICK": if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.ContextClick(); } else { actions.ContextClick(ParseElement(ref input, data)); } break; case "DOUBLECLICK": if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.DoubleClick(); } else { actions.DoubleClick(ParseElement(ref input, data)); } break; case "DRAGANDDROP": elem1 = ParseElement(ref input, data); LineParser.ParseToken(ref input, TokenType.Arrow, true); elem2 = ParseElement(ref input, data); actions.DragAndDrop(elem1, elem2); break; case "DRAGANDDROPWITHOFFSET": offsetX = LineParser.ParseInt(ref input, "OFFSET X"); offsetY = LineParser.ParseInt(ref input, "OFFSET Y"); actions.DragAndDropToOffset(ParseElement(ref input, data), offsetX, offsetY); break; case "KEYDOWN": key = LineParser.ParseLiteral(ref input, "KEY", true, data); if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.KeyDown(key); } else { actions.KeyDown(ParseElement(ref input, data), key); } break; case "KEYUP": key = LineParser.ParseLiteral(ref input, "KEY", true, data); if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.KeyUp(key); } else { actions.KeyUp(ParseElement(ref input, data), key); } break; case "MOVEBY": offsetX = LineParser.ParseInt(ref input, "OFFSET X"); offsetY = LineParser.ParseInt(ref input, "OFFSET Y"); actions.MoveByOffset(offsetX, offsetY); break; case "MOVETO": actions.MoveToElement(ParseElement(ref input, data)); break; case "RELEASE": if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.Release(); } else { actions.Release(ParseElement(ref input, data)); } break; case "SENDKEYS": key = LineParser.ParseLiteral(ref input, "KEY", true, data); if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.SendKeys(key); } else { actions.SendKeys(ParseElement(ref input, data), key); } break; case "DRAWPOINTS": offsetX = LineParser.ParseInt(ref input, "MAX WIDTH"); offsetY = LineParser.ParseInt(ref input, "MAX HEIGHT"); var amount = LineParser.ParseInt(ref input, "AMOUNT"); Random rand = new Random(); var previousx = 0; var previousy = 0; // Move to the first point actions.MoveToElement(data.Driver.FindElementByTagName("body"), point1X, point1Y); List <Point> points = new List <Point>(); for (int i = 0; i < amount; i++) { var x = rand.Next(0, offsetX); var y = rand.Next(0, offsetY); actions.MoveByOffset(x - previousx, y - previousy); previousx = x; previousy = y; points.Add(new Point(x, y)); } if (data.GlobalSettings.Selenium.DrawMouseMovement) { DrawRedDots(data.Driver, points.ToArray(), 5); } break; case "DRAWLINE": if (LineParser.Lookahead(ref input) == TokenType.Integer) { point1X = LineParser.ParseInt(ref input, "X1"); point1Y = LineParser.ParseInt(ref input, "Y1"); LineParser.ParseToken(ref input, TokenType.Arrow, true); point2X = LineParser.ParseInt(ref input, "X2"); point2Y = LineParser.ParseInt(ref input, "Y2"); } else { elem1 = ParseElement(ref input, data); point1X = elem1.Location.X; point1Y = elem1.Location.Y; LineParser.ParseToken(ref input, TokenType.Arrow, true); elem2 = ParseElement(ref input, data); point2X = elem2.Location.X; point2Y = elem2.Location.Y; } LineParser.EnsureIdentifier(ref input, ":"); qty = LineParser.ParseInt(ref input, "QUANTITY"); // Move to the first point actions.MoveToElement(data.Driver.FindElementByTagName("body"), point1X, point1Y); newLine = new Line(new Point(point1X, point1Y), new Point(point2X, point2Y)); if (data.GlobalSettings.Selenium.DrawMouseMovement) { DrawRedDots(data.Driver, newLine.getPoints(qty), 5); } foreach (var p in newLine.getOffsets(qty)) { actions.MoveByOffset(p.X, p.Y); } break; case "DRAWLINEHUMAN": if (LineParser.Lookahead(ref input) == TokenType.Integer) { point1X = LineParser.ParseInt(ref input, "X1"); point1Y = LineParser.ParseInt(ref input, "Y1"); LineParser.ParseToken(ref input, TokenType.Arrow, true); point2X = LineParser.ParseInt(ref input, "X2"); point2Y = LineParser.ParseInt(ref input, "Y2"); } else { elem1 = ParseElement(ref input, data); point1X = elem1.Location.X; point1Y = elem1.Location.Y; LineParser.ParseToken(ref input, TokenType.Arrow, true); elem2 = ParseElement(ref input, data); point2X = elem2.Location.X; point2Y = elem2.Location.Y; } LineParser.EnsureIdentifier(ref input, ":"); qty = LineParser.ParseInt(ref input, "QUANTITY"); if (LineParser.Lookahead(ref input) == TokenType.Integer) { gravity = LineParser.ParseInt(ref input, "GRAVITY"); wind = LineParser.ParseInt(ref input, "WIND"); } // Move to the first point actions.MoveToElement(data.Driver.FindElementByTagName("body"), point1X, point1Y); newLine = new Line(new Point(point1X, point1Y), new Point(point2X, point2Y)); var array = newLine.HumanWindMouse(point1X, point1Y, point2X, point2Y, gravity, wind, 1); var shrinked = ShrinkArray(array, qty); if (data.GlobalSettings.Selenium.DrawMouseMovement) { DrawRedDots(data.Driver, shrinked, 5); } foreach (var p in GetOffsets(shrinked)) { actions.MoveByOffset(p.X, p.Y); } break; } } return(new Action(() => { actions.Build(); actions.Perform(); data.Log(new LogEntry("Executed Mouse Actions", Colors.White)); })); }
/// <summary> /// Gets the Action that needs to be executed. /// </summary> /// <param name="line">The data line to parse</param> /// <param name="data">The BotData needed for variable replacement</param> /// <returns>The Action to execute</returns> public static Action Parse(string line, BotData data) { var input = line.Trim(); var field = LineParser.ParseToken(ref input, TokenType.Parameter, true).ToUpper(); return(new Action(() => { switch (field) { case "SOURCE": data.ResponseSource = LineParser.ParseLiteral(ref input, "SOURCE", true, data); break; case "STATUS": data.Status = (BotStatus)LineParser.ParseEnum(ref input, "STATUS", typeof(BotStatus)); if (data.Status == BotStatus.CUSTOM) { data.CustomStatus = LineParser.ParseLiteral(ref input, "CUSTOM STATUS"); } break; case "RESPONSECODE": data.ResponseCode = LineParser.ParseInt(ref input, "RESPONSECODE").ToString(); break; case "COOKIE": var name = LineParser.ParseLiteral(ref input, "NAME", true, data); data.Cookies.Add(name, LineParser.ParseLiteral(ref input, "VALUE", true, data)); break; case "ADDRESS": data.Address = LineParser.ParseLiteral(ref input, "ADDRESS", true, data); break; case "USEPROXY": var use = LineParser.ParseToken(ref input, TokenType.Parameter, true).ToUpper(); if (use == "TRUE") { data.UseProxies = true; } else if (use == "FALSE") { data.UseProxies = false; } break; case "PROXY": var prox = LineParser.ParseLiteral(ref input, "PROXY", true, data); data.Proxy = new CProxy(BlockBase.ReplaceValues(prox, data), data.Proxy == null ? ProxyType.Http : data.Proxy.Type); break; case "PROXYTYPE": data.Proxy.Type = (ProxyType)LineParser.ParseEnum(ref input, "PROXYTYPE", typeof(ProxyType)); break; case "DATA": data.Data = new CData(LineParser.ParseLiteral(ref input, "DATA", true, data), new WordlistType()); break; case "VAR": { var cVar = new CVar( LineParser.ParseLiteral(ref input, "NAME", true, data), LineParser.ParseLiteral(ref input, "VALUE", true, data), false ); try { cVar.Hidden = LineParser.ParseToken(ref input, TokenType.Parameter, false) .ToBoolean(); } catch { } data.Variables.Set(cVar); } break; case "CAP": { var cVar = new CVar( LineParser.ParseLiteral(ref input, "NAME", true, data), LineParser.ParseLiteral(ref input, "VALUE", true, data), true ); try { cVar.Hidden = LineParser.ParseToken(ref input, TokenType.Parameter, false) .ToBoolean(); } catch { } data.Variables.Set(cVar); } break; case "GVAR": try { var cVar = new CVar( LineParser.ParseLiteral(ref input, "NAME", true, data), LineParser.ParseLiteral(ref input, "VALUE", true, data), false ); try { cVar.Hidden = LineParser.ParseToken(ref input, TokenType.Parameter, false) .ToBoolean(); } catch { } data.GlobalVariables.Set(cVar); } catch { } break; case "NEWGVAR": try { var cVar = new CVar( LineParser.ParseLiteral(ref input, "NAME", true, data), LineParser.ParseLiteral(ref input, "VALUE", true, data), false ); try { cVar.Hidden = LineParser.ParseToken(ref input, TokenType.Parameter, false) .ToBoolean(); } catch { } data.GlobalVariables.SetNew(cVar); } catch { } break; case "GCOOKIES": data.GlobalCookies.Clear(); foreach (var cookie in data.Cookies) { data.GlobalCookies.Add(cookie.Key, cookie.Value); } break; default: throw new ArgumentException($"Invalid identifier {field}"); } data.Log(new LogEntry($"SET command executed on field {field}", Colors.White)); })); }