Prevent escape sequence interpretation in Javascript - 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'

Related

How to pass a "?" as a routing parameter in express while using node js

I am creating a blog website for my college using express and nodejs this might be a silly question but I need an answer.
as you can see from the following piece of code-
enter code here
cons express = require("express");
.....
.....
app.get("/blog/:title_of_blog", function(request, response){
var title_requested = request.params.title_of_blog;
console.log(title_requested);
})
It works fine in all the cases I tried except when if a user enters a string in as a routing parameter like "what is your name?" then it console logs only "what is your name"
So a question mark gets excluded here on which further process depends as it should be exactly the same,
Is there any way I could fix this???
If you do need any additional information please do let me know
Because express will understand ? is for starting a query string. So usually if you want to put blog title to URL, you can parse title to slug using some lib.
In JavaScript, PHP, and ASP there are functions that can be used to URL encode a string.
PHP has the rawurlencode() function, and ASP has the Server.URLEncode() function.
In JavaScript you can use the encodeURIComponent() function.
source
When you apply encoding on your blog title and pass URL Become like this
/blog/what%20is%20your%20name%20%3F
You will got the exact result as you want. :)
certain Characters such as ?, # are not allowed in URL Parsing or I recently discovered even while storing cookies, but there is a simple way to avoid these problems and get your string in the desired way
var encodedString = encodeURI(rawString);
this above line turns all the characters such as # into an easily parsable string and after the string is processed whenever you need the actual string you just have to type one line to get the original string
var originalString = decodeURI(enodedString);

Applescript with do Javascript and passed Applescript Variable

I have written a script that has automated the creation of products on a website I administer. In my process I upload JPEG images of the products and pull the Keywords that are tagged in the JPEG to add into the product information. In this process I use Applescript to Activate Safari and process a Javascript line of code. The line of code includes the a variable that is derived from Applescript Shell Script.
Code below
tell application "Finder"
set sourceFolder to folder POSIX file "/Users/<username>/Desktop/Upload/Temp/HighRes/"
set theFiles to files of sourceFolder
set inputPath to "/Users/<username>/Desktop/Upload/Temp/"
end tell
repeat with afile in theFiles
set filename to name of afile
set fname to text 1 thru ((offset of "." in filename) - 1) of filename
--INPUT CODE TO BE LOOPED OVER BELOW--
--Add Image Keywords from Metadata--
try
set pathVAR1 to "/Users/<username>/Desktop/Upload/Temp/HighRes/"
set pathVAR2 to pathVAR1 & filename
set myvar to do shell script "mdls -name kMDItemKeywords " & quoted form of pathVAR2
set var1 to ((offset of "(" in myvar) + 1)
set var2 to ((length of myvar) - 1)
set myKeywords to ((characters var1 thru var2 of myvar) as string)
--Inputs the Keywords from the Image Metadata--
tell application "Safari"
activate
do JavaScript "document.getElementById('ctl00_cphMainContent_txtKeyWords').value = \"" & myKeywords & "\";" in current tab of window 1
end tell
end try
--END OF CODE TO BE LOOPED OVER--
end repeat
==End Code==
Problem:
The code below is not passing the variable myKeywords to Safari, but if I run a dialog it will appear in the dialog.
do JavaScript "document.getElementById('ctl00_cphMainContent_txtKeyWords').value = \"" & myKeywords & "\";" in current tab of window 1
I don't have a specific solution that will definitely solve your problem, but I do have a number of observations about your script with recommendations on how it can be changed to improve its speed, robustness and adherence to principles of best practice.
Get rid of that try block. You have no idea what's happening in your script when things go wrong if you're masking the errors with unnecessary error-catching. The only line that needs to be enclosed in try...end try is do shell script, but only put it in once you know your code is working. In general, try blocks should only be used:
when your script has the potential to throw an error that is entirely predictable and explainable, and you understand the reasons why and under what conditions the error occurs, allowing you to implement an effective error-handling method;
around the fewest possible number of lines of code within which the error arises, leaving all lines of code whose existence doesn't depend on the result of the error-prone statement(s);
after your script has been written, tested, and debugged, where placing the try block(s) no longer serves to force a script to continue executing in the wake of an inconvenient error of unknown origin, but has a clear and well-defined function to perform in harmony with your code, and not against it.
As a general rule in AppleScript, don't use Finder to perform file system operations if you can avoid it: it's slow, and blocks while it's performing the operations, meaning you can't interact with the GUI during this time. Use System Events instead. It's a faceless application that won't stop other things operating when it's performing a task; it's fast, in the context of AppleScript and Finder in particular, and isn't prone to timing out quite so much as Finder does; it handles posix paths natively (including expansion of tildes), without any coercion necessary using POSIX file; it returns alias objects, which are the universal class of file object that every other scriptable application understands.
There are a couple of instances where Finder is still necessary. System Events cannot reveal a file; nor can it get you the currently selected files in Finder. But it's simple enough to have Finder retrieve the selection as an alias list, then switch to System Events to do the actual file handling on this list.
This is curious:
set filename to name of afile
set fname to text 1 thru ((offset of "." in filename) - 1) of filename
Am I right in thinking that fname is intending to hold just the base file name portion of the file name, and this operation is designed to strip off the extension ? It's a pretty good first attempt, and well done for using text here to itemise the components of the string rather than characters. But, it would, of course, end up chopping off a lot more than just the file extension if the file name had more than one "." in it, which isn't uncommon.
One way to safely castrate the end of the file name is to use text item delimiters:
set filename to the name of afile
set fname to the filename
set my text item delimiters to "."
if "." is in the filename then set fname to text items 1 thru -2 of the filename as text
You should then be mindful or resetting the text item delimiters afterwards or there'll be consequences later on when you try and concatenate strings together.
Another way of chopping of the extension without utilising text item delimiters is string scanning, which is where you iterate through the characters of a string performing operations or tests as you go, and achieving the desired outcome. It's speedier than it sounds and a powerful technique for very complex string searching and manipulations:
set filename to the name of afile
set fname to the filename
repeat while the last character of fname ≠ "."
set fname to text 1 thru -2 of fname
end
set fname to text 1 thru -2 of fname
You could also retrieve the name extension property of the file, get its length, and remove (1 + that) many characters from the end of the file's name. There a myriad ways to achieve the same outcome.
This is wrong in this particular instance:
set myKeywords to ((characters var1 thru var2 of myvar) as string)
characters produces a list, which you then have to concatenate back into a string, and this is unsafe if you aren't sure what the text item delimiters are set to. As you haven't made a reference to it in your script, it should be set to an empty string, which would result in the joining of the characters back into words produce the expected result. However, this could easily not be the case, if, say, you performed the first technique of file extension castration and neglected to set the text item limiters back—then the resulting string would have a period between every single letter.
As a policy in AppleScript (which you can personally choose to adhere to or ignore), it's considered by some as poor form if you perform list to string coercion operations without first setting the text item delimiters to a definitive value.
But you needn't do so here, because rather than using characters, use text:
set myKeywords to text var1 thru var2 of myvar
You're performing a shell command that looks like this: mdls -name kMDItemKeywords <file>, and then the two lines of AppleScript that follow awkwardly try and trim off the leading and trailing parentheses around the text representation of a bash array. Instead, you can turn on the -raw flag for mdls, which simplifies the output by stripping off the name of the key for you. This then places the parentheses as the very first and very last characters; however, since there's a load of dead whitespace in the output as well, you might as well get bash to perform all the clean up for you:
mdls -raw -name kMDItemContentTypeTree <file> | grep -E -io '[^()",[:blank:]]+'
This disregards parentheses, double quotes, commas, and whitespace, so all you get back is a list of keywords, one per line, and without any extra baggage. If you needed to itemise them, you can set a variable to the paragraphs of the output from the do shell script command, which splits the text into lines placing each keyword into a list. But it seems here that you need text and don't mind it being multilinear.
When I started to write this answer, I didn't have an inkling as to what was causing the specific issue that brought you here. Having gone through the details of how mdls formats its output, I now see the issue is with the fact that the myKeywords string will contain a bunch of double quotes, and you've surrounded the placement of the myKeywords entity in your JavaScript expression with double quotes. All of these quotes are only being escaped equally and once only in the AppleScript environment but not in the JavaScript environment, which results in each neighbouring double quote acting as an open-close pair. I ran a similar command in bash to obtain an array of values (kMDContentTreeType), and then processed the text in the way AppleScript does, before opening the JavaScript console in my browser and pasting it to illustrate what's going on:
Anything in red is contained inside a string; everything else is therefore taken as a JavaScript identifier or object (or it would be if the messed up quotes didn't also mess up the syntax, and then result in an unterminated string that's still expecting one last quote to pair with.
I think the solution is to use a continuation character "\" for backward compatibility with older browsers: so you would need to have each line (except the last one) appended with a backslash, and you need to change the pair of double quotes surrounding the myKeywords value in your JavaScript expression to a pair of single quotes. In newer browsers, you can forgo the headache of appending continuation marks to each line and instead replace the pair of outside double quotes with a pair of backticks (`) instead:
❌'This line throws
an EOF error in
JavaScript';
✅'This line is \
processed successfully \
in JavaScript';
✅`This line is also
processed successfully
in JavaScript`;
I had tried the backticks ( ` ) suggested by CJK but that did not work for me. The main issue being raised was that the kMDItemKeywords returned escaped characters.
Heart,
Studio,
Red,
\"RF126-10.tif\",
Tree,
\"Heart Tree\",
occasion,
Farm,
birds,
\"Red Farm Studio\",
\"all occasion\",
all
I was able to get rid of the escaped characters using the following:
NEW CODE
set myKeywords to do shell script "echo " & quoted form of myKeywords & " | tr -d '[:cntrl:]'| tr '[:upper:]' '[:lower:]' | tr -d '\"'"
UPDATED CODE FOR JAVASCRIPT
--Inputs the Keywords from the Image Metadata--
tell application "Safari"
activate
do JavaScript "document.getElementById('ctl00_cphMainContent_txtKeyWords').value = '" & myKeywords & "';" in current tab of window 1
end tell
RESULT
--> " heart, studio, red, rf126-10.tif, tree, heart tree, occasion, farm, birds, red farm studio, all occasion, all"

Awkward escape characters

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.

How to assign large string to a variable without ILLEGAL Token error?

I need to assign a long string (4 pages worth of text) to a variable, so far I've been doing it like this
var myText = "[SOME] Text goes \
.. here ? and 'there' \
is more ( to \
come etc. !)";
slashes at the end need to be added to all of the text, and I can't imagine how long this will take to do manually. Also, I get ILLEGAL error for some reason I don't understand for the first line.
Therefore I wanted to find out the best way to handle this situation. I was looking into solutions of passing in a .txt file, but would rather do it as a really long string (this is not a production app). Also string shown in example is random, showing that there can be a lot of various characters in it that need to be accounted for.
You have to concatenate the string:
var t = ""
+"text line 1"
...
+"text line n"
But I would put the text in a text file and read it using xhr (on client) or io (on server).
You cannot have a multiline string definition in javascript but you have several options :
save your text in a file and read this file from your program
use the multiline npm module which propose a hack to use function comments as multiline string definitions
use ES6 multi-line template strings notation, which have multi-line support - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings#Multi-line_strings
saving the text in a file would seem to me as the preferred option in your case since the text seem to be very long an potentially coming from an untrusted source. You do not want the pasted text to close the string and start doing innapropriate function calls.

Dealing with the Cyrillic encoding in Node.Js / Express App

In my app a user submits text through a form's textarea and this text is passed on to the app and is then processed by jsesc library, which escapes javascript strings.
The problem is that when I type in a text in Russian, such as
нам #интересны наши #идеи
what i get is
'\u043D\u0430\u043C #\u0438\u043D\u0442\u0435\u0440\u0435\u0441\u043D\u044B \u043D\u0430\u0448\u0438 #\u0438\u0434\u0435\u0438'
I then need to pass this data through FlowDock to extract hashtags and FlockDock just does not recognize it.
Can someone please tell me
1) What is the need for converting it into that representation;
2) If it makes sense to convert it back to cyrillic encoding for FlowDock and for the database, or shall I keep it in Unicode and try to make FlowDock work with it?
Thanks!
UPDATE
The complete script is:
result = getField(req, field);
result = S(result).trim().collapseWhitespace().s;
// at this point result = "нам #интересны наши #идеи"
result = jsesc(result, {
'quotes': 'double'
});
// now i end up with Unicode as above above (\u....)
var hashtags = FlowdockText.extractHashtags(result);
FlowDock receives the result which is
\u043D\u0430\u043C #\u0438\u043D\u0442\u0435\u0440\u0435\u0441\u043D\u044B \u043D\u0430\u0448\u0438 #\u0438\u0434\u0435\u0438
And doesn't extract hashtags from it...
These are 2 representations of the same string:
'нам #интересны наши #идеи' === '\u043D\u0430\u043C #\u0438\u043D\u0442\u0435\u0440\u0435\u0441\u043D\u044B \u043D\u0430\u0448\u0438 #\u0438\u0434\u0435\u0438'
looks like flowdock-text doesn't work well with non-ASCII characters
UPD: Tried, actually works well:
fdt.extractHashtags('\u043D\u0430\u043C #\u0438\u043D\u0442\u0435\u0440\u0435\u0441\u043D\u044B \u043D\u0430\u0448\u0438 #\u0438\u0434\u0435\u0438');
You shouldn't have used escaping in the first place, it gives you string literal representation (suits for eval, etc), not a string.
UPD2: I've reduced you code to the following:
var jsesc = require('jsesc');
var fdt = require('flowdock-text');
var result = 'нам #интересны наши #идеи';
result = jsesc(result, {
'quotes': 'double'
});
var hashtags = fdt.extractHashtags(result);
console.log(hashtags);
As I said, the problem is with jsesc: you don't need it. It returns javascript-encoded string. You need when you are doing eval with concatenation to protect from code injection, or something like this. For example if you add result = eval('"' + result + '"');, it will work.
What is the need for converting it into that representation?
jsesc is a JavaScript library for escaping JavaScript strings while generating the shortest possible valid ASCII-only output. Here’s an online demo.
This can be used to avoid mojibake and other encoding issues, or even to avoid errors when passing JSON-formatted data (which may contain U+2028 LINE SEPARATOR, U+2029 PARAGRAPH SEPARATOR, or lone surrogates) to a JavaScript parser or an UTF-8 encoder, respectively.
Sounds like in this case you don’t intend to use jsesc at all.
Try this:
decodeURIComponent("\u043D\u0430\u043C #\u0438\u043D\u0442\u0435\u0440\u0435\u0441\u043D\u044B \u043D\u0430\u0448\u0438 #\u0438\u0434\u0435\u0438");

Categories

Resources