If I have this ;
var a = "(true && false) && true && false"
And if I want to evaluate this string , what are the options ?
If I say, this code will be generated in the browser but there will be absolutely no user input in it , would it be safe to use eval ?
If not, what is the most performant way of parsing it ?
EDIt :
By the way, the string is dynamic , so I can't gaurantee that it's always like above , so it could be :
var a = "(true && false) || (true && (true && false)) && true && false"
FIY :
I know I can use eval, all I'm asking is, why I shouldn't use eval, or is there any other options?
EDIT : the original problem :
var a = function(){ return false} // all of them always return a boolean
var b = function(){ return true}
var c = function(){ return true}
var d = function(){ return false}
var conditions = "(a && b) && c && d"
I can't change the above code , I need to parse it, I need the condition to be evaluated ;
function ExecuteJavascriptString() {
var n = 0;
var s = "(true || false) || (true || (true || false)) && true";
var ifstate = " if (" + s + ") { console.log('done'); } ";
setTimeout(ifstate, 1);
}
ExecuteJavascriptString()
I was thinking maybe you can atleast verify that the string contains what you think it should contain, before running eval on it, using the RegExp /(?:(?:true)|(?:false)|(?:&&)|(?:\|\|)|[()\s])/g:
var validExp = "(true && false && true) || (true && (true && false)) && true";
var evilExp = "(true && false && true) || (true && (true && false)) && true function() { console.log('do evil stuff'); }";
console.log(evalBoolStr(validExp)); //false
console.log(evalBoolStr(evilExp)); //Invalid input
function evalBoolStr(str) {
if(str.match(/(?:(?:true)|(?:false)|(?:&&)|(?:\|\|)|[()\s])/g).join('') === str) {
return eval(str);
}
return 'Invalid input';
}
An attempt at actually writing a parser for boolean strings:
function parseBoolStr(str) {
var expressions = {};
var expressionRegex = new RegExp("\\((?:(?:!*true)|(?:!*false)|(?:&&)|(?:\\|\\|)|\\s|(?:!*\\w+))+\\)");
var expressionIndex = 0;
str = str.trim();
while (str.match(expressionRegex)) {
var match = str.match(expressionRegex)[0];
var expression = 'boolExpr' + expressionIndex;
str = str.replace(match, expression);
match = match.replace('(', '').replace(')', '');
expressions[expression] = match;
expressionIndex++;
}
return evalBoolStr(str, expressions);
}
function evalBoolStr(str, expressions) {
var conditions = str.split(' ');
if (conditions.length > 0) {
var validity = toBoolean(conditions[0], expressions);
for (var i = 1; i + 1 < conditions.length; i += 2) {
var comparer = conditions[i];
var value = toBoolean(conditions[i + 1], expressions);
switch (comparer) {
case '&&':
validity = validity && value;
break;
case '||':
validity = validity || value;
break;
}
}
return validity;
}
return 'Invalid input';
}
function toBoolean(str, expressions) {
var inversed = 0;
while (str.indexOf('!') === 0) {
str = str.replace('!', '');
inversed++;
}
var validity;
if (str.indexOf('boolExpr') === 0) {
validity = evalBoolStr(expressions[str], expressions);
} else if (str == 'true' || str == 'false') {
validity = str == 'true';
} else {
validity = window[str]();
}
for (var i = 0; i < inversed; i++) {
validity = !validity;
}
return validity;
}
var exp1 = "(true && true || false) && (true || (false && true))";
var exp2 = "(true && false) && true && false";
var exp3 = "(true && !false) && true && !false";
var exp4 = "(a && b) && c && d";
console.log(exp1 + ' = ' + parseBoolStr(exp1));
console.log(exp2 + ' = ' + parseBoolStr(exp2));
console.log(exp3 + ' = ' + parseBoolStr(exp3));
console.log(exp4 + ' = ' + parseBoolStr(exp4));
function parseBoolStr(str) {
var expressions = {};
var expressionRegex = new RegExp("\\((?:(?:!*true)|(?:!*false)|(?:&&)|(?:\\|\\|)|\\s|(?:!*\\w+))+\\)");
var expressionIndex = 0;
str = str.trim();
while (str.match(expressionRegex)) {
var match = str.match(expressionRegex)[0];
var expression = 'boolExpr' + expressionIndex;
str = str.replace(match, expression);
match = match.replace('(', '').replace(')', '');
expressions[expression] = match;
expressionIndex++;
}
return evalBoolStr(str, expressions);
}
function evalBoolStr(str, expressions) {
var conditions = str.split(' ');
if (conditions.length > 0) {
var validity = toBoolean(conditions[0], expressions);
for (var i = 1; i + 1 < conditions.length; i += 2) {
var comparer = conditions[i];
var value = toBoolean(conditions[i + 1], expressions);
switch (comparer) {
case '&&':
validity = validity && value;
break;
case '||':
validity = validity || value;
break;
}
}
return validity;
}
return 'Invalid input';
}
function toBoolean(str, expressions) {
var inversed = 0;
while (str.indexOf('!') === 0) {
str = str.replace('!', '');
inversed++;
}
var validity;
if (str.indexOf('boolExpr') === 0) {
validity = evalBoolStr(expressions[str], expressions);
} else if (str == 'true' || str == 'false') {
validity = str == 'true';
} else {
validity = window[str]();
}
for (var i = 0; i < inversed; i++) {
validity = !validity;
}
return validity;
}
function a() {
return false;
}
function b() {
return true;
}
function c() {
return true;
}
function d() {
return false;
}
Usage would then simply be parseBoolStr('true && false'); //false
Related
I am kind of new to this, but this is giving me a headache.
Heres my code what i am trying to solve:
function parseComponents(data: any, excelAttributesArray: string[]) {
let confs = "";
let isValues = false;
let listValues = "";
if (!data) return confs;
if (data["Part"]) {
const part = data["Part"];
excelAttributesArray.forEach((attribute) => {
let attributeValue = part[attribute];
if (attributeValue !== null) isValues = true;
if (attributeValue !== null && attributeValue.Value) {
attributeValue = attributeValue.Value;
}
listValues += attributeValue + ",";
});
const number = part["Number"];
if (isValues) {
confs += `${listValues}${number}`;
}
}
if (data["Components"] && data["Components"].length > 0) {
for (let i = 0; i < data["Components"].length; i++) {
const tmp = parseComponents(
data["Components"][i],
excelAttributesArray
);
if (tmp && tmp.length > 0)
confs += (confs.length > 0 ? "|" : "") + tmp;
}
}
return confs;
}
The confs value is returned as a string. How do i get it return as array?
can you help me?
I'm trying to get this code below to make a excesão links in case the variable would be
var except_link = "blogspot.com, wordpress.com";
But it is only making excesão of 'blogspot.com'
thank you
var except_link = "blogspot.com, wordpress.com";
var allow_file = ".3gp,.7z,.aac,.ac3,.asf,.asx,.avi,.bzip,.divx,.doc,.exe,.flv,.jpg,.png,.gz,.gzip,.iso,.jar,.jav,.mid,.mkv,.mov,.mp3,.mp4,.mpeg,.mpg,.msi,.nrg,.ogg,.pdf,.ppt,.psd,.rar,.rm,.rmvb,.rtf,.swf,.tar,.tar.gz,.tgz,.torrent,.ttf,.txt,.wav,.wma,.wmv,.xls,.zip,180upload,1fichier,1filesharing,2shared,4files,4share,4shared,a2zupload,adf,adrive,adv,amazo,";
except_link = (link_except != null) ? link_except : except_link;
function check(siteurl) {
if ("" + allow_file != "undefined" && allow_file != "" && allow_file.replace(/\s/g, "") != "" && siteurl != "") {
if ((" " + allow_file).indexOf(",") > 0) {
pular = allow_file.split(",")
} else {
pular = new Array(allow_file)
}
for (s = 0; s < pular.length; s++) {
if ((" " + siteurl.toLowerCase()).indexOf(pular[s].toLowerCase()) > 0) {
if ("" + except_link != "undefined" && except_link != "" && except_link.replace(/\s/g, "") != "" && siteurl != "") {
if ((" " + except_link).indexOf(",") > 0) {
pular = except_link.split(",")
} else {
pular = new Array(except_link)
}
for (s = 0; s < pular.length; s++) {
if ((" " + siteurl.toLowerCase()).indexOf(pular[s].toLowerCase()) > 0) {
return false;
break
}
}
return true
} else {
return true
}
}
}
return false
} else {
return false
}
}
You're splitting based on "," where you are delimiting with ", " (comma followed by space). The problem could be that it doesn't match since the second URL in the split array will be " wordpress.com" (wordpress.com with a space in front of it).
To remedy this, you could either change your split function to split accordingly:
except_link = "blogspot.com, wordpress.com" // comma-space
...
except_link.split(", ") // comma-space
Or, change your input string to accommodate your split requirements:
except_link = "blogspot.com,wordpress.com" // comma, no space
...
except_link.split(",") // comma, no space
For example, I am am working on a Pig Latin translator. I want a for loop to change the text to an array and allow the rest of my code to change single words and put it back together again as a result.
var pigLatinTranslator = function(firstWord) {
firstWord = firstWord.toLowerCase();
var splitText = firstWord.split(' ');
var finalResult = [];
for (var i = 0; i < splitText.length; i++) {
var singleWord = splitText[i];
if (singleWord.charAt(0) !== "a" && singleWord.charAt(0) !== "e" && singleWord.charAt(0) !== "i" && singleWord.charAt(0) !== "o" && singleWord.charAt(0) !== "u") {
var consonantsVar;
for (var i = 0; i < singleWord.length; i++) {
var chr = singleWord.charAt(i);
if ((chr === 'q') && (singleWord.charAt(i + 1) === 'u')) {
consonantsVar = (singleWord.slice(i + 2) + singleWord.slice(0, i) + "quay");
break;
} else if (chr === 'a' || chr === 'e' || chr === 'i' || chr === 'o' || chr === 'u') {
consonantsVar = (singleWord.slice(i) + singleWord.slice(0, i) + "ay");
break;
}
}
return consonantsVar;
}
else {
return (singleWord + "ay");
}
return splitText.join(' ');
}
};
How to add a Visual Basic .NET syntax highlighting to CodeMirror editor? Does exists the mode for this language on any library? What should I correct except keywords, blockKeywords and atoms?
Pascal example:
CodeMirror.defineMode("pascal", function(config) {
function words(str) {
var obj = {}, words = str.split(" ");
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
return obj;
}
var keywords = words("and array begin case const div do downto else end file for forward integer " +
"boolean char function goto if in label mod nil not of or packed procedure " +
"program record repeat set string then to type until var while with");
var blockKeywords = words("case do else for if switch while struct then of");
var atoms = {"null": true};
var isOperatorChar = /[+\-*&%=<>!?|\/]/;
var curPunc;
function tokenBase(stream, state) {
var ch = stream.next();
if (ch == "#" && state.startOfLine) {
stream.skipToEnd();
return "meta";
}
if (ch == '"' || ch == "'") {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
}
if (ch == "(" && stream.eat("*")) {
state.tokenize = tokenComment;
return tokenComment(stream, state);
}
if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
curPunc = ch;
return null
}
if (/\d/.test(ch)) {
stream.eatWhile(/[\w\.]/);
return "number";
}
if (ch == "/") {
if (stream.eat("/")) {
stream.skipToEnd();
return "comment";
}
}
if (isOperatorChar.test(ch)) {
stream.eatWhile(isOperatorChar);
return "operator";
}
stream.eatWhile(/[\w\$_]/);
var cur = stream.current();
if (keywords.propertyIsEnumerable(cur)) {
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
return "keyword";
}
if (atoms.propertyIsEnumerable(cur)) return "atom";
return "word";
}
function tokenString(quote) {
return function(stream, state) {
var escaped = false, next, end = false;
while ((next = stream.next()) != null) {
if (next == quote && !escaped) {end = true; break;}
escaped = !escaped && next == "\\";
}
if (end || !escaped) state.tokenize = null;
return "string";
};
}
function tokenComment(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == ")" && maybeEnd) {
state.tokenize = null;
break;
}
maybeEnd = (ch == "*");
}
return "comment";
}
function Context(indented, column, type, align, prev) {
this.indented = indented;
this.column = column;
this.type = type;
this.align = align;
this.prev = prev;
}
function pushContext(state, col, type) {
return state.context = new Context(state.indented, col, type, null, state.context);
}
function popContext(state) {
var t = state.context.type;
if (t == ")" || t == "]" )
state.indented = state.context.indented;
return state.context = state.context.prev;
}
// Interface
return {
startState: function(basecolumn) {
return {
tokenize: null,
context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false),
indented: 0,
startOfLine: true
};
},
token: function(stream, state) {
var ctx = state.context;
if (stream.sol()) {
if (ctx.align == null) ctx.align = false;
state.indented = stream.indentation();
state.startOfLine = true;
}
if (stream.eatSpace()) return null;
curPunc = null;
var style = (state.tokenize || tokenBase)(stream, state);
if (style == "comment" || style == "meta") return style;
if (ctx.align == null) ctx.align = true;
if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
else if (curPunc == "[") pushContext(state, stream.column(), "]");
else if (curPunc == "(") pushContext(state, stream.column(), ")");
else if (curPunc == ctx.type) popContext(state);
else if ( ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
pushContext(state, stream.column(), "statement");
state.startOfLine = false;
return style;
},
electricChars: "{}"
};
});
CodeMirror.defineMIME("text/x-pascal", "pascal");
Thanks for the help!
This worked for me -
I added this definition in clike mode js file
CodeMirror.defineMIME("text/x-vb", {
name: "clike",
keywords: words("AddHandler AddressOf Alias And AndAlso Ansi As Assembly Auto Boolean ByRef Byte " +
"ByVal Call Case Catch CBool CByte CChar CDate CDec CDbl Char CInt Class CLng CObj Const CShort CSng CStr CType " +
"Date Decimal Declare Default Delegate Dim DirectCast Do Double Each Else ElseIf End Enum Erase Error Event Exit False Finally "+
"For Friend Function Get GetType GoSub GoTo Handles If Implements Imports In Inherits Integer Interface Is " +
"Let Lib Like Long Loop Me Mod Module MustInherit MustOverride MyBase MyClass Namespace New Next Not "+
"Nothing NotInheritable NotOverridable Object On Option Optional Or OrElse Overloads Overridable Overrides " +
"ParamArray Preserve Private Property Protected Public RaiseEvent ReadOnly ReDim REM RemoveHandler Resume " +
"Return Select Set Shadows Shared Short Single Static Step Stop String Structure Sub SyncLock Then Throw " +
"To True Try TypeOf Unicode Until Variant When While With WithEvents WriteOnly Xor"),
//blockKeywords: words("catch class do else finally for if switch try while"),
atoms: words("True False Null"),
hooks: {
"#": function(stream, state) {
stream.eatWhile(/[\w\$_]/);
return "meta";
}
}
});
I check if a given url matches another one (which can have wildcards).
E.g. I have the following url:
john.doe.de/foo
I'd now like to check whether the url is valid or not, the user defines the string to check with, e.g:
*.doe.de/*
That works fine, but with the following it should NOT work but it gets accepted:
*.doe.de
Here the function i wrote till now, the urls are stored as firefox prefs and i the "checkedLocationsArray" containts all urls to be checked.
function checkURLS(index)
{
if(index >= 0)
{
var pos = getPos("URL-Mask");
var url = tables[index][pos];
if(url != null && url != "")
{
var urlnow = "";
if(redlist_pref.prefHasUserValue("table.1"))
{
var checkedLocationsArray = new Array();
for(i = 0; i < tables.length; i++)
{
checkedLocationsArray[i] = tables[i][pos];
}
for(i=0;i<checkedLocationsArray.length;i++)
{
urlnow = checkedLocationsArray[i];
if(urlnow == url)
{
return true;
}
if(urlnow.indexOf('*.') != -1)
{
while(urlnow.indexOf("*.") != -1)
urlnow = urlnow.replace("\*.", "\.[^\.]*");
}
if(urlnow.indexOf('.*') != -1)
{
while(urlnow.indexOf(".*") != -1)
urlnow = urlnow.replace(".\*", "([^\.]*\.)");
}
if(urlnow.indexOf('/*') != -1)
{
while(urlnow.indexOf("/*") != -1)
urlnow = urlnow.replace("/*", /\S\+*/)
}
else if(url.lastIndexOf('/') != -1)
{
return false;
}
var regex = new RegExp(urlnow);
var Erg = regex.exec(url);
if(Erg != null)
return true;
}
}
return false;
}
}
}
i think the "else if(url.indexOf('/') != -1)" is the important part. It should work just fine like that, if I alert it I even get that the result is true but it seems like the if is not being executed..
If anything is unclear, please just post a comment. Thanks in advance!
Why don't you just add the characters for beginning and end of string?
function checkURLS(index)
{
if(index >= 0)
{
var pos = getPos("URL-Mask");
var url = tables[index][pos];
if(url != null && url != "")
{
var urlnow = "";
if(redlist_pref.prefHasUserValue("table.1"))
{
var checkedLocationsArray = new Array();
for(i = 0; i < tables.length; i++)
{
checkedLocationsArray[i] = tables[i][pos];
}
for(i=0;i<checkedLocationsArray.length;i++)
{
urlnow = checkedLocationsArray[i];
if(urlnow == url)
{
return true;
}
//Check there's nothing else in the string
urlnow = '^' + urlnow + '$';
if(urlnow.indexOf('*') != -1)
{
while(urlnow.indexOf("*") != -1)
urlnow = urlnow.replace("\*", ".*");
}
else if(urlnow.lastIndexOf('/') != -1)
{
return false;
}
var regex = new RegExp(urlnow);
var Erg = regex.exec(url);
if(Erg != null)
return true;
}
}
return false;
}
}
}
The problem seems that you don't check for the start and the end of the string. Change your code to something like
urlnow = '^'+urlnow+'$'; // this is new
var regex = new RegExp(urlnow);
^ is the RegExp code for string-start and $ the code for string-end. That way you ensure that the whole url has to match the pattern and not only a part of it.
I figured out that I did the url was not the current url, I changed that below.
I also changed that the * are now replaced with a regular expression and the dots have to be there in this situation.
function redlist_checkURLS(index)
{
if(index >= 0)
{
var pos = getPos("URL-Mask");
var url = currenturl.replace("http://", "");
if(url != null && url != "")
{
var urlnow = "";
if(pref.prefHasUserValue("table.1"))
{
var urlsok = 0;
var checkedLocationsArray = new Array();
for(i = 0; i < tables.length; i++)
{
checkedLocationsArray[i] = tables[i][pos];
}
for(i=0;i<checkedLocationsArray.length;i++)
{
urlnow = checkedLocationsArray[i];
if(urlnow == url)
{
return true;
}
if(urlnow.indexOf('*') != -1)
{
while(urlnow.indexOf("*") != -1)
urlnow = urlnow.replace("*", "\\S+")
}
var regex = new RegExp(urlnow);
var Erg = regex.exec(url);
if(Erg != null && Erg == url)
return true;
}
}
return false;
}
}
}
Thanks for your help thought!