I have set file permissions to 777 yet I cannot write to the file with PHP.
I can clearly see in my FTP client that the file has 0777 permissions and when I do:
echo (true === is_writable('file.txt')) ? 'yes' : 'no';
I get 'no';
I also tried:
echo (true === chmod('file.txt', 0777)) ? 'yes' : 'no';
With the same result.
The directory listing goes something like this:
public_html
public 0777
css 0755
js 0755
file.txt 0777
And I'm using .htaccess file to redirect all traffic to the public subfolder. Of course, I have excluded the file from rewriting (it is accessible from the browser I checked):
RewriteRule ^(file).* - [L]
Why is that?
I guess Apache runs as a different user/group than the user/group owning the file. In which case, the file itself needs to be 0777.
public only needs to be 0777 if you plan on adding files to the folder using PHP. Even if the folder itself is not 0777, if the file is and the folder has at least 5 for the user (read/execute), you should be able to write to the file.
In the end, your file tree should look like this:
public_html
public
file.txt 0777
Naturally, you won't be able to change those permissions using PHP, but you can do so from your FTP client.
If it still isn't working, PHP might be running in safe mode or you might be using an extension such as PHP Suhosin. You might get better result changing the owner of the file to the same user/group that is running the script.
To get the user/group id of the executing user, you may use the following:
<?php
echo getmyuid().':'.getmygid(); //ex:. 0:0
?>
Then, you may use chown (in the terminal) to change the owner of the file:
> chown 0:0 file.txt
In opencart i faced this error after installing vqmod and giving all necessary permissions.
after researching a bit, found it.
"MODS CACHE PATH NOT WRITEABLE" is actually refering to vqmod folder itself and not the cache folder.
sudo chmod -R 777 vqmod
in your root directory.....
You have to chmod the file right after you create it.
function Doo_Chmod($path, $chmod = null)
{
if (file_exists($path) === true)
{
if (is_null($chmod) === true)
{
$chmod = (is_file($path) === true) ? 644 : 755;
if (in_array(get_current_user(), array('apache', 'httpd', 'nobody', 'system', 'webdaemon', 'www', 'www-data')) === true)
{
$chmod += 22;
}
}
return chmod($path, octdec(intval($chmod)));
}
return false;
}
Not strictly related to the above question, still, I will put it here for future visitors, as I came here reading the title.
From arch wiki:
File attributes
Apart from the file mode bits that control user and group read, write
and execute permissions, several file systems support file attributes
that enable further customization of allowable file operations. This
section describes some of these attributes and how to work with them.
Warning: By default, file attributes are not preserved by cp, rsync,
and other similar programs. chattr and lsattr
For ext2 and ext3 file systems, the e2fsprogs package contains the
programs lsattr and chattr that list and change a file's attributes,
respectively. Though some are not honored by all file systems, the
available attributes are:
a: append only
c: compressed
d: no dump
e: extent format
i: immutable
j: data journalling
s: secure deletion
t: no tail-merging
u: undeletable
A: no atime updates
C: no copy on write
D: synchronous directory updates
S: synchronous updates
T: top of directory hierarchy
For example, if you want to set the immutable bit on some file, use
the following command:
# chattr +i /path/to/file
To remove an attribute on a file just change + to -.
For a file, with no additional attributes, the lsattr looks like this:
$ lsattr /etc/hosts
-------------e- /etc/hosts
Related
In short, the following code is meant to create a directory structure like:
>Attachments
>Lot
>Layer
The Attachments directory is fixed. The Lot comes out with 0777 permissions. The Layer directory does not. I added the chmod lines after concern that perhaps umask was at fault, but it didn't change anything.
// Create directory for this entry's attachments if needed.
$attachment_dir = $config_ini['OOCDB_defaults']['attachment_dir'];
$attachment_lot_dir = $attachment_dir.$txtLotID."/";
$attachment_lot_layer_dir = $attachment_lot_dir . $txtLayer."/";
if(!is_dir($attachment_lot_dir)){
mkdir($attachment_lot_dir , 0777);
}
if(!is_dir($attachment_lot_layer_dir )){
mkdir($attachment_lot_layer_dir , 0777);
}
chmod($attachment_lot_dir ,0777);
chmod($attachment_lot_layer ,0777);
$sleuthFile = $attachment_lot_layer_dir . "makeSleuthImg.txt";
$fp = fopen($sleuthFile,"w") or die("unable to open File! <br>");
//Write the string to the file and close it.
You have a typographical error:
$attachment_lot_layer_dir = $attachment_lot_dir . $txtLayer."/";
...
chmod($attachment_lot_layer ,0777);
That variable does not exist, so yes that will never work. PHP's mkdir respects umask in Linux (assuming you're on Linux otherwise this wouldn't be happening), so your directories are not being created at 0777 mask as requested; however chmod does not respect umask, so your first call to chmod is in fact changing this directory's mask to 0777. The second call is failing due to the bad variable name. Hence the behavior you're seeing.
FWIW, mkdir has a second optional, boolean parameter that will allow you to recursively create a directory structure in a single call by passing it the full directory path (see here). You should also look at this question to understand what to do with umask before calling mkdir if you want to avoid the subsequent calls to chmod entirely.
We are using a linux dedicated server in our company.
Whenever we create a folder with php script, apache is owning the folder and each time I have to connect to server via root in order to change the owner to the user and the permissions
But I don't know which setting I should change in order to fix this.
I tried to switch the safe mode on/off but it didn't work.
I'd be glad if someone could help me
Thanks in advance
Have you tried using the chown PHP command and chmod PHP command?
There are 2 ways to do this:
chown() where you can change the file permissions via executing that function.
or if you are able to move files around using an FTP, you can drag the file outside of the document root (public_html/), and right click -> change file permissions on the file.
CHMODs are what you want to be looking at. 777 will give anyone and everything access to your file, which you can use as a test to make sure you have file permissions. I don't recommend keeping the permissions on 777 at all though.
This is a portability issue and depends on your server configuration (i.e. mod_php or FCGI with SuExec).
You can try using the chown function right after you created the file, but that will only work if you know who the actual owner should be (which is not always the case). To overcome this issue, I wrote a simple method that tries to find the best possible file mode that always assures reading and writing (as well as execution for directories) without giving excessive permissions:
function xChmod($path, $chmod = null) // adapted from phunction
{
if (file_exists($path) === true)
{
if (is_null($chmod) === true)
{
$chmod = (is_dir($path) === true) ? 777 : 666;
if (extension_loaded('posix') === true)
{
$user = posix_getpwuid(posix_getuid());
if (array_key_exists('name', $user) === true)
{
$chmod -= (in_array($user['name'], explode('|', 'apache|httpd|nobody|system|webdaemon|www|www-data')) === true) ? 0 : 22;
}
}
}
return chmod($path, octdec(intval($chmod)));
}
return false;
}
Basically, if you omit the second $chmod argument, it will use 0777 for folders and 0666 for files by default, however, if PHP is being run under a non-standard user, it will decrement the mode by 22, yielding 0755 for folders and 0644 for files. Bare in mind that this will only work for files that already exist, so if you're creating a directory you'll need to have additional precautions.
I am having problems with functions that create files in the tmp directory such as tmpfile() and tempnam(). They all seem to fail to write to tmp and return false. upload_tmp_dir is set in php ini and file uploads work fine.
When debugging this error I found that sys_get_temp_dir() gets the location of the tmp directory unfortunately it's not supported in my PHP version (5.1.6). I also saw that using the following method replaces the functionality of sys_get_temp_dir():
if ( !function_exists('sys_get_temp_dir')) {
function sys_get_temp_dir() {
if (!empty($_ENV['TMP'])) { return realpath($_ENV['TMP']); }
if (!empty($_ENV['TMPDIR'])) { return realpath( $_ENV['TMPDIR']); }
if (!empty($_ENV['TEMP'])) { return realpath( $_ENV['TEMP']); }
$tempfile=tempnam(__FILE__,'');
if (file_exists($tempfile)) {
unlink($tempfile);
return realpath(dirname($tempfile));
}
return null;
}
}
But there is no reference to a tmp directory in the $_ENV array and tempnam() fails as I mentioned before.
Also open_basedir is not set which I've heard can cause similar problems
How can I find out where the tmp directory is or whether it is even set?
Is this a apache server configuration issue or a PHP one?
Thanks for your help
I am running Ubuntu 18.04 and I could create/modify files in the /tmp directory when I ran the PHP script from the CLI, but when I tried accessing the same script as a web page, I could never find the file that was being created. It turns out that Apache by default will create a private tmp directory. The following post provided some insight on the problem Odd Bits - Private /tmp directory. However, the /usr/lib/systemd directory mentioned in the post did not contain any services for http or apache2 on my machine. To help track down the problem I executed the following command:
sudo find / -mount -type f -exec grep -e "PrivateTmp" '{}' ';' -print
and found in /lib/systemd/system/apache2.service the PrivateTmp=true mentioned in the Odd Bits post. Copying the file from /lib/systemd/system to /etc/systemd/system/ and changing true to false and executing
systemctl daemon-restart
systemctl restart apache2
fixed the problem. A person wiser than me suggested copying the file to /etc instead of editing it in /lib was the correct course of action because /lib is 'owned' by the packages and local edits should be performed in /etc. systemd man page describes the systemd configuration processing in gory details.
you can set the upload temp dir in your php.ini -
something like that should work:
upload_tmp_dir=/your-www/tmp/
Also, in case you can't edit the php.ini or don't want to do it globally you can use this in the beginning of your script:
ini_set('upload_tmp_dir','/your-home-www/tmp/');
TMP, TEMP (and maybe TMPDIR) are valid on Windows only and usually pointing to C:\Windows\TEMP. On Linux default temp location is /tmp. To workaround this (works with tempnam() function) you can create a temp folder somewhere within your website space, specify appropriate access permissions and pass this as first parameter to the above function.
Not a great solution but better than nothing.
Probably not the cleanest but this works on my old 5.1.6 install:
function get_temp_path() {
static $path = null;
if ($path !== null) return $path;
$file = tmpfile();
$meta = stream_get_meta_data($file);
fclose($file);
$path = dirname($meta['uri']);
return $path;
}
I have the same problem and the solution is to change the apache configuration to expose the TEMP variable to PHP, see this post.
Tip for newbies like me: I THOUGHT that PHP couldn't move stuff from my temporary folder, but I was just confused because of the relative positions of folders. This may apply to someone else, so I'll explain, even though it's very tangentially related to this specific question (because this specific question is a likely search result for other people like me who are newbies).
My problem is that I was echoing an upload form FROM a functions.php file inside of /var/www/html/ TO a profile.php file in /var/www/html/user/ which CALLED an uploadphoto.php file in /var/www/html/. Uploaded files were ultimately intended to land in /var/www/html/uploads. This ultimately meant that most of my references to both uploadphoto.php AND uploads/ in functions.php were written "../uploadphoto.php" or "../uploads/[etc.jpg]", respectively, in order to step back into html/ from html/user/ (where the echoed code landed in html/user/profile.php). This led me to intuitively use the following command inside of uploadphoto.php without thinking it through:
move_uploaded_file($_FILES["file"]["tmp_name"][0], "../uploads/$filename")
See the problem? uploadphoto.php is in the same directory as uploads/, so I did not need the ../ here. For hours, I was sure I was messing up my folder permissions again, because I am new to image uploading. I had forgotten to check for more simple-minded errors. Hopefully this helps someone else.
I can't understand why I have to use chmod to get the correct permissions..
The file is created succesfully but with 0755 and not 0775 that I specify in mkdir .
( http://php.net/manual/en/function.mkdir.php )
I have to do chmod after mkdir to set the correct permissions.
Safe mode is off in php.ini and the folder belongs to php's group and owner (www-data)
This doesn't work:
if(!is_dir("/var/www/customers/$username/$project_name"))
{
mkdir("/var/www/customers/$username/$project_name",0775);
}
But this does:
if(!is_dir("/var/www/customers/$username/$project_name"))
{
mkdir("/var/www/customers/$username/$project_name");
chmod("/var/www/customers/$username/$project_name",0775);
}
Yes, it's because of umask...
from comments of docs: http://php.net/manual/en/function.mkdir.php
You might notice that when you create
a new directory using this code:
mkdir($dir, 0777);
The created folder actually has
permissions of 0755, instead of the
specified
0777. Why is this you ask? Because of umask(): http://php.net/manual/en/function.umask.php
The default value of umask, at least
on my setup, is 18. Which is 22 octal,
or
0022. This means that when you use mkdir() to CHMOD the created folder to
0777, PHP takes 0777 and substracts
the current value of umask, in our
case 0022, so the result is 0755 -
which is not what you wanted,
probably.
The "fix" for this is simple, include
this line:
$old_umask = umask(0);
Right before creating a folder with
mkdir() to have the actual value you
put be used as the CHMOD. If you would
like to return umask to its original
value when you're done, use this:
umask($old_umask);
I think you may have to modify your umask.
As noted on the mkdir manpage:
The mode is also modified by the current umask, which you can change using umask().
Now, looking at the umask() manpage, one of the comment listed confirms my inner thought:
"It is better to change the file permissions with chmod() after creating the file."
In other words, I believe the way you are doing it is more secure:
Set your umask so that files are created private to your user, then use chmod to open them up.
Try calling this function before you make your directory: clearstatcache(); Also, maybe you should check if you can do it using just mkdir if you siwtch to another user.
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