112

I'm POSTing the contents of a form field via AJAX to a PHP script and using JavaScript to escape(field_contents). The problem is that any plus signs are being stripped out and replaced by spaces. How can I safely 'encode' the plus sign and then appropriately 'decode' it on the PHP side?

Web_Designer
  • 72,308
  • 93
  • 206
  • 262
jalperin
  • 2,664
  • 9
  • 30
  • 32

6 Answers6

177

Use encodeURIComponent() in JS and in PHP you should receive the correct values.

Note: When you access $_GET, $_POST or $_REQUEST in PHP, you are retrieving values that have already been decoded.

Example:

In your JS:

// url encode your string
var string = encodeURIComponent('+'); // "%2B"
// send it to your server
window.location = 'http://example.com/?string='+string; // http://example.com/?string=%2B

On your server:

echo $_GET['string']; // "+"

It is only the raw HTTP request that contains the url encoded data.

For a GET request you can retrieve this from the URI. $_SERVER['REQUEST_URI'] or $_SERVER['QUERY_STRING']. For a urlencoded POST, file_get_contents('php://stdin')

NB:

decode() only works for single byte encoded characters. It will not work for the full UTF-8 range.

eg:

text = "\u0100"; // Ā
// incorrect
escape(text); // %u0100 
// correct
encodeURIComponent(text); // "%C4%80"

Note: "%C4%80" is equivalent to: escape('\xc4\x80')

Which is the byte sequence (\xc4\x80) that represents Ā in UTF-8. So if you use encodeURIComponent() your server side must know that it is receiving UTF-8. Otherwise PHP will mangle the encoding.

Brane
  • 3,257
  • 2
  • 42
  • 53
bucabay
  • 5,235
  • 2
  • 26
  • 37
  • One follow-up: When I encodeURIComponent(text) and text includes characters like the smart quote (&rsqo;), the php script seems to see junk characters. I assume it's a charset problem, but I don't know how to resolve it. I'm doing the AJAX POST with "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", and I'm using PHP5 on the server side. – jalperin Sep 03 '09 at 18:35
  • How are you viewing these characters? You have to make sure the browser knows it is UTF-8. In HTML you can set `` or `` you can also set it in PHP with the Content-Type HTTP Header. `header('Content-Type: text/html;charset=UTF-8');` PS: &rsqo; does not decode in the browser (FF3.5). – bucabay Sep 03 '09 at 22:47
  • 6
    I had a problem with the plus (+) character changing into space. Everything else went fine in UTF8. I had good luck using with encodeURIComponent(JSON.stringify(rootObject)). Thank you! – zneo Aug 16 '11 at 19:25
  • When running into this problem with passwords (which were collected via a javascript form post) I solved it with password = encodeURIComponent(password). When passed to PHP, the encoded POST value of password works out correctly. – lowcrawler Jan 01 '15 at 19:47
22

In JavaScript try:

encodeURIComponent() 

and in PHP:

urldecode($_POST['field']);
fedorqui
  • 275,237
  • 103
  • 548
  • 598
Deniss Kozlovs
  • 4,761
  • 2
  • 28
  • 35
  • 7
    encodeURIComponent is the right answer — but as it generates URL encoded data and not HTML encoded data, html_entity_encode is way off. – Quentin Sep 03 '09 at 13:33
  • 2
    `urldecode` is also way off as PHP will decode it automatically before populating `$_POST`. – Quentin Jul 18 '18 at 14:03
5

The hexadecimal value you are looking for is %2B

To get it automatically in PHP run your string through urlencode($stringVal). And then run it rhough urldecode($stringVal) to get it back.

If you want the JavaScript to handle it, use escape( str )

Edit

After @bobince's comment I did more reading and he is correct. Use encodeURIComponent(str) and decodeURIComponent(str). Escape will not convert the characters, only escape them with \'s

Rob Allen
  • 17,381
  • 5
  • 52
  • 70
  • 1
    *Don't* use `escape` (or `unescape`) in JavaScript; they aren't the same as URL-encoding and will go wrong for + and any non-ASCII Unicode characters. encodeURIComponent/decodeURIComponent is almost always what you want. – bobince Sep 03 '09 at 14:48
4

To make it more interesting and to hopefully enable less hair pulling for someone else. Using python, built dictionary for a device which we can use curl to configure.

Problem: {"timezone":"+5"} //throws an error " 5"

Solution: {"timezone":"%2B"+"5"} //Works

So, in a nutshell:

var = {"timezone":"%2B"+"5"}
json = JSONEncoder().encode(var)
subprocess.call(["curl",ipaddress,"-XPUT","-d","data="+json])

Thanks to this post!

Marcin Nabiałek
  • 109,655
  • 42
  • 258
  • 291
Pawr
  • 139
  • 1
  • 5
0

If you have to do a curl in php, you should use urlencode() from PHP but individually!

strPOST = "Item1=" . $Value1 . "&Item2=" . urlencode("+")

If you do urlencode(strPOST), you will bring you another problem, you will have one Item1 and & will be change %xx value and be as one value, see down here the return!

Example 1

$strPOST = "Item1=" . $Value1 . "&Item2=" . urlencode("+") will give Item1=Value1&Item2=%2B

Example 2

$strPOST = urlencode("Item1=" . $Value1 . "&Item2=+") will give Item1%3DValue1%26Item2%3D%2B

Example 1 is the good way to prepare string for POST in curl

Example 2 show that the receptor will not see the equal and the ampersand to distinguish both value!

Jasonw
  • 5,054
  • 7
  • 43
  • 48
Marc
  • 9
  • 1
-1

my problem was with the accents (á É ñ ) and the plus sign (+) when i to try to save javascript "code examples" to mysql:

my solution (not the better way, but it works):

javascript:

function replaceAll( text, busca, reemplaza ){
  while (text.toString().indexOf(busca) != -1)
  text = text.toString().replace(busca,reemplaza);return text;
}


function cleanCode(cod){
code = replaceAll(cod , "|", "{1}" ); // error | palos de explode en java
code = replaceAll(code, "+", "{0}" ); // error con los signos mas   
return code;
}

function to save:

function save(pid,code){
code = cleanCode(code); // fix sign + and |
code = escape(code); // fix accents
var url = 'editor.php';
var variables = 'op=save';
var myData = variables +'&code='+ code +'&pid='+ pid +'&newdate=' +(new Date()).getTime();    
var result = null;
$.ajax({
datatype : "html",
data: myData,  
url: url,
success : function(result) {
    alert(result); // result ok                     
},
}); 
} // end function

function in php:

<?php
function save($pid,$code){
    $code= preg_replace("[\{1\}]","|",$code);
    $code= preg_replace("[\{0\}]","+",$code);
    mysql_query("update table set code= '" . mysql_real_escape_string($code) . "' where pid='$pid'");
}
?>