Clear POST Data Upon Refresh PHP - php

I have a form that re-submits on refresh. I've searched SO and have found nothing relating to my specific issue. I know it is better to have a separate PHP page, but for this specific project it needs to all be on one PHP page. I need the POST to reset when the page is refreshed so the form isn't automatically sent again.
Please note that I CANNOT have the page redirect somewhere else therefore I cannot use Post/Redirect/Get. The outcome I'd like to have is this: Person visits for the first time, enters correct code, script runs, then next time they visit or refresh the page etc, they have to complete the form again. Any suggestions would be much appreciated.
$code = '';
$hide = "<script>$('form').fadeOut(500).remove();
$('.wrapper').addClass('form-success');
$('.container').delay(1800).fadeOut(500);</script>";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$code = secure($_POST["code"]);
}
function secure($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
if (intval($code) == 1234) {
echo $hide;
$code = '';
} else {
echo "Failed";
$code = '';
}

Are you sure? It's perfectly fine to redirect the user to the current page, and I'm pretty sure that's your best option. So after processing the code, redirect the user to the current page, and a refresh will no longer re-submit the form. Just make sure you redirect using HTTP Response code 303; [it triggers a GET request][1]:
This method exists primarily to allow the output of a POST-activated script to redirect the user agent to a selected resource. The new URI is not a substitute reference for the originally requested resource. The 303 response MUST NOT be cached, but the response to the second (redirected) request might be cacheable.
You can do this by using header after the submit has been processed (but before any html has been send to the user):
header('Location: '.$_SERVER["PHP_SELF"], true, 303);

if (!empty($_POST)) setcookie ("last_post", implode($_POST),time()+360000);
if (!empty($_POST) and $_COOKIE['last_post'] == implode($_POST)) $_POST = [];
With a POST request, we will add data to the cookies, with subsequent POST requests, we check them and if they are different from each other, we pass the parameters further.

Related

Preventing user access to submission page without having first completed the form

Say I have a form on example.com/contact that processes on example.com/submitted. In theory anyone can currently access example.com/submitted directly although this isn't ideal because of the message displayed. There's this question from 7 years ago but the answers in that don't work.
Theoretically the contents of the form page don't matter as long as it was posted. I don't want to have to echo out the contents of the submitted page as it is complete. I just need something simple like if the referrer wasn't example.com/form or POST method.
All I need is to only allow access to example.com/submitted if the user has actually submitted something. I've tried PHP and htaccess methods (PHP preferred) but nothing I've found has worked. Processing on the same page would remove this issue but the submitted page contains entirely different content.
Any advice would be appreciated as I can't find anywhere with a working answer.
Have the action of your form on example.com/contact point to example.org/submitted so that the form contents get posted to your submitted page.
Then, on your submitted page, check the method, and redirect to to contact on GET (or better, everything that isn't POST):
if ($_SERVER['REQUEST_METHOD'] !== 'POST')
header("Location: http://example.com/contact");
else if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST)) {
// validate input
// save to your CSV
// display `submitted` page
}
You can accomplish a check on both the refferer and the request method by doing so:
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['HTTP_REFERER'] == "http://example.com/form") {
// Your code
}
Try this:
contact.php
session_start();
...
$_SESSION['form-submitted'] = 0;
if(isset($_POST['submit'])){//use your button value
//do your stuff
$_SESSION['form-submitted'] = 1;
//redirect to submitted file
}
submitted.php
if(isset($_SESSION['form-submitted']) && $_SESSION['form-submitted'] == 1){
//show content
} else {
//redirect to contact page
}
This will allow you to catch the get requests and check if the form was not submitted.
Have you tried this one yet ?
if (!isset($_POST)) {
header("Location: http://example.com/contact");
}

PHP: display message if redirected from PHP file

I'm probably going about this the complete wrong way, but here's where I am at.
I have a page called adminquery.php and on it is a form. When that form is submitted, it calls a file called adduser.php
This page attempts to add the user sent by POST to a database and sends back one of two messages (added or updated) which should display on the adminquery.php page.
if ($row[0] == 1)
{
//update
$_SESSION['errMsg'] = "user updated";
}
else
{
//add
$_SESSION['errMsg'] = "user added";
}
header("Location: adminquery.php");
die();
adminquery.php displays the message
if(isset($_SESSION['errMsg'])){
echo "<p>".$_SESSION['errMsg']."</p>";
}
So far, so good. However, when I reload adminquery.php or access it from another page, I want it to not display this _SESSION message which is no longer applicable.
So I thought I would check the originating page when loading adminquery.php and, if it's not been accessed from adduser.php I would empty the message
$referringSite = $_SERVER['HTTP_REFERER'];
if (strpos($referringSite, 'adduser') == false) {
//$_SESSION['errMsg'] = $referringSite;
$_SESSION['errMsg'] = "";
}
The commented line is used to check the referring page and it displays adminquery.php as the referring page rather than adduser.php (which has been called but not displayed). It seems like unless the page has been displayed or an element on it clicked to reopen adminquery.php that it's not recognised as the referring page.
Is there some simpler solution I'm not seeing?
Setting an empty string won't clear the session variable. You need to unset it like so:
unset($_SESSION['errMsg']);
Also, you don't need to check the referrer. Since the user script sets that variable, the admin query script can just check if it exists, and if so, remove it after displaying the appropriate message.
You must unset this session variable.
if(isset($_SESSION['errMsg'])){
echo "<p>".$_SESSION['errMsg']."</p>";
unset($_SESSION['errMsg']);
}

Zend Redirecting

For some reason my zend application is redirecting when it's not supposed to.
The index view just shows the form. The next view shows some information from a database based on the information supplied by the form. The user then clicks on a confirm button which sends them to anotherAction which constructs and sends an email. I've got a try/catch block where it tries to send the email. If successful, set one variable, otherwise set another.
Psudo-code:
public function indexAction()
{
$form = new Form();
if(!empty($_POST))
{
if($form->isValid($_POST))
{
$this->_helper->FlashMessenger($_POST); //store $_POST in temporary session
//show a different view
//do something else
}
}
$this->view->form = $form;
}
So I'm instantialising a form, if the user posts the form then validate it and store the session variables in a flash session and show a differnet view. In all cases show the form (if it has been sent then it will be auto-populated).
public function anotherAction()
{
$messages = $this->_helper->FlashMessenger->getMessages();
if (!empty($messages[0]))
{
$post = $messages[0];
$mail = new My_Mail();
//set up email
try
{
$mail->send();
$success = true;
}
catch (Zend_Exception $e)
{
$success=false;
//save $e to log
}
$this->view->success = $success;
}
else
{
//if not sent here by /page, then redirect to it.
$this->_helper->redirector->goToRouteAndExit(array(), 'page', true);
}
}
In this action, I'm checking for the session. If it's got the form data in it, then try to send an email and set variable; otherwise redirect back to the form. The view variable is used to show one message or the other (email sent / email failed to send).
Here's the problem: It redirects back to the form anyway. The form is submitted and confirmed, we go to the next page where it does something then it redirects back to the page with the form on it. Why is it doing this and how do I stop it?
[edit]
The plot thickens: If I open the confirm link in a new tab it will run and stop correctly. If I do it in the same tab/window it runs twice and redirects.
[another edit]
I have removed all the code in the second action.
The code is now:
public function anotherAction()
{
$messages = $this->_helper->FlashMessenger->getMessages();
if (!empty($messages[0]))
{
;
}
else
{
$this->_helper->redirector->goToRouteAndExit(array(), 'page', true);
}
}
and it is still redirecting.
For the confirm button I have
<button>Confirm</button>
Could the anchor and button both be calling the next-page?
[final edit]
Ok, this IS the problem. It looks like both the button and the anchor are calling the page! So the first time it runs it's ok then it runs again and redirects me :(
Well, there we go. Learn something new everyday.
Thanks for the help all.
I assume your form submits to /controller/another/ ...
What happens in the //do something block of code there in that action? Since we know that it's not really doing both the "if" and the "else" in the same pass ... it must be doing something in the "if" that you're not showing here that either triggers it to recall the function, _forward()'s, or somehow is getting to this point a 2nd time where it then evaluates the else part of your logic.
Can you post a more complete sample to review?
try replacing your redirect with a die() or $this->_forward( 'page' ) to see if any php warning messages are being hidden by the redirect.
Both the button and the anchor are calling the page! So the first time it runs it's ok then it runs again and redirects me.
Removed the button.
Try the following:
$this->redirect()->toRoute('routeName',array('controller'=>'controllerName','action'=>'actionName'));
$this->redirect()->toUrl('UrlLink')

PHP Application guarantee no re-post

I might not have known what to search for to get this answer so please point me to the correct post if this has been dealt with already.
Now then, I have a little custom CMS and I want to ensure users don't re-submit their $_POST data by refreshing the page. So I've done something like this:
<?
//Start a session to hold variables I want after my redirect
session_start();
if($_POST){
//Do some php stuff and if I'm happy with the results...
$_SESSION['some_vars'] = $whatever;
//Bring me back here but without the $_POST data
header('Location: '.THIS_PAGE);
exit;
}
?>
When the script reloads I use my session variables and trash the session.
I'm wondering if anybody has a better way to handle this. It's fairly non cumbersome but I'm always looking for more efficiency.
Thanks.
EDIT: By the way, stackoverflow.com does this somehow when you post a question if what I'm doing seems unclear, but they also make a permalink while they're at it.
You have actually implemented what is called the Post-Redirect-Get pattern, and it is absolutely a correct way to do this. I do this myself. I use it so often, I usually implement some minor helper functions into my base controller classes to help me use it:
public function prgRedirect($url = null, $sessionData = null)
{
if ($sessionData !== null) {
if (! isset($_SESSION)) session_start();
$_SESSION['_PRG'] = $sessionData;
}
if ($url === null) $url = $_SERVER['HTTP_REFERER'];
header("Location: ".$url);
}
public function getPrgData()
{
if (! isset($_SESSION)) session_start();
if (isset($_SESSION['_PRG'])) {
$data = $_SESSION['_PRG'];
unset($_SESSION['_PRG']);
}
else {
$data = null;
}
return $data;
}
I usually use it with REST-style URLs, so a POST request will do whatever it has to do, save some data to session using prgRedirect(), which then redirects back to the GET url for the same resource/page. The handler for the GET method will call getPrgData() at the top of the execution and see if there's anything in the session data.
if its important that user dont insert the same data I'm sure there must be some unique column in your database (like headline maybe?). so just check if this headline already exists. you wont need to use any sessions that way
What about:
1. Generate random string (uniqid or md5)
2. Store it in session and put in into hidden input at the form
3. Check form value and session value - if it matches - process the form. Clear the session value.
There are actually two problems here:
users hitting the refresh button in their browser when the data is already saved and you are in a page which saves the data
user hits the "back" button in the browser and clicks "submit" button once again.
In the first scenario, the best scheme is to follow the GET-after-POST pattern where you use the header("location:somewhere_else.php") call to redirect the user. This way you do not have to worry about being called two times consecutively, since the page where you posted the data, is not in the browser's history list (because the server had returned 302 header).
The second scenario hurts a bit more, because the GET-after-POST does not help. If the user submits the form twice, the you may save the data twice. In this case, there may be several solutions:
put a "form identifier" (a random string) in every form you send to the client. When client submits the form, check if you already have such identifier in session data. If you don't have it, save form data and remember the identifier in user's session as "already used". If you find the identifier in session data, don't save anything - it's a duplicate.
check the database for exactly the same values that are submitted. If they match, do not save a duplicate. However, the user may have clicked "back" button, changed some piece of data and then re-submitted the form.

Detect whether the browser is refreshed or not using PHP

I want to detect whether the browser is refreshed or not using PHP, and if the browser is refreshed, what particular PHP code should execute.
When the user hits the refresh button, the browser includes an extra header which appears in the $_SERVER array.
Test for the refresh button using the following:
$refreshButtonPressed = isset($_SERVER['HTTP_CACHE_CONTROL']) &&
$_SERVER['HTTP_CACHE_CONTROL'] === 'max-age=0';
If the page was refreshed then you'd expect two requests following each other to be for the same URL (path, filename, query string), and the same form content (if any) (POST data). This could be quite a lot of data, so it may be best to hash it. So ...
<?php
session_start();
//The second parameter on print_r returns the result to a variable rather than displaying it
$RequestSignature = md5($_SERVER['REQUEST_URI'].$_SERVER['QUERY_STRING'].print_r($_POST, true));
if ($_SESSION['LastRequest'] == $RequestSignature)
{
echo 'This is a refresh.';
}
else
{
echo 'This is a new request.';
$_SESSION['LastRequest'] = $RequestSignature;
}
In an AJAX situation you'd have to be careful about which files you put this code into so as not to update the LastRequest signature for scripts which were called asynchronously.
<?php
session_start();
if (!isset($_SESSION["visits"]))
$_SESSION["visits"] = 0;
$_SESSION["visits"] = $_SESSION["visits"] + 1;
if ($_SESSION["visits"] > 1)
{
echo "You hit the refresh button!";
}
else
{
echo "This is my site";
}
// To clear out the visits session var:
// unset($_SESSION["visits"]);
?>
If you mean that you want to distinguish between when a user first comes to the page from when they reload the page check the referrer. In php it is: $_SERVER["HTTP_REFERER"]. See if it is equal the page your script is running on. It may be the case that the client doesn't provide this information, if that happens you could set a cookie or session variable to track what the last requested page was.
To prevent duplicate form processing when a user hits the browser refresh or back button, you need to use a page instance id session variable, and a hidden form input that contains that variable. when the two don't match, then the user has refreshed the page, and you should not reprocess the form. for further details, see:
https://www.spotlesswebdesign.com/blog.php?id=11
If someone refreshes a page, the same request will be sent as the previous one. So you should check whether the current request is the same as the last one. This can be done as follows:
session_start();
$pageRefreshed = false;
if (isset($_SESSION['LAST_REQUEST']) && $_SERVER['REQUEST_URI'] === $_SESSION['LAST_REQUEST']['REQUEST_URI']) {
if (isset($_SERVER['HTTP_REFERER'])) {
// check if the last request’s referrer is the same as the current
$pageRefreshed = $_SERVER['HTTP_REFERER'] === $_SESSION['LAST_REQUEST']['HTTP_REFERER'];
} else {
// check if the last request didn’t have a referrer either
$pageRefreshed = $_SERVER['HTTP_REFERER'] === null;
}
}
// set current request as "last request"
$_SERVER['LAST_REQUEST'] = array(
'REQUEST_URI' => $_SERVER['REQUEST_URI'],
'HTTP_REFERER' => isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null
);
I haven’t tested it but it should work.

Categories