store arbitrary JavaScript code into a string variable - javascript

I have a program (written in Clojure) that injects some JS code into a JS function, then evaluates it via Nashorn. I have no control over the code passes (it may contain quotes, simple quotes...).
It looks like this :
;; Clojure
(eval-str (str "print(evaluateCode(\"" s " \"))"))
// equivalent code in pseudo-js just for those not reading Clojure fluently
evalJS("println(evaluateCode(" + arbitraryJS + "))")
The evaluateCode function is already loaded.
// already loaded in Nashorn
function evaluateCode(code) {
// do something with the code
//...
eval(code);
}
This works fine for simple programs, ex. if arbitraryJS = "var a=123; print(a); return a;".
But as soon as the program contains quotes, it breaks. ex. "var a = 123; print("a is now", a);"
Note : the actual code is there.

You need to escape the string. place a \ before every ".
If you need the \ itself use it double \\
Sorry, I am not allowed to comment yet... :/

I would suggest to escape the quotes and backslashes. I would go for single quotes as JS string delimiters, as in Clojure you are bound to use double quotes for delimiting strings:
;; Clojure
(eval-str (str "print(evaluateCode('"
(clojure.string/replace s #"(['\\\\])" "\\\\$1")
"'))"))
The find and replace patterns each have four backslashes. As in Clojure backslash is an escape character, they actually denote only two backslashes. In regular expressions backslash is also an escape character, so in the end they just denote one, literal backslash each. So this means "prefix any occurrence of backslash or quote with a backslash."
You shouldn't worry about comments and templates and such, as the escape characters only exist in Clojure (after the replace), but are resolved the moment the complete string is parsed by the Javascript engine. The evaluateCode function will never see the escape characters, but the plain value of s.
Example
;; Clojure
(def s "a = 'test'; // 'test' used here")
(eval-str (str "print(evaluateCode('"
(clojure.string/replace s #"(['\\\\])" "\\\\$1")
"'))"))
This will evaluate to:
(eval-str "print(evaluateCode('a = \\'test\\'; // \\'test\\' used here'))")
Note that the backslashes are doubled in the above representation, but that is because Clojure needs that. The actual string only has single occurrences of the backslashes. If instead of calling eval-str, you would call println with the same argument, you would get this output:
print(evaluateCode('a = \'test\'; // \'test\' used here'))
That is the string interpreted by the Javascript engine, and so it interprets the backslashes as escape characters, passing the clean string to evaluateCode.
So if evaluateCode looked like this:
function evaluateCode(code) {
alert(code);
}
It would produce this alert:
a = 'test'; // 'test' used here
So, the escaping backslashes are not there at all in Javascript. It will see the exact same value as the Clojure symbol s represents.

In the after end I used the Apache Commons Lang StringUtils since the other solutions did not work. See it here.

Related

Regex works in Browser but not in NodeJs

On a browser this
"C:\\backup\\".replace(/\\\\/g, '\\')
returns:
"C:\backup\"
BUT in NodeJs v12.13
'C:\\backup\\'
Is it intended to not work the similar way?
If so, how to replace all double backslash to a single one in Node ?
In JavaScript string a single backslash is represented using "\\". That's because \" represents a single " character and doesn't terminate the string.
The regex you wrote actually has no effect because the string doesn't contain two backslashes next to one another.
You can (and should) use \\ in any place/function that expects a backslash.
alert("Backslash: \\");
// alert("Backslash: \"); // SyntaxError
However, the JavaScript console sometimes likes to display the sting in JavaScript notation, so it replaces \ with \\ in order to print valid code. This also sometimes happens when typing just a string in the console REPL.
console.log("%o", "\\");
console.log({ backslash: "\\"});
Notice the "sometimes". Per spec, the JavaScript console printer is implementation-defined. Although most consoles, including Node.js's, in these circumstances display "\\" (a valid JavaScript string), Chrome and other Chromium-based browsers display "\" (the actual string value, wrapped in ").
P.S.: There's also a way to make the parser parse a single backslash as a single backslash, using String.raw(), however, it has some limitations:
alert(String.raw `C:\Windows\System32\calc.exe`);
// alert(String.raw `C:\Windows\System32\`); // SyntaxError because string ends with \

Putting regular expressions in strings

I am trying to dynamically create a javascript file B using a javascript file A (written in Node.js) by writing a string from A to a .js file B. I want to use regular expressions in the javascript file B. This requires me to put the regex functions for B in a string in A. However, whenever I use the backslash (escape character), file A interprets the regex function immediately, instead of treating it as a string.
Some code to help in understanding my problem:
var mongodata = "Some String with square and curly brackets ]}{]]},]},}{}{{}},{[[][,][,";
mongodata = 'var mongodata = ' + mongodata + ';\n function setData(){mongodata = mongodata.replace(/\[ /g,"").replace(/\] \},/g,"</td></tr>").replace(/\] \}/g,"</td></tr>"); document.getElementById("mongodata").innerHTML = mongodata;}';
That mongodata string is intended to be used as the content of a dynamically created .js file.
I understand the wording of this question may be slightly confusing. Please let me know if more clarification is needed.
In your string, just like the \n character, all the other backslashed expressions are being evaluated, so you must escape the backslashes. In other words, write a RegExp that outputs a RegExp. The proper way of escaping the backslashes themselves is \\\ , but you might need to escape other characters as well to prevent their evaluation.
Perhaps I'm misunderstanding your problem, but maybe put the string being assigned to mongodata in escaped quotes:
var mongodata = "\'Some String with square and curly brackets ]}{]]},]},}{}{{}},{[[][,][,\'";
Bit of a lottery this one. I too don't quite understand your question.
You can escape all of the RegEx special characters (. * ? [ ] Etc). You can also dynamically create RegEx operators using:
var objRegEx = new RegExp( pattern, modifiers );
Like I say, lottery... stab in the dark...

RegExp for remove first and last char and turn ending double slashes into single

I have the following Javascript code to obtain the inner string from an RegExp:
Function.prototype.method = function (name,func){
this.prototype[name] = func;
return this;
};
RegExp.method('toRawString', function(){
return this.toString().replace(/^.(.*).$/,"$1");
});
The purpose of this, is to avoid in string double quoting. For example, if you have a Windows file path "C:\My Documents\My Folder\MyFile.file", you can use it like the following:
alert(/C:\My Documents\My Folder\MyFile.file/.toRawString());
However it is not working for ""C:\My Documents\My Folder\" since it causes syntax error. The only way to avoid it is to keep double quoting at the end of the string. Thus it will be written
alert(/C:\My Documents\My Folder\\/.toRawString());
The fact is any odd number of back slashes on the end of the string will be an error, so all ending back slashes must be double escaped. It will not be hard to use a multiple line small implementation, but are there any single RegExp solution?
NOTE
When using toRawString the RegExp object for this is usually NOT going to be used for any other purpose except for that method. I just want to use the syntax of RegExp to avoid double back slashes in source code. Unfortunately the ending double slashes cannot be easily avoid. I think another workaround is to force a space at the end but that is another question then.
UPDATE
I finally solved the "another question" and posted the code here.
OK, I get what you're trying to do! It's hacky : )
Try something like:
return this.toString().slice(1, -1).replace(/\\+$/, '\\')
Hope that helps.
If you want to include the double quotes in the string just wrap it with single quotes.
s = '"C:\\My Documents\\My Folder\\MyFile.file"'
console.log(s) // Output => "C:\My Documents\My Folder\MyFile.file"
This produces a syntax error:
/C:\My Documents\/
But that regular expression could be written correctly like this:
/C:\\My Documents\\/
Or like this:
new RegExp("C:\\\\My Documents\\\\")
I think your function is just fine and is returning a correct result. Regular expressions just can't end with an unpaired backslash. It's not that you're double escaping - you're just escaping the escape character.
This would produce an error too:
new RegExp("C:\\My Documents\\")
A regular expression like this, for instance, can't be written without a pair of backslashes:
/C:\\What/
Without the second backslash, \W would be interpreted as a special character escape sequence. So escaping the escape character isn't only necessary at the end. It's required anywhere it might be interpreted as the beginning of an escape sequences. For that reason, it might be a good rule of thumb to always use two backslashes to indicate a backslash literal in a regular expression.

Json String with comment out quotes in variable

I have a JSON string hardcoded in my Javascript.
valiJsonString = '{"ssss","ddddddddd\"ddd"}';
The DOM says -> {"ssss","ddddddddd"ddd"}
Can someone tell me why javascript replace my \" into " ?
// try to parse
valiJsonString secureEvalJSON (valiJsonString) //<-- error: jsonString is not valid
working example
"The DOM says" doesn't make much sense, as the DOM doesn't say anything. Do you mean the object browser in Firebug (or some other development console)?
Now, inside a string, \" is the quote character. You have to compensate for this escaping since you do not want it, but instead a verbatim slash.
So perhaps you want \\ followed by ", which is the slashed character followed by the quote character.
In addition, the given JSON looks like it ought to represent an array not an object, since you have no keys:
var str = '["ssss","ddddddddd\\"ddd"]';
The actual value of this JSON-format string inside your browser is now:
["ssss","ddddddddd\"ddd"]
\ is an escape character. try \\
If you want your string to come through escaped, then you need to escape your escape character:
valiJsonString = '{"ssss","ddddddddd\\"ddd"}';
I've added second \ (\ is escape char) and fixed lack of = and type of table {} vs []
http://jsfiddle.net/4wVaR/9/

Escaping quotes from Rails Variables when using them for Javascript?

I am having problems when trying to use a rails variable within javascript code.
For example, I might define a link_to_remote, with parameter
:complete => "alert('my_var');"
If my_var = "I'm testing.", then the javascript code will break due to the single quote closing the code prematurely. If I try using escape_javascript(my_var) so that the quote gets turned into \', it doesn't seem to fix the problem.
I've noticed that when you try alert('I\'m testing'); there's a problem, but if you do alert('I\\'m testing'), it works. Since escape_javascript only turns ' into \', rather than \\', does somebody have a suggestion for how to handle this?
Thanks!
Eric
when you try alert('I\'m testing'); there's a problem
Backslash is also an escape in Ruby strings! So the string literal:
"alert('I\'m testing');"
means the string:
alert('I'm testing');
the backslash is gone already before JavaScript gets a look at it. When you are writing a JavaScript string literal inside a Ruby string literal you need to escape the escape, \\, to get a real \ that will then, in JavaScript, escape the apostrophe.
escape_javascript correctly generates the backslash for JavaScript, if a backslash was included in its input. But again, if you're writing a string literal, you have to escape the backslash to get a real backslash:
escape_javascript("\b") -> this is a backspace character!
escape_javascript("\\b") -> this is backslash-then-letter-b;
escaped for JavaScript literal to double-backslash-then-b.
So, this is fine:
"'"+escape_javascript(myvar)+"'"
alternatively, you can use a JSON encoder to create the JavaScript string literal including the surrounding quotes.

Categories