PDA

View Full Version : Distinguishing submit from refresh?


gorilla1
07-20-2002, 03:18 PM
I have a piece of code where text is being entered on a form and password entered and then a submit is done, at which point I write the data to a file, as long as the password is ok, and then I write all items in the file back out to the screen. To get the added item to show on screen, the user must do a refresh. Unfortuantely, if the user immediately does a second refresh, then the added itm gets written to the file a second time. And will keep doing so if he keeps refreshing. I would like to put a flag in the logic to say, already written to file, don't write again, and then go clear the flag at some other point. However, I really can't see where else to clear the flag - there is no way in the submit routine that I can see to detect whether this is initial submit, or a refresh. Anyone know how to handle this?

G

Spookster
07-20-2002, 04:16 PM
Why is it that you need to hit refresh to get the item to show? That shouldn't be needed. As for determing whether or not an item has been submitted all that needs to be done is to give the submit button a name and check to see if that variable was set or not.

gorilla1
07-20-2002, 06:22 PM
Thanks, Spookster. Yes, the submit variable is set, but I don't think I can distinguish whether when I test it it is immediately after the submit or after the refresh after the submit. In both cases it will show the variable as set... As for why the refresh is needed, I'm not sure where I go wrong. Below is the code, with some extraneous checks left out for brevity...

.
.
.
if($HTTP_POST_VARS['submit']) {
if($HTTP_POST_VARS['password'] == 'xxx') {
if(!$HTTP_POST_VARS['name']) {
echo "You must enter a name";
exit;
}
$fp = fopen('items.txt','a');
if(!$fp) {
echo "Error opening file!";
exit;
}
.
.
.
$outline = etc... . $strip;
.
.
.
fwrite($filp, $outline);
if(!fclose($filp)) {
echo "Error closing file";
exit;
}
echo "<b>Item added</b>\n";

} else {
echo "Invlaid password";
}
}

?>
<FORM ACTION="<?=$PHP_SELF?>" METHOD="POST" NAME="itementry" class="textg">
Your name:<BR>
<INPUT TYPE="text" SIZE="30" NAME="name"><BR>
The Item:<BR>
<TEXTAREA NAME="items" COLS="70" ROWS="8"></TEXTAREA><BR><BR>
Password:<BR>
<INPUT TYPE="password" SIZE="30" NAME="password"><BR>
<INPUT TYPE="submit" NAME="submit" VALUE="Post to File"><BR>
</FORM>

Spookster
07-20-2002, 06:36 PM
Hmmm. I don't see a need for a refresh. Can you explain what this is suppose to do. You are having a person type in their name and password along with some other input and then apending that input to items.txt?

gorilla1
07-20-2002, 07:06 PM
Spookster,

Yes, exactly. The contents of the file are informational items submitted by various folks.... I suppose the problem lies with the following... The display I show has a section driven by one form (the general admin part of the page), which has edit, delete, activate, etc., buttons next to each 'item' in the file, with all items in the file displayed. Then below that is the 'add item' form that I have referred to in this thread. So when the viewer does the add item, the item does not appear in the general admin display above until a refresh is done. I guess I was not thinking so clearly and failed to explain that.

G

Spookster
07-20-2002, 07:47 PM
Ok I think I understand. In the general admin part are you closing the file once you have opened it? Maybe you could post the relevant code for that as well?

gorilla1
07-20-2002, 08:08 PM
The gist of it (the admin part) is this: For each item in the file, I write the file contents for that item and a line following like so to the browser:

<a href=\"$PHP_SELF?action=delitem&id=$key\">Delete</a>

(except that in addition to delete there are several other editing action options).

Then, using the delete case above as an example, if $action == "delitem"
I remove that item from my array and rewrite the entire file. So, yes, I do close the file after performing the chosen action.

G

Spookster
07-20-2002, 09:59 PM
Can we see the code though?

gorilla1
07-21-2002, 01:52 AM
Spookster,
I'm sorry, but I'm modifying code for someone (I didn't write the original code), so I don't feel comfortable posting alot of it... I had another idea, which was to store off the submitted text, and then at the top of the submit code, to check whether the submitted text equals the stored off, and if so I know it is a refresh and I should not write the file again... But nothing seems to be working at this point, so I think I will leave this for tonight.. Thanks for all the ideas.

G

Spookster
07-21-2002, 03:42 AM
If I were to see how everything else is working I could post a solution that doesn't require a refresh.

gorilla1
07-21-2002, 05:57 PM
OK, thanks, Spookster. Below I have boiled the code logic down to its essence (yet still a working version) so that it exhibits the precise problem - namely, that 1) a refresh is needed to view the updated item, and 2) consecutive refreshes will result in consecutive duplicate entries in the file, even though only one entry was intended for submission. Thanks again.

G.

<?

$recin = file('items.txt');

foreach($recin as $linein) {
$linein = trim($linein);
echo $linein . "</b>\n";
echo "<BR><BR>\n";
}


if($HTTP_POST_VARS['submit']) {
$filepnt = fopen('items.txt','a');
if(!$filepnt) {
echo "Open error";
exit;
}
$lineout = $HTTP_POST_VARS['Item'];
$lineout = str_replace("\r\n","<BR>",$lineout);
$lineout .= "\r\n";
fwrite($filepnt, $lineout);
if(!fclose($filepnt)) {
echo "Close error";
exit;
}
echo "<b>added this iem</b>\n";
}

?>
<FORM ACTION="<?=$PHP_SELF?>" METHOD="POST" NAME="Itemform">
Item:<BR>
<TEXTAREA NAME="Item" COLS="65" ROWS="5"></TEXTAREA><BR><BR>
<INPUT TYPE="submit" NAME="submit" VALUE="Post"><BR>
</FORM>

gorilla1
07-24-2002, 03:40 PM
Spookster,

I had no success trying to avoid the refresh. Did you have a thought on it?

G

Spookster
07-24-2002, 04:58 PM
Put everything as you have it now in a .txt file and post a link to it and ill take a look at it.

gorilla1
07-24-2002, 05:10 PM
It's right there in the 07-21-2002 12:57 PM post - 23 lines of code.

G

Spookster
07-25-2002, 03:25 AM
Well I put together a script using various different methods but all end up with the same problem as you originally had. This is very strange.

It has me perlexed at the moment. I'll have to investigate it some more.

Spookster
07-25-2002, 05:36 AM
Ok firepages just pointed something very obvious out to me. Your program is simply backwards. lol

The reason the text you submit doesn't show up until the page is refreshed or something else is submitted is because you are reading the file in before the text actually gets written to the file. You simply need to write the text first then read in the file. Here is the version I had written. I was doing the same thing reading first then writing. DUH!!! :)



<?php
$item_received = $HTTP_POST_VARS['Item'];
$submit = $HTTP_POST_VARS['submit'];

$filename = "items.txt";

if(isset($submit)){
$fp = fopen($filename, "a");
$lock = flock($fp, LOCK_EX);
if($lock){
$item_received .= "\n";
fputs($fp, $item_received);
flock($fp, LOCK_UN);
}
fclose($fp);
}


$fp = fopen ($filename, "r");
$lock = flock($fp, LOCK_EX);
if($lock){
while (!feof ($fp)) {
$item = fgets($fp, 4096);
echo $item;
echo "<br>";
flock($fp, LOCK_UN);
}
}
fclose ($fp);

?>

gorilla1
07-25-2002, 03:56 PM
Spookster,

Your program is simply backwards. lol The program is backwards? Or did you misunderstand its purpose? The intent of the script was to display to the viewer the current set of items, and then give the viewer the option of adding an item. Much as on a web page there might be a display of previous comments, and then the viewer can add a comment. It looks to me like the script you wrote does not intend to write the existing items out first. I'm not sure, though, because it doesn't write anything out at all - at least not when combined with the form that I had posted. Not sure why - I'm still trying to get it (your script) to work and I can't yet see why it does not.

G
To be clear, here is the script (your script, plus the form I had posted):
<?php
$item_received = $HTTP_POST_VARS['Item'];
$submit = $HTTP_POST_VARS['submit'];

$filename = "items.txt";

if(isset($submit)){
$fp = fopen($filename, "a");
$lock = flock($fp, LOCK_EX);
if($lock){
$item_received .= "\n";
fputs($fp, $item_received);
flock($fp, LOCK_UN);
}
fclose($fp);
}


$fp = fopen ($filename, "r");
$lock = flock($fp, LOCK_EX);
if($lock){
while (!feof ($fp)) {
$item = fgets($fp, 4096);
echo $item;
echo "<br>";
flock($fp, LOCK_UN);
}
}
fclose ($fp);

?>


<FORM ACTION="<?=$PHP_SELF?>" METHOD="POST" NAME="Itemform">
Item:<BR>
<TEXTAREA NAME="Item" COLS="65" ROWS="5"></TEXTAREA><BR><BR>
<INPUT TYPE="submit" NAME="submit" VALUE="Post"><BR>
</FORM>Your program is simply backwards. lol

firepages
07-25-2002, 05:39 PM
What Spookster meant by backwards was that originally you were

1)reading the file
2)adding to it (if submitted)
3)displaying it

when it should have been (as is now)

1)adding to it (if submitted)
2)reading the file
3)displaying it

The code you posted above works fine for me so you must have some permissions issues (I ran on windows where FLOCK etc is ignored so I can not comment on that part of it)

gorilla1
07-25-2002, 06:03 PM
originally you were
1)reading the file
2)adding to it (if submitted)
3)displaying it



Firepages, No, I was

1) Reading the file AND displaying it
2) adding the submission

when it should have been (as is now)

1)adding to it (if submitted)
2)reading the file
3)displaying it


As I just described in the prior post, what you are laying out is a different program specification than the one I wrote. I want to display the file first. So it only "should have been" what you lay out if you want to accomplish something different than what the program I included in my post does and is intended to do. That is not what it should be if you want to display the file first. Correct? or am I missing something? See my example above in the prior post about a script that appends new comments to those already displayed (or try the actual code in my 7/21 post).


The code you posted above works fine for me so you must have some permissions issues

I am running on Windows on my own machine using firepages php/apache. I can write to the same file in the same directory using another program, so I most definitely do not have any "permissions issues"... (In fact, what I see it is doing is writing the file successfully, but with an entry that is blank).

G

firepages
07-25-2002, 06:45 PM
well this is on *NIX - and reading and writing seems to work unless I am missing something?

http://www.firepages.com.au/test/f_test.php

gorilla1
07-25-2002, 06:57 PM
Firepages,

Yeah, I just uploaded it to a website that is running apache and php3 and it runs fine. I wonder why not on my own machine - exact same program. Must be soemthing different in the firepages apache/php implementation? I don't get it.

OK, now I see the light as far as the program logic... However, this program will still duplicate an entry if a refresh is done immediately following a submit.

G

Spookster
07-25-2002, 07:28 PM
I am running it on phpdev4 on windows here.

As for duplicating the data that problem will exist in any situation where you are going to have the form in the same page as where you are processing the input.

In this case you should simply need to clear the $submit variable. The program will only add to the file when that variable is set. So at the end of the program clear it.

As for the flock, I put that in there so as to eliminate any possible chance of simultaneous requests to read/write to the file. This will cause simultaneous requests to go into a queue and wait for their turn to read/write to the file.

firepages
07-25-2002, 07:57 PM
Like Spookster says unless you post to a different page than the display page you are going to have issues, the only way around them is to use sessions, but then you need to get the user to actively kill the session in some way or another, remember whenever the page is refreshed all of the _POST and _GET vars are sent again.

So you could set a session on the first submit, and dissallow subsequent sunbmissions (via refresh) by the eistance of the session variable, but again you then have to kill that sessoin var to post again...

gorilla1
07-25-2002, 08:27 PM
Ok.. Yeah, I tried both unset($submit); and $submit = NULL; at the end of the routine to clear the variable, but neither prevented the duplicate on refresh. Is there a way I can store off the value of $item_received so that I have it available the next time through the php code? Then I could at least detect duplicate content. (I don't really follow as far as killing session variables)

As far as why the program does not work on my own machine, I will have to look further for the answer.

G

Spookster
07-25-2002, 08:34 PM
I guess the question would have to be is there a way to clear the server variable:

$HTTP_POST_VARS['Item'];

at the end of the program.

I'd have to research that one. Unless firepages knows of any way off the top of his head. He's the PHP God. :) I'm just a servant. lol

Spookster
07-25-2002, 08:53 PM
I can't test this right now as I am at work but try this:

unset($HTTP_POST_VARS["submit"]);

at the end of the program.

I have a feeling though that it will get set again as the page is refreshed but can't hurt to try.

well actually now that I think about it the way it get's set is when they click the submit button so maybe this will work?

gorilla1
07-25-2002, 09:03 PM
Spookster,

flock a nice feature... I saw this: unset($GLOBALS['_SESSION']['foo_var']);

in the discussion here on unsetting a session variable within a function:

http://www.php.net/manual/en/function.unset.php

G

gorilla1
07-25-2002, 09:09 PM
Well, I tried it as you wrote it: unset($HTTP_POST_VARS["submit"]);

and no luck.

G

gorilla1
07-26-2002, 03:07 AM
I installed the firepages php4 on my two w98 systems last night. On both the program writes to the file, but the file is empty. All other programs I have tried run fine. I wonder if you guys are running an older installation of php4?

G

Spookster
07-26-2002, 08:27 AM
Im running firepages phpdev4 with php4.06

Ok ive tried a dozen different approaches with no success. Here are a couple of more methods. One of them dealing with sessions which firepages suggested:

http://www.devnetwork.net/forums/viewtopic.php?t=1410&highlight=httppostvars+clear

The seond method suggested regards pulling the data from the file in using the file() method then reversing it and checking the first line and compare it with the data being submitted and if they are equal then a refresh occurred. Of course that is assuming the next user that comes along doesn't submit the same exact item then that method would fail.

I am completely out of ideas. You stumped us. Are you happy now? Now get out of my forum

:D

firepages
07-26-2002, 10:03 AM
I added a session to the example here -

http://www.firepages.com.au/test/f_test.php

you cant repost (or refresh) until you have 'killed' the session, but thats a pain I know - so the second example that Spooks pointed out may be a plan ??, in extreeme cases er CC info etc you can use the session to enforce no further repayments for a set abount of time - say 5 minutes or so before the session expires??

gorilla1
07-26-2002, 04:10 PM
Now get out of my forum
Hehehe... OK, I guess I will try the compare with prior record in file. Thanks for all the help, both of you.

G

Centaur
07-27-2002, 10:40 AM
There is an approach which is used in many forum engines. In fact, this very forum uses it. When the user posts a form, the form handler does not immediately show the result page. Instead, the user gets a &ldquo;Thanks for posting, you will soon be returned to the thread, click <a>here</a> if your browser does not redirect you&rdquo; page with a browser redirection meta:<META http-equiv="Refresh" content="0; URL=your-list-and-form">This way, dupe records will only appear if the user manages to refresh the redirection page.

firepages
07-27-2002, 10:57 AM
! - thats actually a very good point Centaur !

Spooks - you should have thought of that :)

gorilla1
07-27-2002, 01:06 PM
Good point. By the way, the compare with last record worked well..

G

Spookster
07-27-2002, 05:14 PM
Originally posted by firepages
Spooks - you should have thought of that :)

lol Now why didn't I think of that.

Actually didn't both of us mention that at some point in this unbearably long thread? :thumbsup:

gorilla1
07-27-2002, 09:57 PM
Lest this thread end prematurely, another question or two...

How does that page with the refresh get called? The form handler writes to the database or file, etc., etc., and then wants to throw up that page with the meta refresh and the message about what the poster should do. How is control passed to that piece of html?

And the second question: More generally, let's say I list out a bunch of items from a file and give the viewer the option to delete them. The viewer picks one and clicks on delete. My php handler gets control and displays that item alone along with a message, "are you sure you want to delete this", etc. What determines whether that display is on a new screen or how do you control this?

Er, one more elementary question....
Spookster used flock up there for the file handling. Does mySQL have that built in so that multiple users updating won't corrupt the database, or is there something one must do to handle multiple access possibilities?

G ;)

Spookster
07-27-2002, 10:37 PM
Ok im gonna start charging you per post. :D

Ok what you can do is in you main page with the form just put the coding in for reading the file.

In another php file you put the code for writing to the file and then either use php to load the main page again or you can throw some html in there and say

Adding Item please wait.....

and add a meta refresh tag that redirects back to the main page again.

I wrote something similar for someone in this thread:

http://www.codingforums.com/showthread.php?s=&threadid=2276

In that case the user entered a file name and it generates a html page and then redirects to that page.

In your case the user enters the item and it writes to the file and then redirects to the main page.


So now you want to delete items? Ackkkk. This would be much easier with a database.

Well you would need to search the file for that particular string and then delete it. If you are going to go through with this you might want to consider placing all these various operations into functions and maybe wrap it into a php class.


As for databases yes they have their own equivalent of file locking to prevent that.

gorilla1
07-28-2002, 12:28 AM
If you do barter, I can work in exchange..

Ah, I see. You don't transfer control really, you just output some html.

As for deleting, I don't think it's a problem as long as I make each record a formatted line in the file and i keep an index.
But yes, a database is easier.

Thanks.

G

yellowjacket
03-15-2005, 05:16 PM
I had some problems with this too.. so I had to become a member and share my solution.


$_SESSION['procUid'] = uniqid(); // this generates a random char seq.


//in your form do something like this.

<form...
<input type='hidden' name='procUid' value='".$_SESSION['procUid']."'>
...
</form>



//in you receiving page where you're processing the form info do something like this.


if ($_POST['procUid'] == $_SESSION['procUid']) {

// do all your processing here or call a method that does.

//once there's no error's regenerate the uid.
$_SESSION['procUid'] = uniqid();

//this will ensure that anyway the user comes here.. be double-click, refresh, or back button they won't process again
//even better is to have a unique ID for each page and store the current one in the session..
//so you know that only one page can ever be processed at that time... they can type in the URL with params and it still won't process.


}


Hope this helps
Mike