This question already has an answer here:
Save input data in text file [closed]
(1 answer)
Closed 7 years ago.
I've got this login code (I'm conscious it is really unsafe).
How could I store multiple passwords in a .txt file?
<?php
$passwords = file('pass.txt');
# Check for session timeout, else initiliaze time
session_start();
if (isset($_SESSION['timeout'])) {
if ($_SESSION['timeout'] + 10 < time()) {
session_destroy(); } }
else {
$_SESSION['pass']="" ; $_SESSION['timeout']=time(); }
# Store POST data in session variables
if (isset($_POST["pass"])) {
$_SESSION['pass']=hash('sha256',$_POST['pass']) ; }
# Check Login Data. Password is hashed (SHA256). In this case it is 'admin'.
$flag = 0;
foreach ($passwords as $pass) {
if ($pass == $_SESSION['pass']) {
$flag = 1;
}
}
if ($flag == 1) {
echo 'session';}
else {
echo'<form method="POST" action=""><input type="password" name="pass"></form>';}
?>
This is pass.txt, from which I want to read the passwords
65e84be33532fb784c48129675f9eff3a682b27168c0ea744b2cf58ee02337c5
5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
I will start with, yes - you are very correct that it's unsafe. Especially if the passwords are stored in a txt file accessible to the web.
I am guessing that the password doesn't have to match with a username, so you could simply store the passwords either in a plain txt file, or (for slightly more security) store them as an array in an included PHP file (which wouldn't be displayed as plain text if it's location is compromised).
For plain text, read the file into an array
$passwords = file('path/to/file.txt');
Or include the PHP file with the array (which for the sake of this example is stored in an array called $passwords.
Then set a flag and run through the array checking and replace the final condition with one that tests the flag.
$flag = 0;
foreach ($passwords as $pass) {
if ($pass == $_SESSION['pass']) {
$flag = 1;
}
}
if ($flag == 1) {
echo 'session';}
else {
echo'<form method="POST" action=""><input type="password" name="pass"></form>';}
I personally not recommend you to store password in .txt , but still i may help you .. You want to store multiple passwords using file handling you can do this using json functions ..
function writeToFile($filename, $msg)
{
$msgArray=array();
if(file_exists($filename))
{
$arrMsg=json_decode(file_get_contents($filename),true);
foreach ($arrMsg as $ob)
{
array_push($msgArray,$ob);
}
unlink($filename);
}
array_push($msgArray,$msg);
$msgArrayJSON=json_encode($msgArray);
// open file
$fd = fopen($filename, "a");
// write string
fwrite($fd, $msgArrayJSON. PHP_EOL);
// close file
fclose($fd);
}
And by using the above function you may add user like
writeToFile('user.json', array("username"=>$id,"password"=>$name));
Finally , you could get users from file as below
$user_array=json_decode(file_get_contents('user.json'),true);
You can use the PHP functions fopen() and fwrite() like this:
<?php
/* the a is used to place the writer at the end of the file, w would place it
at the beginning of the file overwriting already stored data*/
$myfile = fopen("newfile.txt", "a") or die("Unable to open file!");
$txt = "My Mother\n";
fwrite($myfile, $txt);
// or direct input
fwrite($myfile, "My Sister\n");
fclose($myfile);
?>
Notice the \n to go to the next line in the text file.
Ofcourse a database would be the best way to go, but if you want to do it with text files I highly recommand you to still try to create some structure. Have a look at XML or JSON.
Related
I am attempting to create a login page for my website. I have it set up so the user can create an account and these credentials are saved to a csv, saved on my ftp. (All the HTML and CSS is functional) I would like the system to work as follows:
1. From login page the user enters their credentials.
2. The CSV is searched, when the email is found the inputted password is compared with the corresponding password in the CSV.
3. If they match then another page is opened/If they don't match an error is displayed.
Here is the CSV:
Test#gmail.com,password1
Test2#gmail.com.password2
Here is the php which writes to the CSV:
<?php
$filename = $_POST['filename'];
foreach($_POST as $name => $value)
{
IF ($value != "Submit" and $value !=$filename)
{
$messagedisplay = $messagedisplay . $name. ": " . $value . "<BR>";
$filedata = $filedata . $value . ",";
}
}
$filedata = rtrim($filedata,",");
$filedata = $filedata . PHP_EOL;
$fs = fopen($filename,a);
fwrite($fs,$filedata);
fclose($fs);
$messagedisplay = "Your account has been created, please return to the main website and login.";
print $messagedisplay;
?>
Any ideas on how I would check the CSV to see if a) the email exists in the CSV and b) check the passwords match, subsequently redirecting to another page. Thanks.
In your case you could slurp the csv into an array. Then it's as simple as iterating through the array until you find a match.
<?php
$credentials = [
['foo', 'jubblies'],
['bar', 'jangles']
];
$check_credentials = function($username, $password) use ($credentials) {
foreach($credentials as $credential)
if($credential[0] == $username && $credential[1] == $password)
return true;
return false;
};
var_dump($check_credentials('foo', 'jiblets'));
var_dump($check_credentials('foo', 'jubblies'));
var_dump($check_credentials('ace', 'detective'));
Output
boolean false
boolean true
boolean false
Reading your credentials from a csv file into an array (similar format as above) could be accomplished something like this:
function get_credentials_from_file($path) {
$fp = fopen($path, 'r');
while ($line = fgetcsv($fp)) {
$lines[] = $line;
}
fclose($fp);
return $lines;
}
$credentials = get_credentials_from_file('/tmp/file.csv');
See also fputcsv, for csv writing.
Take care when storing user data.
If you end up reading and writing from/to a csv or text file, you'll have to manage file locks etc. It could well be easier to use a database.
See: Php's password_hash and password_verify to avoid storing plain text passwords.
I am adding username and userid into a text file onload of a page as follows:
$.post("addusersonload.php", {userid:chatusrid,username:chatusrname}, function (data) {
});
addusersonload.php
$name = $_REQUEST['username'];
$usrid = $_REQUEST['userid'];
fwrite(fopen('addusersonload.txt', 'a'), "$usrid,$name\n");
I am getting the value in text field as follows:
UserA, 1
UserB, 2
UserA, 1
UserB, 2
I want to check the textfile that the same value exists or not before writing into it.so that the duplication will not occur!!
I guess a DB is the best option for what you need, but, if you really need to write to a file, you can use:
if(!empty($_POST['username']) and !empty($_POST['userid'])){
$log_file = "sum_file.txt";
$logContent = file_get_contents("sum_file.txt");
$user = $_POST['username'];
$userId = $_POST['userid'];
if (!preg_match("/($user),\\s+($userId)\$/m", $logContent)) {
file_put_contents($log_file, "$user, $userId", FILE_APPEND);
}
}
I personally recommend you to use db , but still i may help you .. You should use json for this
function writeToFile($filename, $msg)
{
$msgArray=array();
if(file_exists($filename))
{
$arrMsg=json_decode(file_get_contents($filename),true);
if($msg['userId']==$arrmsg['userId'])
die('already there'); //checking done
foreach ($arrMsg as $ob)
{
array_push($msgArray,$ob);
}
unlink($filename);
}
array_push($msgArray,$msg);
$msgArrayJSON=json_encode($msgArray);
// open file
$fd = fopen($filename, "a");
// write string
fwrite($fd, $msgArrayJSON. PHP_EOL);
// close file
fclose($fd);
}
And by using the above function you may add user like
writeToFile('user.json', array("userId"=>$id,"userName"=>$name));
Finally , you could get users from file as below
$user_array=json_decode(file_get_contents('user.json'),true);
quick question. I setup a timecard and PO system for a family business. The employees enter their username and password to enter the system. Every time the family hired someone though they send me the info. I use htpasswd generator, and open the file up, add it, and then re-upload use ftp. My wife enter's their info into the db using a php page i setup though and i'm wondering if there is a way to allow her a txt field that can she can copy and past the generated pw into the htpasswd file. Without having me to always change it.
To summarize: is there a form command that when i put in the txt field and push submit it automatically puts the txt into the htpasswd file
You'll need to create a php page. This answer has an example of the code you need:
$username = $_POST['user'];
$password = $_POST['pass'];
$new_username = $_POST['newuser'];
$new_password = $_POST['newpass'];
$action = $_POST['action'];
//read the file into an array
$lines = explode("\n", file_get_contents('.htpasswd'));
//read the array and change the data if found
$new_file = "";
foreach($lines as $line)
{
$line = preg_replace('/\s+/','',$line); // remove spaces
if ($line) {
list($user, $pass) = split(":", $line, 2);
if ($user == $username) {
if ($action == "password") {
$new_file .= $user.':'.$new_password."\n";
} else {
$new_file .= $new_username.':'.$pass."\n";
}
} else {
$new_file .= $user.':'.$pass."\n";
}
}
}
//save the information
$f=fopen(".htpasswd","w") or die("couldn't open the file");
fwrite($f,$new_file);
fclose($f);
Here is also a slightly more complete solution. Or just look it up on Google.
My telecom vendor is sending me a report each time a message goes out. I have written a very simple PHP script that receive values via HTTP GET. Using fwrite I write the query parameter to a CSV file.The filename is report.csv with the current date as a prefix.
Here is the code :
<?php
error_reporting(E_ALL ^ E_NOTICE);
date_default_timezone_set('America/New_York');
//setting a the CSV File
$fileDate = date("m-d-Y") ;
$filename = $fileDate."_Report.csv";
$directory = "./csv_archive/";
//Creating handle
$handle = fopen($filename, "a");
//These are the main data field
$item1 = $_GET['item1'];
$item2 = $_GET['item2'];
$item3 = $_GET['item3'];
$mydate = date("Y-m-d H:i:s") ;
$pass = $_GET['pass'];
//testing the pass
if (isset($_GET['pass']) AND $_GET['pass'] == "password")
{
echo 'Login successful';
// just making sure the function could write to it
if (!$handle = fopen($directory.$filename, 'a')){
echo "Cannot open file ($filename)";
exit;
}
//writing the data I receive through query string
if (fwrite($handle, "$item1,$item2,$item3,$mydate \n") === FALSE) {
echo "Cannot write to file ($filename)";
exit;
}
fclose($handle);
}
else{
echo 'Login Failure please add the right pass to URL';
}
?>
The script does what I want, but the only problem is inconsistency, meaning that a good portion of the records are missing (about half the report). When I log to my account I can get the complete report.
I have no clue of what I need to do to fix this, please advice.
I have a couple of suggestions for this script.
To address Andrew Rhyne's suggestion, change your code that reads from each $GET variable to:
$item1 = (isset($_GET['item1']) && $_GET['item1']) ? $_GET['item1'] : 'empty';
This will tell you if all your fields are being populated.
I suspect you problem is something else. It sounds like you are getting a seperate request for each record that you want to save. Perhaps some of these requests are happening to close together and are messing up each other's ability to open and write to the file. To check if this is happening, you might try using the following code check if you opened the file correctly. (Note that your first use of 'fopen' in your script does nothing, because you are overwriting $handle with your second use of 'fopen', it is also opening the wrong file...)
if (!$handle = fopen($directory.$filename, 'a')){
$handle = fopen($directory.date("Y-m-d H:i:s:u").'_Record_Error.txt', 'a');
exit;
}
This will make sure that you don't ever lose data because of concurrent write attempts. If you find that this is indeed you issue, you can delay subsequent write attempts until the file is not busy.
$tries = 0;
while ($tries < 50 && !$handle = fopen($directory.$filename, 'a')){
sleep(.5);//wait half a second
$tries++;
}
if($handle){
flock($handle);//lock the file to prevent other requests from opening the file until you are done.
} else {
$handle = fopen($directory.date("Y-m-d H:i:s:u").'_Record_Error.txt', 'a');//the 'u' is for milliseconds
exit;
}
This will spend 25 seconds, trying to open the file once every half second and will still output your record to a unique file every time you are still unable to open the file to write to. You can then safely fwrite() and fclose() $handle as you were.
Is there any alternative to file_get_contents that would create the file if it did not exist. I am basically looking for a one line command. I am using it to count download stats for a program. I use this PHP code in the pre-download page:
Download #: <?php $hits = file_get_contents("downloads.txt"); echo $hits; ?>
and then in the download page, I have this.
<?php
function countdownload($filename) {
if (file_exists($filename)) {
$count = file_get_contents($filename);
$handle = fopen($filename, "w") or die("can't open file");
$count = $count + 1;
} else {
$handle = fopen($filename, "w") or die("can't open file");
$count = 0;
}
fwrite($handle, $count);
fclose($handle);
}
$DownloadName = 'SRO.exe';
$Version = '1';
$NameVersion = $DownloadName . $Version;
$Cookie = isset($_COOKIE[str_replace('.', '_', $NameVersion)]);
if (!$Cookie) {
countdownload("unqiue_downloads.txt");
countdownload("unique_total_downloads.txt");
} else {
countdownload("downloads.txt");
countdownload("total_download.txt");
}
echo '<META HTTP-EQUIV=Refresh CONTENT="0; URL='.$DownloadName.'" />';
?>
Naturally though, the user accesses the pre-download page first, so its not created yet. I do not want to add any functions to the pre download page, i want it to be plain and simple and not alot of adding/changing.
Edit:
Something like this would work, but its not working for me?
$count = (file_exists($filename))? file_get_contents($filename) : 0; echo $count;
Download #: <?php
$hits = '';
$filename = "downloads.txt";
if (file_exists($filename)) {
$hits = file_get_contents($filename);
} else {
file_put_contents($filename, '');
}
echo $hits;
?>
you can also use fopen() with 'w+' mode:
Download #: <?php
$hits = 0;
$filename = "downloads.txt";
$h = fopen($filename,'w+');
if (file_exists($filename)) {
$hits = intval(fread($h, filesize($filename)));
}
fclose($h);
echo $hits;
?>
Type juggling like this can lead to crazy, unforeseen problems later. to turn a string to an integer, you can just add the integer 0 to any string.
For example:
$f = file_get_contents('file.php');
$f = $f + 0;
echo is_int($f); //will return 1 for true
however, i second the use of a database instead of a text file for this. there's a few ways to go about it. one way is to insert a unique string into a table called 'download_count' every time someone downloads the file. the query is as easy as "insert into download_count $randomValue" - make sure the index is unique. then, just count the number of rows in this table when you need the count. the number of rows is the download count. and you have a real integer instead of a string pretending to be an integer. or make a field in your 'download file' table that has a download count integer. each file should be in a database with an id anyway. when someone downloads the file, pull that number from the database in your download function, put it into a variable, increment, update table and show it on the client however you want. use PHP with jQuery Ajax to update it asynchronously to make it cool.
i would still use php and jquery.load(file.php) if you insist on using a text file. that way, you can use your text file for storing any kind of data and just load the specific part of the text file using context selectors. the file.php accepts the $_GET request, loads the right portion of the file and reads the number stored in the file. it then increments the number stored in the file, updates the file and sends data back to the client to be displayed any way you want. for example, you can have a div in your text file with an id set to 'downloadcount' and a div with an id for any other data you want to store in this file. when you load file.php, you just send div#download_count along with the filename and it will only load the value stored in that div. this is a killer way to use php and jquery for cool and easy Ajax/data driven apps. not to turn this into a jquery thread, but this is as simple as it gets.
You can use more concise equivalent yours function countdownload:
function countdownload($filename) {
if (file_exists($filename)) {
file_put_contents($filename, 0);
} else {
file_put_contents($filename, file_get_contents($filename) + 1);
}
}