How to put a submission limit on a form with PHP - php

I'm trying to create a .php page that contains a form with a submission limit. I'm looking for these steps in order:
User arrives to form
User see's that form is still open
User submits info for form
Form adds +1 to a txt file that will +1 upon every form submission until the txt file reaches the number 10.
If the txt file equals the preset of 10 I would like the form to disappear and allow no more submissions.
I've tried using fopen, and making it work using $limit = fopen("count.txt", "r") but im so confused as to what needs to happen first. The code I'm using are snippets from other php codes I've written and found online. Normally I can figure out things like this as I know its most likely simple.
<?php
$limit = fopen("count.txt", "r") or die("Unable to open file!");
echo fread($myfile,filesize("count.txt"));
if ($limit = 10){
echo ("Cannot Submit Anymore");}
else{
echo ('<form>
First name:<br>
<input type="text" name="firstname"><br>
Last name:<br>
<input type="text" name="lastname">
</form>');}
fclose($myfile);
$limit = fopen('count.txt', 'c+');
flock($limit, LOCK_EX);
$count = (int)fread($limit, filesize('count.txt'));
ftruncate($limit, 0);
fseek($limit, 0);
fwrite($limit, $count + 1);
flock($limit, LOCK_UN);
fclose($limit);
?>
I'm completely stuck and not sure of the order in which everything needs to be to work.

Figured out what I needed to do, although I don't know if the code is compliant. Anyway, here is what I did:
5 Pages Total:
index.php [Landing Page]
tally.php [PHP code for updating the different txt files]
count.txt [How many seats purchased. In this case it had the number 0 typed into it]
left.txt [How many seats left. In this case it had the number 10 typed into it]
max.txt [How many seats im selling. In this case it had the number 10 typed into it]
index.php [Landing Page]:
<?php
$max = file_get_contents('max.txt');
$limit = file_get_contents('count.txt');
$left = file_get_contents('left.txt');
$maxed = 'Sorry, All Seats Have Been Sold';
if ($limit >= $max){
echo $maxed;}
else{
echo '
<form action="tally.php"> // This form can be edited to your needs
First name:<br><input type="text"><br>
Last name:<br><input type="text">
<input type="submit" value="Submit">
</form>' . 'Seats Remaining:' . $left;}
?>
tally.php [PHP code for updating the different txt files]:
<?php
$limit = fopen("count.txt", "c+");
flock($limit, LOCK_EX);
$count = (int)fread($limit, filesize("count.txt"));
ftruncate($limit, 0);
fseek($limit, 0);
fwrite($limit, $count + 1);
flock($limit, LOCK_UN);
fclose($limit);
$left = fopen("left.txt", "c+");
flock($left, LOCK_EX);
$remaining = (int)fread($left, filesize("left.txt"));
ftruncate($left, 0);
fseek($left, 0);
fwrite($left, $remaining - 1);
flock($left, LOCK_UN);
fclose($left);
header('Location: http://www.yoursite.com/'); // this links back to your submission form
exit;
?>
count.txt [How many seats purchased]:
0
left.txt [How many seats left]
10
max.txt [How many seats im selling]
10
Hope this helps someone in the future, this code throws up tons of error logs when ran on my server that I can see in the backend but it works for me and for what I need. If someone can improve upon this one day I and many others in the future would be very grateful.

Related

Counter stored in .txt file not incrementing

So I've just now edited the Code I've posted to make it much nicer to read...
This first block of code is my Counter Code used for the hits on a succesfull submition button. But for some reason the value of $Total will not increase by 1 even tho it was a succesfull submition.
<?php
$f = fopen('count.txt', 'r+'); // use 'r+' instead
$total = fgets ($f);
flock($f, LOCK_EX); // avoid race conditions with concurrent requests
$total = (int) fread($f, max(1, filesize('count.txt'))); // arg can't be 0
/*if someone has clicked submit*/
if (isset($_POST['submit'])) {
rewind($f); // move pointer to start of file so we overwrite instead of append
fwrite($f, ++$total);
}
fclose($f);
?>
And here is the submition button which I'm using to submit my form.
<input type="reset" value="Formular löschen" style="width:49%" />
<input type="submit" name="submit" value="Formular absenden" style="width:49%" />
Im trying to use this coed for my Club so that when the People submit the form they get the number as a refference Number also sent to them in the email sent.
I really hope thet there is a eays way of doing this without a DB.
Mark
If you want to see what i mean what the problem is, here is the page with the code impelemented.
First of all a couple of tips you may find useful when you are manipulating files:
You have to always check the files and folders permissions, just to make sure.
Be careful with multi-thread code, you may get really unexpected results when several threads are changing a file at the same time, so try to control that using locks, as you did.
I think you missed you <form> tag, so I had to invent my own one.
Use this code as a guide to make your own one:
<form method="post" action="test.php">
<input type="submit" name="submit" value="Submit" />
</form>
<?php
// Thread-safe <-- Use me
function incrementFile ($file){
$f = fopen($file, "r+") or die("Unable to open file!");
// We get the exclusive lock
if (flock($f, LOCK_EX)) {
$counter = (int) fgets ($f); // Gets the value of the counter
rewind($f); // Moves pointer to the beginning
fwrite($f, ++$counter); // Increments the variable and overwrites it
fclose($f); // Closes the file
flock($fp, LOCK_UN); // Unlocks the file for other uses
}
}
// NO Thread-safe
function incrementFileSimplified ($file){
$counter=file_get_contents('count.txt');
$counter++;
file_put_contents('count.txt', $counter);
}
// Catches the submit
if (isset($_POST['submit'])) {
incrementFile("count.txt");
}
?>
Hope this helps you! :)
This happens because you never set $total before writing it to the file.
You need to set $total by reading its value from the file, like this:
$total = fgets ($f) right after fopen function call.
However, you may have troubles with concurrency without exclusive file lock so you may lose some submissions count.

Form search save in file & display result

What is the most elegant and efficient way of search a string against injected script file in PHP.
The flow:
i want make form search when user input strings & click search, data searched save on txt/php file with auto create new file based on month & year ex: -201601.php / txt
then data was saved on safety query with serial key on each string
then if data on -201601.php contents have more than 1000+ query, the data old was deleted automatic
then how showing 50 strings based on random strings on -201601.php
then in -201601.php there are no double string or same string
If you have a solution for my issue and want to post an answer, please add some explanation so that I can understand why/how you did it so that I won't come asking the same questions all over again. Thanks
Im search & create file that i want making it with my plot imagination. Here is what I have so far manually :
<center>
<form action="./cari.php?q=" method="GET">
<input type="text" name="q" value="" placeholder=" Cari .." style="cursor: pointer;width:69%"/>
<input type="submit" value="Search"/>
</form>
</center><?php
if(isset($_GET['q'])) {
$data = ''.$_GET['q']."<br>\n";
$ret = file_put_contents('rcnt.php', htmlspecialchars($data), FILE_APPEND | LOCK_EX);
if($ret === false) {
die('There was an error writing this file');
}
else {
//echo "$ret bytes written to file";
}
}
//else {die('no post data to process');}
?>
Im stuck searching with cant find related tutorial & hope find answer :(
Please your help, i want learn more with this, i use XAMPP 5.6
First step, the ?q= var the browser will create, you don`t need to set this on your form action.
<form method="get">
<input type="text" name="q" placeholder="search">
</form>
The PHP code will be:
<?php
if(!empty($_GET["q"]))
{
$file = fopen(date("Ym") . ".txt","a+");
fwrite($file, $_GET["q"] . "\r\n"); //\r\n jump the line
flose($file);
}
?>
If today is the 1st search of the 1st day of the month, the file will not exists, then, the PHP will create it, otherwise, will open and write on it.
Hope it could help you.
We could try this way:
<?php
$theFile = date("Ym") . ".txt";
$myFile = file($theFile);
for($i = 0; $i < 100; $i++){ //deleting the first 100 lines
unset($myFile[$i]);
}
//rewriting the file without the 100st first lines
file_put_contents($theFile, implode($myFile));
?>

PHP - Stop while loop after reading every single line from text file

I want the Code below to read individual line of text from dataFile.txt and show it in input field.
Problem is After reading first line from text document it shows all remaining lines of text from text file into input field. But on clicking submit it should show second line only then again on submitting it should show third line only, inside input field. please help.
<?php
$file = __DIR__."/dataFile.txt";
$f = fopen($file, "r");
$array1 = array();
<form action="datagGet.php" method="get">
<input type="text" value="
<?php while ( $line = fgets($f, 100) )
{
$nl = mb_strtolower($line);
echo $nl;
if(isset($_GET['done']))
{
$nl++;
}
else
{
break;
}
}
?>"
name="someText">
<input type="submit" name="done" >
</form>
You have several problems with you code. And the first comment above points to many of the. Key is the fact that the $_GET['done'] is set for the form submit and therefore you will echo all the lines of the output. It never breaks.
Also there is the fact that you are opening the file for reading each submit of the form. Although I don't see a simple way around this unless you store the file contents between requests.
One possible option is to use 'file()' to read the entire contents into an array. And then use sessions to store which line has been read. Then on each submit, look for the index of the array from the session read; advance it by one read the file again and return that line. Wow wasteful. But okay for simple site.
so use file to get the lines in an array.
output the first line into the value.
store the next index to be read in the $_SESSION variable like $_SESSION['next_line'] = 1
then upon further submissions. read it all back in. look up the 'next_line', and output that line.
so, for example
$array = file('your file name');
$output = $array[0];
if (isset($_SESSION['next_line']))
$_SESSION['next_line'] = intval($_SESSION['next_line']) + 1;
else
$_SESSION['next_line'] = 1;//prime the pump
echo the form with $output
then rinse and repeat. e.g. read, get output (next_line) with file, set $_session = next_line + 1; render output in form.
ps. some extra notes
* of course you'll need to start session on each request.
* you'll need to check if the $_SESSION['next_line'] is set. if not, set it to 1 (prime it)

Simple Captcha in PHP with rand()

I'm trying to make a simple captcha in PHP, but it does not work. The query is not currently executing. This is my current code:
<?php
$Random = rand(1, 100);
$Random2 = rand(1,100);
echo "Result: ".$Random." + ".$Random2." ?";
?>
<input type="text" name="r_input"/><br />
$Cap = mysql_real_escape_string($_POST['r_input']);
$Result = $Random+$Random2;
if(isset($_POST['myButton']) and trim($Var) and trim($Var2) and trim($Var3) and $Cap==$Result){
//My Query
}
When you use rand() to generate 2 values, and show those 2 values, and give the form for the user to enter the answer, ...
... the user enters the answer and submits back to the server ...
... the server gets the answer, and then GENERATES 2 NEW VALUES, that don't correspond to the answer given by the user.
Try using session variables to store the generated values in, and match against when the user submits the form!
<?php
session_start();
$captcha_id = 'captcha_' . rand();
$_SESSION['$captcha_id']['val1'] = rand(1,1000);
$_SESSION['$captcha_id']['val2'] = rand(1,1000);
echo "
<form action='' method='post'>
<p>Result: {$_SESSION['$captcha_id']['val1']} + {$_SESSION['$captcha_id']['val2']} = </p>
<input type='hidden' name='captcha_id' value='{$captcha_id}' />
<input type='text' name='captcha_answer' />
<p>?</p>
</form>
";
if (
isset($_POST['captcha_id'])
&& isset($_SESSION[$_POST['captcha_id']])
&& isset($_POST['captcha_answer'])
&& $_SESSION[$_POST['captcha_id']]['val1'] + $_SESSION[$_POST['captcha_id']]['val2'] == intval($_POST['captcha_answer'])
) {
unset($_SESSION[$_POST['captcha_id']]); // don't let this answer be reused anymore.
// do allowed stuff
}
?>
Because $Random and $Random2 have a different value each time.
When you show the form for the first time, they may have the values $Random = 12 and $Random2 = 26. The User sees those, adds them up correctly and types in 38 (which is the correct answer for those two values). The answer is sent to the script again, the values of $Random and $Random2 are generated again (this time as $Random = 23 and $Random2 = 30 which equals 53) and the answer the user has sent is not correct any more.
So you would need to store those values in hidden fields and add these up, instead of the generated ones, like so:
<input type="hidden" name="rand_1" value="<?php echo $Random; ?>">
<input type="hidden" name="rand_2" value="<?php echo $Random2; ?>">
<?php
if ($_POST['rand_1'] + $_POST['rand_2'] == $_POST['r_input']) {
// Query etc.
EDIT: As suggested by #nl-x you should use the Session variables instead of hidden fields to prevent abuse of the captcha:
<?php
$Random = $_SESSION['rand_1'] = rand(1, 100);
$Random2 = $_SESSION['rand_2'] = rand(1,100);
echo "Result: ".$Random." + ".$Random2." ?";
?>
And check those values against the given result afterwards:
<?php
$Cap = mysql_real_escape_string($_POST['r_input']);
$Result = $_SESSION['rand_1'] + $_SESSION['rand_2'];
if ($Result == $Cap) {
// ...
You never re-enter PHP mode after you output your form field:
<input type="text" name="r_input"/><br />
<?php // <----this is missing
$Cap = mysql_real_escape_string($_POST['r_input']);
Pardon me, but you are not making a real captcha. The purpose of the captcha is to distinguish the human from the bots. I would highly suggest you to pick a image database, and randomize a function to call a image. Internally, i would check if the text/description of the image matches with what the user typed.
The only thing you will rand() is what image to load from your image database.
That's a not-healthy way to do it, and there are plenty of better ways to do this. But it's more closer to a captcha than just your current code.
There is also a lot of libraries and engines that can do the job for you.
I'm not a pro at PHP, or even programming at all, but i think you're going to the wrong side - your code won't block any... malicious actions at all, or whatever kind of action that you will try to prevent with the captcha.
Search google for the libraries. PhpCaptcha is one of them. And here is a very simple quickstart guide for phpcaptcha.
Here's a code example, extracted from PHPCaptch that I linked above.
At the desired position in your form, add the following code to display the CAPTCHA image:
<img id="captcha" src="/securimage/securimage_show.php" alt="CAPTCHA Image" />
Next, add the following HTML code to create a text input box:
<input type="text" name="captcha_code" size="10" maxlength="6" />
[ Different Image ]
On the very first line of the form processor, add the following code:
<?php session_start(); ?>
The following php code should be integrated into the script that processes your form and should be placed where error checking is done. It is recommended to place it after any error checking and only attempt to validate the captha code if no other form errors occured. It should also be within tags.
include_once $_SERVER['DOCUMENT_ROOT'] . '/securimage/securimage.php';
$securimage = new Securimage();
This includes the file that contains the Securimage source code and creates a new Securimage object that is responsible for creating, managing and validating captcha codes.
Next we will check to see if the code typed by the user was entered correctly.
if ($securimage->check($_POST['captcha_code']) == false) {
// the code was incorrect
// you should handle the error so that the form processor doesn't continue
// or you can use the following code if there is no validation or you do not know how
echo "The security code entered was incorrect.<br /><br />";
echo "Please go <a href='javascript:history.go(-1)'>back</a> and try again.";
exit;
}
Following the directions above should get Securimage working with minimal effort.
This code is included here as well.
Good luck!

Make checks for submit buttons

I encountered some problems, I want this script to:
Open test.txt file.
Check if user have added any text to the txt file.
If user have added any text, delete the existing line and replace it with the new. From $_POST.
If user have not, add $_POST in test.txt
Problem:
When I spam the submit button, the .txt will mess up. Anyone know how to make checks, so it does not mess up?
Please don't suggest MYSQL, I need these in .txt file.
Thanks.
function cutline($filename,$line_no=-1) {
$strip_return=FALSE;
$data=file($filename);
$pipe=fopen($filename,'w');
$size=count($data);
if($line_no==-1) $skip=$size-1;
else $skip=$line_no-1;
for($line=0;$line<$size;$line++)
if($line!=$skip)
fputs($pipe,$data[$line]);
else
$strip_return=TRUE;
return $strip_return;
}
if ($userid = 1) {
if(!isset($_POST['submit'])){
?>
<center><form action="" method="POST">
<b>HWID</b>
<input type="text" name="HWID" />
<input type="submit" value="Add HWID" name="submit">
</form>
</center>
<?php
}else{
$userid= 1;
$userid = "user=" . $userid;
$file = "test.txt";
$lines = file($file);
$count = 1;
foreach ($lines as $e) {
if(strpos($e, $userid) !== FALSE){
cutline($file,$count);
++$count;
}
}
$fh = fopen($file, 'a') or die("can't open file");
$stringData = $userid . $_POST['HWID'] . "\n";
fwrite($fh, $stringData);
}
}
}else{
echo "You're not logged in";
}
?>
I am not 100% sure how the text file is messing up, but I guess locking won't help here as locks are released when the script finished (or is reloaded).
It looks like you just "kill" your cutline while in progress and the remaining lines will not be written. One way to fix this could be to save the new content of the file in a temporary variable and call fwrite only once. (I am not 100% sure if this will work)
Another possibility is to write the results of cutline into a temporary file and replace the old file with the new one, when the cutline method is done. This can happen inside the method.
In either ways the existing file will not be touched if the script gets killed in an unsafe state. But you can still loose the new input from the user when he manages to reload the page right after the function call of cutline and before you add the new input in this line
fwrite($fh, $stringData);
I think this is really hard to force as this operation is quite fast.
EDIT:
Don't forget to test the script using multiple users at the same time, if this is a valid use case. If two or more guys are editing the same file at the same time it will mess up as well. So you might end up with some locking but that will not solve the problem described here.

Categories