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
);
}
}
}
Related
I have a time problem. I'm making a karaoke website were I use php for certain operations. The site is made with Drupal. My problem is that I'm using date() to make a file name of the song that is recorded. But this file name is used in two places on my page. The first place makes the file name as soon as the page loads and "echo" it to be used by an applet. The applet is to upload the file at the end when the user leaves the page after recording the song.
The second place will use the file name when a button is pressed. This code will write the file name into a node (My Songs) to be accessed later on. So both file names have to be the same. The problem is that there is a discrepancy between the times both codes use the constant. So the name of the file written in the node My Songs is not the same as the file name that was uploaded. Because there is 4-5 minutes difference when both codes use the file name. I suppose the function: date('dmhi') is stored in the Constant and not the string (result) of the function. I tried using a variable and initializing it first with a string so it would remain a string, but it didn't work. I'm more of a C++ and VB coder, so I don't get how the variables and constants work in php. I searched the web for days and I'm not finding any answers. I hope you people can help me. Here is part of my code:
First occurance:
<?php
Global $user;
profile_load_profile($user);
$name = $user->name;
define("FILE", $title . $name . date('dmhi') . ".spx");
echo "<param name=\"refreshURL\" value=\"http://english.karavid.com/node/2?sampleName=" . FILE . "&movie=" . $movie . "&title=" . $title . "&name=" . $name . "\">\n";
echo "<param name=\"uploadFileName\" value=\"" . FILE . "\">\n";
?>
Second occurance when the button is pressed:
$node1->body = substr($node1->body, 0, -8) . "<tr>
<th scope=\"col\">" . $title . "</th>
<th scope=\"col\">" . date('j M Y') . "</th>
<th scope=\"col\"></th>
</tr> </table>";
node_save($node1);
Thanks in advance for any clue you can give me.
Nathalie
EDIT:
I will try to explain better. I'm generating a page that will build some code inside an applet (a recorder for the voice). Inside that applet, I use php to make part of the applet code. That part is to make the applet upload the recording done by the user. Now, I need a file name that will be different for every user. And if the user records the same song many times during the day, the file name has to be different, so I'm using the date and time inside the file name. With the function date();
But that file name is generated on loading. So the file name will include the time upon loading the page. Later on when the user REALLY DO save the song, time has past but the file name that is uploaded contains the time upon loading not the time of saving. This happens because the file name is "echo"(ed) inside the applet at the time of loading the page. There is no other way I can work it around.
But, I would like to preserve that time so that I can use it again. The thing is when I try to use the file name again, the time is no longer the same. A few minutes has passed. So the file name is not the same. And when the file name is written on another page(node or file) after the recording upon saving , it's not the same as the previous one.
I know it's a bit complicated. But basically, I need to generate a file name with the time included inside it. And use the same file name on two occasions that will be separated with a time frame. But the file name should not change.
I'm not really sure what you're asking.
You could create a function to return the date...
public function myDate(){
return date('dmhi');
}
And call
echo $this->myDate();
Or if you wanted to set the date on the first call and have subsequent calls retrieve the same date
private $_myDate;
public function myDate(){
if($this->_myDate == null)
$this->_myDate = date('dmhi');
return $this->_myDate;
}
Edit
Try it without $this?
$_myDate = null;
function myDate(){
if($_myDate == null)
$_myDate = date('dmhi');
return $_myDate;
}
$date = myDate();
Edit 2
Why not just do this?
$myDate = date('dmhi');
$file = $title . $name . $myDate . ".spx";
Then
$node1->body = substr($node1->body, 0, -8) . "<tr>
<th scope=\"col\">" . $title . "</th>
<th scope=\"col\">" . $myDate . "</th>
<th scope=\"col\"></th>
</tr> </table>";
So after trying many things, I found a way to work around it. I post it here in case someone needs to do this in the future.
On my page I have a form that I use for the "save" button. I simply added this at the end of the form:
echo "<input type=\"hidden\" value=\"" . FILE . "\" name=\"filename\" id=\"filename\">
</form>";
So it prints the file name I need when the page is loading and it remains hidden. So when the "save" button is pushed later on, the final code runs and I just recuperate the constant that was passed into this hidden field, like this:
$file = $_POST["filename"];
It's not a perfect solution, but it works. If anyone has a better one, please let me know.
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
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
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
how do we attach mysql_insert_id() in a file uploads so that each file gets unique name ? I did try the following code but didn't work. please advice. Yhanks
$id = mysql_insert_id();
$dest = trim($uploaddir. $id. basename($_FILES['photo']['name']));
This should be
if(false !== ($id = mysql_insert_id())
{
$dest = sprintf("%s%d_%s",$uploaddir,$id,trim(basename($_FILES['photo']['name']));
if(!file_exists($dest))
{
//move_uploaded_file
}else
{
//You cant program :(
}
}else
{
//DB Error.
}
You should write your code so you add the file to the directory before you add to database.
Get the data from $_FILES
Sanitize the data and validate the file Size,Ext,Headers,Name
Make sure the file does not already exists
Generate a UniqueID and create a hash from a static string, Example 1
Store the file on the server and verify its move ok
Add meta data to the database along with the unique ID and file location
Bobs your uncle.
Example 1:
define('FILE_NAME_SALT','MySecret$alt');
$uid = md5(rand(0,100) . $uid . FILE_NAME_SALT . $FileName);
Store file like HASH.ext
This is a problem that you can take some steps to solve yourself before asking. For starters, print out $id. Is it a valid Id? Or is it FALSE (it might be). Then echo out $uploaddir, $_FILES['photo']['name'], and basename($_FILES['photo']['name']). Finally, echo out $dest. I'd be rather surprised if you don't catch the mistake by doing these simple debugging exercises.
You could use a hashing function to do this. For example, md5 or sha1 are good choices for unique filenames. You could use a filename that the md5() function returns given the file's initial name.