38

Try it out:

encodeURIComponent("'@#$%^&");

If you try this out you will see all the special characters are encoded except for the single quote. What function can I use to encode ALL the characters and use PHP to decode them?

Thanks.

Ilya Karnaukhov
  • 3,838
  • 7
  • 31
  • 53
  • Could you be more specific about the PHP part, please? How to you send them? What does currently not work? – Bergi Jun 05 '12 at 12:09
  • The whole process is abit complicated to explain. I send the encoded value to the database using ajax and PHP (that's why the quote has to be encoded otherwise MySQL problems occur) then I retrieve the value using PHP and I decode it using rawurldecode() – Ilya Karnaukhov Jun 05 '12 at 12:25
  • 1
    Arghh, no! PHP **must** escape all SQL queries itself for security reasons. If the quotes needed to be escaped by JS you've done something wrong. – Bergi Jun 05 '12 at 12:44

7 Answers7

57

I'm not sure why you would want them to be encoded. If you only want to escape single quotes, you could use .replace(/'/g, "%27"). However, good references are:

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    First I didn't want to use something like this but apparently PHP's rawurldecode supports the decoding of the quote from "%27". So, problem solved! Cheers mate. – Ilya Karnaukhov Jun 05 '12 at 12:25
  • Regarding the question as to why you'd want to do this: If you want to use javascript to build html, e.g., `var html = "foo";` you will want to make sure the internal single quotes are properly escaped. – speedplane May 03 '17 at 05:52
  • @speedplane But you don't use `encodeURI(Component)` for that. If you build HTML strings, you use `htmlAttributeEscape`! – Bergi May 03 '17 at 12:08
  • @Bergi Is `htmlAttributeEscape` a standard function? – speedplane May 03 '17 at 15:47
  • @speedplane No, I meant [any function that escapes HTML](http://stackoverflow.com/q/1787322/1048572) attribute values – Bergi May 03 '17 at 16:09
  • @Bergi Is that really the right way to do it? if `link="/?foo&bar"` that would result in an html link as ``. Wouldn't `encodeURIComponent(link).replace(/'/g, "%27")` be preferable? – speedplane May 03 '17 at 22:44
  • @speedplane Yes it is. Entity-encoding the value is exactly the expected result. I don't see how `%2F%3Ffoo%26bar` would be preferable. – Bergi May 03 '17 at 23:10
  • That's not quite the choice. If the URL is `/?foo='fiz'&bar`, then the choice is between: `/?foo=%27fiz%27&bar` and `/?foo='fiz'&bar`. Both are ugly but will probably work, the latter may be more pedanticly correct for HTML, but the former can be copied and pasted into a URL. – speedplane May 09 '17 at 18:34
  • @speedplane Yes, the latter is the correct one. I guess whether you percent-encode or entity-encode the quotes doesn't matter, but you need to properly escape the *html special characters*. `encodeURIComponent` does not do that, it leads to `%2F%3Ffoo%3D'fiz'%26bar`. – Bergi May 09 '17 at 21:16
12

You can use:

function fixedEncodeURIComponent (str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, escape);
}

fixedEncodeURIComponent("'@#$%^&");

Check reference: http://mdn.beonex.com/en/JavaScript/Reference/Global_Objects/encodeURIComponent.html

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Biswajit Maji
  • 869
  • 13
  • 23
  • 1
    Is there universal method to combine escape and encodeURIComponent?.. escape works with single quotes but fixedEncodeURIComponent with '#'.. – Gennady G Oct 02 '18 at 12:33
3

Just try encodeURI() and encodeURIComponent() yourself...

console.log(encodeURIComponent('@#$%^&*'));

Input: @#$%^&*. Output: %40%23%24%25%5E%26*. So, wait, what happened to *? Why wasn't this converted? TLDR: You actually want fixedEncodeURIComponent() and fixedEncodeURI(). Long-story...

encodeURIComponent() : Do not use. Use fixedEncodeURIComponent(), as defined and explained by the MDN encodeURIComponent() Documentation, emphasis mine...

To be more stringent in adhering to RFC 3986 (which reserves !, ', (, ), and *), even though these characters have no formalized URI delimiting uses, the following can be safely used:

function fixedEncodeURIComponent(str) { return encodeURIComponent(str).replace(/[!'()*]/g, function(c) { return '%' + c.charCodeAt(0).toString(16); }); }

While we're on the topic, also don't use encodeURI(). MDN also has their own rewrite of it, as defined by the MDN encodeURI() Documentation. To quote their explanation...

If one wishes to follow the more recent RFC3986 for URLs, which makes square brackets reserved (for IPv6) and thus not encoded when forming something which could be part of a URL (such as a host), the following code snippet may help:

function fixedEncodeURI(str) { return encodeURI(str).replace(/%5B/g, '[').replace(/%5D/g, ']'); }

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
3

Recent answer (2021)

Using JavaScript's URLSearchParams:

console.log(new URLSearchParams({ encoded: "'@#$%^&" }).toString())
GG.
  • 21,083
  • 14
  • 84
  • 130
2

You can use btoa() and atob(), this encodes and decodes the given string including single quote.

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
1

I found a neat trick that never misses any characters. I tell it to replace everything except for nothing. I do it like this (URL encoding):

function encode(w){return w.replace(/[^]/g,function(w){return '%'+w.charCodeAt(0).toString(16)})}

function encode(w){return w.replace(/[^]/g,function(w){return '%'+w.charCodeAt(0).toString(16)})}

loader.value = encode(document.body.innerHTML);
<textarea id=loader rows=11 cols=55>www.WHAK.com</textarea>
HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Dave Brown
  • 923
  • 9
  • 6
1

As @Bergi wrote, you can just replace all the characters:

function encoePicture(pictureUrl)
{
 var map=
 {
          '&': '%26',
          '<': '%3c',
          '>': '%3e',
          '"': '%22',
          "'": '%27'
 };

 var encodedPic = encodeURI(pictureUrl);
 var result = encodedPic.replace(/[&<>"']/g, function(m) { return map[m];});
 return result;
}
HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
neomib
  • 3,503
  • 4
  • 17
  • 27