Sorry for my bad English.
I must to check 2 csv files, if strings with one id is different, must write to file.
If there is no string with id from 1st file in second file, must write this to file too.
it works, but with element (id=47) i have got a trouble. it into to files, but script sad, that there is only in one.
download script you can from here
http://sil-design.ru/uploads/script.zip
If you do a echo $str1[0].' - '.$str2[0].'<br />'; you will see that the two 47's are never compared. Also I am not sure what the t is in: $f2 = fopen($fileurl, 'rt');.
If you open your backup.csv in notepad and place your cursor after the 47;XL and hold delete to delete anything after it and save. Then try your script again, it should work. It seems that the backup.csv was created in a weird way, I am guessing PHP is getting an EOF before the file has even ended!
Related
I want to delete a file by using PHP. I have used the unlink() function, but I was wondering about the security of unlink. Is the file completely deleted from the server? I want to make sure that there is no way to get the file back and the file is completely removed from the server.
open the file in binary mode for writing, write 1's over the entire file, close the file, and then unlink it. overwrites any data within the file so it cannot be recovered.
Personally i would say use 1's instead of 0's as 1's are actual data and will always write, where as 0's may not write, depending on several factors.
Edit: After some thought, and reading of comments, i would go with a hybrid approach, depending on "how deleted" you want the file to be, if you simply wish to make it so the data cannot be recovered, overwrite the entire files length with 1's as this is fast, and destroys the data, the problem with this, is it leaves a set length of uniform data on the disk which infers a file USED to be there and gives away the files length, giving vital pieces of forensic information. Simply writing random data will not avoid this also, as if all the drive sectors around this file are untouched, this will also leave a forensic trace.
The best solution factoring in forensic deletion, obfuscation and plausible deniability (again, this is overkill, but im adding it for the sake of adding it), overwrite the entire length of the file with 1's and then, for HALF the length of the file in bytes, write from mt_rand in random length sizes, from random starting points, leaving the impression that many files of varying lengths used to be in this area, thus creating a false trail. (again, this is completely overkill and is generally only needed by serial killers and the CIA, but im adding it for the sake of doing so).
the US government used to recommend a seven step wipe, for disks.
1) all '1's
2) all '0's
3) the pattern '01'
4) the pattern '10'
5) a random pattern
6) all '1'
7) a random pattern,
re the code sample, using a language like PHP is wrong for this type of wipe as your relaying on the OS really wipeing the file and not doing something cleaver like only wipeing it the last time or just unlinking it, however...
(untested)
$filename = "/usr/local/something.txt";
$size = filesize($filename);
$pat1 = chr(0);
$pat2 = chr(255);
$pat3 = chr(170);
$pat4 = chr(85);
$mask = str_repeat($pat1, $size);
file_put_contents($filename, $mask);
$mask = str_repeat($pat2, $size);
file_put_contents($filename, $mask);
$mask = str_repeat($pat3, $size);
file_put_contents($filename, $mask);
$mask = str_repeat($pat4, $size);
file_put_contents($filename, $mask);
This might not answer HOW to perfectly delete a file "with PHP", but it answers your question: "Is the file completely deleted from the server ?"
In some cases, No! (on UNIX/POSIX OS).
According to the highest voted comment on the offical PHP unlink() manual page, the unlink function does not really delete the file, it's deleting the system link to the file's content ! As files can have several files names (!) [symlinks?] the file will only be deleted when ALL file names are unlinked. So, if your file has 2 names, then unlink() will not really delete the file unless you unlink() both file names. Dear linux guys, please correct me here if necessary.
This might be why the function is called unLINK() and not delete() !!!
Here a full quote of the excellent comment:
Deleted a large file but seeing no increase in free space or decrease of disk usage? Using UNIX or other POSIX OS? The unlink() is not about removing file, it's about removing a file name. The manpage says: `unlink - delete a name and possibly the file it refers to''. Most of the time a file has just one name -- removing it will also remove (free, deallocate) thebody' of file (with one caveat, see below). That's the simple, usual case.
However, it's perfectly fine for a file to have several names (see the link() function), in the same or different directories. All the names will refer to the file body and keep it alive', so to say. Only when all the names are removed, the body of file actually is freed. The caveat: A file's body may *also* bekept alive' (still using diskspace) by a process holding the file open. The body will not be deallocated (will not free disk space) as long as the process holds it open. In fact, there's a fancy way of resurrecting a file removed by a mistake but still held open by a process...
Have a look on unlink()'s sister function link() here.
The (imo) best way to delete a file via PHP:
The way to go to really delete a file with PHP (in linux) is to use the exec() function, which executes real bash commands (doing things with linux bash feel correct btw). In this case, the file test.jpg would be deleted by doing:
exec("rm test.jpg);
More info on how to use rm (remove) correctly can be found for example here. Please note: PHP needs the right to delete the file!
UPDATE: Unfortunatly, the linux rm command ALSO does not really delete the file if it has two names/links. Look here for more info.
I'll have a deeper research on that and give feedback...
It is possible that because of some fragmentation on the disk some parts of file will stay, even if the file is totally overwritten.
The other way is to run (by shell_exec()) external program, that is system specific. Here is an example (for Windows), however I have not tested it.
You should do multiple passes of overwriting to deminish traces. For instance using the US DoD 5220-22.M : "Overwrite all addressable locations with a character, its complement, then a random character and verify" (from killdisk site)
Here's what the EFF recommends to permanently remove a file http://ssd.eff.org/tech/deletion.
In my embedded Ubuntu device, I use: echo exec('rm /usr/share/subdirectory/subdirectory/filename'); This works for me.
if you use rm -f (--force) then linux will
ignore nonexistent files and arguments, never prompt
rm -d will
remove empty directories
If you enter rm --help at the prompt you get the help screen. The last lines read:
Note that if you use rm to remove a file, it might be possible to recover some of its contents, given sufficient expertise and/or time. For greater assurance that the contents are truly unrecoverable, consider using shred.
Since my system is a "closed" system then I'm not concerned about violating security issues. My logic being that one must have the system password to SSH into the OS and the only user interface is via web pages.
#Sliq's comments are still true to date. You need to decide for your case.
If I use a local filename, the filename is properly copied, however, if you leave local filename empty, you are supposed to receive the content of the file.
Example code:
$stat = $sftp->get('xmlfile.cml','xmlfile.xml');
print "$stat";
(This works fine)
$xmlcontent = $sftp->get('cp1301080801_status.xml');
print "Content of file = $xmlcontent<>";
*(This prints what looks more like the stat of the file instead of the content. It starts with the date (which is the modofoed timestamp of file, followed by some numbers and the name of the web server repeated about 10 times with a number after it that increases each time - like maybe a port number or byte offset) *
It would make things easier if I didn't have to fopen the local file after the transfer. Anyone have an idea what is going on here?
Can you post a copy of the logs? Here's an example of how to get them:
http://phpseclib.sourceforge.net/ssh/examples.html#logging
Note the define() and the $ssh->getLog() stuff.
As for the specific problem you're having... what does print "$stat" do? It should print "1".
Also, fwiw, you're opening two different files in your example. My best guess, atm, is that you're thinking you're opening the same files and expecting the content to be the same when in fact they should be different and that what you're getting with both of the $sftp->get()'s is, in fact, correct.
The logs will tell us for sure.
I have big sql file, i need to change some lines there, now i have such data in my file
INSERT INTO `LINK_LA_TYP` VALUES
('1','8917181','1','24','2'),
('1','8934610','1','24','1'),
('1','9403766','1','30','1'),
('1','9422299','1','30','2'),
I done that, for example on $count line i write one more
INSERT INTO LINK_LA_TYP VALUES
but then my file looks like this:
INSERT INTO `LINK_LA_TYP` VALUES
('1','8917181','1','24','2'),
('1','8934610','1','24','1'),
('1','9403766','1','30','1'),
INSERT INTO `LINK_LA_TYP` VALUES
('1','9422299','1','30','2'),
But i need that previous line symbol , change to ; How i can do this in big file?
So i need to see file and write there line(done) and then change , to ; on previous line, and do this on every ~500 line (depends on counter) to the end of file
This is the simplest workflow:
Create a temporary file. Then:
Read one line at a time from the original file
Do your work on that line
Write the changed line to the temporary file
Repeat.
When you are done, simply rename the temp file to the correct filename, which will remove the old file.
If each line are going to be the exact same size as before, you may instead change the file inline. You can do this by aligning the file pointer correctly with fseek and then writing. This is a little bit trickier to achieve but may save you the space for the temp file (and possibly be a little bit faster as well). This is only possible if the resulting file size will be exactly the same as the original file size (e.g., if you only change certain bytes from one character to another).
If you read in the file stream (for example via fgets; see example there), you should count the lines and replace the comma with a semicolon on line X; and insert a new line at X + 1. No need to get a previous line.
Took some time to mock this together.
sed -i ':a;N;$!ba;s/,\n INSERT INTO/;\n INSERT INTO/g' your_file.sql
You can put this in exec() if you really want to run it from php script.
I'm planning to run a php program from Mac Terminal. I have a folder on my desktop with around 800 .csv files and I need to write a php program that reads through and reads each one so that I can run some transformations on the data it's storing. I know how to parse the .csv once it's loaded but I'm wondering if there is a way to load each file without having to name it explicitly? I don't have a list of the 800 file names but I feel like there has to be a way to just read in all the files in a folder in a loop or something without having the title of each file listed -- I don't have much coding experience, so forgive me if there's an obvious answer of which I'm oblivious.
Thank you!
There are a few way todo this but glob'ing is very straightforward:
<?php
foreach (glob("*.csv") as $filename) {
//do somthing
}
?>
You can loop through all files in a directory using readdir() :http://php.net/manual/en/function.readdir.php.
Once you get the file name using readdir() you can parse it by either breaking the file content into an array and working with the cells by looping through the array using str_getcsv() (requires at least phpv5.3) or the old fashion fgetcsv() to read through the file one line at a time. For each file create a string variable, and after line you read through and transform, simply append the modified line to this string with an end-of-line character appended as well. After reading through the entire file, simply replace the file contents of the original with file_put_contents()
I have a .txt file that includes a list of about 500 file names. I need to generate the actual files based on the list. I could use either CMD locally, or PHP. Which ever is best. Each file name is on a separate line within the .txt and there is no other punctuation or syntax. Let's say, for example, the .txt file is named colors.txt: and EACH LINE inside the text file contains a unique file name, like this:
red.php
blue.php
green.php
orange.php
yellow.php
magenta.php
light-yellow.php
purple.php
How would I go about actually turning these names in the list into files? And, better yet, is there a way to include content into the files as they are generated? For example, if I wanted to insert <?echo "hello world";?> automatically within each and every new .php file as it was being created, how could I? Thanks
NOTE: This is a batch-script for windows.
To create these files from your colors.txt list and add the echo line to each file, use the following FOR /F loop:
FOR /F "tokens=*" %%A IN (colors.txt) DO (
(ECHO ^<?echo "hello world";?^>)>"%%A"
)
Notice in the ECHO command you must escape the < and > characters with ^ to make them into a literal string or else the batch script will think they are redirection commands.
I'm not exactly sure what you're trying to do here. My gut tells me there may be a better way to solve the bigger picture problem you are dealing with. Nonetheless, you could try something like the following:
foreach (file('colors.txt') as $filename) {
file_put_contents($filename, '<?php echo "hello world";');
}
You would probably also want to do some sanity checking on the filenames to make sure they are safe to use.