Create directory in php avoiding 777 permission - php

I have a php script that is used to create different directories for different users to store their images.
One way to do this is use 777 permision like this:
$path = 'images/product/'.$pid;
if( ! file_exists($path)) {
$mask=umask(0);
mkdir($path, 0777);
umask($mask);
}
Is there any other alternative that doesn't involve to use 777 permision for the directory, for example to set the file owner and group?

Changing the file owner/group requires privileges that your Apache should not have if you want to run it safely.
However, you don't necessarily need 0777. I guess you are storing images, so you can use 0644!
Side note: chgrp() and chown() are the 2 functions giving you the ability to change file group/owner

Related

Create writable directories

For a project I'm implementing a file-upload system. For every user account I would like the script to create a different sub-folder. Lets say their user_id's.
Each time a user is added, the system will create a new sub-folder for their own uploads. For example:
Uploads/
- user1
- user2
- user3
By executing mkdir('Uploads/'.$user_id, 0777); it will create a new subfolder. Everything is fine.
However my application is not able to write to this folder. How do I have php make directories with the required file permissions? I have tried using chmod with no success.
This might help chmod and mkdir
$dirMode = 0777;
mkdir($directory, $dirMode, true);
// chmod the directory since it doesn't seem to work on recursive paths
chmod($directory, $dirMode);
For mkdir, mode is ignored on Windows. and 0777 is by default. and the third param is recursive which allows the creation of nested directories specified in the pathname.
sometimes the directory created with another mode than specified ( 0755 instead 0777 etc).
to solve that use :
<?php
$old = umask(0);
mkdir($dir,0777);
umask($old);
?>

mkdir(folder_name) with 755 permission in php

I have my web application hosted in /var/www folder. I am creating a folder from one of the PHP scripts of the web application. The default permission of the created folder is drwx------, i.e. 700. But I want that folder to have at least 755 permission.
Up to now I tried: mkdir($path, 0755) and chmod($path, 0755) PHP functions but without any success.
Does anybody know how to solve my problem please?
Millions of thanks beforehand.
Have you tried changing the umask ?
Have a look here: http://nl3.php.net/manual/en/function.umask.php
The easiest way it to:
$oldmask = umask(0);
chmod($path, 0755);
umask($oldmask)
Since you have default permission of 700, which means the parent directory (the directory in which you are trying to create the folder) do not have rw permission for group owner or other users. Most often the running demon(httpd) is not the owner of the parent folder and hence cannot modify the directory.
In simple terms, the php script do not have access to modify or add new directory. You need to change the permission of the parent folder to at least drwxrw-rw- (or 0755).
Use ssh, cpanel or ftp client to do this. If you do it using php script you will end with the same problem again, as parent of parent will have again 0700. ;)

php mkdir() chmod and permissions

i was using this basic script:
$folderPath = "../path/to/$folder/";
mkdir("$folderPath");
i create this directory and then upload photos to it. I've been doing this for a good 4-5 months now and suddenly i start getting 'FORBIDDEN' errors when I attempt to view the contents of the folder via web browser
The directory is being created the same and the photos are still uploading without a problem, but I cannot access the photos
I tried rewriting the script and using chmod to change the permissions but I'm having no luck at all
All the older folders were being created with: -w- rwx r-x r-x
and I can't get this recreated
I've tried adding a chmod line into my script:
$folderPath = "../sales/inventory/$folder/";
mkdir("$folderPath");
chmod("$folderPath", 0755);
but I can't recreate the same permissions, I'm trying to understand how chmod works, but I can't figure out how to get this very basic function working properly again
Try looking out for a HTAccess file, where the "Options -Indexes" option will be mentioned, as this is mostly used for not showing the contents of a folder in a web browser. The file needs to be searched in the following manner:-
In the folder "root_folder/sales/inventory/$folder/", where "$folder" is as mentioned in your code.
If not found, try in the folder "root_folder/sales/inventory/".
If not found, try in the folder "root_folder/sales/".
If not found, try in the folder "root_folder/".
When you get the code of "Options -Indexes" written in the HTAccess file, you can remove / comment that line of code from there, or you can also write another HTAccess file in your required folder of "$folder", where the code will be "Options Indexes".
Also in the PHP page, the logic must be like this:-
<?php
$folderPath = "../sales/inventory/$folder/";
mkdir("$folderPath");
chmod("$folderPath", 0755);
// Use of "copy()" / "move_uploaded_file()" function here, using some "$targetFile" variable.
chmod($targetFile, 0755);
?>
This will help you when you will be unlinking / deleting the uploaded files from the "$folder" folder.
Hope it helps.
If your $folder variable includes some sub-directories your parent directories are maybe not being chmoded to the right permissions. This was the problem I was having on a hired OVH Gentoo server.
Imagine that $folder = '/store1/ally23/shelf42'; so your final directory structure is
../sales/inventory/store1/ally23/shelf42, and you want 0777 permisions.
You do:
mkdir($folderPath, 0777, true) || chmod($folderPath, 0777);
Only the final directory shelf42 is chmoded to 0777. The intermediary directories are created with default permissions (in my case 0744).
There is no recursive option in PHP's chmod command, so you have to loop over the intermediary directories and chmod them individually.
If you're in a shared environment, you may also want to chown after upload, to be on the safe side. Especially if you're running your web server under a user other than your virtual host has permission to access (EG: "nobody" vs "mysite".) This is common with cPanel servers, FWIW.
Simply umask means the default permissions for new files/directories:
<?php
umask(022);
?>
This sets the default permissions for user, groups, and others respectively:
0 - read, write and execute
1 - read and write
2 - read and execute
3 - read only
4 - write and execute
5 - write only
6 - execute only
7 - no permissions

Move a file and rename it

Figured PHP's rename would be my best bet. I didn't see many examples on how to use relative URLs in it though, so I kind of compromised. Either way, this give me permission denied:
I want to do this:
$file = "../data.csv";
rename("$file", "../history/newname.csv");
Where ../ of course would go back 1 directory from where the script is being ran. I couldn't figure out a way...so I did this instead:
$file = "data.csv";
$path = dirname(realpath("../".$file));
rename("$path/$file", "$path/history/newname.csv");
However I am getting permission denied (yes the history folder is owned by www-data, and yes data.csv is owned by www-data). I thought it was weird so I tried a simple test:
rename( 'tempfile.txt', 'tempfile2.txt' );
and I made sure www-data had full control over tempfile.txt...still got permission denied. Why? does the file your renaming it to have to exist? can you not rename like linux's mv? So I instead just copy() and unlink()?
In order to move a file from "../" to "../history/", a process needs write permission to both "../" and "../history/".
In your example, you're obviously lacking write permission to "../". Permissions for the file being moved are not relevant, by the way.
Not only ownership plays a role, but also file permissions. Make sure that the permissions are set up correctly on the source file and destination directory (e.g. chmod 644 data.csv).
Is www-data the same user as Apache?
Edit: Take care to provide existing, absolute paths to realpath(). Also beware of the following:
$path = dirname(realpath("../".$file));
This might yield nothing, because the file ../data.csv might not exist. I.e., the result of realpath() on a non-existent file is false.
Here's some code that might work better for you:
$file = "data.csv";
$path1 = realpath($file);
$path2 = realpath(dirname($file).'/..').'/history/newname.csv';
rename($path1, $path2);
You should be extremely careful that $file cannot be edited by the visitor, because he could change a request manipulate which file is renamed to where.

PHP - rmdir (permission denied)

I have an easy script to create and delete a folder, but when I try to delete a folder, it brings up and error.
The code:
<?php
if ($_POST['hidden']) {
$key = "../g_test/uploads";
$new_folder = $_POST['nazevS'];
$new_dir_path = $key."/".$new_folder;
$dir = mkdir($new_dir_path);
if($dir)
chmod ($new_dir_path, 0777);
}
if ($_POST['hiddenSS']) {
$key = "../g_test/uploads";
$new_folder = $_POST['nazevS'];
rmdir($key."/".$new_folder);
}
?>
The error msg:
Warning: rmdir(../g_test/uploads/) [function.rmdir]: Permission denied in /home/free/howto.cz/m/mousemys/root/www/g_test/upload.php on line 51
Does anyone know how to delete the folder (hopefuly with everything inside) ?
Also if you see any other improvments, the code could have, feel free to tell me. :-)
Thanks, Mike.
Generally speaking PHP scripts on Unix/Linux run as user "nobody", meaning they need the "all" privileges so it's a permissions problem with the directory. Also, to delete a file or directory in Linux/Unix you need write privileges on the parent directory. That might be your problem.
If you have problems with the files or directories you create, use chmod() on them to set the right permissions.
Also it might not be empty.
Also, it's worth mentioning that
$new_folder = $_POST['nazevS'];
$new_dir_path = $key."/".$new_folder;
is really bad from a security point of view. Sanitize that input.
For the purpose of this answer, I will put the security risks of allowing any and all uploads in a directory aside. I know it's not secure, but I feel this issue is outside the scope of the original question.
As everybody said, it can be a permission problem. But since you've created the directory in your code (which is most likely running as the same user when deleted). It doubt it is that.
To delete a directory, you need to make sure that:
You have proper permissions (as everyone pointed out).
All directory handles must be closed prior to deletion.
(leaving handles open can cause Permission denied errors)
The directory must be empty. rmdir() only deletes the directory, not the files inside. So it can't do its job if there is still stuff inside.
To fix number 2, it is extremely simple. If you are using something like this:
$hd = opendir($mydir);
Close your handle prior to deletion:
closedir($hd);
For number 3, what you want to do is called a recursive delete. You can use the following function to achieve this:
function force_rmdir($path) {
if (!file_exists($path)) return false;
if (is_file($path) || is_link($path)) {
return unlink($path);
}
if (is_dir($path)) {
$path = rtrim($path, DIR_SEPARATOR) . DIR_SEPARATOR;
$result = true;
$dir = new DirectoryIterator($path);
foreach ($dir as $file) {
if (!$file->isDot()) {
$result &= force_rmdir($path . $file->getFilename(), false, $sizeErased);
}
}
$result &= rmdir($path);
return $result;
}
}
It looks like you need access rights on the folder you're trying to edit.
To change this:
chmod ug+rw /home/free/howto.cz/m/mousemys/root/www/g_test/
or maybe you'll need to do
sudo chmod ug+rw /home/free/howto.cz/m/mousemys/root/www/g_test/
Make sure that this is what you want to do and that your application is secure. Don't give write rights to any application since it could lead to security issues.
The webserver requires write access to the folder you're trying to delete. You can provide this with:
chgrp -R www-data g_test/uploads
chmod g+w g_test/uploads
where www-data is the user that the webserver runs under (may be apache or some variation depending on your OS and server installation). After this you can run rmdir (or rm -r if the directory isn't empty).
Also, keep in mind that giving the web server the ability to write to a directory posses security problems. In certain situations, this could allow a malicious user to run arbitrary code (i.e. take over your machine), or modify your website (i.e. server spyware).
For these reasons, you should only give dirs write perms that:
absolutely need them
don't contain source code
are outside the dir containing scripts
owned by the server
In this setup on a production machine, you could set up a separate directory just for this type of file, that only Apache can write to. If you have to deploy files to this directory, use sudo or the root account to do so to limit the accounts that have access.
For a more complete description of what I mean, have a look at the security tips section in the Apache documentation.

Categories