Awkward escape characters - javascript

Whilst trying to console.log a string I've run into a rather annoying issue. I store the string 2^{\\frac{1}{2}}x=1 in a Node.js database yet when outputting it gives 2^{rac{1}{2}}x=1. I predicted issues with the \f escape character and as such I added the 2nd \ to escape that problem. But the issue remains and I'm stumped as to how to fix it.
When looking at the Mongoose debug output it clearly stores it in the data correctly:
It is assigned like this:
contentHolder = "<%= testData.topics[i].questions[t].methods[p][0].content %>";
Yet when I run this line:
console.log(contentHolder);
I get this:
2^{rac{1}{2}}x=1

If you view the 'source' in your web browser I imagine you'll see that this:
contentHolder = "<%= testData.topics[i].questions[t].methods[p][0].content %>";
will have generated this:
contentHolder = "2^{\frac{1}{2}}x=1";
When that JS string literal is interpreted the \f will be converted into a form feed character, which obviously isn't what you want.
There are various ways you could try to fix the escaping but I think I'd just use JSON.stringify:
contentHolder = <%- JSON.stringify(testData.topics[i].questions[t].methods[p][0].content) %>;
There may be some edge cases where this still doesn't quite get the escaping right but unless you're outputting values entered by users that's unlikely to be a problem.

Related

Prevent escape sequence interpretation in Javascript

I want to escape correctly a windows path that I get from cmd command.
for example when I tap where node in cmd, I will get a path like this :
C:\Users\mypc\AppData\Roaming\npm\ts-node
This is not a correct escaped string That I can pass between variable and it is not json validated.
I want to write a function that escape correctly this string.
const input = "C:\Users\mypc\AppData\Roaming\npm\ts-node"
const output = "C:\\Users\\mypc\\AppData\\Roaming\\npm\\ts-node"
I tried spliting the string, and many tries, but did'nt works.
When I console log the input, It will console like this, converting \n (in \node) as linebreak and \t in (\ts-node) as tab.
console.log(input)
/*
C:UsersmypcAppDataRoaming
pm s-node
*/
I find a pretty solution using String.raw like this :
const solution_1 = String.raw`C:\Users\mypc\AppData\Roaming\npm\ts-node`
console.log(solution_1)
// C:\Users\mypc\AppData\Roaming\npm\ts-node
The problem is that I can't pass a variable to String raw
const input = "C:\Users\mypc\AppData\Roaming\npm\ts-node"
const solution_2 = String.raw`${input}`
console.log(solution_2)
/*
C:UsersmypcAppDataRoaming
pm s-node
*/
I need a solution to pass a variable to String.raw or other technique to escape a string by a function.
You are confusing code and values. Code is what you write in your text editor. Obviously since source code in various programming languages have syntax and that syntax use the same characters that can appear in data there are some data that must be written differently in source code.
For example, if you want to write the data "Hello' in code you must either write:
let data1 = "\"Hello'"
or
let data2 = '"Hello\''
This is because the javascript language interprets the characters " and ' as part of its syntax. But let's be VERY CLEAR about this. Both data1 and data2 contain exactly the same data. That is, they both contain:
"Hello'
They don't contain \"Hello' or "Hello\'. You must understand this completely in order to not confuse yourself. Source code is not the same as the value of the data. Source code is just a way we write the data so that our programming language understand it.
When you do:
const input = "C:\Users\mypc\AppData\Roaming\npm\ts-node"
The value of input is:
C:UsersmypcAppDataRoaming
pm s-node
You need to write that data in a different way so that it will have the right value. You need to write:
const input = "C:\\Users\\mypc\\AppData\\Roaming\\npm\\ts-node"
The value of input is now:
C:\Users\mypc\AppData\Roaming\npm\ts-node
Let's remind ourselves again. This is the VALUE of the variable. The variable DOES NOT actually contain C:\\Users\\mypc\\AppData\\Roaming\\npm\\ts-node.
Now, here's another example. I'm creating a text file called "path.txt" and in it I write:
C:\Users\mypc\AppData\Roaming\npm\ts-node
Very carefully note what I'm writing in my text file. This is not a javascript source code. This is just data. I'm not writing C:\\Users\\mypc\\AppData\\Roaming\\npm\\ts-node because I'm not writing javascript here. I'm just writing data.
Now if I do this:
let data3 = fs.readFileSync('path.txt');
The value of data3 is:
C:\Users\mypc\AppData\Roaming\npm\ts-node
That's right. Javascript DOES NOT interpret the escape sequence AT ALL. Let me remind you again. Javascript does not interpret string escape sequence in data (eg, data you entered from the terminal or a file). It only does that in source code.
So. The answer to
I want to escape correctly a windows path that I get from cmd command.
Is you need to do nothing at all. There is no escaping being done by javascript.
But note: command shells like cmd.com or PowerShell on Windows or bash, dash, tcsh, fish etc. on Linux and Mac OS also have their own syntax. So in order to write the command correctly so that your shell (eg. cmd.com) will pass the correct data to your node.js process you need to understand your shell's syntax.
I don't use Windows so I'm not sure what you need to write on cmd.com to get it right but on Linux/Mac OS, assuming I have this script:
// testing.js
let data = process.argv[2];
console.log(data);
I can execute the script like this:
node ./testing.js C:\Users\mypc\AppData\Roaming\npm\ts-node
This is because bash (the shell I'm using) does not escape the \ character.
I only know the
console.log(JSON.stringify(input)), and the
console.log(util.inspect(input)) solutions, but the first backlash will disappear.
'C:UsersmypcAppDataRoaming\npm\ts-node'

Parsing malformed JSON in JavaScript

Thanks for looking!
BACKGROUND
I am writing some front-end code that consumes a JSON service which is returning malformed JSON. Specifically, the keys are not surrounded with quotes:
{foo: "bar"}
I have NO CONTROL over the service, so I am correcting this like so:
var scrubbedJson = dirtyJson.replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2": ');
This gives me well formed JSON:
{"foo": "bar"}
Problem
However, when I call JSON.parse(scrubbedJson), I still get an error. I suspect it may be because the entire JSON string is surrounded in double quotes but I am not sure.
UPDATE
This has been solved--the above code works fine. I had a rogue single quote in the body of the JSON that was returned. I got that out of there and everything now parses. Thanks.
Any help would be appreciated.
You can avoid using a regexp altogether and still output a JavaScript object from a malformed JSON string (keys without quotes, single quotes, etc), using this simple trick:
var jsonify = (function(div){
return function(json){
div.setAttribute('onclick', 'this.__json__ = ' + json);
div.click();
return div.__json__;
}
})(document.createElement('div'));
// Let's say you had a string like '{ one: 1 }' (malformed, a key without quotes)
// jsonify('{ one: 1 }') will output a good ol' JS object ;)
Here's a demo: http://codepen.io/csuwldcat/pen/dfzsu (open your console)
something like this may help to repair the json ..
$str='{foo:"bar"}';
echo preg_replace('/({)([a-zA-Z0-9]+)(:)/','$1"$2"${3}',$str);
Output:
{"foo":"bar"}
EDIT:
var str='{foo:"bar"}';
str.replace(/({)([a-zA-Z0-9]+)(:)/,'$1"$2"$3')
There is a project that takes care of all kinds of invalid cases in JSON https://github.com/freethenation/durable-json-lint
I was trying to solve the same problem using a regEx in Javascript. I have an app written for Node.js to parse incoming JSON, but wanted a "relaxed" version of the parser (see following comments), since it is inconvenient to put quotes around every key (name). Here is my solution:
var objKeysRegex = /({|,)(?:\s*)(?:')?([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*)(?:')?(?:\s*):/g;// look for object names
var newQuotedKeysString = originalString.replace(objKeysRegex, "$1\"$2\":");// all object names should be double quoted
var newObject = JSON.parse(newQuotedKeysString);
Here's a breakdown of the regEx:
({|,) looks for the beginning of the object, a { for flat objects or , for embedded objects.
(?:\s*) finds but does not remember white space
(?:')? finds but does not remember a single quote (to be replaced by a double quote later). There will be either zero or one of these.
([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*) is the name (or key). Starts with any letter, underscore, $, or dot, followed by zero or more alpha-numeric characters or underscores or dashes or dots or $.
the last character : is what delimits the name of the object from the value.
Now we can use replace() with some dressing to get our newly quoted keys:
originalString.replace(objKeysRegex, "$1\"$2\":")
where the $1 is either { or , depending on whether the object was embedded in another object. \" adds a double quote. $2 is the name. \" another double quote. and finally : finishes it off.
Test it out with
{keyOne: "value1", $keyTwo: "value 2", key-3:{key4:18.34}}
output:
{"keyOne": "value1","$keyTwo": "value 2","key-3":{"key4":18.34}}
Some comments:
I have not tested this method for speed, but from what I gather by reading some of these entries is that using a regex is faster than eval()
For my application, I'm limiting the characters that names are allowed to have with ([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*) for my 'relaxed' version JSON parser. If you wanted to allow more characters in names (you can do that and still be valid), you could instead use ([^'":]+) to mean anything other than double or single quotes or a colon. You can have all sorts of stuff in here with this expression, so be careful.
One shortcoming is that this method actually changes the original incoming data (but I think that's what you wanted?). You could program around that to mitigate this issue - depends on your needs and resources available.
Hope this helps.
-John L.
How about?
function fixJson(json) {
var tempString, tempJson, output;
tempString = JSON.stringify(json);
tempJson = JSON.parse(tempString);
output = JSON.stringify(tempJson);
return output;
}

Store Html.Raw() in a string in Javascript, ASP.NET MVC 3

I'm using ASP.NET and I have a string of HTML in the database.
I want to get that html into a variable on the client.
If I do this:
var x = '#Html.Raw(myModel.FishValue)'
it works fine, because it's essentially doing
var x = '<p>hello!</p>';
however if there are quotes in the html it breaks the page.
My initial guess would be to .Replace the raw string to add escapes to the quotes, however both .ToString() and .ToHtmlString() (as Html.Raw returns an IHtmlString) do not produce the same markup as simple Html.Raw().
So I'm at a loss of what best to do.
What about replacing before calling the Html.Rawmethod?
var x = '#Html.Raw(myModel.FishValue.Replace("'","\\'"))'
UPDATE:
There might be other escape chars in the string coming from the model. For that reason I would recommend replacing the slashes first as well. Of course it all depends on what might come from the server in your model.
var x = '#Html.Raw(myModel.FishValue.Replace("\\","\\\\'").Replace("'","\\'"))'
A sample snippet representing the behavior in the javascript:
//Let's say my Model Content is > I'd Say \ is a escape character. You can't "Escape"
// YOu would have to replace ' --> \' and \ --> \\
var stringFromServer = 'I\'d Say \\ is a escape character. You can\'t "Escape"'
alert(stringFromServer)
Try this:
var x = '#(System.Web.HttpUtility.HtmlEncode(myModel.FishValue))';
If you need to decode the HTML on the client side use
unescape(x)
I think JQuery (not sure if you're using it or not) handles encoded HTML strings so you might not need unescape().
Try out the anti-xss library from Microsoft (which will be included I believe by default in asp.net 4.5):
AntiXss.JavascriptEncode(yourContent)
Anti-Xss is available 4.1 beta. If you want to use it in your application which I highly recommend, check out:
http://weblogs.asp.net/jgalloway/archive/2011/04/28/using-antixss-4-1-beta-as-the-default-encoder-in-asp-net.aspx

Regex won't find '\u2028' unicode characters

We're having a lot of trouble tracking down the source of \u2028 (Line Separator) in user submitted data which causes the 'unterminated string literal' error in Firefox.
As a result, we're looking at filtering it out before submitting it to the server (and then the database).
After extensive googling and reading of other people's problems, it's clear I have to filter these characters out before submitting to the database.
Before writing the filter, I attempted to search for the character just to ensure it can find it using:
var index = content.search("/\u2028/");
alert("Index: [" + index + "]");
I get -1 as the result everytime, even when I know the character is in the content variable (I've confirmed via a Java jUnit test on the server side).
Assuming that content.replace() would work the same way as search(), is there something I'm doing wrong or anything I'm missing in order to find and strip these line separators?
Your regex syntax is incorrect. You only use the two forward slashes when using a regex literal. It should be just:
var index = content.search("\u2028");
or:
var index = content.search(/\u2028/); // regex literal
But this should really be done on the server, if anywhere. JavaScript sanitization can be trivially bypassed. It's only useful for user convenience, and I don't think accidentally entering line separator is that common.

javascript ampersand (&) in return data will not show as value

I have this bit of code:
...
var aData = request.responseXML.getElementsByTagName('data')[0];
var sDescription = aData.getElementsByTagName('description')[0].firstChild.data;
alert(escape(sDescription));
document.getElementById('tempLabourLineDescription').value = sDescription;
...
sDescription is outputting: SUPPORT ASSY-FUEL TANK MOUNTING, R&R (LH) (L-ENG)
I think it is obvious what i want to do here (get the sDescription in to a field called tempLabourLineDescription but that just will not work.
However, if i in my php script replace or delete the &-char from that string it all works fine. So i thought, just escape the darn string. But that will just not work.
alerting the string doesn't work either until i remove the &-character.
What is doing this? Is sDescription not a string when it comes out of the xml file?
How can i solve this?
The answer is in this snippet:
var aData = request.responseXML...
You're expecting XML. An & by itself is not legal XML. You need to output your result like this:
SUPPORT ASSY-FUEL TANK MOUNTING, R&R (LH) (L-ENG)
It's very difficult to tell without seeing your output script, but the first thing to try is to mask the ampersand: &
The neater way, though, would be to add CDATA to your XML output:
<data><![CDATA[SUPPORT ASSY-FUEL TANK MOUNTING, R&R (LH) (L-ENG)]]></data>
your XML parser on client side should understand it no problem.
You escape the ampersand by using the HTML eqv. &
If you are unable to alter the XML output from the server (it's not your app or some other issue), a "hack" fix would be:
function htmlizeAmps(s){
return s.replace(/\x26/g,"&"); //globalreplace "&" (hex 26) with "&"
}
document.getElementById('tempLabourLineDescription').value = htmlizeAmps(sDescription);

Categories

Resources