PHP avoid browser reposting $_POST on page refresh? - html

I wonder what are the techniques i can use to avoid users to post form twice when they refresh page and chose submit again?
e.g. i have form inside regiter.php and process it as well inside register.php.
1st i could process in another file e.g. register_process.php and redirect to register.php, but then i have to create about 20 new pages and relocate a lot of code, i dont want that option.
2nd i could play with headers i dont remember exact trick but had some bad experience with that - users seen old data on page after refreshing it...
3rd i could just redirect upon success to some dummy.php and from dummy.php jump back to register.php then even if they refresh page browser would not re-post, however it does not protect against them using back button and choosing re-post, i know i could expire page, but i find that annoying experience for me and probably other users to see page expired error.
4th use some unique "access key" for each form once page loaded that will post with form and once used cannot be reused, however i kind of struggle with logics of that feature. how do know key was used without storing it in MySQL DB, i think time based accesis not great either because some users can take long between page open and form submit.
I need more suggestions how to avoid users reposing form again.

Try this:
<?php
session_start();
if( strcasecmp($_SERVER['REQUEST_METHOD'],"POST") === 0) {
$_SESSION['postdata'] = $_POST;
header("Location: ".$_SERVER['PHP_SELF']."?".$_SERVER['QUERY_STRING']);
exit;
}
if( isset($_SESSION['postdata'])) {
$_POST = $_SESSION['postdata'];
unset($_SESSION['postdata']);
}
This will basically save the POST data and cause the browser to re-request as a GET request.

5th. Use AJAX or jQuery and when the form is clicked on the page submit that data in the background. Output a response to the screen. Mark that form as submitted, or save to a session, and when they refresh they will not be able to submit the form again.
In my opinion it is the best way to do it anyway. I had a scoreboard with 20 or more forms it is worked really well to send the data without refreshing. You can return a response and make the page look very professional. Using jQuery you can also use some great form validation to make sure that they are submitting the fields that are required.

I think that the best solution would be something like this:
* create a md5 or base64 of posted data
* compare this hash with a session variable (let's call it $_SESSION['repost'])
* if hashes match, skip whatever this save should do and output a warning
* if hashes do not match, or hash is not present
* assign session variable with current hash
* do whatever save should do

When you consider the first option, I don't know about the design (programming design ^^) of your website, but you should only need 1 page. Let's says you call redirect.php with all the parameters, you should call your controller and your controller should know regardless of the parameters what to do with them.
It is a good habit to be able to do some abstraction and good design when programming, it help alot in those situation.

Other way is store the last post in the session variable, and check if is equal, like this:
<?php
... program ...
if ($_SESSION['PREPOST'] == $_POST) {
// DO SOMETHING
}
... program ...
$_SESSION['PREPOST'] = $_POST;
?>

Related

Perl table Extract or other method for multi page table

I'm trying to extract elements from a table, I have successfully used get and HTML:TableExtract to get elements of the table. The problem is the table is multi page and navigated with an arrow button to show additional pages. How would i extract these other pages as they are not new links but I think generated with JS or such?
Specifically I am trying to extract the table under Data for this Data Range at:
http://ycharts.com/companies/GOOG/pe_ratio#series=type:company,id:GOOG,calc:pe_ratio,,id:AAPL,type:company,calc:pe_ratio,,id:AMZN,type:company,calc:pe_ratio&zoom=3&startDate=&endDate=&format=real&recessions=false
See how there is the Viewing x of 45 and the First, Previous, Next, Last button.
The rest of the table elements can be viewed with next, how would i extract these in perl?
Update::
Hi Simbabque, Thanks for the response.
So I see if you click on next it calls:
ng-click="getHistoricalData(historicalData.currentPage+1)"
Is there a way I can call this method? I tried to use click,but it is not bound a name. (JS?)
I was trying to use Mechanize::Firefox now but I feel like their must be an easy way to use regular Mech and call the function and re-read the page?
The website builds up the tables using AJAX requests. Those are a little harder to parse. You can use WWW::Mechanize to fetch the initial page and then hit the AJAX calls for the table. It helps you keep track of cookies and stuff automatically.
use strict; use warnings;
use WWW::Mechanize;
my $mech = WWW::Mechanize->new;
$mech->get('http://ycharts.com/companies/GOOG/pe_ratio#series=type:company,id:GOOG,calc:pe_ratio,,id:AAPL,type:company,calc:pe_ratio,,id:AMZN,type:company,calc:pe_ratio&zoom=3&startDate=&endDate=&format=real&recessions=false');
my $response = $mech->post(
'http://ycharts.com/companies/GOOG/pe_ratio/data_ajax',
{
startDate => '1/1/1962',
endDate => '12/3/2013',
pageNum => 4,
}
);
if ( $response->is_success ) {
print $response->decoded_content; # or whatever
} else {
die $response->status_line;
}
This is just a basic example and will not work. It gives a 403 Forbidden. Probably there is more data required. Use Firebug or a similar tool to inspect what is happening. For example, there's another call to http://ping.chartbeat.net/ping?h=ycharts.com&p=%2Fcompanies%2FGOOG%2Fpe_ratio&u=o3m6snxteynby1b8&d=ycharts.com&g=20054&n=1&f=00001&c=10.81&x=200&y=1812&o=1663&w=658&j=30&R=0&W=1&I=0&E=109&e=6&b=1903&t=usmc0fjfd1j0h87g&V=16&_ happening automatically every now and again, with varying parameters. That is most likely required to keep the session going.
This page is pretty sophisticated. This might not be the best approach.
You could also try to use WWW::Mechanize::Firefox or even Selenium to remote-operate a browser. That will be better suited as it takes care of all the AJAX stuff that is happening.
Or you could look for a public API that just hands over that data voluntarily. I bet there is one around... or just pay for a ycharts pro account and hit the download button. ;-)

How to keep confirmation messages after POST while doing a post-submit redirect?

Hello,
I'm looking for advise on how to share certain bits of data (i.e. post-submit confirmation messages) between individual requests in a web application. Let me explain:
Current approach:
user submits an add/edit form for a resource
if there were no errors, user is shown a confirmation with links to:
submit a new resource (for "add" form)
view the submitted/edited resource
view all resources (one step above in hierarchy)
user then has to click on one of the three links to proceed (i.e. to the page "above")
Progmatically, the form and its confirmation page are one set of classes. The page above that is another. They can technically share code, but at the moment they are both independent during processing of individual requests.
We would like to amend the above as follows:
user submits an add/edit form for a resource
if there were no errors, the user is redirected to the page with all resources (one step above in hierarchy) with one or more confirmation messages displayed at the top of the page (i.e. success message, to whom was the request assigned, etc)
This will:
save users one click (they have to go through a lot of these add/edit forms)
the post-submit redirect will address common problems with browser refresh / back-buttons
What approach would you recommend for sharing data needed for the confirmation messages between the two requests, please?
I'm not sure if it helps, it's a PHP application backed by a RESTful API, but I think that this is a language-agnostic question.
A few simple solutions that come to mind are to share the data via cookies or in the session, this however breaks statelessness and would pose a significant problem for users who work in several tabs (the data could clash together). Passing the data as GET parameters is not suitable as we are talking about several messages which are dynamic (e.g. changing actors, dates).
Thanks,
M.
It sounds like type of user messaging system is needed. By this what I mean the process could look similar to the following:
The user submits the form
The system could register the user for a set of notifications/messages (store in a DB table or something along those lines.
The system send the redirect response to the user
On the next page load for the user the system would check to see if the user had any pending messages.
If they do then remove them from the pending list/table and add them to the page
This keeps you from having a page state issue while still providing the user with the messages to be displayed, note that you might need to tweak the specifics to your needs.
Hope this helps.
ASP.NET
Since the question is presented as language agnostic, you might be interested in ASP.NET's Server.Transfer which does exactly what you want to achieve.
PHP
However for PHP, the situation doesn't seem to be very easy and all solutions that come into my mind have design smells:
Sessions
Using sessions to mark your data with certain flags and then check and use them on overview page. You just have to be sure you always unset these data after you don't need them anymore, which might be tricky.
Database
Queue those data in database as confusedGeek described in his post, but I don't think it's a good idea to query every single request like this. It's going to be quite many requests on DB server if you application is bit bigger, which might slow things down.
cURL
Taking advantage of cURL in PHP, if you have the chance:
<?php
$curl = curl_init( );
curl_setopt( $curl, CURLOPT_URL, "http://localhost/something.php" );
curl_setopt( $curl, CURLOPT_POST, true );
curl_setopt( $curl, CURLOPT_POSTFIELDS, $_POST );
curl_exec( $curl );
curl_close( $curl );
?>
<form action="test.php" method="post">
<input id="textfield" name="textfield" />
<input type="submit" />
</form>
This piece of code takes something.php on server side, allows to send POST data to it and shows you its content (which could be just print_r( $POST ); in this example). This one could do what you need, but it has once again one flaw - the URL won't change, so users might get confused - and I wouldn't really recommend it.
I personally think your case might be a design flaw. Why would you want to take all resources from form page and move them to other? Isn't easier to work with your data in a file / class designed for it and then just decide what outcome you have? If something fails, it returns the user on page with form and if everything went well, you post the data to DB and show overview page with some happy message that everything went okay.
If you really want to proceed with the way of sending everything to other page, using AJAX/AJAJ could be another solution for you.

implementing captcha in Flash

I'm developing a flash registration form and I need to incorporate dynamic 'captcha' images for confirmation.
Can anyone recommend a best solution for doing this?
Captcha is used to prevent bots from submitting html forms which is easily accomplished since html is easily understood and processed programmatically. The same is not true for a Flash application. It would be difficult for a bot to generically submit Flash forms if it was not specifically made to target your site.
Therefore you don't need to worry about the spam problem captcha solves when working with a Flash application.
Making a strong captcha is not a trivial task. It must be hard enough for bots to fail, but easy enough for humans to succeed... I would take a look at existing systems and possibly use them. reCAPTCHA is popular http://recaptcha.net/ . It might be possible to use it through flash, but I have not looked into it.
It's not that different from a captcha in an HTML form, really.
Suppose you're using php on the server and you have a captcha.php scritp that generates the captcha image and saves its value in the session. In an HTML form, you'd use an element and set its src to captcha.php. The user would fill up a field with the text they see in the image. In the script that receives the post, you'd check if the user input matches the session value.
In a flash form, it's exactly the same. You load the image calling captcha.php and ask the user to type the extra field. Then, when you post the data to the server you pass the value typed by the user in the captcha field and the server matches that against the value it has stored in the session when you called captcha.php.
So, basically, it's the same as in an HTML form.
Chances are, bots aren't going to be written for your website. If the need ever arises, a simple "add these two numbers for me, k?" would be simple enough.
In all honesty, i doubt someone would write letter recognition to sign up a few hundred times on your website =/
You should be more worried about someone disassembling [or whatever the flash term is] your .swf s and simply sending "register" messages to your server =/
And yes, by that, i tried to imply that Captcha must be applied server side, or, really, its not that hard to go around.
We had a strong need to implement CAPTCHA into a flash animation/form.
The most important point to note is that either FF or IE (can’t remember which one) doesn’t send any cookies back with a web service call. So if you’re submitting your form to a .Net web service you can’t use the session state of the http request to store the captcha text and then compare the user entered captcha value on submttion to the web service (session enabled web method)
We implemented the following:
Set a unique token value (Guid) on the web page
pass this token as a flashvar to the flash movie
load the captcha image into the flash with the token as a url param. Ie captchaImg.aspx?t=xxxxxxx
during that request save the random captcha text in a table with the token
when the user submits their form, compare the token and user entered captcha value with the one in the table
This approach works very well for us.
It’s also web farm safe.
public class Captcha extends Sprite{
private var question:String = "How do you feel?";
private var _answer:String;
private var isRobot:Boolean;
public function Captcha(answer:String){
_answer = answer;
}
public function checkAnswer():Boolean
if(answer != "sad"){
isRobot = true;
return isRobot;
}else{
isRobot = false;
return isRobot;
}
}
}

insert query on same page from which data is transfered

i am writing code to insert data into mysql on same page from where i retrive data by post method . it working fine but when i refresh page it will insert again.
my question is that how to stop reexcuting the insert query on refreshing page
This is being caused by the POST data being sent again when you refresh. Your browser should give you a warning that it's doing that. If you're not getting that warning, you might be using GET instead of POST which is not a good idea for actions which change or insert data.
Check your form has this attribute:
<form method="post">
If you want to avoid it altogether, just redirect the browser after the post back.
<?php
if ($_POST) {
// insert into database
header("location: thisPage.php");
// don't bother with die() here
}
Since the redirect is not being used for security purposes, and you're just redirecting back to the same page, it's not really necessary to die() afterwards.
You probably want to use the Post-Redirect-Get pattern to resolve this situation. It's good that you use POST to send data to your server. After you've done the necessary modifications, redirect your user to the page you want him to see, with a simple redirect-header. This will NOT break the back button, and a click on it will take the user back to the form, without sending the data again.
Add some variable to your form and then during saving reset it's value.
if(isset($_POST['save']))
{ //do your saving
$save="";
}

Retaining HTTP POST data when a request is interrupted by a login page

Say a user is browsing a website, and then performs some action which changes the database (let's say they add a comment). When the request to actually add the comment comes in, however, we find we need to force them to login before they can continue.
Assume the login page asks for a username and password, and redirects the user back to the URL they were going to when the login was required. That redirect works find for a URL with only GET parameters, but if the request originally contained some HTTP POST data, that is now lost.
Can anyone recommend a way to handle this scenario when HTTP POST data is involved?
Obviously, if necessary, the login page could dynamically generate a form with all the POST parameters to pass them along (though that seems messy), but even then, I don't know of any way for the login page to redirect the user on to their intended page while keeping the POST data in the request.
Edit : One extra constraint I should have made clear - Imagine we don't know if a login will be required until the user submits their comment. For example, their cookie might have expired between when they loaded the form and actually submitted the comment.
This is one good place where Ajax techniques might be helpful. When the user clicks the submit button, show the login dialog on client side and validate with the server before you actually submit the page.
Another way I can think of is showing or hiding the login controls in a DIV tag dynamically in the main page itself.
You might want to investigate why Django removed this feature before implementing it yourself. It doesn't seem like a Django specific problem, but rather yet another cross site forgery attack.
2 choices:
Write out the messy form from the login page, and JavaScript form.submit() it to the page.
Have the login page itself POST to the requesting page (with the previous values), and have that page's controller perform the login verification. Roll this into whatever logic you already have for detecting the not logged in user (frameworks vary on how they do this). In pseudo-MVC:
CommentController {
void AddComment() {
if (!Request.User.IsAuthenticated && !AuthenticateUser()) {
return;
}
// add comment to database
}
bool AuthenticateUser() {
if (Request.Form["username"] == "") {
// show login page
foreach (Key key in Request.Form) {
// copy form values
ViewData.Form.Add("hidden", key, Request.Form[key]);
}
ViewData.Form.Action = Request.Url;
ShowLoginView();
return false;
} else {
// validate login
return TryLogin(Request.Form["username"], Request.Form["password"]);
}
}
}
Just store all the necessary data from the POST in the session until after the login process is completed. Or have some sort of temp table in the db to store in and then retrieve it. Obviously this is pseudo-code but:
if ( !loggedIn ) {
StorePostInSession();
ShowLoginForm();
}
if ( postIsStored ) {
RetrievePostFromSession();
}
Or something along those lines.
Collect the data on the page they submitted it, and store it in your backend (database?) while they go off through the login sequence, hide a transaction id or similar on the page with the login form. When they're done, return them to the page they asked for by looking it up using the transaction id on the backend, and dump all the data they posted into the form for previewing again, or just run whatever code that page would run.
Note that many systems, eg blogs, get around this by having login fields in the same form as the one for posting comments, if the user needs to be logged in to comment and isn't yet.
I know it says language-agnostic, but why not take advantage of the conventions provided by the server-side language you are using? If it were Java, the data could persist by setting a Request attribute. You would use a controller to process the form, detect the login, and then forward through. If the attributes are set, then just prepopulate the form with that data?
Edit: You could also use a Session as pointed out, but I'm pretty sure if you use a forward in Java back to the login page, that the Request attribute will persist.