am05mhz am05mhz - 1 month ago 26
PHP Question

why laravel needs to chmod() a file or folder after being created or uploaded?

recently, I have deployed a web server configuration with Apache, PHP-FPM, and MariaDB. it was running smoothly until my colleague deployed laravel 4 app on it with image uploading capability.

The problem was I have disabled PHP's

chmod()
function along with
system()
etc functions, while the script for uploading images uses
chmod()
and
umask()
(my colleague said that this is the default behavior).

I know that there is a debate over the danger of
chmod
wih PHP like this site that tells it is harmless, and this post that tells that a server should never be 777

what I don't understand is, why do you need to
chmod()
something when the PHP process can read the uploaded file properly even without
chmod()
? it can even create folders and delete folders without
chmod()
as those files and folders are created with the correct permission for PHP process.

tl;dr

so that brings to my question, is it true that file uploading in laravel 4 need
chmod()
to function properly? and why?

edit

for those who like to know the code (this code is found in
vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/File/UploadedFile.php
):

$target = $this->getTargetFile($directory, $name);

if (!@move_uploaded_file($this->getPathname(), $target)) {
$error = error_get_last();
throw new FileException(sprintf('Could not move file "%s" to "%s" (%S)', $this->getPathname(), $target, strip_tags($error['message'])));
}

@chmod($target, 0666 & ~umask());

Answer

I can't speak for the Laravel's reasoning behind this. It does looks like it is built into their functionality, but a quick search on this brought up comments under http://php.net/manual/en/function.move-uploaded-file.php.

The comments suggest that after moving uploaded files with move_uploaded_file, the permission is set to 0600. This would be fine if the web server and PHP process were running under the same desired user, but not if it relied on the group or a web server running under a generic user like apache or nobody. So my assumption would be Laravel did this for compatibility with the latter systems as 0600 means rw for the user and no access to the group or others.