Stop automatic URL decoding in PHP/Drupal - php

I am sending a custom XML data from jQuery to Drupal/PHP as follows:
$.ajax({
type: 'POST',
url: this.href,
success: function(data){
alert('Form is successfully saved');
},
error:function(XMLHttpRequest, textStatus, errorThrown){
alert("Error");
},
data: 'myxml='+ mydata
});
My XML tags contains URLs, so I encode them, and before making an AJAX call, data looks somewhat like this:
mydata="<txtLinkLocation>http%3A%2F%2Fportal.cubewerx.com%2Fcubewerx%2Fcubeserv%2Fcubeserv.cgi%3FCONFIG%3Dhaiti%26SERVICE%3DWFS%26DATASTORE%3DOSM%26request%3DGetCapabilities</txtLinkLocation>";
And, in PHP I get the received data, and I store it as follows:
$receivedXML = $_POST['myxml'];
Now, contains of $receivedXML looks like this:
<txtLinkLocation>http://portal.cubewerx.com/cubewerx/cubeserv/cubeserv.cgi?CONFIG=haiti&SERVICE=WFS&DATASTORE=OSM&request=GetCapabilities</txtLinkLocation>
My question is why URL inside this string is being been automatically decoded? Why is this happening? I do not want any automatic operation to be performed on data that is being sent through AJAX call. How to stop this behavior? I feel like I am missing some fundamental concepts here...

$_POST data is sent to the server in the same way as $_GET. It has to be sent urlencoded else it may break. This means that by default, PHP will decode urlencodes because it expects the data to be urlencoded.

PHP decodes $_GET and $_REQUEST data it by default, see the note in urldecoding on auto-encoding server variables. Turns out that $_POST does too.
Solution: urlencode() your data again if you want it to be encoded.

Related

POST data not appearing in CakePHP controller

I'm using AJAX on a knockout.js form to post some information that CakePHP should receive, however, Cake doesn't seem to find anything. Also, the alert isn't appearing despite a 200 status (OK) from the POST.
Here's the AJAX
$.ajax({
url: "/orders/finalize_payment",
type: "POST",
dataType: "json",
contentType: "json",
data: JSON.stringify({"customer": customer_id}),
success: function(){
alert("success");
}
});
Here's the corresponding action in the orders controller. Right now, I completely stripped it to just the bare minimum.
function finalize_payment($id = null){
$this->layout = false;
$this->autoRender = false;
if($this->request->is('post')){ //the user has submitted which status to view
print_r($this->request->data);
echo "test"; //just to make sure it's reaching this point
}
}
When I open up the network tab in chrome, it shows the request payload as
customer: 1
The POST shows as success, status 200. I checked the response headers and it just shows
array
(
)
test
Despite chrome showing a payload being sent, CakePHP isn't finding it apparently.
Update
I changed the request from AJAX to $.post and it worked. I still have no clue why
$.post("/orders/finalize_payment",{"customer_id":customer_id},function(data){
alert('success');
});
Don't encode post data as json
The code in the question won't appear in any php script, the reason is this:
contentType: "json"
It's not a form-url-encoded request, so e.g. the following code:
print_r($_POST);
print_r(file_get_contents('php://input'));
will output:
Array()
'{"customer":123}'
If you want to submit data as json, you'll need to read the raw request body:
$data = json_decode(file_get_contents('php://input'));
There might be times when that's desirable (api usage), but that isn't the normal way to use $.post.
The normal way
The normal way to submit data, is to let jQuery take care of encoding things for you:
$.ajax({
url: "/orders/finalize_payment",
type: "POST",
dataType: "json", // this is optional - indicates the expected response format
data: {"customer": customer_id},
success: function(){
alert("success");
}
});
This will submit the post data as application/x-www-form-urlencoded and be available as $this->request->data in the controller.
Why $.post works
I changed the request from AJAX to $.post and it worked. I still have no clue why
Implicitly with the updated code in the question you have:
removed the JSON.stringify call
changed from submitting json to submitting application/x-www-form-urlencoded
As such, it's not that $.post works and $.ajax didn't ($.post infact just calls $.ajax) - it's that the parameters for the resultant $.ajax call are correct with the syntax in the question.
As you're using CakePHP you may find adding RequestHandler to your components fixes the problem.
public $components = array([snip], 'RequestHandler');
Doing this allowed me to transparently access JSON posted data using $this->request->data. The other answer's advice to not encode POST data as JSON becomes a bit awkward, given that certain JS frameworks, such as Angular, post JSON as default.
Using raw data and json you can use:
$data = $this->request->input('json_decode');
**Data is an object now, not an array.
Then you can use:
$this->MyModel->save($data).
Nicely formatted question :)
I'm pretty sure I have the answer, though I could be wrong... Basically, $this->request is an object in Cake, and $this->request->data is a variable/array that's a property of the object.
The data you're sending to Cake is going straight into the object (if this is even possible), not into the data array. This is why when Cake generates forms using the HtmlHelper, the names are, for example data[User][username].
I think, if you put JSON.stringify({"customer": customer_id}) into a 'data' array and send that, it should work.
Have a look at this post. You're data string probably isn't correct. Therefore CakePHP might not be able to put it in $this->request->data.
Use print_r($this->request->params);
function finalize_payment($id = null){
$this->layout = false;
$this->autoRender = false;
if($this->request->is('post')){ view
print_r($this->request->params);
} }

javascript unexpected token < , is there any way I can escape the errors(or atleast skip those useless characters)

In php, I have an array like this :
$arr['a'] = "some big data so may contain some chars that bring us headache"
$arr['b'] = "some big data same as above"
$data = json_encode($arr)
echo $data
My javascript code containing a jquery ajax call, $.ajax . It calls the file containing the above php code so, on success, the json_encoded(by php) is returned to my javascript variable . In my javascript file, I am doing like this :
jsdata = JSON.parse(data); //Getting error here
$.ajax({
type: "post",
data: jsdata,
url: "url",
crossDomain: true,
dataType: 'jsonp'
}).done(function(d) {
print("success");
});
From the above code, in the line jsdata = JSON.parse(data), I am getting errors something like
Error : UNEXPECTED TOKEN <
As the data contains lot of different content, its normal to get those errors . They need to be escaped properly . Can anyone tell me how to do that correctly . Whatever the data may be , I shouldnot get error regarding the data .
Thanks
Well, a couple of things you should probably know jsdata = JSON.parse(data); tries to parse whatever json string you assigned to data, and return it as a JS object. I think you want to do the opposite: jsdata = JSON.stringify(data);
Besides, since you are using jQuery, you could just leave that line out: jQuery will convert the data to the appropriate format before sending the request anyway, no need to bother with parsing or stringify-ing it yourself.
Yeah you forgot the ; at the end of two lines, so PHP is outputing an error, which is no JSON-compliant.
Always do this :
Catch errors and output them in a way that is understable by your application (a 5xx status can be enough)
Next time you have this, use Chrome Developper tool or Firebug to see what your app really returns
Also, you're outputing json, not jsonp which is different and what your app expects
$.ajax({
type: "post",
data: jsdata,
url: "url",
crossDomain: true,
dataType: 'jsonp',
success: function(d) {
print("success");
}
})
try it this way
This is much more simple than it might seem.
Call urlencode($arr['a']) and urlencode($arr['b']) (for each data value in $arr) before encoding the JSON and echoing $data to the JavaScript. This will URL-Encode the data in the array so that it will cause you no problems.
When you are done parsing the JSON, you will have to call the JavaScript function unescape(string) on each of the large data values. This will return them to the way they originally were. It's a sort of superhero-team-up of PHP and JavaScript!

transferring a javascript value to a php variable

What is the best way to transfer the following outputted value into a php variable?
$(document).getUrlParam("id");
Through an ajax post.
$.ajax({
type: 'POST',
url: url,
data: data,
success: success,
dataType: dataType
});
You should use JSON format to send and receive data from javascript to PHP. For example
function sendData(){
//with jquery, you can use `.post()`, `.get()` or for more control `.ajax()`
$.post(
//URL to send the data
url,
//data being sent, transformed to JSON
{dataSent: JSON.stringify(clientSideData)},
//Do something after sendind the data to server
function(dataReceived){
//transform data from json format to javascript object
var dataLog = jQuery.parseJSON(dataReceived);
//Do stuff
}
)
}
PHP:
//Receive data from POST
var phpVar = json_decode($_POST['dataSent'])
//send data back to javascript
echo json_encode(phpVar)
While all of these answers will get the value from javascript into the PHP script, I'd wonder if you need javascript at all.
From what I can see from a brief google the getUrlParam plugin is useful for getting and then breaking down the URL. Have you had a look at the variables available through $_SERVER? I'm sure you'd be able to find something suitable in there.

Proper way to format user-entered text input for sending via JSON/AJAX to PHP?

I'm running into some problems with user-entered input that I want to send to PHP as JSON via AJAX that contains special characters, like ", ', etc. I'm sending the contents of an array (used for slickgrid), and everything works fine unless those characters are included. I know that PHP has the handy function mysql_real_escape_string, but is there any sort of jquery analogue? Here is the relevant code:
req = $.ajax({
url: url,
dataType: "text",
data: {"data": $.JSON.encode(data)},
type: "post",
success: onSaveSuccess,
error: onSaveError
});
Here's the PHP it is submitted to:
<?php
//$data = array();
//if (isset($_POST['data']))
//{
//$data = json_decode($_POST['data']);
//}
//header('Content-Type: text/javascript');
//echo json_encode($data);
print_r($_POST);
?>
To be clearer, when special characters are included, neither the success nor error events are triggered.
I looked in firebug and it doesn't appear to send anything at all when the special characters are included... Of course, it does when it's just letters or something.
It was due to the script from here apparently failing on certain kinds of input. Switching to json2.js and using JSON.stringify has solved the problem.
data: {"data": $.JSON.encode(data)},
Passes up a more complex JSON object than you need.
$data = json_decode($_POST['data']);
Is looking for a serialized JSON object but jQuery is doing a lot of work for you in the background.
Try this
data: $.JSON.encode(data),
In your AJAX call. Then in PHP
$data['myPostValue'] = $_POST['myPostValue'];
You're sending a JSON object to the $.ajax call, and it is changing it into the name value pair that the server would normally get from a post.
javascript has an escape() function. you can $.JSON.encode(escape(data)) might work

%cd transformed to Í in ajax to php call

I have this weird issue which i'm absolutely don't even know how to address...
i have this little AJAX call:
$('#toexcel').live("click",function() {
var sql = grid.data().sql;
$.ajax({
url: "toExcel.php",
data: "sql="+sql,
success: function(response){
window.location.href = response.url;
}
});
alert(sql);
});
});
which passes sql query from grid object to toExcel. toExcel uses PHPExcel object to output excel file.
now:
when alert pops up it has normally looking query ...LIKE '%cdviled%'...
but when i access this query in toExcel.php it looks like ...LIKE 'Íviled04%'....
and query obviously fails.
why????? how??
PHP is interpreting %cd as a URL-encoded entity. You will want to run your parameters through encodeURIComponent() before sending off the ajax request.
Although, you might get better (and more secure) results by simply sending the search term via ajax and letting PHP assemble the SQL on the server side!
%cd is a valid URL-encoded representation of Í and PHP handles it as such.
The solution is simple. Change:
data: "sql="+sql,
to:
data: "sql="+encodeURIComponent(sql),

Categories