PHP header() redirect with POST variables [duplicate] - php

This question already has answers here:
PHP Redirection with Post Parameters
(8 answers)
Closed 9 years ago.
I'm working with PHP, and I'm making an action page which a form posts to. The page checks for errors, then if everything is fine, it redirects them to the page where the data has been posted. If not, I need to to redirect them back to the page they were at with an error and the POST variables. Here is the gist of how it works.
The HTML would look like this...
<form name="example" action="action.php" method="POST">
<input type="text" name="one">
<input type="text" name="two">
<input type="text" name="three">
<input type="submit" value="Submit!">
</form>
action.php would look like this...
if(error_check($_POST['one']) == true){
header('Location: form.php');
// Here is where I need the data to POST back to the form page.
} else {
// function to insert data into database
header('Location: posted.php');
}
In the case of an error, I need it to POST back to the first page.
I can't use GET, because the input will be too large.
I don't want to use SESSION, if possible.
Is this possible?

// from http://wezfurlong.org/blog/2006/nov/http-post-from-php-without-curl
function do_post_request($url, $data, $optional_headers = null)
{
$params = array('http' => array(
'method' => 'POST',
'content' => $data
));
if ($optional_headers !== null) {
$params['http']['header'] = $optional_headers;
}
$ctx = stream_context_create($params);
$fp = #fopen($url, 'rb', false, $ctx);
if (!$fp) {
throw new Exception("Problem with $url, $php_errormsg");
}
$response = #stream_get_contents($fp);
if ($response === false) {
throw new Exception("Problem reading data from $url, $php_errormsg");
}
return $response;
}

If you don't want to use sessions, the only thing you can do is POST to the same page. Which IMO is the best solution anyway.
// form.php
<?php
if (!empty($_POST['submit'])) {
// validate
if ($allGood) {
// put data into database or whatever needs to be done
header('Location: nextpage.php');
exit;
}
}
?>
<form action="form.php">
<input name="foo" value="<?php if (!empty($_POST['foo'])) echo htmlentities($_POST['foo']); ?>">
...
</form>
This can be made more elegant, but you get the idea...

It is not possible to redirect a POST somewhere else. When you have POSTED the request, the browser will get a response from the server and then the POST is done. Everything after that is a new request. When you specify a location header in there the browser will always use the GET method to fetch the next page.
You could use some Ajax to submit the form in background. That way your form values stay intact. If the server accepts, you can still redirect to some other page. If the server does not accept, then you can display an error message, let the user correct the input and send it again.

It would be beneficial to verify the form's data before sending it via POST. You should create a JavaScript function to check the form for errors and then send the form. This would prevent the data from being sent over and over again, possibly slowing the browser and using transfer volume on the server.
Edit:
If security is a concern, performing an AJAX request to verify the data would be the best way. The response from the AJAX request would determine whether the form should be submitted.

Use a smarty template for your stuff then just set the POST array as a smarty array and open the template. In the template just echo out the array so if it passes:
if(correct){
header("Location: passed.php");
} else {
$smarty->assign("variables", $_POST);
$smarty->display("register_error.php");
exit;
}
I have not tried this yet but I am going to try it as a solution and will let you know what I find. But of course this method assumes that you are using smarty.
If not you can just recreate your form there on the error page and echo info into the form or you could send back non important data in a get from and get it
ex.
register.php?name=mr_jones&address==......
echo $_GET[name];

Related

how to load the php file in the form action only after php submit button was executed

I am not a PHP expert.
I have a form that has Captcha validation image.
the form has a button "submit", and the code for the submit
is within the same page (let's call it "code 1"):
<form method="post" name="emailForm" action="email.php">
Name:<input type="text" name="name"><br>
Email Add:<input type="text" name="email"><br>
Message:<textarea rows="10" cols="40" name="message">/textarea><br>
<input name="SubmitCF" type="submit" value="Send Email" class="button1"><br>
</form>
As I understand, the php concept is that the button action code in done by the following code fragment, and not by loading the file stated in the form's "action" tag, which is the php file "email.php" (in the form's declaration above) as in the following code fragment (let's call it "code 2"):
<?php
if (isset($_POST['SubmitCF'])) {
// Validate Captcha code ...
}
}
?>
The problem I face is as follows:
when I have the "action="email.php" " in the form declaration,
then the "email.php" is run but not the validation captcha code in "code 2", therefore the Captcha code is not validated (which is a bug).
but when I delete the "action="email.php" from the form's declaration, then "code 2" is executed, and the "email.php" is not
loaded and executed, and is it also a bug.
What is the way to validate the Captcha code, and only after the Captcha is validated, make the "email.php" in the form;s "action" declaration load and run?
how to run the "submit" button code within the same page, and only upon confirmation, load and execute the php file which is in the form's action declaration.
Many thanks to the answering members for their help and time.
You can do something like this:
In code 1 file, remove action="email.php" first, and let the form submit to the same page.
Check if the captcha is answered correctly on the page, if yes, redirect to the page email.php and transfer the current POST values.
Do what is in email.php
I found this question might be helpful, you can check it out.
EDIT: You can do sth like this via output buffering:
ob_start(); //place this before the first output or header, or the first line simply
header(sth…);
header(sth…);
echo “sth outputs”;
header(“Location: http://yourpage”);
And then transfer the data in the link or use session:
//from the reference question
function do_post_request($url, $data, $optional_headers = null)
{
$params = array('http' => array(
'method' => 'POST',
'content' => $data
));
if ($optional_headers !== null) {
$params['http']['header'] = $optional_headers;
}
$ctx = stream_context_create($params);
$fp = #fopen($url, 'rb', false, $ctx);
if (!$fp) {
throw new Exception("Problem with $url, $php_errormsg");
}
$response = #stream_get_contents($fp);
if ($response === false) {
throw new Exception("Problem reading data from $url, $php_errormsg");
}
return $response;
}

Put every POST and GET requests on hold except one specific, then continue

I need only PHP answers.
Setup : Apache Server and PHP version 7.4.
I'm working on a CAPTCHA plugin for WordPress. On that purpose, I thought I'd validate the CAPTCHA field before validating any other request.
This means I want to perform the CAPTCHA POST request before any other $_REQUEST is complete.
These other requests can be multiples, and I won't be able to handle their scripts.
I thought I'd detect if a POST or GET request has been made, then maybe call sleep() and perform my POST meanwhile.
The problem is : sleep() pauses the whole script whereas I only want the other POST and GET requests to be paused...
if ($_SERVER['REQUEST_METHOD'] === 'POST' OR $_SERVER[‘REQUEST_METHOD’] === 'GET' AND $_POST["myRequest"]) {
// Pause every POST and GET requests apart from $_POST["myRequest"] until $_POST["myRequest"] is performed
} else {
continue;
}
You could use session and keep track of the request and save the request if $_POST['myRequest'] is not present, than load the previous request from session or a file. Like this:
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST' OR $_SERVER[‘REQUEST_METHOD’] === 'GET') {
// POST myRequest has been done before
if(isset($_SESSION['.my-request.lock'])) {
// If present remove it
unset($_SESSION['.my-request.lock']);
if(isset($_SESSION['my-data.json'])) {
$my_prev_request = json_decode( $_SESSION['my-data.json'] );
unset($_SESSION['my-data.json']);
}
// Process other requests
} else {
if(isset($_POST['myRequest'])) {
$_SESSION['.my-request.lock'] = true;
// Do your own thing
} else {
// No myRequest and no file, save request data to load it after POST myRequest
$_SESSION['my-data.json'] = json_encode( $_REQUEST );
}
}
} else {
// Display Error ?
continue;
}

How can I implement Google Recaptcha v3 in a PHP form?

I would like to insert a contact form the new version (V3) of Recaptcha.
I have looked for different solutions, but they only show part of the code, they are incomplete or I get an error, and most of the solutions found are very complicated for something so simple and I do not understand the code.
I have searched this and other forums to implement the new version of ReCaptcha (V3) in my forms.
I needed to know how to:
Insert it with JS
How to validate it with PHP
What new fields were needed in my form.
I did not find any simple solution, which would show me all these points, or it was too complicated for somebody who just wanted to insert a contact form on their website.
At the end, taking some code portions of multiple solutions, I use a simple and reusable code, in which you only have to insert the corresponding keys.
Here it is.
The basic JS code
<script src="https://www.google.com/recaptcha/api.js?render=your reCAPTCHA site key here"></script>
<script>
grecaptcha.ready(function() {
// do request for recaptcha token
// response is promise with passed token
grecaptcha.execute('your reCAPTCHA site key here', {action:'validate_captcha'})
.then(function(token) {
// add token value to form
document.getElementById('g-recaptcha-response').value = token;
});
});
</script>
The basic HTML code
<form id="form_id" method="post" action="your_action.php">
<input type="hidden" id="g-recaptcha-response" name="g-recaptcha-response">
<input type="hidden" name="action" value="validate_captcha">
.... your fields
</form>
The basic PHP code
if(isset($_POST['g-recaptcha-response'])){
$captcha=$_POST['g-recaptcha-response'];
}
else
$captcha = false;
if(!$captcha){
//Do something with error
}
else{
$secret = 'Your secret key here';
$response = json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secret."&response=".$captcha."&remoteip=".$_SERVER['REMOTE_ADDR']));
if($response->{'success'}==false)
{
//Do something with error
}
}
//... The Captcha is valid you can continue with the rest of your code
//... Add code to filter access using $response . score
if ($response->{'success'}==true && $response->{'score'} <= 0.5) {
//Do something to denied access
}
You have to filter access using the value of $response->{'score'}. It can takes values from 0.0 to 1.0, where 1.0 means the best user interaction with your site and 0.0 the worst interaction (like a bot). You can see some examples of use in ReCaptcha documentation.
You only have to add your keys, no more changes needed:
src="https://www.google.com/recaptcha/api.js?render=your reCAPTCHA site key here"
grecaptcha.execute('your reCAPTCHA site key here'
and
$secret = 'Your secret key here';
Obviously you also have to change the action of the form, in this example:
action = "your_action.php"
In the answer above, these lines need to be updated in order to be able to read the response values in PHP:
$response = json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secret."&response=".$captcha."&remoteip=".$_SERVER['REMOTE_ADDR']));
$response->{'success'}
$response->{'score'}
Looks like Google improved their docs since the first answers. Here is how I do it.
Client side integration in form:
The docs for this are here: https://developers.google.com/recaptcha/docs/v3
According to Google you should include the Recaptcha API on every page so that it can observe the user's behavior. So I added this line to the end of my footer which is included in every page (no parameters needed):
<script src="https://www.google.com/recaptcha/api.js"></script>
On the form you use a submit button like so:
<button class="g-recaptcha" data-sitekey="PASTE-YOUR-RECAPTCHA-SITE-KEY-HERE" data-callback="onSubmit" data-action="submit">Submit Form</button>
And add the following JavaScript function that submits the form:
function onSubmit() {
var form = document.forms[0]; // change this if you have multiple forms
if (/* possible client-side form validation code here */) {
form.submit();
}
}
Server side validating code:
The docs for this are here: https://developers.google.com/recaptcha/docs/verify
For this I created a helper function:
/**
* Checks if the current script has a valid Google Captcha response token.
* #returns True, if the script has a valid repsonse token, otherwise false.
*/
function isCaptchaValid()
{
$captcha = isset($_POST['g-recaptcha-response']) ? $_POST['g-recaptcha-response'] : false;
if (!$captcha) {
return false;
}
$postdata = http_build_query(
array(
"secret" => "PASTE-YOUR-RECAPTCHA-SECRET-KEY-HERE",
"response" => $captcha,
"remoteip" => $_SERVER["REMOTE_ADDR"]
)
);
$opts = array(
'http' =>
array(
"method" => "POST",
"header" => "Content-Type: application/x-www-form-urlencoded",
"content" => $postdata
)
);
$context = stream_context_create($opts);
$googleApiResponse = file_get_contents("https://www.google.com/recaptcha/api/siteverify", false, $context);
if ($googleApiResponse === false) {
return false;
}
$googleApiResponseObject = json_decode($googleApiResponse);
return $googleApiResponseObject->success;
}
No need to check any score value as done in the other answers. According to the docs there isn't even a score property in the response object. I checked it and there is one, but I don't use it.
You should call it at the beginning of the PHP script that handles your form submit like so:
if (!isCaptchaValid()) {
die("STOP! You are a bot."); // or do something else
}

Settup form script for ajax and post calls

i would like to know if its possible to set up my script so it can be handled by http ajax call and alternatively also the classic post way:
on the top i am first doing this:
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) AND strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'){
$AnswerType = 'die';
}
if ($_SERVER['REQUEST_METHOD'] === 'POST'){
$AnswerType = 'session';
}
Then i check if either of these two is set by doing the following:
if ($AnswerType == 'die' || $AnswerType == 'session' ){
*here i run my script*
}
When the script ends i finally try to send all responses in my $respond_message array back the way the form where initialy posted:
if ($AnswerType = 'die'){
die(print_r($respond_message));
}
if ($AnswerType = 'session'){
$_SESSION['formrespondmessage'].= print_r($respond_message);
header("Location: /");
}
You want the script to react different on ajax and on simple post request? I think in this case the best solution is just to pass any variable, which indicates, that data is being sent by ajax. Like this:
postparams['ajax']=1;
$.post(...
And then in php make check like this:
if (isset($_POST['ajax'])) {
code for ajax request
} else {
code for simple post request
}
Not sure about your code, I prefer not to use so complicated scripts, at least you need to add () after serializeArray, possibly everything else looks ok. I would do like this:
<form name="form1" id="form1">
<input type="text" name="qq" value="ww">
</form>
<input type="button" onclick="dt=$('#form1').serializeArray();dt[dt.length]={name: 'ajax', 'value': 1};$.post('test.php', dt, function(data) {alert(data)});">
And in php file just check if isset($_POST["ajax"]). For example, my looks like this:
<?
if (isset($_POST["ajax"])) print_r($_POST);
?>

How to send post data to any url (with redirection) without using curl or fsocket in php

I would like my page to be redirected to new url with some post data being sent to it.
I don't want to use curl or fsocket because they will not redirect user to that new url.
Is there any alternative for header("Location: blahblahblah"); to send post data?
I tried with document.form.submit(); and it worked but some users are facing problem with javascript.
Can any one provide alternate solution for this?
Is there any php function to redirect user to new url along with some post data being sent to this url.
Thanks in advance.
function do_post_request($url, $data, $optional_headers = null)
{
$params = array('http' => array(
'method' => 'POST',
'content' => $data
));
if ($optional_headers !== null) {
$params['http']['header'] = $optional_headers;
}
$ctx = stream_context_create($params);
$fp = #fopen($url, 'rb', false, $ctx);
if (!$fp) {
throw new Exception("Problem with $url, $php_errormsg");
}
$response = #stream_get_contents($fp);
if ($response === false) {
throw new Exception("Problem reading data from $url, $php_errormsg");
}
return $response;
}
Have a look at this link http://netevil.org/blog/2006/nov/http-post-from-php-without-curl
the canonical way to do a redirect is with javascript, right? you need to have a simple page where you :
a) generate a form with the action url being the place you want to go
b) write hidden fields to contain your post_data
c) have javascript submit your form for you on load
You can't mimic the behaviour of a form using PHP. You may send POST data, but not redirect the user with the same request. You'll need to do it with a form. As Igor describes, it's possible to change the expected behaviour of forms with Javascript but I'd recommend against it.
What's wrong with using header("Location: $new_url")? That is performing a redirect and is the right way to do it AFTER POSTing data.
Edit: Updated to clarify that this is not how data is posted.
Alternative solutions if you just need to transfer data but POST is not mandatory:
redirect user and transmit data via query string
save data in a session and redirect user

Categories