Why does jquery.serialize change LF to CRLF? - javascript

I'm trying to post this form:
<form id="the-form" enctype="multipart/form-data" >
<textarea class="form-control" name="list" id="list"></textarea>
</form>
with this script:
$.post( "/route", $('#the-form').serialize());
and debug of the script shows that JSON.stringify($('#list').val())
returns "line1\nline2\nline3"
while $('#the-form').serialize() returns
wordlist=line1%0D%0Aline2%0D%0Aline3.
So why does jquery.serialize encodes \n to %0D%0A? Is there a way to make serialize return string with %0A EOL?

This is by design, see here:
When serializing text, encode all line breaks as CRLF pairs per the application/x-www-form-urlencoded specification.
which says:
Line breaks are represented as "CR LF" pairs (i.e., `%0D%0A').
--
Is there a way to make serialize return string with %0A EOL?
None apart from removing %0D's manually after serializing.

As georg mentioned, this is intended functionality.
You can replace instances of %0D%0A in the serialized string as follows:
var formVars = $('#the-form').serialize().replace(/%0D%0A/g, '%0A');

Related

"Literally" insert string into HTML input

I want to insert a string "literally" into an HTML input field using jQuery.
The problem is that the string contains escaped characters and character codes, and all of those need to still be there when the string is inserted.
My problem seems to be with escaped characters (thanks for the comments that pointed that out). I can't figure out how I can insert the string without the escaped characters and codes being translated.
The literal strings come from a file data.txt. To clarify, this is just an exemplary string that is used to demonstrate that there can be escaped quotes and character codes etc. in the strings.
TEST\"/**\x3e
They are loaded (in node.js) from the file into an array of strings.
Wrapper code (Node.js) visits the page using the Chrome dev tools.
Here, for each string a script is prepared that is injected and executed on the page.
Therefore the inputString is inserted into the script, before it is injected.
So here is my problem with string escaping. I have the strings in literal format as data and I currently inject them as dynamically generated JavaScript code which is where escaping problems occur.
Injected Code
// this was (currently incorrectly) injected into the page before
// from the array of input strings that was loaded from data
let insertString = "TEST\"/**\x3e"; // <-
let form = $("form").first();
let inputs = form.find(":input").not(":input[type=submit]");
let input = inputs.first();
input.focus().val(insertString);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Exemplary form code on the page -->
<form action="post" method="post">
<label for="name">Name: </label>
<input id="name" type="text" name="input">
<input type="submit" value="Submit">
</form>
What we got
What I want
The string is not inserted as is.
For example the character code \x3e is translated to >.
Also the escaped \" is translated to ".
It needs to be inserted just as it would be when copying and pasting from the data file.
Thoughts on a potential (manual) solution
So one potential solution is to rework the data.txt file and escape the strings correctly. So the first line might be TEST\\\"/**\\x3e, as #Jamiec and #Barmar have proposed.
// injected before
let insertString = "TEST\\\"/**\\x3e"; // <- manually escaped
let form = $("form").first();
let inputs = form.find(":input").not(":input[type=submit]");
let input = inputs.first();
input.focus().val(insertString);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Exemplary form code on the page -->
<form action="post" method="post">
<label for="name">Name: </label>
<input id="name" type="text" name="input">
<input type="submit" value="Submit">
</form>
The string will then be inserted as intended, but the solution is still not satisfying, because it would be better for me to not touch the input data.
It would be best to have the input strings in the data.txt file exactly as they will look when they are inserted into the page.
This would require and additional step between loading the input data and inserting each string into the script (that is then injected into the page). Potentially this preprocessing can be done with regexp replacements.
You need to escape all the backslashes and quotes in the string. You can do this using a regular expression.
function escape_string(string) {
return string.replace(/[\\"']/g, "\\$&");
}
console.log('let str = "' + escape_string(prompt("Type a string")) + '";');
This has nothing to do with encoding, nor input fields - it is simply string escapes - so can be demonstrated using the console (or any other way of displaying a string).
In order to see the literal escape character \ in a string you must escape the escape character with \\ - see below:
var text1 = "TEST\"/**\x3e";
console.log(text1)
var text2 = "TEST\\\"/**\\x3e";
console.log(text2)
As you can see the first output is your exact problem, where as the second escapes the escape character so you get what you expect in the output.

JSP attribute JSON object is dropping escape characters in Javascript

I have a server-side controller which is adding an attribute which is a Java object converted to JSON using Jackson:
ObjectMapper mapper = new ObjectMapper();
model.addAttribute("commentObj", mapper.writeValueAsString(commentObject);
My commentObject has a field "comments" which contains quotation marks (") that JSON needs to escape. When I do a simple print-out from the JSP of the commentObject, everything looks good:
[{"commentId":123,"comments": "this \"test\" is here"}]
As you see, the quotes get escaped properly (\").
My problem comes with the javascript on this page that also needs to access this object. So when I run the following:
<script>
var test = ${commentObj};
</script>
If I take a look at the 'test' var, the comments field now reads as follows:
"this "test" is here"
vs.
"this \"test\" is here"
This causes a problem because JSON.parse() will throw an error on 'test' because it is not properly formed JSON anymore.
So my question is, how do I manage to get my commentObj into a javascript object while keeping the escape characters so that I can JSON.parse it properly?
Sorry, written at the end of a long day while sick and only just realized now that the 'test' var ends up being a fully formed JS object. So I am able to use that.
That said, I still have the question of how that is happening? It seems to me that it should be coming in as a JSON string that I need to call JSON.parse on. Anyone have an explanation?

Convert Unicode Javascript string to PHP utf8 string

I make form with input text.
<input type="text" id="input" value=""/>
i received utf-8 string from web like this (with javascript, jquery)
var str = '\u306e\u7c21\u5358\u306a\u8aac\u660e';
str is 'の簡単な説明'.
set input field value to 'str'
$('#input').val(str);
this input replace all of escape string '\' and set string like this.
<input type"text" id="input" value="u306eu7c21u5358u306au8aacu660e"/>
no problem in this point. display character is also good.
But.
When I save this string into my database with PHP
PHP put this value non-escaped utf8 string 'u306eu7c21u5358u306au8aacu660e' to database
and next time I've call
<input type="text" id="input" value="<?=$str?>">
and browser displays raw value
just 'u306eu7c21u5358u306au8aacu660e'
not 'の簡単な説明'
I don't know what is wrong.
I've tried
$str = json_decode("\"".$str."\"");
html_entity_decode(...);
mb_convert_encoding(...);
but not working correctly...
How can I covert this non-escaped utf-8 string to general utf-8 string?
You've MUST have MultiByte String support. With some extra work here is what you need:
<?php
$str = 'u306eu7c21u5358u306au8aacu660e';
function converter($sequence) {
return mb_convert_encoding(pack('H*', $sequence), 'UTF-8', 'UCS-2BE');
}
# array_filter is not important here at all it just "remove" empty strings
$converted = array_map('converter', array_filter(explode('u', $str)));
$converted = join('', $converted);
print $converted;
Just as a side note you OUGHT TO FIND a better strategy in order to
split the unicode sequences. By "exploding" string by u char is
somewhat ingenuo.
Also, I strongly advise you read the excelent blog post by Armin Ronacher, UCS vs UTF-8 as Internal String Encoding.

Why are endline characters illegal in HTML string sent over ajax?

Within HTML, it is okay to have endline characters. But when I try to send HTML strings that have endline characters over AJAX to have them operated with JavaScript/jQuery, it returns an error that says that endline characters are illegal. For example, if I have a Ruby string:
"<div>Hello</div>"
and jsonify it with Ruby by to_json, and send it over ajax, parse it within JavaScript by JSON.parse, and insert that in jQuery like:
$('body').append('<div>Hello</div>');
then it does not return an error, but if I do a similar thing with a string like
"<div>Hello\n</div>"
it returns an error. Why are they legal in HTML and illegal in AJAX? Are there any other differences between a legal HTML string loaded as a page and legal HTML string sent over ajax?
string literals can contain line breaks, they just need to be escaped with a backslash like so:
var string = "hello\
world!";
However, this does not create a line break in the string, as it must be an explicit \n escape sequence. This would technically become helloworld. Doing
var string = "hello"
+ "world"
would be much cleaner
Specify the type of the ajax call as 'html'. Jquery will try to infer the type when parsing the response.
If the response is json, newlines should be escaped.
I'd recommend using a library to serialize json. You're unlikely to handle all the edge cases if you roll your own.
Strings in JavaScript MUST appear on a single line, with the exception of escaping that line:
var str = "abc \
def";
However note that the newline is escaped and will not appear in the string itself.
The best option is \n, but note that if it is already going through something that parses \n then you will need to double-escape it as \\n.
Seeing how you're already escaping the JSON properly by using to_json in Ruby, I do believe the bug is in jQuery; when there are newlines in the string it has trouble determining whether you meant to create a single element or a document fragment. This would work just fine:
var str = "<div>Hello\n</div>";
var wrapper = document.createElement('div');
wrapper.innerHTML = str;
$('body').append(wrapper);
Demo

URL Encoding in JS for meaningful URLs and Rails Page Caching

I'm running a Rails Application which gets a lot of traffic at the moment so I started using Page Caching to increase the performance. So far everything works like a charm. But when I tried to also cache search results I run into a strange problem.
My Approach:
Use meaningful URLs for searching and pagination (/search?query=term&page=3 becomes /search/term/3)
Use Javascript to submit the form - if JS is disabled it falls back to the old form (which also works with my routes, but without caching)
My Code:
// Javascript
function set_search_action() {
window.location = '/search/' + escape(document.getElementById('query').value);
return false;
}
// HTML
<form action="/search" id="search_form" method="get" onSubmit="return set_search_action();">
<input id="query" name="query" title="Search" type="text" />
<input class="submit" name="commit" type="submit" value="Search" />
</form>
The Problem
Everything works for single words like "term". But when I search for "term1 term2" the form is submitted to /search/term1 term2/ or /search/term1 term2/1 . It should be submitted to /search/term1+term2 That's what the JS escape function should do I think.
So far it works also with spaces in development mode. But I guess it will become a problem in production mode with caching enabled (URLs shouldn't contain any whitespaces).
Any ideas on what I did wrong? Thanks!
It should be submitted to /search/term1+term2
Nope. Plus symbols only represent spaces in application/x-www-form-urlencoded content, such as when the query-string part of the URL is used to submit a form. In the path-part of a URL, + simply means plus; space should be encoded to %20 instead.
That's what the JS escape function should do I think.
Yes it does, and that's the problem. escape encodes spaces to +, which is only suitable for form submissions; used in a path, you will get an unexpected and unwanted plus sign. It also mangles non-ASCII characters into an arbitrary format specific to the escape function that no URL-decoder will be able to read.
As Tomalak said, escape()/unescape() is almost always the wrong thing, and in general should not be used. encodeURIComponent() is usually what you really want, and will produce %20 for spaces, which is safe as it is equally valid in the path part or the query string.
Never use escape()! It's broken and highly dis-recommended for what you do. Use encodeURIComponent() instead.
To have + instead of %20, append a .replace(/%20/g, "+").

Categories

Resources