Add php delete button to foreach upload statement - php

I am using a foreach php statement to list all of the uploaded files within a directory.
It looks like this:
<?php
$path = "$dir/";
foreach (glob("$path*") as $filename) {
$path_parts = pathinfo($filename);
$result = $path_parts['filename'];
echo "<li><a href='" . $filename ."'/>". $result . "</a></li><tr>";
}
?>
This prints out a nice simple list of all files.
What I would like to do for each item, is add a delete button next to it. I am thinking the only way to do this, would be to add a form into the foreach statement, with just a button that posts the $filename variable to some PHP with the delete function in.
The only thing I am uncertain of is if the best way to get the filename to the new php.
I am thinking along the lines of:
<?php
$path = "$dir/";
foreach (glob("$path*") as $filename) {
$path_parts = pathinfo($filename);
$result = $path_parts['filename'];
echo "<li><a href='" . $filename ."'/>". $result . "</a></li><tr>";
echo "<form method='post' action='delete.php'>
<button type='submit' name='submit' value='Submit' />
</form>";
}
?>
So using that, I can create a button next to the filename for deletion, but the only way I can think of taking the actualy filename through to the delete PHP file, is to add in a hidden text field with the filename as the value.
This would work but seems a bit clunky. Can anyone advise if this is acceptable or if there is a better alternative?

The addition of the filename/id/whatever to the form is not really that clunky .. it's more of a necessity unless you want javascript to be mandatory (then you can get the filename from the sibling li or something. However, there are a couple problems:
HTML
You have a random tr tag (should this be br) at the end of each list. Your li are outside of a ul or ol block, and the form must be inside of an li (that is you cannot have <ul><li /><form /></ul> as valid markup). Not a huge deal, but this may cause some display problems for you.
UI
It would be pretty annoying to have to click individual "deletes" on a long list of files, and it looks like there is no way to recover from this. Even better would be to have them be check boxes so you could delete multiple files at once and change your mind before your final decision. Then, you only need one form and it makes even more sense to have individual inputs for each file.
Security
I'm not sure how you get $dir (I really hope register globals isn't on), but you should make absolutely certain that requested file deletions contain a valid path to delete and preferably don't contain ../ or a leading / or something. You should validate this input.

A hidden field with the file name would suffice, you can use php's $_POST to get the filename in the other script. Another option would be to post it to the script using a get parameter with the filename, so you only change the get parameter part.
The real problem is that you should sanitize the input the second script receives. It is just very important that people can only delete files they're allowed to delete.
At the very minimum you should check if the file is in a specific folder. Other options are only deleting files from one folder (so not accepting paths) or abstracting filenames away behind id's

Related

Set img src without knowing extension

So I have a few images in the server (public_html/img/profile_pictures/).
This is how I currently set the image:
echo "<img src='img/profile_pictures/main_photo.png'/>";
The main_photo can change each day, but if it changes to main_photo.jpg insted, it wont show (because the extension is hardcoded on that line(.png)). Is it possible to display the photo without knowing the extension for the image file?
If you want a PHP code, then try this. This code will look for main_photo.* inside your folder and automatically set the extension upon finding one.
Remember to set the path properly
<?php
$yourPhotoPath = "img/profile_pictures/";
foreach (glob($yourPhotoPath.'main_photo.*') as $filename) {
$pathInfo = pathinfo($filename);
$extension = $pathInfo['extension'];
$fileName = chop($pathInfo['basename'], $extension);
echo "<img src='".$yourPhotoPath.$fileName.$extension."'/>";
}
?>
if a Photo isn't loaded, it's width and size is null.
Although I would advise you to write a class that checks and loads images, I get a feeling you want a simple solution. so, given by the premise that the photo is either
<img src='img/profile_pictures/main_photo.png'/>
or
<img src='img/profile_pictures/main_photo.jpg'/>
and that neither this path nor this filename ever changes and in the folder is only one picture,
you could simply echo both.
The img of the one that is empty will not be shown.
A better way was to write a class that loads your photo and checks if the photo is really there, like
$path = 'img/profile_pictures/main_photo.png';
if(!file_exists('img/profile_pictures/main_photo.png'))
{
//use the jpg path
$path = 'img/profile_pictures/main_photo.jpg';
}
You can ofc just inline this if case, but it's bad practise to intermix buisinesslogic and format logic, so I advice you to write a class for it.

Adding a variable to a form using PHP

I hope this question was not asked before, but I found nothing by searching.
Now, I have a small problem to solve...
I want to enable my website to rename contents of a folder. The website lists all contents of the folder by using scandir. To edit the names there are input fields prefilled with the current names. All of that is done by a for loop.
The point is, that I would like to add a variable to the form, that gets transfered via post to my action, when the form is submitted, but without having the variable in an input field. The context is, that I need to somehow get the original file name to the action. My first idea was to just set a $_POST value manually, but this does not work, as this value won't be specific to this form.
Is there a way to do this? Or should I just use a hidden input field, although this does not seem to be the most ellegant solution to me.
Thank you for helping!
EDIT:
echo "<li><form action='rename.php' method='post'>";
echo "<input type='text' name='nName' value=$dateiName>";
echo "<input type='submit' value='ändern'></form></li>";
This is the form that gets created multiple times. If using a hidden input is the way to go, I will use it. Just don't like the idea of having a input field that is invisible.
You need the input field (hidden) with the original value of the file name. Then you have to compare the original value with the value in the text field and if the values are different, then you will rename the file. If you don't have the initial value, you can not find the file to be renamed.
For the sake of "security", you could use a hash of the original filename as the key of your array input :
<input type="text" name="filenames[<?php echo hash('sha256', $originalFileName) ?>]" />
You could then loop like this after submitting the form :
$files = scandir($dir);
foreach ($_POST['filenames'] as $hash => $newname) {
foreach ($files as $file) {
if (hash('sha256', $file) === $hash) {
rename(
$dir . DIRECTORY_SEPARATOR . $file,
$dir . DIRECTORY_SEPARATOR . $newname
);
}
}
}

Clarifcation - Delete files which are not in a mySQL TABLE

Delete files which are not in a mySQL TABLE
The link above is to a Stack Overflow question with an answer that is (I believe) pretty close to what I'm looking for. I'm actually just seeking further clarification on the answer given.
The Question
I'm trying to delete files (picture files) in a folder only if they're
not present in a specific database table.
Just like a check of filenames and if they're present in the table
it's ok but if not delete them.
Any ideas how to do that?
The accepted answer
$result = mysql_query("SELECT filename FROM no_delete");
while($row = mysql_fetch_assoc($result)) {
$do_not_delete[] = $row['filename']; }
foreach(glob("*") as $filename) {
if (!in_array($filename, $do_not_delete)) {
//delete them
}
}
I'm not too savvy with PHP, but I don't believe they are specifying a folder path on the server here, are they? I'd like to be able to look inside a specific folder and check whether any images in that folder are within any database tables. If not, delete that image.
Before calling glob("*") just add a line chdir(""). Then you can search whichever directory you want to look at. I just went one level higher in the call below. You may specify whichever directory you want. Before doing a delete, just add an echo statement to $filename to verify if the correct files are being deleted.
chdir("../");
foreach(glob("*") as $filename) {
if (!in_array($filename, $do_not_delete)) {
//delete them
}
As described in this answer the first parameter, i.e. pattern, can contain the path to a directory relative to the current working directory of the script (which can be changed with chdir()) or an absolute path.
Consider this example from this tutorial page:
$dir = "/etc/php5/*";
// Open a known directory, and proceed to read its contents
foreach(glob($dir) as $file)
{
echo "filename: $file : filetype: " . filetype($file) . "<br />";
}

IF statement not working in self-referencing form

I'm trying to use an if statement in PHP to create a directory to upload files into. I'm using a form that references itself, so that I can create another folder and upload another set of files to a different folder with a different name, or another set of files to the same folder if I so choose, once the first has completed. The problem is that the if statement I'm using doesn't seem to work. When I submit the form, it created the folder a second time whether the folder already exists or not.
What is going on with my if statement?
<?php
$dirname = $_REQUEST['dirname'];
$taken = $_REQUEST['taken'];
$location = $_REQUEST['location'];
$subject = $_REQUEST['subject'];
$urldirectory = $_REQUEST['urldirectory'];
function makeDirectory($dirname) {
mkdir(trim($dirname, 0777));
mkdir(trim($dirname.'/thumbs', 0777));
}
if (file_exists($dirname)) {
echo "the directory exists and it is called: " . trim($dirname);
} else {
makeDirectory($dirname);
}
//........... code omitted from here for brevity............
?>
<form enctype="multipart/form-data" method="post" action="upload2.php">
<input type="submit" name="submit" value="Upload" />
There are some problems in the way how you handle directory creation and checking:
You check if $dirname exists and if it doesn't you create trim($dirname, 0777).
trim expects a string as second parameter, but you pass an integer (i.e. 0777). My guess is, you want to pass 0777 to mkdir, not to trim.
I don't know about the second point, but the first point definitely can lead to file_exists($dirname) failing on two consecutive form submissions with the same form values. I suggest to sanitize request values as early as possible, i.e. to use
$dirname = trim($_REQUEST['dirname']);
and use $dirname from there on without the need for any further trimming

PHP move chosen files from A folder to B folder

This is a tricky one and I'm not sure where to start, so any help will be grateful.
I have a parent folder called 'source' (c:/dev/source) which contains several child folders.
I need a PHP script that will display the child folders with checkboxes next to each, and a text field for a new folder name, allowing users to tick the checkboxes of the ones they want to copy to a 'destination of c:/dev/destination/the_folder_name_they_typed_in
When they click submit, the selected child folders will be copied from c:/dev/source to c:/dev/destination/the_folder_name_they_typed_in
This is all running on a local internal development server. The child folders will always be in c:/dev/source/
Somme advice:
Use a whitelist for allowed characters in destination folder. Only commit the operation if it matches:
^[a-z0-9_-]+$
You can use array indices for directory names. This way you can iterate thru the ckeckboxes with foreach ($_POST["dirs"]) { ... }
<input type="checkbox" name="dirs[directory_name]"/>
<input type="checkbox" name="dirs[other_dir_name]"/>
<input type="checkbox" name="dirs[third_directory_name]"/>
Always checkthe directory names against a whitelist like above. (If you allow characters like . or / or many other it can be a security risk).
Here's a not well known little bit of code called DirectoryIterator. It's not fully documented on the PHP site, but heres the jist of it:
Create a list of files and folders with checkboxes next to them, slap them all in an array.
$Directory = new RecursiveDirectoryIterator('c:/dev/source');
$Iterator = new RecursiveIteratorIterator($Directory);
?><form method="post"><?
foreach($Iterator as $r){
if($r->isDot()) continue;
echo "<input type=\"checkbox\" name=\"copy[]\" value=\"".($r->getSubPathName())."\"> ".$r->getSubPathName() . " <br>";
}
?></form><?
Now add this part to the top of the file
<?php
if($_POST){
if(is_array($_POST['copy'])) foreach($_POST['copy'] as $c){
#copy($c, str_replace('c:/dev/source','c:/dev/dest', $c));
echo "copied: $c to ". str_replace('c:/dev/source','c:/dev/dest', $c) . "<br>";
}
}
I'm not fully sure what result you get from $r->getSubPathName() can you let me know if it outputs an array? if so it might be that you replace that with $r->getSubPath() and then add the "c:/dev/source" to the variable $c when you copy it?
Further Reading:
here

Categories