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.
Related
My code of file.php:
<?php
if(!isset($_GET['filename']) OR $_GET['filename'] == NULL) {
print("Error!");
exit();
}
$_GET['filename'] = htmlentities($_GET['filename'], ENT_QUOTES, "utf-8");
session_start();
include_once("/var/www/html/get.php");
for($i = 0; $i < $GLOBALS['files']['ile']; $i++) {
if($GLOBALS['files'][$i]['name'] == $_GET['filename']) {
if($GLOBALS['files'][$i]['priv'] == NULL OR $GLOBALS['files'][$i]['owner'] == $_SESSION['id'] OR (isset($_SESSION['privs']) AND in_array($GLOBALS['files'][$i]['priv'], $_SESSION['privs']))) {
if(file_exists($GLOBALS['files'][$i]['loc'])) {
header("Content-length: ".filesize($GLOBALS['files'][$i]['loc']));
header("Content-type: ".mime_content_type($GLOBALS['files'][$i]['loc']));
readfile($GLOBALS['files'][$i]['loc']);
} else {
print("Can't find that file!");
}
}
}
}
?>
In get.php file, I loads (from database) information about files I wanted to have access using that file above in site.
$_SESSION['privs'] //it's an array that holds privileges, i.e: site.priv.mess
$GLOBALS['files'] //holds info about all files that user can load, i.e: $GLOBALS['files'][0]['name'] is a name of first file in array
$GLOBALS['files'][0]['loc'] //holds info about first file localisation
$GLOBALS['files']['ile'] // holds sizeof($GLOBALS['files'])
With pictures that works well, but if I try to load larger file, i.e. video that weights 300MB, then file loads, all looks good, but if I reloads site, it won't work anymore...
I tried to delete my cookies in browser (to change my session ID) and it works... But what can I do to make it works better?
EDIT: On Firefox all looks good, only freezes on Chrome :(
EDIT2: Closing session with: session_write_close(); before reading file fixed my curse :P Thanks y'all
Check your php.ini or use phpinfo() to check your values for upload_max_filesize, post_max_size and memory_limit. Maybe also check the max execution time of the php script.
I need to send unit ID from Arduino's to web using the form:
http://somdomain.com/path/phpscript.php?ID=5
the arduino code is a slam dunk but i need help with the PHP script to accept the server side data and to save the ID number only to a text file named id_file.txt for later parsing.
there are 20 units and i need 1 ID number/line
I'm lost to even the structure of the file.
Please Help if possible.
Make Arduino Invoke a page like
http://somdomain.com/path/phpscript.php?ID=5
Then the phpscript.php will look like this
<?php
//first line just checks to see if ID is set and if so it'll run the script. This stops the script from running if ID isn't set and someone just randomly comes to the webpage
if (isset($_GET['ID'])) {
$id = $_GET['ID'] . "\n"; //I added \n to denote a new line so when you write to this file it'll just append the ID's there
$myfile = fopen("newfile.txt", "w") or die("Unable to open file!");
fwrite($myfile, $id); //the second parameter is whatever you want to write to that file
fclose($myfile);
}
If you wanted to write a new line to the same file that should work
You can use the following code to write to a file.
$filename='myfilename.txt';
if(isset($_GET['ID'])){
$id= $_GET['ID'];
if(is_numeric($id)){
if(file_put_contents($filename,$id,FILE_APPEND)!== FALSE){
echo "id successfully saved";
}else{
echo "there is a error saving your id";
}
}
}
later you can read from the file..
$filearray = file($filename,FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach($filearray as $id){
echo $id;// this print the id's
}
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.
Ok, so I have a form that takes a username and a code. This is then passed to php for processing. I am not super php saavy, so I want to be able to take a specific portion of the out put and write it to a text file, this form would be used over and over, and I want the text to be appended to the file. As you can see from the output I'm looking to capture, it's basically writing to some code that will be used for usernames in a css. So here is what I have...
The HTML Form
<html><body>
<h4>Codes Form</h4>
<form action="codes.php" method="post">
Username: <input name="Username" type="text" />
Usercode: <input name="Usercode" type="text" />
<input type="submit" value="Post It!" />
</form>
</body></html>
The PHP
--><html><body>
<?php
$Usercode = $_POST['Usercode'];
$Username = $_POST['Username'];
echo "You have recorded the following in our system ". $Username . " " . $Usercode . ".<br />";
echo "Thanks for contributing!";
echo .author[href$="/$Username"]:after {
echo content: "($Usercode)"
echo }
?>
</body></html>
All that I would like to be written to the text file would be this portion..
--> .author[href$="/$Username"]:after {
content: "($Usercode)"
}
Basically, the text file would have line after line of that exact same code, but with different usernames and usercodes. Hopefully, the variable $Usercode and $Username can also be captured and written into the output in the manner that I have it written. I'm just baffled by output buffering in php and clean and flush etc, and fwrite doesn't seem to be able to write without wiping a file clean each time it writes to it. I may be wrong of course. Anyone care to help?
Try this:
<?php
$output = "--> .author[href=$Username]:after { \n"
."content: ($Usercode)\n"
."}";
$fp = fopen($file, 'a');
fwrite($fp, $output);
fwrite($fp, "\n");
fclose($fp);
?>
The flag a will open already a text file and place the pointer to the end of file, so this will not overwrite your already file, more information in fopen.
You can use the function file_put_contents($file, $data, FILE_APPEND); where $file is the path of the file you are writing to, data is the whatever value you are writing to the file. This assumes you are using php5. If not, you will have to create a handle with fopen, write to the file with fwrite and end with fclose to close the file pointed to in your fopen handle.
I've created a form that is made up of 2 input fields and a wysiwyg text area (ckeditor). I have a function using ajax to gather the ckeditor data to be submitted. I have the form properly submitting to the database, but I also need it to write to a text file. How would I go about doing this?
Edit to include code:
using onclick to submit:
onclick=\"javascript:submitData()\"
ajax function:
function submitData(){
var params='';
if(document.getElementById('title').value!='' && document.getElementById('date').value!='' && CKEDITOR.instances.article.getData()!=''){
//build params
params='&title='+document.getElementById('title').value;
params+='&date='+document.getElementById('date').value;
params+='&article='+escape(CKEDITOR.instances.article.getData());
var httpRequest=new ajaxObject('form.php',processData);
httpRequest.update('id=submitData'+params);
}
submit to database, then try to submit to flat file:
$saving = $_REQUEST['saving'];
if ($saving == 1) {
$data = $formData['title'];
$data .= $formData['date'];
$data .= $formData['article'];
$file = "/txt/data.txt";
$fp = fopen($file, "a") or die("Couldn't open $file for writing!");
fwrite($fp, $data) or die("Couldn't write values to file!");
fclose($fp);
}
I suppose that, somewhere in your PHP script, there is something like
mysql_query("insert into your_table ... ");
that inserts to the database ?
Well, close to that line, you have to write to your file.
The simplest solution I can think about is to use file_put_contents :
file_put_contents('path to your file', $content);
If you just want to create a new file, or override an existing one ; and :
file_put_contents('path to your file', $content, FILE_APPEND);
If you want to add your text at the end of an existing file (and create the file if it doesn't exist).
Of course, you can also use a combinaison of fopen, flock, fwrite, and fclose ; but it means a bit more work ^^
I am staggering around like a blind man in the world of PHP,
but I have over come the problem your having, I am using flat files to store dynamic content of a website, html snippets edited in CKeditor and saved as text files, these are then included in each page of the website.
Here is what I have in the Page that contains the CKeditor form.
<? $contentv = $_GET["contentv"];?><head>
<script type="text/javascript" src="../ckeditor/ckeditor.js"></script>
<form action="1.php?contentv=<? echo $contentv?>" method="post">
<textarea rows="25" cols="70" name="content">
<?
$cext = ".txt";
$files ="../content/";
$fn = $files.$contentv.$cext;
print htmlspecialchars(implode("",file($fn)));
?>
</textarea>
<br>
</form>
<p>
<script type="text/javascript">
CKEDITOR.replace( 'content' );
</script>
<script type="text/javascript">
window.onload = function()
{
CKEDITOR.replace( 'content' );
};
</script>
<?php
$editor_data = $_POST[ 'content' ];
?>
<script type="text/javascript">
var editor_data = CKEDITOR.instances.conent.getData();
</script>
Save that as 1form.php and change the addresses to fit your needs or just create a folder called "content" in the same folder as this script and create a text file in that folder called 1.txt
Next you need a file to process the text and save it as a text file
<? $contentv = $_GET["contentv"];?>
<?
$cext = ".txt";
$fn = "./content/".$contentv.$cext;
$content = stripslashes($_POST['content']);
$fp = fopen($fn,"w") or die ("Error opening file in write mode!");
fputs($fp,$content);
fclose($fp) or die ("Error closing file!");
echo "<meta http-equiv=\"refresh\" content=\"0; url=./1form.php?contentv=$contentv\" />\n";
?>
Now save that as 1.php
Text files need to exist in the first instance, as mention before.
Check the path to where you store your files and edit code accordingly
This does use CKeditor so that needs to be on your server as well.
Then you can call the page like this,
http://yourserver.co.uk/1form.php?contentv=1
This way you can call lots of content with 1 form and one saving file.
I have elaborated to control all the content in this way, less strain on server time and makes for easier backup, means you don't need SQL, not that SQL's bad, just another option.
Easiest way would be to have the script invoked via ajax write the data to the text file as well as inserting into the db.
Here's what I would do. I'm going to make a few assumptions here about how you're handling the database portion, but you should be able to translate this into working code just fine.
<?php
$wysiwyg_data = $_POST["wysiwyg_data"];
// After you've sent stuff to the DB
$fh = fopen("my_data.txt", "wb");
fwrite($fh, $wysiwyg_date);
fclose($file_handler);
?>
Basically, here's what we're doing:
Grab the data from $_POST (or wherever you're getting it from after you've tossed it in the DB)
Open a text file ("my_data.txt") for writing. If it doesn't exist, it will be created. If you want to control where this file gets created, just pass in an absolute file path
Write the data to the file
Close the file
And your done.
As for the AJAX portion, you would simply pass your data to this script via the sendstring property with the name "wysiwyg_data".
I hope this helps.