This file_write() function will give $filename the write permission before writing $content to it.
Note that many servers do not allow file permissions to be changed by the PHP user.
<?php
function file_write($filename, &$content) {
if (!is_writable($filename)) {
if (!chmod($filename, 0666)) {
echo "Cannot change the mode of file ($filename)";
exit;
};
}
if (!$fp = @fopen($filename, "w")) {
echo "Cannot open file ($filename)";
exit;
}
if (fwrite($fp, $content) === FALSE) {
echo "Cannot write to file ($filename)";
exit;
}
if (!fclose($fp)) {
echo "Cannot close file ($filename)";
exit;
}
}
?>
is_writable
(PHP 4, PHP 5)
is_writable — ファイルが書き込み可能かどうかを調べる
説明
bool is_writable
( string
$filename
)
filenameが存在して、かつそれが書き込み可能であれば
TRUEを返します。引数filenameはディレクトリ名とすることができ、
ディレクトリが書き込み可能であることを調べることが可能です。
PHP は、Web サーバーが実行されているユーザー ID('nobody' が多い) でファイルにアクセスすることを覚えておいてください。 セーフモードの制限は働きません。
パラメータ
-
filename -
調べたいファイル名。
返り値
filename が存在して書き込み可能な場合に
TRUE を返します。
例
例1 is_writable() の例
<?php
$filename = 'test.txt';
if (is_writable($filename)) {
echo 'このファイルは書き込み可能です';
} else {
echo 'このファイルは書き込みできません';
}
?>
エラー / 例外
失敗したときは E_WARNING が発生します。
注意
注意: この関数の結果は キャッシュされます。詳細は、 clearstatcache() を参照してください。
ヒント
PHP 5.0.0 以降、この関数は、 何らかの URL ラッパーと組合せて使用することができます。 どのラッパーが stat() ファミリーをサポートしているかを調べるには サポートするプロトコル/ラッパー を参照してください。
参考
- is_readable() - ファイルが存在し、読み込み可能であるかどうかを知る
- file_exists() - ファイルまたはディレクトリが存在するかどうか調べる
- fwrite() - バイナリセーフなファイル書き込み処理
agrenier at assertex dot com ¶
9 years ago
starrychloe at yahoo dot com ¶
5 years ago
To Darek and F Dot: About group permissions, there is this note in the php.ini file:
; By default, Safe Mode does a UID compare check when
; opening files. If you want to relax this to a GID compare,
; then turn on safe_mode_gid.
safe_mode_gid = Off
darek at fauxaddress dot com ¶
7 years ago
It appears that is_writable() does not check full permissions of a file to determine whether the current user can write to it. For example, with Apache running as user 'www', and a member of the group 'wheel', is_writable() returns false on a file like
-rwxrwxr-x root wheel /etc/some.file
JimmyNighthawk ¶
7 years ago
Regarding you might recognize your files on your web contructed by your PHP-scripts are grouped as NOBODY you can avoid this problem by setting up an FTP-Connection ("ftp_connect", "ftp_raw", etc.) and use methods like "ftp_fput" to create these [instead of giving out rights so you can use the usual "unsecure" way]. This will give the files created not the GROUP NOBODY - it will give out the GROUP your FTP-Connection via your FTP-Program uses, too.
Furthermore you might want to hash the password for the FTP-Connection - then check out:
http://dev.mysql.com/doc/mysql/en/Password_hashing.html
gr ¶
2 years ago
The results of this function seems to be not cached :
Tested on linux and windows
<?php
chmod($s_pathFichier, 0400);
echo'<pre>';var_dump(is_writable($s_pathFichier));echo'</pre>';
chmod($s_pathFichier, 04600);
echo'<pre>';var_dump(is_writable($s_pathFichier));echo'</pre>';
exit;
?>
legolas558 d0t users dot sf dot net ¶
6 years ago
This is the latest version of is__writable() I could come up with.
It can accept files or folders, but folders should end with a trailing slash! The function attempts to actually write a file, so it will correctly return true when a file/folder can be written to when the user has ACL write access to it.
<?php
function is__writable($path) {
//will work in despite of Windows ACLs bug
//NOTE: use a trailing slash for folders!!!
//see http://bugs.php.net/bug.php?id=27609
//see http://bugs.php.net/bug.php?id=30931
if ($path{strlen($path)-1}=='/') // recursively return a temporary file path
return is__writable($path.uniqid(mt_rand()).'.tmp');
else if (is_dir($path))
return is__writable($path.'/'.uniqid(mt_rand()).'.tmp');
// check tmp file for read/write capabilities
$rm = file_exists($path);
$f = @fopen($path, 'a');
if ($f===false)
return false;
fclose($f);
if (!$rm)
unlink($path);
return true;
}
?>
legolas558 dot sourceforge comma net ¶
6 years ago
Since looks like the Windows ACLs bug "wont fix" (see http://bugs.php.net/bug.php?id=27609) I propose this alternative function:
<?php
function is__writable($path) {
if ($path{strlen($path)-1}=='/')
return is__writable($path.uniqid(mt_rand()).'.tmp');
if (file_exists($path)) {
if (!($f = @fopen($path, 'r+')))
return false;
fclose($f);
return true;
}
if (!($f = @fopen($path, 'w')))
return false;
fclose($f);
unlink($path);
return true;
}
?>
It should work both on *nix and Windows
NOTE: you must use a trailing slash to identify a directory
greg at gregwhitescarver dotcalm ¶
7 years ago
In response to Darek:
We have two servers: one running PHP 5.0.4 and Apache 1.3.33, the other running PHP 4.3.5 and Apache 1.3.27. The PHP 4 server exhibits the behavior you are describing, with is_writable() returning 'false' even though the www user is in the group that owns the file, but the PHP 5 server is returning 'true.'
claude dot paroz at ne dot ch ¶
9 years ago
Under Windows, it only returns the read-only attribute status, not the actual permissions (ACL).
See http://bugs.php.net/bug.php?id=27609
wuhai ¶
5 years ago
I was trying to create a new file using fwrite, and i had the following error. Any idea?
Warning: fwrite(): supplied argument is not a valid stream resource in
haccel at email dot com ¶
6 years ago
Ooooops, sorry! My mistake. is__writable should be:
<?php
function is__writable($path)
{
if ($path{strlen($path)-1}=='/') //Start function again with tmp file...
return is__writable($path.uniqid(mt_rand()).'.tmp');
elseif (ereg('.tmp', $path))
{ //Check tmp file for read/write capabilities
if (!($f = @fopen($path, 'w+')))
return false;
fclose($f);
unlink($path);
return true;
}
else //We have a path error.
return 0; // Or return error - invalid path...
}
?>
The original could've deleted a folder if the path was invalid to start with (no trailing slash..) and the folder was writable to begin with...
haccel at email dot com ¶
6 years ago
Be careful of legolas558 dot sourceforge comma net's example, try this instead:
<?php
function is__writable($path)
{
if ($path{strlen($path)-1}=='/')
return is__writable($path.uniqid(mt_rand()).'.tmp');
elseif (file_exists($path) && ereg('.tmp', $path))
{
if (!($f = @fopen($path, 'w+')))
return false;
fclose($f);
unlink($path);
return true;
}
else
return 0; // Or return error - invalid path...
}
?>
Nils Kuebler ¶
7 years ago
this one recursivly checks if a folder and all its contents are writeable
<?php
function is_removeable($dir)
{
$folder = opendir($dir);
while($file = readdir( $folder ))
if($file != '.' && $file != '..' &&
( !is_writable( $dir."/".$file ) ||
( is_dir( $dir."/".$file ) && !is_removeable( $dir."/".$file ) ) ))
{
closedir($dir);
return false;
}
closedir($dir);
return true;
}
?>
