How do you safely encode a URL using JavaScript? - javascript

specially * and ! characters which are not encoded using encodeUriComponent

As I've said in the comments, you don't have to encode * or ! in a query string. This is perfectly fine, for instance: http://example.com?foo=bar*!
You seem intent on doing it anyway. You can, if you want, but you don't have to.
Here's how you would if it were necessary:
var param = "bar*!";
param = encodeURIComponent(param)
.replace(/\*/g, '%2a') // 2a is the %-encoding of *
.replace(/!/g, '%21'); // 21 is the %-encoding of !
var url = "http://example.com?foo=" + param;
(If you need to unnecessarily encode other characters, you can get the %-encoding value for them like this: "*".charCodeAt(0).toString(16).)
Or actually, we can automate that:
var param = "bar*!";
param = encodeURIComponent(param).replace(/[*!]/g, function(m) {
return "%" + m.charCodeAt(0).toString(16);
});
var url = "http://example.com?foo=" + param;
...just add any others within the character class (the [...] in the regular expression). (This is less efficient, but it's unlikely to matter.)
But if whatever you're passing this parameter to fails with a raw * or !, I would expect it to fail with an encoded one as well.

Related

How to convert string from ENV to hex in JavaScript? [duplicate]

I have a string in JS in this format:
http\x3a\x2f\x2fwww.url.com
How can I get the decoded string out of this? I tried unescape(), string.decode but it doesn't decode this. If I display that encoded string in the browser it looks fine (http://www.url.com), but I want to manipulate this string before displaying it.
Thanks.
You could write your own replacement method:
String.prototype.decodeEscapeSequence = function() {
return this.replace(/\\x([0-9A-Fa-f]{2})/g, function() {
return String.fromCharCode(parseInt(arguments[1], 16));
});
};
"http\\x3a\\x2f\\x2fwww.example.com".decodeEscapeSequence()
There is nothing to decode here. \xNN is an escape character in JavaScript that denotes the character with code NN. An escape character is simply a way of specifying a string - when it is parsed, it is already "decoded", which is why it displays fine in the browser.
When you do:
var str = 'http\x3a\x2f\x2fwww.url.com';
it is internally stored as http://www.url.com. You can manipulate this directly.
If you already have:
var encodedString = "http\x3a\x2f\x2fwww.url.com";
Then decoding the string manually is unnecessary. The JavaScript interpreter would already be decoding the escape sequences for you, and in fact double-unescaping can cause your script to not work properly with some strings. If, in contrast, you have:
var encodedString = "http\\x3a\\x2f\\x2fwww.url.com";
Those backslashes would be considered escaped (therefore the hex escape sequences remain unencoded), so keep reading.
Easiest way in that case is to use the eval function, which runs its argument as JavaScript code and returns the result:
var decodedString = eval('"' + encodedString + '"');
This works because \x3a is a valid JavaScript string escape code. However, don't do it this way if the string does not come from your server; if so, you would be creating a new security weakness because eval can be used to execute arbitrary JavaScript code.
A better (but less concise) approach would be to use JavaScript's string replace method to create valid JSON, then use the browser's JSON parser to decode the resulting string:
var decodedString = JSON.parse('"' + encodedString.replace(/([^\\]|^)\\x/g, '$1\\u00') + '"');
// or using jQuery
var decodedString = $.parseJSON('"' + encodedString.replace(/([^\\]|^)\\x/g, '$1\\u00') + '"');
You don't need to decode it. You can manipulate it safely as it is:
var str = "http\x3a\x2f\x2fwww.url.com";
​alert(str.charAt(4)); // :
alert("\x3a" === ":"); // true
alert(str.slice(0,7))​; // http://
maybe this helps: http://cass-hacks.com/articles/code/js_url_encode_decode/
function URLDecode (encodedString) {
var output = encodedString;
var binVal, thisString;
var myregexp = /(%[^%]{2})/;
while ((match = myregexp.exec(output)) != null
&& match.length > 1
&& match[1] != '') {
binVal = parseInt(match[1].substr(1),16);
thisString = String.fromCharCode(binVal);
output = output.replace(match[1], thisString);
}
return output;
}
2019
You can use decodeURI or decodeURIComponent and not unescape.
console.log(
decodeURI('http\x3a\x2f\x2fwww.url.com')
)

Get javascript node raw content

I have a javascript node in a variable, and if I log that variable to the console, I get this:
"​asekuhfas eo"
Just some random string in a javascript node. I want to get that literally to be a string. But the problem is, when I use textContent on it, I get this:
​asekuhfas eo
The special character is converted. I need to get the string to appear literally like this:
​asekuhfas eo
This way, I can deal with the special character (recognize when it exists in the string).
How can I get that node object to be a string LITERALLY as it appears?
As VisionN has pointed out, it is not possible to reverse the UTF-8 encoding.
However by using charCodeAt() you can probably still achieve your goal.
Say you have your textContent. By iterating through each character, retrieving its charCode and prepending "&#" as well as appending ";" you can get your desired result. The downside of this method obviously being that you will have each and every character in this annotation, even those do not require it. By introducing some kind of threshold you can restrict this to only the exotic characters.
A very naive approach would be something like this:
var a = div.textContent;
var result = "";
var treshold = 1000;
for (var i = 0; i < a.length; i++) {
if (a.charCodeAt(i) > 1000)
result += "&#" + a.charCodeAt(i) + ";";
else
result += a[i];
}
textContent returns everything correctly, as ​ is the Unicode Character 'ZERO WIDTH SPACE' (U+200B), which is:
commonly abbreviated ZWSP
this character is intended for invisible word separation and for line break control; it has no width, but its presence between two characters does not prevent increased letter spacing in justification
It can be easily proven with:
var div = document.createElement('div');
div.innerHTML = '​xXx';
console.log( div.textContent ); // "​xXx"
console.log( div.textContent.length ); // 4
console.log( div.textContent[0].charCodeAt(0) ); // 8203
As Eugen Timm mentioned in his answer it is a bit tricky to convert UTF characters back to HTML entities, and his solution is completely valid for non standard characters with char code higher than 1000. As an alternative I may propose a shorter RegExp solution which will give the same result:
var result = div.textContent.replace(/./g, function(x) {
var code = x.charCodeAt(0);
return code > 1e3 ? '&#' + code + ';' : x;
});
console.log( result ); // "​xXx"
For a better solution you may have a look at this answer which can handle all HTML special characters.

Simple way to change current URL

I am trying to find a simpler way to change 2 variables on the current url without having to split the url and re-building it.
for example if i have a url http://www.anysite.com/any/12/this/url/10/20 and want to change the last to variables 10 and 20 to 20 and 30 for example is there are simpler way than using window.location.href.split("/") then having to re-build the whole url?
With the regexp function replace:
url.replace(/([0-9]*)\/([0-9]*)$/, function( str , n1 , n2 ){
var new_n1 = 10 + parseInt( n1 , 10 );
var new_n2 = 10 + parseInt( n2 , 10 );
return new_n1 + '/' + new_n2;
});
this replaces a part of the string which have the format: [number]/[number] and which is at the end of the string 'url' (because there's a $ at the end of the pattern) by a string which have the format: [number+10]/[number+10].
Using a regular expression would be the best way to avoid spilting, if that's what you want.
See (for instance):
https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Regular_Expressions
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/RegExp
As for replacing the URL, it would be a matter of location.replace(/* new URL here*/), with the benefit of actually replacing the URL in the browser history.
You can grab it is a string then trim and append as you see fit.
You could grab it as a string and use search and replace.
You could grab it as a string and run GREP against it.
But, honestly, might be easiest to just do the split/array thing.
It all depends on the formatting rules you have to adhere to.
You can use a regex:
var url = "http://www.anysite.com/any/12/this/url/10/20";
var newURL = url.replace(/10\/20$/, "20/30");
This regex looks for "10/20" at the end of the URL and replaces it with "20/30". Depending upon what exact circumstances you want to do the replacement, you might tweak the regex a bit to allow or disallow certain situations.
Ok, here is a function you can use.
function amendHref( a, b) {
var str = window.location.href;
var newHref = str.replace( /[\d]+\/[\d]+$/, a + "/" + b );
// ^^^^^ digit one or more times
// ^^ ( escaped ) forward slash
// ^^^^ digit one or more times
// ^ end of string
window.location.href = newHref;
}
Fiddle here

How to extract end of URL in Javascript?

I have URLs in the form:
serverName/app/image/thumbnail/2012/4/23/1335228884300/bb65efd50ade4b3591dcf7f4c693042b
Where serverName is the domain name of the server.
I would like to write a JS function that accepts one of these URLs and returns the very last (right-most) forward-slash-delimited string. So if the URL above was passed into the function, it would return "bb65efd50ade4b3591dcf7f4c693042b";.
function getImageDirectoryByFullURL(url) {
// ... Not sure how to define regexp to delimit on forward slashes,
// or how to start searching from end of string.
}
split by slashes /, pop off the last and return it
function getImageDirectoryByFullURL(url){
return url.split('/').pop()
}
//a step by step breakdown
function getImageDirectoryByFullURL(url){
url = url.split('/'); //url = ["serverName","app",...,"bb65efd50ade4b3591dcf7f4c693042b"]
url = url.pop(); //url = "bb65efd50ade4b3591dcf7f4c693042b"
return url; //return "bb65efd50ade4b3591dcf7f4c693042b"
}
what this does is split the url per / and returns an array of values in between, but not including, the slashes. then, since what's returned by split() is an array, we can use pop() to pop off the last item and return it.
In this case, substr() might be faster than split(). Not 100% sure.
function getImageDirectoryByFullURL(url){
return url.substr(url.lastIndexOf("/")+1);
}
Edit: I forgot, you don't need to include the extra length parameter. Without passing that in you just get a substr to the end of the string, which is what is desired. While this solution is admittedly a little uglier than Joseph's answer, it is twice as fast in Chrome and something like fives times as fast in Firefox.
To make it a little more robust and allow for the possible presence of a trailing slash, hash tags or query parameters on the URL:
function getImageDirectoryByFullURL(url){
url = url.replace(/#[^#]+$/, "").replace(/\?[^\?]+$/, "").replace(/\/$/, "");
return url.substr(url.lastIndexOf("/") + 1);
}
And a working demo with a bunch of test cases: http://jsfiddle.net/jfriend00/akVVf/
Since there are no sensible regular expression versions, consider:
return url.replace(/^.*\//,'');
Also you can try something like this, getting the same result.
function getImageUrl( url){
var result = url.substring(url.lastIndexOf("/") + 1);
return result;
}

How can I replace %2C with a <comma> in javascript?

#&q=car&category=Car%20Audio%2CAccessories&brand=
I borrowed a this function from a previous question asked on SO:
function insertParam(key, value)
{
key = escape(key); value = escape(value);
var kvp = document.location.hash.substr(1).split('&');
var i=kvp.length; var x; while(i--)
{
x = kvp[i].split('=');
if (x[0]==key)
{
x[1] = value;
kvp[i] = x.join('=');
break;
}
}
if(i<0) {kvp[kvp.length] = [key,value].join('=');}
//this will reload the page, it's likely better to store this until finished
document.location.hash = kvp.join('&');
}
I use it like this:
insertParam("category",xy);
insertParam("brand",zy);
My problem is it is decoding comma's to %2C. I know I can handle the characters on the server side, but how can I make it look pretty with javascript? By pretty I mean replace %2c with a comma.
I do not know why in the previous answer that was striked out, but the answer was correct.
alert(decodeURIComponent('%2C'));
So, you break your query strings into elements, splitting by & symbol. Than you split the results by = symbol and apply decodeURIComponent on both name and the value.
ps: key = escape(key); value = escape(value); you should not use escape here (it is different for different browsers. and by 'different' I meant IE). Use encodeURIComponent.
pps: because they either encode commas or don't encode &=???
alert(encodeURIComponent('&=,'));
outputs %26%3D%2C
This worked for me for undoing encodeURIComponent() on URIs that contain commas:
.replace(/%2C/g,",")
decodeURIComponent(foo) is the thing you are looking for.
Edit: Misread your question.
Use replace(/&/g, "%26").replace(/=/g, "%3D") instead of escape on key and value to do this.
None of the 3 functions encodeURI, encodeURIComponent or encode work for this task, because they either encode commas or don't encode &=.

Categories

Resources