if(isset($_POST['submit']))
{
$file = $_FILES['file']['name'];
$fh = fopen($file,'r+');
// string to put username and passwords
$users = '';
while(!feof($fh)) {
$user = explode(' ',fgets($fh));
foreach ($user as $value)
{
$number= rand(1000,10000);
$final_number[] = $value .','. $number;
}
}
//print_r($final_number);
file_put_contents($_FILES['file']['name'], $final_number);
}
this is my code for appending a random text to a string with comma and save it in text file but when i am saving it it is not saving properly after comma it is going to next line which should not happen plzz.. help me
Your code starts with a very big issue: you try to open and read from a file that, most probably, doesn't exist.
$file = $_FILES['file']['name'];
$fh = fopen($file,'r+');
As you can read in the documentation, assuming that your form contains an input element of type file having the name file, $_FILES['file']['name'] is the original name of the uploaded file, on the user's computer. It is only the name and it is not the name of the file on the server. It is provided just as a hint for the file's content (check the filename extension) but you cannot rely on it.
The content of the file is temporarily stored on the webserver in a file whose path can be found in $_FILES['file']['tmp_name']. You should pass it to the PHP function is_uploaded_file() to be sure the file was uploaded and your script is not the victim of an injection attempt then, if you need to keep it, use move_uploaded_file() to move it where you need. If you don't move it, when your script ends the temporary file is deleted.
Another problem of your code is on the lines:
$user = explode(' ',fgets($fh));
foreach ($user as $value)
As explained in the documentation, the function fgets() called without a second argument reads a line from the input file, including the newline character that ends it. Since you split the line into words I think you don't need the newline character. You can remove it by using trim() with the string returned by fgets() before passing it to explode().
The last issue of the code is:
file_put_contents($_FILES['file']['name'], $final_number);
Because $final_number is an array1, file_put_contents() joins its elements to get a string and writes the string into file. This operation concatenates the random value generated for a $value with the next $value and there is no way to tell which is which after the data is stored in the file. You probably need to keep them on separate lines. Use function implode() on $final_number, with "\n" as its first argument and write the generated string into the file instead.
The last one: don't write the generated content to $_FILES['file']['name']. It is not safe! It contains a string received from the browser; a malicious user can put whatever path they want there and your script will overwrite a file that it shouldn't change.
Create a directory dedicated to store files generated by your code and generate filenames based on an always incremented counter (the current time() or microtime() f.e.) for the files you store there. Never trust the data you receive from the browser.
1 $final_number is used as $final_number[] = ... and, because it is not defined when this line of code is executed for the first time, PHP creates an empty array for you and stores it in $final_number. Don't rely on this feature. Always initialize your variables before their first use. Put $final_number = array(); before the while().
I am going to use a different approach than you, let's say that the data you want to save to the file is stored in the variable $data.
So to append this data to the file with a comma at first, we can use just two lines of code:
$previousFileContent = file_get_contents("filename.txt");
file_put_contents("filename.txt", trim($previousFileContent . "," . $data));
Related
I'm having a slight problem where I am using "openssl_encrypt" to encrypt a string of text that contains HTML, writing that string to a file, and then in a separate page, I am decrypting the entire file using "openssl_decrypt". I've made sure to use the same encryption key, same method, and same iv. I imagine this is something that, as a newbie to encryption, I just can't see. Thank you in advance for any help!
Here is some example code:
//An example of the string
$string = "<div class='mod'><div><span class='datetimestamp'>On 06/28/2016 at 04:32:09 PM, ** modified a record with id of \"5\" in the \"results\" table:</span><br><span class='record-label'>Prev Record:</span>jobnumber='none', dropdate='07/06/2016', eventdate='07/16/2016', dealership='ABC Nissan', pieces='3700', datatype='DB', letter='t'";
//The encryption
$encrypt = openssl_encrypt($string, 'AES-256-XTS', '93jkak3rzp72', 1, '45gh354687ls0349');
$file = fopen("logs/2016-06-28.log", 'a');
fwrite($file, $encrypt);
fclose($file);
//The decryption - DONE IN A SEPARATE PAGE
$file = #fopen("logs/2016-06-28.log", "r");
if ($file) {
while (($data = fgets($file)) !== false) {
$decrypt .= openssl_decrypt($data, 'AES-256-XTS', '93jkak3rzp72', 1, '45gh354687ls0349');
}
}
Perhaps the issue is that you are trying to append additional encrypted data, that will not generally work for several reasons, a major one being that AES is block based and there will most likely be padding. Many modes use some form of chaining and this will also fail when appending encrypted data.
You are opening the file you are writing to in append mode, that is not what you need, instead use write w mode. That is causing each encryption to be appended to the previous data and the reason the first tie works but subsequent times. If you examine the file length after each encryption it will be apparent what is happening.
You need to use:
$file = fopen("logs/2016-06-28.log", 'w');
From the php fopen docs:
'w' Open for writing only; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it.
'a' Open for writing only; place the file pointer at the end of the file. If the file does not exist, attempt to create it. In this mode, fseek() has no effect, writes are always appended.
I wouldn't use fgets() as it only gets a single line from a file at a time and you can't split up an encrypted string and decrypt single pieces at a time.
You could use fgets() but you need to read in everything and store it in an variable and then after you have everything decrypt.
Or you can simply use something like file_get_contents() to get the entire file's content and then decrypt.
I am trying to write a file in PHP. So far it works "kind of".
I have an array of names in the format {Rob, Kevin, Michael}. I use the line of code
foreach($Team as $user)
{
print_r($user);
//create a file for each user
$file = fopen("./employee_lists/".$user, 'w');
//I have also tried: fopen("employee_lists/$user", 'w');
// ... ... ...
//write some data to each file.
}
This works as expected: The print_r shows "Rob Kevin Michael", however, the filenames are saved are as follows: ROB~1, KEVIN~1, MICHAE~1
When I'm going on to use these files later in my code, and I want to relate the usernames of "Rob" to ROB~1, I'll have to take some extra step to do this. I feel like I'm using fopen incorrectly, but it does exactly what I want minus this little naming scheme issue.
It seems like your $user variable contains an invalid character for file system paths (my best guess would be a new line).
Try:
$file = fopen("./employee_lists/".trim($user), 'w');
You should sanitize $user before using it a as file name.
$pattern = '/(;|\||`|>|<|&|^|"|'."\n|\r|'".'|{|}|[|]|\)|\()/i';
// no piping, passing possible environment variables ($),
// seperate commands, nested execution, file redirection,
// background processing, special commands (backspace, etc.), quotes
// newlines, or some other special characters
$user= preg_replace($pattern, '', $user);
$user= '"'.preg_replace('/\$/', '\\\$', $user).'"'; //make sure this is only interpreted as ONE argument
By the way, it's a bad idea using an user name for a file name. It's better to use a numeric id.
Can someone suggest a complex algorithm in php to name files that would be uploaded so that it never repeats? i wonder how youtube which has millions of videos does it??
Right now i use an random number and get its 16 character sha1 hash and name the file with that name but i'm pretty sure it will eventually repeat and generate an error as file will not be able to save in the file system.
something like:
$name = sha1(substr(sha1(md5($randomnumber)),0,10));
somebody once told me that its impossible to break the hash generated by this code or at least it'll take 100 years to break it.
you could do:
$uniq = md5(uniqid(rand(), true));
You could also apped user id of users uploading the file, like:
$uniq = $user_id_of_uploader."_".md5(uniqid(rand(), true));
Generate a GUID (sometimes called UUID) using a pre-existing implementation. GUIDs are unique per computer, timestamp, GUID generated during that timestamp and so on, so they will never repeat.
If making a GUID isn't available, using sha1 on the entire input and using the entire output of it is second best.
$name = 'filename'.$user_id(if_available).md5(microtime(true)).'extension';
Try to remove special characters and white spaces from the file name.
If you are saving name in database then a recursive function can be helpful.
Do below with proper methods.
First slice its extension and filename
Now Trim the filename
Change multiple Space into single space
Replace special character and whitespace into to _
Prefix with current timestamp using strtotime and salt using md5(uniqid(rand(), true)) separated by _ (Thanks to #Sudhir )
Suffix with a special signature using str_pad and limit the text length of a file
Now again add extension and formatted file name
hope it make sense.
Thanks
I usually just generate a string for the filename (implementation is not incredibly important), then check if a file already exists with that name. If so, append a counter to it. If you somehow have a lot of files with the same base filename, this could be inefficient, but assuming your string is unique enough, it shouldn't happen very often. There's also the overhead of checking that the file exists.
$base_name = generate_some_random_string(); // use whatever method you like
$extension = '.jpg'; // Change as necessary
$file_name = $base_name . $extension;
$i = 0;
while (file_exists($file_name)) {
$file_name = $base_name . $i++ . $extension;
}
/* insert code to save the file as $file_name */
I'm at a loss as to how I could build a loop to pdftotext and entire directory through a shell_exec() statement.
Something like :
$pdfs = glob("*.pdf");
foreach($pdfs as $pdfs) {
shell_exec('pdftotext '.$pdfs.' '.$pdfs'.txt');
}
But I'm unsure how I can drop the .pdf extension the 2nd time I call $pdfs in my shell_exec() statement and replace that with .txt
Not really sure this loop is correct either....
Try
foreach(glob("*.pdf") as $src) {
// Manually remove file extension because glob() may return a dir path component
$parts = explode('.', $src);
$parts[count($parts) - 1] = 'txt';
$dest = implode('.', $parts);
// Escape shell arguments, just in case
shell_exec('pdftotext '.escapeshellarg($src).' '.escapeshellarg($dest));
}
Basically, loop the PDF files in the directory and execute the command for each one, using just the name component of the file name (extracted with pathinfo())see edit for the output file (so test.pdf becomes test.txt).
Using the result of glob() directly in foreach easily avoids the variable naming collision you had in the code above.
EDIT
I have change the above code to manually remove the file extension when generating the output file name. This is because glob() may return a directory component of the path strings, as well as just a file name. Using pathinfo() or basename() will strip this off, and since we know that a . will be present in the file name (the rule passed to glob() dictates this) we can safely remove everything after the last one. I have also added escapeshellarg() for good measure - it is highly unlikely (if not impossible) that a file name that already exists would fall foul of this, but it is best to be safe.
$pdfs = glob("*.pdf");
$fmt='/path/to/pdftotext "%s" "%s.txt"';
foreach($pdfs as $thispdf) {
shell_exec(sprintf($fmt, $thispdf, basename($thispdf, ".pdf")));
}
Would appreciate some assistance
i have a txt file witht he following contents:
1234|dog|apartment|two
1234|cat|apartment|one
1234|dog|house|two
1234|dog|apartment|three
I want to delete the entry where the animal is "dog" living in an "house"
<?php
if (isset($_POST['delete_entry]))
{
//identifies the file
$file = "db.txt";
//opens the file to read
#$fpo = fopen($file, 'r');
//while we have not reached the end of the file
while(!feof($fpo))
{
//read each line of the file into an array called animal
$animal[] = fgets($fpo);
}
//close the file
fclose($fpo);
//iterate through the array
foreach ($animal as $a)
{
if the string contains dog and apartment
if ((stripos ($a, 'dog']))&&(stripos ($a, 'house')))
{
//dont do anything
}
else
{
//otherwise print out the string
echo $a.'<br/>';
}
}
}
?>
This successfully prints out the array without the entry where 'dog' and 'house' appears.
I need to write this back to the flat file though, but running into difficulties.
I have tried a variety of options include writting back to the file immediately when each entry is found.
Warning: feof() expects parameter 1 to be resource, boolean given in
Warning: fwrite(): 9 is not a valid stream resource in
Warning: fclose(): 9 is not a valid stream resource in
These are amongst the errors i have encountered. Now from my understanding of arrays,
- when i go through this array called animal,
- it checks index [0] for the two conditions and
- if the entry is not found, it assigns to to $a.
- It then goes through the array starting at index [1],
- and so forth.
Each time the new value is assigned to $a.
I thought that printing it to file each time it appears might work, but this is where i get the fwrite and fclose errors above, and no idea how to resolve this (yet).
I still have to do the bit where i need to replace 'apartment' with house, for one specifically selected entry, but will get there once I have sorted out the "delete"
I dont need code, maybe just a logic flow that might assist me.
Thanks
To save some time, you could store your data in array only if it passes your validation rules when it's being read from file, and after reading the end of file, you'd have array ready for writing it back to file.
How about this for steps:
Read the file.
Store File contents in array.
Remove item from array.
Overwrite the file with new contents.
What you can do is opening the source file in read mode and a temporary file in write mode. As you read content from the "in" file, you write lines to the "out" file. When the "in" file is processed and closed, you rename "out" to "in". This way you need to worry less about memory constraints.
When processing each line, it's better if you split on '|', so you know that the second element contains an animal name and the third element contains a housing name. Who knows if a cat is living in a doghouse.
<?php
$fileName = 'db.txt';
$data = #file($fileName);
$id = 0;
$animal = "";
$type = "";
$number = 0;
$excludeAnimal = array("dog");
$excludeHouseType = array("house");
foreach($data as $row) {
list($id,$animal,$type,$number) = explode("|",$row);
if(in_array($animal,$excludeAnimal) && in_array($type,$excludeHouseType))
continue
/* ... code ... */
}
?>
Although this doesn't answer your original question, I'd like to share what I've come up with.
I'm pretty sure this will do your entire script in three lines:
$file = file_get_contents( 'db.txt');
$result = preg_replace('/^\d+\|dog\|house\|\w+$/m', '', $file);
file_put_contents( 'db.txt', $result);
It uses a regex to replace the lines with dog|house, then writes the file back.
Read and dump all data until the one you want deleted into $array_1.
Read and dump rest of file into $array_2.
Concatenate 2 arrays in a $newarray, rewrite to original flatfile.
Simple!