how to delete files that not Exists show in db - php

i want write a code in php that
go to dir "upload" and see if is a file that dont Exists in my db
and remove this file if it find.
$like = scandir(upload);
$myFile1 = upload;
$myFile1 .= '/';
$myFile1 .= $like;
$rs = mysql_query('SELECT url from blog');
while(list($url) = mysql_fetch_row($rs))
{
if($like != $url){
unlink($myFile1);
}
}
its write me a eror
Warning: unlink(upload/Array) [function.unlink]:

scandir returns an array of files; you'll need to step through that array, to check each one individually:
$like = scandir('upload');
foreach ($like as $thisFile) {
$rs = mysql_query("SELECT url FROM blog WHERE url='$thisFile'");
if (! mysql_num_rows($rs)) {
if($thisFile != "." and $thisFile != ".."){
unlink ('upload/' . $thisFile);
}
}
}
You're checking each file in that directory to see if it has an entry in the blog table; if it doesn't, it's passed to unlink. I've not tested this code, but it should give you an idea about how it runs.
A couple of notes:
What if there are directories in the directory? You should add some checking to skip over them. Don't forget that you'll have ./ and ../ in there.
What if there's an entry in the blog of ..\..\..\..\etc\passwd? You should add some checking to make sure that $thisFile isn't something you don't want to delete.
This is using mysql; that's deprecated, and you should look at migrating to mysqli or PDO for the query. You can also then convert the query into a prepared statement, which will help it run more efficiently.

Related

Delete images from folder using php

I try to delete multiple images from folder and also from database, deleting from database is working fine, problem is with deleting from folder I'm using explode function because I have store multiple images inside one column in database. It just won't delete images from folder.
$query = "DELETE FROM table_gallery WHERE id = $deleteId";
$result = mysqli_query($con, $query);
while($row = mysqli_fetch_assoc($result)) {
$temp = explode(',',$row['images'] );
foreach($temp as $image){
$images[]="uploads/gallery/".trim( str_replace( array('[',']') ,"" ,$image ) );
}
foreach($images as $file) {
// Delete given images
unlink($images);
}
}
You have a few issues going on here,
1) Variable Confusion
The most notable is this:
foreach($images as $file) {
// Delete given images
unlink($images);
}
You are opening the array of $images and then dealing with each element in the array as a string reference ($file), but your unlink() command is calling the array, and you can't do that.
Unlink requires you to give it a filepath string. Not an array.
Fix:
foreach($images as $file) {
// Delete given images
unlink($file);
}
Better:
As an aside, if unlink($file); does not work, then you should check your filepath is correct. Remember the current PHP working directory is the directory the PHP script is in, so you should probably set your deleted image path to being the full server filepath such as:
unlink($_SERVER['DOCUMENT_ROOT']. $file);
To ensure you're certain of the file you're deleting.
foreach($images as $file) {
// Delete given images
// /serverfolder/accountfolder/public_html/uploads/gallery/imagename.jpg
unlink($_SERVER['DOCUMENT_ROOT'].$file);
}
2) Your Safety and Security:
Your variable $deleteId might be safe, but it might not. We can't tell from the code you show but you should be aware that if the $deleteId variable is, for example;
$deleteId = '1 OR id > 1';
// which generates:
$query = "DELETE FROM table_gallery WHERE id = 1 OR id > 1";
This is a security risk for your SQL and will delete all records on your database table (and folder). You should use Prepared Statements to ensure this doesn't ever happen.
3) Logic Confusion
you have a reference call mysqli_fetch_assoc but the DELETE SQL command will not return a result set, instead if it is successful it will simply return true.
Returns false on failure. For successful queries which produce a result set, such as SELECT, SHOW, DESCRIBE or EXPLAIN, mysqli_query() will return a mysqli_result object. For other successful queries, mysqli_query() will return true.
You need to structure your code somewhat differently, loading the images column value BEFORE you delete the row.
So, to restructure your code:
Check variables are safe.
load images column values
cycle through values and delete
Once deletion is confirmed then DELETE SQL.
For example:
$query = "SELECT images FROM table_gallery WHERE id = ".(int)$deleteId;
$result = mysqli_query($con, $query);
$abort = false;
while($row = mysqli_fetch_assoc($result)) {
$temp = explode(',',$row['images'] );
foreach($temp as $image){
$images[]="uploads/gallery/".trim( str_replace( array('[',']') ,"" ,$image ) );
}
foreach($images as $file) {
// Delete given images
if(!unlink($_SERVER['DOCUMENT_ROOT'].$file)){
// Delete failed so abort
$abort = true;
}
}
//
if(!$abort){
// all correct images on disk deleted ok so delete DB row
if(mysqli_query($con, "DELETE FROM table_gallery WHERE id = ".(int)$deleteId)){
// Yay deleted ok!
}
}
}
Closing thought:
You need to learn to read your PHP error logs which will spell out all the above.

Delete file if it's not in an array

I have a bunch of extra garbage uploads in a directory from when I was testing my app. The files I want to keep are in a table in my database. I want to delete a file in the directory if it's not in the table. Here is my attempt
<?php
$query = 'SELECT file_name FROM DummyFile';
$statement = $db->prepare($query);
$statement->execute();
$files_in_use = $statement->fetchAll();
$statement->closeCursor();
$path = getcwd();
$all_files_in_directory = scandir($path);
$all_files_in_directory = array_diff($all_files_in_directory, array('.', '..'));
foreach($all_files_in_directory as $file) {
if (!in_array($file, $files_in_use)) {
unlink($file);
}
}
?>
However this code deletes every single file in the directory regardless. Which means my conditional in the loop is evaluating to true every time when it shouldn't be. Please help
You're assuming $files_in_use is an array of filenames. It's not; it's an array of database rows, each being an array itself.
To get just the filenames you need:
$files_in_use = array_column($statement->fetchAll(), 'file_name');
The rest of your code should then work.

Download to root and after delete files from database

I have this function, and this deletes textfiles after a certain age from my database automatically.
$r = new textfiles;
$db = new DB;
$currTime_ori = $db->queryOneRow("SELECT NOW() as now");
...
if($this->site->textfilesretentiondays != 0)
{
echo "PostPrc : Deleting textfiles older than ".$this->site->textfilesretentiondays." days\n";
$result = $db->query(sprintf("select ID from textfiles where postdate < %s - interval %d day", $db->escapeString($currTime_ori["now"]), $this->site->textfilesretentiondays));
foreach ($result as $row)
$r->delete($row["ID"]);
}
Now I would edit this function so that at first all textfiles are automatically downloaded in a root directory /www/backup and then the script should delete the textfiles with the string $r->delete($row["ID"]);
At the moment I have no idea how I could implement this.
For me it's seems to be impossible to give you an completely answer to your question because leak of informations.
Do you store the whole file-content in database or only the path and filename?
It would help us to see whats the content of "$row" which represents one row from database.
If you just store the filename (and optionally the path) you could use the "copy" (http://php.net/manual/de/function.copy.php) function from php to copy the file to your backup-directory. Please note, you have to ensure that the user who's executing the script or running the web-server have the privileges to write into the directory.
You could add this functionality to class textfiles as as method like makeBackup.
There are few information, but I'll give it a try. If you want to backup the rows before deleting them, you can store them in .txt file in json_encoded form using this piece of code inserted in the FOREACH loop, before delete command:
$myfile = fopen("/www/backup/".$row["ID"].".txt", "w") or die("Unable to open file!");
$txt = json_encode($row);
fwrite($myfile, $txt);
fclose($myfile);
By your approach ..
function delete ($id){
$result = $db->query(sprintf("select * from textfiles where id=$id);
//if you have filepath use copy as SebTM suggested
$path = $row['path']; //assuming path is the column name in ur db
$filename = basename($path); //to get filename
$backup_location = '/www/backup/'.$filename;
copy($path, $backup_location);
//if you have data in db
$content = $row['data'] //assuming data to be backed up to file is in a field 'data'
$backup_location = '/www/backup/file.txt';
file_put_contents($backup_location, $content);
}
But this is not the most optimal approach , you could shift even the initial query into delete function above , and call delete function only once, instead of calling it in a loop ..

Running SQL scripts to PostgreSQL using PHP/PDO

I need to run some SQL scripts to my database, to update the schema and data (some kind of migration).
Because there is some logic to check before running each script, I'm writting a small PHP tool to execute the scripts, but I have a simple problem: Can I load and execute a "simple" SQL script (including table manipulation, triggers & stored procedures updates) directly, or should I add markers to the script (to mark where each sentence ends), and run the script sentence by sentence?
For the database access I'm using the PDO.
I had a similar situation today.
My solution is extremely simple, but is just smart enough to allow for comments and statements that span multiple lines.
// open script file
$scriptfile = fopen($script_path, "r");
if (!$scriptfile) { die("ERROR: Couldn't open {$scriptfile}.\n"); }
// grab each line of file, skipping comments and blank lines
$script = '';
while (($line = fgets($scriptfile)) !== false) {
$line = trim($line);
if(preg_match("/^#|^--|^$/", $line)){ continue; }
$script .= $line;
}
// explode script by semicolon and run each statement
$statements = explode(';', $script);
foreach($statements as $sql){
if($sql === '') { continue; }
$query = $pdo->prepare($sql);
$query->execute();
if($query->errorCode() !== '00000'){ die("ERROR: SQL error code: ".$query->errorCode()."\n"); }
}

Delete records from Mysql based on txt

I have a simple txt file with email addresses. I want to check if these addresses are in my database and if so: delete them.
The txt file is not in a csv format, but every email addresses is on a new line. I'm wondering whats the best way to do this.
Steps:
This regular expression will match a new line
([^\n]*\n+)+
Add a comma after every line (or replace the NEWLINE with comma) so the list will become from
email1#com.com
email2#com.com
email3#com.com
to email#com.com,email2#com.com,email3#com.com
Add brackets to the beggining and end:
(email#com.com,email2#com.com,email3#com.com)
Add the following sql:
DELETE FROM database.schema.table WHERE email_address IN (email#com.com,email2#com.com,email3#com.com);
Execute the SQL.
You can execute the query from php or directly in the database, keep backups please else you might screw up smth...
Hope this helps...
Good Luck
The function you're looking for is fgets().
<?php
$emails = array();
if( ! $fh = fopen('file.txt', 'r') ) { die('could not open file'); }
while( $buffer = fgets($fh, 4096) ) {
$emails[] = $buffer;
}
fclose($fh);
foreach($emails as $email) {
$query = sprintf("DELETE FROM table WHERE email LIKE '%s'", $email);
// do the query
}
<?php
$file = file("emails.txt");
foreach ($file as $email) {
$query = sprintf("DELETE FROM table WHERE email LIKE '%s'", $email);
# execute query
}
?>
Read the emails in one at a time and then run the delete query with the value. DO NOT USE mysql_query (unless you trust the input from text file, but even then just use the newer libraries please). If the records are there, they will be deleted, if not no biggie nothing happens. Done.

Categories