I am trying to delete a folder with files inside of it but the following code does delete the files, but not the folder.
$nameFolder = $_GET['delete'];
$dir = '../projecten/projecten/'.$nameFolder.'';
$filesIN = glob($dir."/"."*");
$status = 'false';
foreach($filesIN as $files) //here i take all the files
unlink($files);
$status = 'true';
if($status=='true'){
rmdir($dir);
$status = 'false';
}
[edited] Only empty directories can be deleted.
Try:
<?php
//recursively remove a directory
function rrmdir($dir) {
foreach(glob($dir . '/' . '*') as $file) {
if(is_dir($file)){
rrmdir($file);
}else{
unlink($file);
}
}
rmdir($dir);
}
//Example
$nameFolder = $_GET['delete'];
$dir = '../projecten/projecten/'.$nameFolder.'';
rrmdir($dir);
?>
source: http://www.php.net/manual/pt_BR/function.rmdir.php#108113
I would check the file permissions. On linux:
ls -al /path/to/projecten/projecten/
In simple terms the web server user must have write access to the directory in order to delete the file, for example the user www-data. In the below example the user lt can delete the test file:
drwxrwxr-x 2 lt lt 4096 Apr 29 08:54 test
Also I don't understand this bit of code:
$status = 'true';
if($status=='true'){
rmdir($dir);
$status = 'false';
}
Why not just have:
rmdir($dir);
As $status will always be 'true'.
You could also try using a system call, eg:
system `rm -rf /full/path/to/projecten/projecten/$nameFolder`;
Be very careful with that system command though - If you delete the wrong directory there is no going back!
A safer system command to use if you know the directory is empty would be:
system `rmdir /full/path/to/projecten/projecten/$nameFolder`;
But as pointed out in the comments above be very careful deleting a directory based on a $_GET variable. Imagine if the GET variables was '../../projecten' especially with the 'rm -rf' system command
Not an answer, but please change:
$nameFolder = $_GET['delete'];
To:
$nameFolder = basename($_GET['delete']);
And you may want to also add a:
if (is_dir('../projecten/projecten/'.$nameFolder) {
// ... do stuff here
} else {
// not a valid path
}
Related
I have a Video folder on my server which has 755 permission. The problem is: when someone goes to upload video file, it can't be upload into that folder because of permission error.
If I change the permission to 777, then Video can be uploaded. But I don't want to allow the folder permission to 777 for security reason.
Is there any way in PHP to temporary change the permission to 777 while uploading video?
PHP provides a function, chmod() for the task.
Attempts to change the mode of the specified file to that given in mode.
You can put it in an if statement, and if it returns false, you can skip the upload file part.
The usage will be like
if( chmod($path, 0777) ) {
// more code
chmod($path, 0755);
}
else
echo "Couldn't do it.";
As described in the chmod function manual, the $mode must be in octal format - with leading zero, i.e chmod($path, 0777)
There is a way (PHP provides chmod function) but since PHP is not the owner of the folder, you won't be able to change the permission. And I think you are solving the wrong problem. Add webserver and PHP in the same group and give 775 to the folder.
You have to initialize the config for the upload, like this:
$config['remove_spaces'] = FALSE;
$config['upload_path'] = $path;
$this->upload->initialize($config);
$this->load->library('upload', $config);
You can use chmod() function.
For more information, try here
Warning: You cannot undo the file permissions that are changed by the script below. Proceed with extreme caution.
Important: this code should only be used if you remember to delete it immediately after use. As above, its use may put your site into an insecure state.
//replace dirname(__FILE__) with desired folder.
file_fix_directory(dirname(__FILE__));
function file_fix_directory($dir, $nomask = array('.', '..')) {
if (is_dir($dir)) {
// Try to make each directory world writable.
if (#chmod($dir, 0777)) {
echo "Made writable: " . $dir . "";
}
}
if (is_dir($dir) && $handle = opendir($dir)) {
while (false !== ($file = readdir($handle))) {
if (!in_array($file, $nomask) && $file[0] != '.') {
if (is_dir("$dir/$file")) {
// Recurse into subdirectories
file_fix_directory("$dir/$file", $nomask);
}
else {
$filename = "$dir/$file";
// Try to make each file world writable.
if (#chmod($filename, 0666)) {
echo "Made writable: " . $filename . "";
}
}
}
}
closedir($handle);
}
}
or you can use terminal for this
chmod -R 755 public_html/test
I am using this function in codeigniter to try to check and make directories and sub directories only if they do not exist. Only the k_uploads is made but an error occurs in making the sub directory in the main directory 'k_upoloads'. The structure should be as
k_uploads (main directory)
-2012 (subdirectory in main directory - made per year in k_uploads)
-Jan(subdirectory in 2012 - made every month in 2012)
-subdirx (subdirectory in Jan - holds the excel files for that month)
xxyyy.xlsx (month files in subdirx)
Each year and month directories and sub directories should be created. I cant figure where the problem is, it works with plain php but not in codeigniter.
public function makeDir(){
$labref = $this->uri->segment(3);
$dirName='k_uploads';
echo $store_dir= date('Y').'/'.date('M').'/'.$subdirx;
if(!is_dir($dirName))
$k= mkdir($dirName, 0777);
if($k){
echo $dirName. 'dir has been created';
}else{
echo 'An error occured';
}
if(is_dir($dirName))
$w= mkdir($store_dir,0777);
if($w){
echo $sore_dir. 'subdirs have been created';
}else{
echo 'An error occured';
}
}
mkdir has a recursive flag which can be set. This will create the full path. See PHP: mkdir
so you should use mkdir($store_dir,0777, true)
The function could look something like the following:
public function makeDir(){
$subdirx = $this->uri->segment(3);
$store_dir= APPPATH . 'k_uploads/' . date('Y').'/'.date('M').'/'.$subdirx;
if(!is_dir($store_dir)) {
return mkdir($dirName, 0777, true);
} else {
return true;
}
}
In order to do this, you will need to create each sub-directory in a sequence, as PHP will not do this for you. You might want to check if the directory already exists using is_dir() while doing so.
Here's an example:
function createDir($dirToMake) {
$root = "/home/sites/test/www/";
$dArray = explode("/",$dirToMake);
if (file_exists($root) && is_dir($root)) {
// just a quick check
if (substr($root,0,-1) !== "/") $root .= "/";
foreach ($dArray as $v) {
if (strlen($v) == 0) continue;
$root = $root.$v."/";
if (file_exists($root) && is_dir($root)) continue;
mkdir($root);
}
}
else throw new Exception("Root directory does not exist");
}
This function also allows for the usual mistakes (// being one of them), and will loop through, creating the sub-directory architecture needed if it doesn't exist already.
This is what I've got so far. I need to be able to apply 0666 to all the files in the archive. Can't I do that as I am exporting? What is a sample code for changing the chmod during unarchiving or after unarchiving?
$zip = new ZipArchive;
if ($zip->open('upload/'. $username . $file_ext) === TRUE) {
$zip->extractTo('dir/' . $username);
$zip->close();
} else {
echo 'failed';
}
Thanks for all of the help!
Brandon
Setting 0666 on directories might not be what you want ;-)
File creation in any process in Linux will use with 0777 for directories and 0666 for files but it depends on the umask value what the final permissions will be. By default the umask value is 0022 which creates files like 0644; it works like a subtraction.
So by resetting the umask to 0 you probably get what you need.
umask(0);
$zip = new ZipArchive;
if ($zip->open('upload/'. $username . $file_ext) === TRUE) {
$zip->extractTo('dir/' . $username);
$zip->close();
} else {
echo 'failed';
}
$value can = a folder structure to the language file. Example: languages/english.php
$value can also = the files name. Example: english.php
So I need to get the current folder that $value is in and delete the folder ONLY if there are no other files/folders within that directory (after deleting the actual file as I am doing already, ofcourse).
foreach($module['languages'] as $lang => $langFile)
{
foreach ($langFile as $type => $value)
{
#unlink($module_path . '/' . $value);
// Now I need to delete the folder ONLY if there are no other directories inside the folder where it is currently at.
// And ONLY if there are NO OTHER files within that folder also.
}
}
How can I do this?? And wondering if this can be done without using a while loop, since a while loop within a foreach loop could take some time, and need this to be as quick as possible.
And just FYI, the $module_path should never be deleted. So if $value = english.php, it should never delete the $module_path. Ofcourse, there will always be another file in there, so checking for this is not necessary, but won't hurt either way.
Thanks guys :)
EDIT
Ok, now I'm using this code here and it is NOT working, it is not removing the folders or the files, and I don't get any errors either... so not sure what the problem is here:
foreach($module['languages'] as $lang => $langFile)
{
foreach ($langFile as $type => $value)
{
if (#unlink($module_path . '/' . $value))
#rmdir(dirname($module_path . '/' . $value));
}
}
NEVERMIND, this works a CHARM!!! Cheers Everyone!!
The easyest way is try to use rmdir. This don't delete folder if it is not empty
rmdir($module_path);
also you can check is folder empty by
if(count(glob($module_path.'*'))<3)//delete
2 for . and ..
UPD: as I reviewed maybe you should replace $module_path by dirname($module_path.'.'.$value);
Since the directory you care about might be part of the $value, you need to use dirname to figure out what the parent directory is, you can't just assume that it's $module_path.
$file_path = $module_path . '/' . $value;
if (#unlink($file_path)) {
#rmdir(dirname($file_path));
}
if (is_file($value)) {
unlink($value);
} else if (is_dir($value)) {
if (count(scandir($value)) == 2) }
unlink($value)
}
}
http://php.net/manual/en/function.is-dir.php
http://www.php.net/manual/en/function.scandir.php
The code below will take a path, check if it is a file (i.e. not a directory). If it is a file, it will extract the directory name, then delete the file, then iterate over the dir and count the files in it, if the files are zero it'll delete the dir.
Code is as an example and should work, however privileges and environment setup may result in it not working.
<?php
if(!is_dir ( string $filename )){ //if it is a file
$fileDir = dirname ( $filename );
if ($handle = opendir($fileDir)) {
echo "Directory handle: $handle\n";
echo "Files:\n";
$numFiles=0;
//delete the file
unlink($myFile);
//Loop the dir and count the file in it
while (false !== ($file = readdir($handle))) {
$numFiles = $numFiles + 1;
}
if($numFiles == 0) {
//delete the dir
rmdir($fileDir);
}
closedir($handle);
}
}
?>
Does anyone know how I can check to see if a directory is writeable in PHP?
The function is_writable doesn't work for folders.
Edit: It does work. See the accepted answer.
Yes, it does work for folders....
Returns TRUE if the filename exists and is writable. The filename argument may be a directory name allowing you to check if a directory is writable.
this is the code :)
<?php
$newFileName = '/var/www/your/file.txt';
if ( ! is_writable(dirname($newFileName))) {
echo dirname($newFileName) . ' must writable!!!';
} else {
// blah blah blah
}
to be more specific for owner/group/world
$dir_writable = substr(sprintf('%o', fileperms($folder)), -4) == "0774" ? "true" : "false";
peace...
You may be sending a complete file path to the is_writable() function. is_writable() will return false if the file doesn't already exist in the directory. You need to check the directory itself with the filename removed, if this is the case. If you do that, is_writable will correctly tell you whether the directory is writable or not. If $file contains your file path do this:
$file_directory = dirname($file);
Then use is_writable($file_directory) to determine if the folder is writable.
I hope this helps someone.
According to the documentation for is_writable, it should just work - but you said "folder", so this could be a Windows issue. The comments suggest a workaround.
(A rushed reading earlier made me think that trailing slashes were important, but that turned out to be specific to this work around).
I've written a little script (I call it isWritable.php) that detects all directories in the same directory the script is in and writes to the page whether each directory is writable or not. Hope this helps.
<?php
// isWritable.php detects all directories in the same directory the script is in
// and writes to the page whether each directory is writable or not.
$dirs = array_filter(glob('*'), 'is_dir');
foreach ($dirs as $dir) {
if (is_writable($dir)) {
echo $dir.' is writable.<br>';
} else {
echo $dir.' is not writable. Permissions may have to be adjusted.<br>';
}
}
?>
stat()
Much like a system stat, but in PHP. What you want to check is the mode value, much like you would out of any other call to stat in other languages (I.E. C/C++).
http://us2.php.net/stat
According to the PHP manual is_writable should work fine on directories.
In my case, is_writable returned true, but when tried to write the file - an error was generated.
This code helps to check if the $dir exists and is writable:
<?php
$dir = '/path/to/the/dir';
// try to create this directory if it doesn't exist
$booExists = is_dir($dir) || (mkdir($dir, 0774, true) && is_dir($dir));
$booIsWritable = false;
if ($booExists && is_writable($dir)) {
$tempFile = tempnam($dir, 'tmp');
if ($tempFile !== false) {
$res = file_put_contents($tempFile, 'test');
$booIsWritable = $res !== false;
#unlink($tempFile);
}
}
this is how I do it:
create a file with file_put_contents() and check the return value, if it is positive (number of written in Bytes) then you can go ahead and do what you have to do, if it is FALSE then it is not writable
$is_writable = file_put_contents('directory/dummy.txt', "hello");
if ($is_writable > 0) echo "yes directory it is writable";
else echo "NO directory it is not writable";
then you can delete the dummy file by using unlink()
unlink('directory/dummy.txt');