php $_POST array empty upon form submission - php

I have a custom Content Management System (CMS) I've built that works perfectly on my dev box (Ubuntu/PHP5+/MySQL5+).
I just moved it up to the production box for my client and now all form submissions are showing up as empty $_POST arrays.
I found a trick to verify the data is actually being passed using file_get_contents('php://input'); and the data is showing up fine there -- the $_POST/$_REQUEST arrays are always empty.
I've also verified the content-type headers are correct as well via firebug (application/x-www-form-urlencoded; charset=utf-8).
This issue is happening regardless of whether a form is submitting via AJAX or a regular form submit.
Any help is greatly appreciated!

When using JSON content-type the $_POST array will not populate (only with multi-part forms I believe)
Here is how I correct the issue:
$_POST = json_decode(file_get_contents("php://input"), true);

Here's another possible cause:
My form was submitting to domain.example without the www. and I had set up an automatic redirect to add the www. The $_POST array was getting emptied in the process.
So to fix it all I had to do was submit to www.domain.example

I had a similar problem. Turned out to be a simple fix. In the form I had
<form action="directory" method="post">
where directory was the name of... the directory. My POST array was totally empty. When I looked at the url in my browser, it was displayed with a forward slash on the end.
Adding the forward slash to the end of my action did the trick -
<form action="directory/" method="post">
My $_POST array was full again!

Make sure that, in php.ini:
track_vars (it's only available on very old PHP versions) is set to On
variables_order contains the letter P
post_max_size is set to a reasonable value (e.g. 8 MB)
(if using suhosin patch) suhosin.post.max_vars and suhosin.request.max_vars are large enough.
I suppose the second suggestion of mine will solve your problem.

I've found that when posting from HTTP to HTTPS, the $_POST comes empty.
This happened while testing the form, but took me a while until I realize that.

I came across a similar yet slightly different issue and it took 2 days to understand the issue.
In my case also POST array was empty.
Then checked with file_get_contents('php://input'); and that was also
empty.
Later I found that browser wasnt asking confirmation for resubmitting form data after If I refresh the page loaded after POST submission. It was directly refreshing page. But when I changed form URL to a different one it was passing POST properly and asked for resubmitting data when attempted to refresh page.
Then I checked what is wrong with actual URL . There were no fault with URL, however it was pointing to a folder without index.php in URL and I was checking POST at index.php.
Here I doubted the redirection from / to /index.php causes POST data to be lost and tested URL with appending index.php to the URL.
That Worked.
Posted it here so someone would find it helpful.

If you are posting to a index.php file in a directory for example /api/index.php make sure in your form you specify the full directory to the file e.g
This
<form method="post" action="/api/index.php">
</form>
OR
<form method="post" action="/api/">
</form>
works.
But this fails
<form method="post" action="/api">
</form>

I could solve the problem using enctype="application/x-www-form-urlencoded" as the default is "text/plain". When you check in $DATA the seperator is a space for "text/plain" and a special character for the "urlencoded".
Kind regards
Frank

Having the enable_post_data_reading setting disabled will cause this. According to the documentation:
enable_post_data_reading
Disabling this option causes $_POST and $_FILES not to be populated. The only way to read postdata will then be through the php://input stream wrapper. This can be useful to proxy requests or to process the POST data in a memory efficient fashion.

<form action="test.php" method="post">
^^^^^^^^^^^^^
Okay, this was stupid and I will be embarassing myself in public, but I knocked up a little test script for something in PHP and when my $_POST array was empty, StackOverflow is the first place I looked and I didn't find the answer I needed.
I had only written
<form action="test.php">
and forgotten to specify the method as being POST!
I am sure someone will snigger, but if this helps someone else who does the same thing, then I don't mind! We all do it from time to time!

Don't have an elegant solution at this point but wanted to share my findings for the future reference of others who encounter this problem. The source of the problem was 2 overriden php values in an .htaccess file. I had simply added these 2 values to increase the filesize limit for file uploads from the default 8MB to something larger -- I observed that simply having these 2 values in the htaccess file at all, whether larger or smaller than the default, caused the issue.
php_value post_max_size xxMB
php_value upload_max_filesize xxMB
I added additional variables to hopefully raise the limits for all the suhosin.post.xxx/suhosin.upload.xxx vars but these didn't have any effect with this problem unfortunately.
In summary, I can't really explain the "why" here, but have identified the root cause. My feeling is that this is ultimately a suhosin/htaccess issue, but unfortunately one that I wasn't able to resolve other than to remove the 2 php overridden values above.
Hope this helps someone in the future as I killed a handful of hours figuring this out. Thanks to all who took the time to help me with this (MrMage, Andrew)

In my case, when posting from HTTP to HTTPS, the $_POST comes empty. The problem was, that the form had an action like this //example.com When I fixed the URL to https://example.com, the problem disappeared.

same issue here!
i was trying to connect to my local server code via post request in postman, and this problem wasted my time alot!
for anyone who uses local project (e.g. postman):
use your IPv4 address (type ipconfig in cmd) instead of the "localhost" keyword.
in my case:
before:
localhost/app/login
after:
192.168.1.101/app/login

Make sure that the name property of each field is defined.
This create you an empty POST on PHP
<input type="text" id="Phone">
But, this will work
<input type="text" name="Phone" id="Phone">

I had the same problem.
The problem was .htaccess.
I have a HTTPS rewrite rule and was sending the post requests to http:// instead of https://.
The post request cleared due to redirect.

REFERENCE: http://www.openjs.com/articles/ajax_xmlhttp_using_post.php
POST method
We are going to make some modifications so POST method will be used when sending the request...
var url = "get_data.php";
var params = "lorem=ipsum&name=binny";
http.open("POST", url, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
http.send(params);
Some http headers must be set along with any POST request. So we set them in these lines...
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");
With the above lines we are basically saying that the data send is in the format of a form submission. We also give the length of the parameters we are sending.
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
We set a handler for the 'ready state' change event. This is the same handler we used for the GET method. You can use the http.responseText here - insert into a div using innerHTML(AHAH), eval it(JSON) or anything else.
http.send(params);
Finally, we send the parameters with the request. The given url is loaded only after this line is called. In the GET method, the parameter will be a null value. But in the POST method, the data to be send will be send as the argument of the send function. The params variable was declared in the second line as lorem=ipsum&name=binny - so we send two parameters - 'lorem' and 'name' with the values 'ipsum' and 'binny' respectively.

I know this is old, but wanted to share my solution.
In my case the issue was in my .htaccess as I added variables to raise my PHP's max upload limit. My code was like this:
php_value post_max_size 50MB
php_value upload_max_filesize 50MB
Later I notice that the values should like xxM not xxMB and when I changed it to:
php_value post_max_size 50M
php_value upload_max_filesize 50M
now my $_POST returned the data as normal before.
Hope this helps someone in the future.

In my case it was because I was using jQuery to disable all inputs on the page just before using jQuery to submit the form.
So I changed my "disable every input even the 'hidden' types":
$(":input").attr("disabled","disabled");
to "disable only the 'button' type inputs":
$('input[type=button]').attr('disabled',true);
This was so the user couldn't accidentally hit the 'go' button twice and hose up our DB!
It seems that if you put the 'disabled' attribute on a 'hidden' type form input their values won't be sent over if the form is submitted!

For me, .htaccess was redirecting when mod_rewrite wasn't installed. Install mod_rewite and all is fine.
Specifically:
<IfModule !mod_rewrite.c>
ErrorDocument 404 /index.php
</Ifmodule>
was executing.

I just spent hours to fix a similar issue. The problem in my case, was the the
max_input_vars = "1000"
by default, in the php.ini. I had a really huge form without uploads. php.ini is set to upload_max_filesize = "100M" and post_max_size = "108M" and it was surely not the issue in my case. PHP behavior is the same for max_input_vars when it exceeds 1000 variables in the form. It returns and empty _POST array. I wish I could have found that one hours, and hours ago.

Another simple reason for an empty POST array can be caused by not closing a form with </form> and then adding a second <form>...</form>. When the second form is submitted the POST array will be empty.

In addition to MRMage's post:
I had to set this variable to solve the problem that some $_POST variables (with an large array > 1000 items) disappeared:
suhosin.request.max_vars = 2500
"request", not "post" was the solution...

Not the most convenient solution perhaps, but I figured it out that if I set the form action attribute to the root domain, index.php can be accessed and gets the posted variables. However if I set a rewritten URL as action, it does not work.

This is sort of similar to what #icesar said.
But I was trying to post stuff to my api, located in site/api/index.php, only posting to site/api since it gets passed on to index.php by itself. This however, apparently cause something to get messed up, as my $_POST got emptied on the fly. Simply posting to site/api/index.php directly instead solved it.

My problem was that I was using the HTML <base> tag to change the base URL of my test site. Once I removed that tag from the header, the $_POST data came back.

In my case (php page on OVH mutualisé server) enctype="text/plain" does not work ($_POST and corresponding $_REQUEST is empty), the other examples below work.
`
<form action="?" method="post">
<!-- in this case, my google chrome 45.0.2454.101 uses -->
<!-- Content-Type:application/x-www-form-urlencoded -->
<input name="say" value="Hi">
<button>Send my greetings</button>
</form>
<form action="?" method="post" enctype="application/x-www-form-urlencoded">
<input name="say" value="Hi">
<button>Send my application/x-www-form-urlencoded greetings</button>
</form>
<form action="?" method="post" enctype="multipart/form-data">
<input name="say" value="Hi">
<button>Send my multipart/form-data greetings</button>
</form>
<form action="?" method="post" enctype="text/plain"><!-- not working -->
<input name="say" value="Hi">
<button>Send my text/plain greetings</button>
</form>
`
More here: method="post" enctype="text/plain" are not compatible?

I was getting the following error from Mod Security:
Access denied with code 500 (phase 2). Pattern match "((select|grant|delete|insert|drop|alter|replace|truncate|update|create|rename|describe)[[:space:]]+[A-Z|a-z|0-9|\*| |\,]+[[:space:]]+(from|into|table|database|index|view)[[:space:]]+[A-Z|a-z|0-9|\*| |\,]|UNION SELECT.*\'.*\'.*,[0-9].*INTO.*FROM)" at REQUEST_BODY. [file "/usr/local/apache/conf/modsec2.user.conf"] [line "345"] [id "300013"] [rev "1"] [msg "Generic SQL injection protection"] [severity "CRITICAL"]
Once I removed my mod security configuration to test, it all worked as expected. Now I just need to modify my rules to stay secure but flexible enough for my needs :)

Make sure you use name="your_variable_name" in input tag.
I mistakenly use id="your_variable_name".
I spent much time to catch the bug.

I run into the same issue also when I migrated to new server. setting the value for post_max_size in the php.ini file fixed my issue.

In my case, I had target="_blank" in my <form> tag. Removing it solved the issue.
But, if you need to open a new page after submission nonetheless, just replace _blank with a random value, like newtab (it can really be anything).
Before:
<form target="_blank" action="api/" enctype="application/x-www-form-urlencoded" method="post">
After:
<form target="newtab" action="api/" enctype="application/x-www-form-urlencoded" method="post">

Related

PHP allow user to only view file after form submission

I have a basic file. The user can only view the file after a successfull form submission.
Now I know I have a variety of options I could use including placing it in a dir and modifying my .htaccess and then use a parameter which I pass through a routing script to let the user view the file as pointed out by numerous answers to somewhat similar questions. (which would probably be best option)
However Im just curious about something. "How Secure" would the following be.
Both files reside in a directory called xyz
Directory public_html/xyz
Form.php
<form method ="post" action="displayInfo.php" />
displayInfo.php
Now what I would like to know is IF i set the following code at the start of displayInfo.php would it stop with unauthorized access (i.e. prevent user from viewing the file IF he / she did not successfully submit the form)
if($_SERVER['REQUEST_METHOD'] !== 'POST'){
die("first submit the form")
}
No it wouldn't. I could defeat your security precaution with a simple cURL command:
curl -X POST https://example.com/displayInfo.php
The check for a POST request will pass, because it indeed a post request. However, it has absolutely none of the data you wanted.

Post to server returns empty via Postman

This is my my index.php file
<?php
print_r($_POST);
exit;
?>
I'm posting to my website using postman in chrome, but nothing gets there. I get back only
Array
(
)
I know that postman works because I used it when I had free webhosting. Now I asked a friend for a little space on his website, but for some reason the post data is not printed.How can I solve this ?
Here is a photo with what is happening: http://6pix.net/images/16687663370157764163.png .
Here are the Possible Mistakes and the way to debug it
1. Check if your web server supports php
You can check this by running a .php file with some output statements such as echo
2. Check if you are pointing the page properly
You shall check this by outputting some content
3. Try with full path
Some servers needs to get full path i.e., it won't support point the index.html or index.php if the directory path was given
Additional Note :
If the above issues doesn't helps then you might check with the .htaccess , blocking of REST Calls etc.,.
If you really (like shown within your screenshot) do
print_r($_REQUEST);
please check your php.ini for your
request_order
variables_order
If "post" is not within that order, $_REQUEST will not have "post" content inside.

PHP Post Method Not Working

My apologies for asking this question that I'm sure has been done before.
I'm not that knowledgable as far as PHP so the research I've done on this has been fruitless.
I've purchased and used an HTML template which has an email subscribe form at the bottom. The form is supposed to capture the entered email and add it to a text file with a list of submitted emails from what I understand.
Here is the excerpt from the html in the footer:
<form action="save-email.php" method="post" style="margin-top: 0px;">
<input type="text" name="email" placeholder="Get email updates...">
</form>
And here is the content of the corresponding save-email.php file:
<?php
$email = $_POST['email'];
$fp = fopen('submitted-emails.txt', 'a');
$savestring = $email . '
';
fwrite($fp, $savestring);
fclose($fp);
header('Location: ' . $_SERVER['HTTP_REFERER']);
?>
I've contacted the creators who pretty much told me to make sure my PHP version was up to date and that it was a server configuration error so they won't help me further...
I have PHP version 5.5.9 on an Ubuntu 14.04 Digital Ocean VPS
I've also edited the php.ini file to have register_globals turned on, but that did not help so I turned it off as I've read that is a security issue.
Any help would be greatly appreciated, thank you very much.
This answer is in another context then question Because I was here to check the solutions.
I was posting(method="post") the form but it was not posting the data. When I check the data with print_r($_POST) I was getting blank array.
I have felt this issue several times on servers.
The cause of this error is redirection from .htaccess file.
Some time it happens our site is running on http://www.example.com/* and we have created rules in .htaccess to redirect all the request to http://example.com/* to http://www.example.com/* or vice versa.
If post request is to different location then this issue occurs. So make sure the post url starting string should be same(www or without www check in url).
I have spent lot of time on the same issue but could not find the solution any where in stackoverflow. So I have given the solution.
Try to create a file with name submitted-emails.txt at the same directory with save-email.php and change the permissions of file to +w for all users.
Well, Are you sure post not working, Please check post method contains data or not by using.
var_dump($_POST); and var_dump($_REQUEST);
if you not found email id in post then it will be in request if it is then your request is submitting by get method.
if it display an array with email entered in post then your post method in working and problem is with file file was unable to open due to security problem/incorrect path or may be due to file permission. So check and let me know.

JQuery's $.post returns 403 Forbidden on the same domain

I'm having issues with jquery's $.post function, and (what I think) the cross-domain security thing.
The weird part is that the page I'm trying to post to, is in the same directory as the page that sends the post.
This is the javascript code of 'latest.php', the file that makes the post request:
$.post("upload.php", { base64: fCanvas, description: description }, function(data){
// some things happen here
});
upload.php is a php script that uploads the content of the base64 variable to Tumblr.
The javascript console shows a 403 Forbidden error. I tried chmodding -777 'upload.php', but that didn't change anything.
Using $.get instead of $.post works, but is undesired due to security reasons, and the length limit of $get data (I'm sending a base64 encoded image).
EDIT: I changed one of the $.get requests on 'latest.php' to a $.post one, and it's working...
$.post("base64.php", { url: t_url },
function(data){
data = "data:image/gif;base64,"+data;
draw(data);
});
So, I'm completely clueless of what's going wrong.
403 Forbidden is a server-generated response and has nothing to do with the "Same Origin Policy". Can't really offer any help further than that, but it's going to be configuration related - not a cross-domain issue.
Edit: I was going to suggest that it was a lack of execute permissions, but you already did the 777 chmod, and you can hit it with a GET, which is kind of perplexing. For the sake of not being completely useless, here's a link that suggests you need to use 644 instead of 777.
Another suggestion: is mod_security enabled in your .htaccess (or other config)? It's known to be unfriendly towards form values that contain stuff like markup/urls or other potential XSS attempts.
Well. I got it working.
I tried sending a smaller (still base64-encoded) image to my upload.php script, and it did the job. It appears that jQuery's post function can't handle large (thats relative, it's just a 640x453 image) amounts of data.
I solved the problem by using a XMLHttpRequest() instead. It works like a charm.
If anybody knows the exact problem with jQuery's Ajax, please let me know, because I still don't know exactly why my data caused a HTTP Forbidden error.
hi the forbidden error it's because uses post method and in the server side CORS are not implemented to work with Client CORS
check mod_security with your hosting provider!
the most issues similar to this solved when whitelisted or disabled it!
Try using a absolute link (has worked for me).

Redirect POST request and keep data. Possible?

My problem is simple. I need to upload a file directly to the correct server (which has currently low workload).
Therefore I do:
<?php
$server = file_get_contents('http://my-api.com/upload-server.php'); // returns url
?>
then i print my form like
<form method="post" action="<?php echo $server; ?>"...
Now I would like to shift this step to when the upload starts, like so:
<form method="post" action="http://my-api.com/upload-gateway.php"...
this url should do a redirect to the "real" server.
So that the upload page doesn't slow down loading and I have static html code that I can cache, embed etc...
Problem is that this works perfetly fine with get requests but not with post requests.
The request seems like to get transformed into a get request when redirecting using the location header. All post data is lost.
Is this impossible or am I doing it wrong? And yes, I considered a remote dynamic javascript that prints the html code with the correct server in the first place. I would rather like not to do that...
any ideas? Maby alternative uplod techniques?
edit:
this is the exact html code i use:
<form method='post' enctype='multipart/form-data' action='http://storage.ivana.2x.to/rest.php?action=target'>
<input type=hidden name=testfield value="test">
File to upload: <input type=file name=upfile><br>
Notes about the file: <input type=text name=note><br>
<br>
<input type=submit value=Press> to upload the file!
</form>
this is the redirect code i use:
if($_GET["action"] == "target") {
header("Location: http://storage.ivana.2x.to/rest.php?action=test");
}
this is the output code i use to see the results:
if($_GET["action"] == "test") {
echo "<pre>";
var_dump($_POST);
var_dump($_GET);
var_dump($_FILES);
}
the result when uploading a small file looks like:
array(0) {
}
array(1) {
["action"]=>
string(4) "test"
}
array(0) {
}
If you really want to load balance through the code while potentially caching the page with the upload form, first select the default download server (url); then, onSubmit call the server and find the best upload target and adjust the action attribute accordingly.
With this method, users who do not activate JS still get what they want, users with JS enabled get the better upload target, and you can still cache. Additionally, the timing of the cache request could potentially be more opportunistic, since the URL request will occur very shortly before the actual upload.
The only hitch will be the call to get the URL, which you can more easily performance tune (I imagine) than the process you are describing above. Uploading a file twice through a header directive and/or cURL call don't seem like a good tradeoff for caching a single html file, IMO. But I don't know what you're up against, either.
If you don't want to heavily administer the server environment and introduce load balancing, this is the option I would suggest.
Note, also, I am not a server administrator by trade.
You could try returning a code 302 (temporary moved), not 100% that would let your browser post the data to the changed url though, but it's worth something to check out.
[Edit]
According to this wikipedia article, the POST data would be converted to GET, which probably won't work for a file upload.
This is not a good solution. The file will be uploaded in it's entirety before the PHP script is even started. This means that if you succeed with what you're trying to do the client will have to upload the file twice!
I recommend that you try to figure out which server to send the request to when you're creating the form, so the action attribute in the form tag will point directly to the lesser loaded machine.
Or even better: use a serverside loadbalancer and make your HTTP infrastructure transparent to the browser. This is essentially a sysadmin problem.
i might be wrong but.. your form's action points to ?action=target and in your rest.php you do a header to "?action=test" well of course you wont find your $POST nor your $FILES!... a header() does not send those variables..
if you want to send your post and your file to a differente location you'll need to use the cUrl library.. but it wont be easy :)
Good Luck

Categories