Reputation: 195
I have several thousand entries in a database that were scraped from a website. They are strings which list conditions which must be met. For example: "(Thing1 and Thing2) or (Thing3 and Thing4)"
I would like a user to enter a list of conditions they have, and then check them against the database. Due to the fact that these strings come from a trusted site, and are so close to valid boolean conditions already I'm tempted to put them in an eval()
statement. I could parse the string, find the conditions, check if they are true, and replace them with 1 or 0. Then replace (and, or) with (&&, ||). Then I would check to make sure everything at that point is one of: space, 1, 0, &, |, (, or ). If not, log the error in some way. If it is just those characters do:
eval("Boolean((1 && 0) || (0 && 0))")
I realize eval()
is generally a bad idea, so I'm open to other ideas. However, in this case I feel the security is increased if I check for just those characters before running the eval, and since the input is data scraped from a trusted site.
I'm planning on doing this in javascript, but could also do it in PHP on the server.
Upvotes: 0
Views: 161
Reputation: 12324
If you really want to avoid eval() at all cost, you could use something like this:
function evalBoolean(str) {
while (str.length > 1) {
str = str.replace(/0 && 0|0 && 1|1 && 0|0 \|\| 0|\(0\)/g, "0");
str = str.replace(/1 && 1|0 \|\| 1|1 \|\| 0|1 \|\| 1|\(1\)/g, "1");
}
return (str == "1");
}
alert(evalBoolean("((0 && 1) || (1 && 1))"));
alert(evalBoolean("(((0 || 1) && (0 || 0)) && ((1 || 1) || 0))"));
If you think there could be malformed input, use this safer version which returns undefined if it can't resolve the expression.
function evalBoolean(str) {
var len;
while (str.length > 1) {
if (str.length == len) return; else len = str.length;
str = str.replace(/0\s*&&\s*0|0\s*&&\s*1|1\s*&&\s*0|0\s*\|\|\s*0|\(\s*0\s*\)|\s*0\s*/g, "0");
str = str.replace(/1\s*&&\s*1|0\s*\|\|\s*1|1\s*\|\|\s*0|1\s*\|\|\s*1|\(\s*1\s*\)|\s*1\s*/g, "1");
}
return (str == "1");
}
alert(evalBoolean(" (( (0|| 1) &&(0 || 0) )&& ( (1||1) ||0))"));
alert(evalBoolean("((1 && 0) && 1 )) ( && 1"));
Upvotes: 1