|
chmod
Changes file mode
(PHP 4, PHP 5)
Code Examples / Notes » chmodhalf-dead
[Editor's note: That is due the fact Win32 systems treat premissions. You do not really have any other levels but read-only. Maxim] On WinME with apache chmod also works to a certain limit. What happens is that apparently only the first number is counted, so 0666 (read-write) is the same as 0777, 0644, 0600, etc, and 0444 (read-only) is the same as 477, 400, etc. ..didn't test 0500 series info
When using ftp_rawlist, in order to get the chmod number from the attributes, i use this code: <?php function chmodnum($mode) { $realmode = ""; $legal = array("","w","r","x","-"); $attarray = preg_split("//",$mode); for($i=0;$i<count($attarray);$i++){ if($key = array_search($attarray[$i],$legal)){ $realmode .= $legal[$key]; } } $mode = str_pad($realmode,9,'-'); $trans = array('-'=>'0','r'=>'4','w'=>'2','x'=>'1'); $mode = strtr($mode,$trans); $newmode = ''; $newmode .= $mode[0]+$mode[1]+$mode[2]; $newmode .= $mode[3]+$mode[4]+$mode[5]; $newmode .= $mode[6]+$mode[7]+$mode[8]; return $newmode; } ?> some examples: drwxr-xr-x => 755 drwxr-xr-x => 755 dr-xr-xr-x => 555 drwxr-xr-x => 755 drwxr-xr-x => 755 drwxr-xr-x => 755 drwxr-xr-x => 755 drwxrwxrwt => 776 drwxr-xr-x => 755 drwxr-xr-x => 755 lrwxrwxrwx => 777 used some of already posted code... oliver hankeln
Well, you don't need octals. You need a value that can easily computed and remembered if printed in octal. 511 (decimal) is the same as 777 (octal). So it's the same wether you write chmod("foo",511) or chmod("foo",0777) The latter is just better readable. gnettles2
Usually when you're trying to write to af file, you'll need to chmod the file to something like 666 or 755. You can use a command to chmod the file for you, which is especially useful when you're making a script where you're setting it up so that your users don't have to peform a bunch of actions to setup the script. When i wrote my news program script, I only had two files. install.php and config.php. All you had to do was chmod install.php to 666 and open it up in a web browser and answer a few questions. The script itself setup the rest of the files and chmodded them for you.
masha
Usefull reference: Value Permission Level 400 Owner Read 200 Owner Write 100 Owner Execute 40 Group Read 20 Group Write 10 Group Execute 4 Global Read 2 Global Write 1 Global Execute (taken from http://www.onlamp.com/pub/a/php/2003/02/06/php_foundations.html) jazeps basko
To convert 'rwxr-xr--' to a number representation of chmod, i use this: <?php function chmodnum($mode) { $mode = str_pad($mode,9,'-'); $trans = array('-'=>'0','r'=>'4','w'=>'2','x'=>'1'); $mode = strtr($mode,$trans); $newmode = ''; $newmode .= $mode[0]+$mode[1]+$mode[2]; $newmode .= $mode[3]+$mode[4]+$mode[5]; $newmode .= $mode[6]+$mode[7]+$mode[8]; return $newmode; } ?> agrenier
This function will chmod a $filename before writing to it if: 1 - It exists 2 - It is not writeable 3 - PHP has permission to chmod files If PHP can't chmod, then the script will end. Otherwise it will attempt to write to a new file. <?php function file_write($filename, $flag, &$content) { if (file_exists($filename)) { if (!is_writable($filename)) { if (!chmod($filename, 0666)) { echo "Cannot change the mode of file ($filename)"; exit; }; } } if (!$fp = @fopen($filename, $flag)) { 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; } } ?> neosmart technologies
The program mentioned below (CHMOD-Win) has been rewritten since, and CHMOD-Win version 3.0 is available for download at http://neosmart.net/dl.php?id=4 It is a conversion utility for CHMOD on Windows and ACL on Linux, comes in handy for installing commercial scripts or defining security policies. webmaster
Thanks for your code, "imoldgreg at o2 dot co dot uk". I am using it for an instalation script that has to CHMOD a bunch of files. I have found it faster to use the same connectino for each, as shown below. <?php // Thanks to "imoldgreg at o2 dot co dot uk" for the base 'CHMOD via FTP' script. function chmod_open() { // Use your own FTP info $ftp_user_name = 'chmod@XXXXXXXXX.com'; $ftp_user_pass = 'XXXXXXXXXX'; $ftp_root = '/'; $ftp_server = 'localhost'; $conn_id = ftp_connect($ftp_server); $login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass); return $conn_id; } function chmod_file($conn_id, $permissions, $path) { if (ftp_site($conn_id, 'CHMOD ' . $permissions . ' ' . $ftp_root . $path) !== false) { return TRUE; } else { return FALSE; } } function chmod_close($conn_id) { ftp_close($conn_id); } // CHMOD the required setup files // Connect to the FTP $conn_id = chmod_open(); // CHMOD each file and echo the results echo chmod_file($conn_id, 777, 'master/cache/') ? 'CHMODed successfully!' : 'Error'; echo chmod_file($conn_id, 777, 'master/files/') ? 'CHMODed successfully!' : 'Error'; echo chmod_file($conn_id, 777, 'master/store/') ? 'CHMODed successfully!' : 'Error'; echo chmod_file($conn_id, 766, 'master/config.php') ? 'CHMODed successfully!' : 'Error'; echo chmod_file($conn_id, 777, 'master/images/avatars/upload/') ? 'CHMODed successfully!' : 'Error'; // Close the connection chmod_close($conn_id); ?> Here, the same FTP connection is used for each CHMOD command, making the execute time lower. This is essential for me, since my script is also copying a bunch of files. til_roque
Problem: you are trying to circumvent SAFE_MODE setting that prevents you from using chmod() on files you uploaded via a regular ftp client, because php may run as user 'nobody', which is not the user from your ftp session. using ini_set() won't work using ftp_chmod() won't work either Solution: copy file to some temorary directory. delete original file altogether. copy temporary file back to original location. do the chmod() hodgman
My PHP script refused to delete read-only files (which is probably a good thing), but I couldnt find out how to fix this on windows. The solution is simple, i just replaced <?php @unlink( $entry ); ?> with: <?php @chmod( $entry, 0777 ); @unlink( $entry ); ?> chmod isnt supposed to work on windows, but 0777 seems to clear the read only flag, and 0444 seems to set the read only flag. martin
Just for those peoples can't remeber the codes 777 and so on I just created a small class :-) <?php class Chmod { private $dir; private $modes = array('owner' => 0 , 'group' => 0 , 'public' => 0); public function setOwnermodes($read,$write,$execute) { $this->modes['owner'] = $this->setMode($read,$write,$execute); } public function setGroupmodes($read,$write,$execute) { $this->modes['group'] = $this->setMode($read,$write,$execute); } public function setPublicmodes($read,$write,$execute) { $this->modes['public'] = $this->setMode($read,$write,$execute); } public function getMode() { return 0 . $this->modes['owner'] . $this->modes['group'] . $this->modes['public']; } private function setMode($r,$w,$e) { $mode = 0; if($r) $mode+=4; if($w) $mode+=2; if($e) $mode+=1; return $mode; } } $test = new Chmod; $test->setOwnermodes(true,true,true); $test->setGroupmodes(true,true,true); $test->setPublicmodes(true,true,true); chmod($dir , $test->getMode()); // chmods $dir to 0777 ?> sticky bit avenger
Just a little hint. I was once adwised to set the 'sticky bit', i.e. use 1777 as chmod-value. Do NOT do this if you don't have root privileges. When 'sticky bit' is set ONLY the fileuser can delete it afterwards, typically 'httpd' or something like that in case of an upload-script for example. I was unaware of this and actually had to make a script for deleting these files as I could not do this from ftp/ssh even though I did have read/write/execute access to both files and folders. Use simply '0777' or similiar.
ff7cayn
It does work on Windows. I use Win 98 with the Sambar Server. The only chmods allowed are the 775 and 666 mod. 775 for non-writeable and 666 for writeable. The only thing is that the usergroups doesn't work. Note: the 0 at the start doesn't work with windows. use only the decimal kind. Have fun :) pmichaud
In the previous post, stickybit avenger writes: Just a little hint. I was once adwised to set the 'sticky bit', i.e. use 1777 as chmod-value... Note that in order to set the sticky bit on a file one must use '01777' (oct) and not '1777' (dec) as the parameter to chmod: <?php chmod("file",01777); // correct chmod("file",1777); // incorrect, same as chmod("file",01023), causing no owner permissions! ?> Rule of thumb: always prefix octal mode values with a zero. mmj048
If you want to use a string for the second parameter, including user input, you MUST use octdec. http://www.php.net/octdec raven_25041980
If you have a mode as a string, chmod will insanely mess up your permissions. Instead of using <?php @chmod($file_or_dir_name, $mode); ?> use <?php @chmod(file_or_dir_name, intval($mode, 8)); ?> where 8 -> the base to convert into. You need octals, baby, for chmod... More on intval here: http://www.php.net/manual/en/function.intval.php neil
If you get a warning like chmod(): Operation not permitted in /home/folder/public_html/admin/includefiles/fileupload.php on line 24 You can use the ftp_site() function to send a CHMOD command through. <?php $ftp_details['ftp_user_name'] = $row['username']; $ftp_details['ftp_user_pass'] = $row['password']; $ftp_details['ftp_root'] = '/public_html/'; $ftp_details['ftp_server'] = 'ftp'.$_SERVER['HTTP_HOST']; function chmod_11oo10($path, $mod, $ftp_details) { // extract ftp details (array keys as variable names) extract ($ftp_details); // set up basic connection $conn_id = ftp_connect($ftp_server); // login with username and password $login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass); // try to chmod $path directory if (ftp_site($conn_id, 'CHMOD '.$mod.' '.$ftp_root.$path) !== false) { $success=TRUE; } else { $success=FALSE; } // close the connection ftp_close($conn_id); return $success; } ?> The key thing to remember is that the document root and the ftp root are not the same. e.g. document root may be "/home/folder/public_html/" but the ftp root might be "/public_html/" Hope this helps someone. You might need this solution if you are on a shared server. agrenier
If you find that chmod does not work on your file and that a new file cannot be created, first try to chmod the directory where the file is being created to 0666/0777. Then PHP should be able to write/append files with mode 0644.
alex
If you cannot chmod files/directories with PHP because of safe_mode restrictions, but you can use FTP to chmod them, simply use PHP's FTP-functions (eg. ftp_chmod or ftp_site) instead. Not as efficient, but works.
memp
If you are storing your mode in a variable like $mode = 0755; you will run into the inevitable octal mode problem. An easy way around that is to use the octdec() function. chmod("some_filename.ext", octdec($mode)); jon
if 'mode' is held in a variable and is and octal value you need to convert it to decimal before passing it to the function: chmod ($filename, octdec($mode)) redeyeleader
Here's a version that works with PHP 5.x - I use this to watermark images on a shared server. <?php // Connect to the FTP to chmod the file via FTP $ftpUserName = 'username'; $ftpUserPass = 'userpass'; $ftpServer = 'ftp.example.com'; $ftpConn = ftp_connect($ftpServer); if (!$ftpConn) { die("Unable to connect to $ftpServer"); } if (@ftp_login($conn_id, $ftpUserName, $ftpUserPass)) { echo "Connected as $ftpUserName @ $ftpServer"; } else { echo "Couldn't connect as $ftpUserName"; ftp_close($ftpConn); die("Closed connection to $ftpServer"); } //Now change permissions to 666 or whatever you need echo ftp_chmod($ftpConn, 0666, $ftpFilename) ? "CHMOD successful!" : 'Error'; // do what you need here //Now change permissions back to 644 or whatever echo ftp_chmod($ftpConn, 0644, $ftpFilename) ? "CHMOD successful!" : 'Error'; // Close the connection ftp_close($conn_id); ?> zual__
greate ftp newfolder=dir; chmod --dir change 777; <?php $ftp_server='server'; $conn_id = ftp_connect("$ftp_server"); ftp_login($conn_id, user, password); ftp_mkdir($conn_id, dir/dir); ftp_site($conn_id, 'CHMOD 777, dir/dir'); ftp_close($conn_id); ?> haasje
For recursive chmod'ing see the function below. Only really usefull when chmod'ing a tree containing directories only, jet, since you don't want an executable bit on a regular file. Who completes the function so it's accepting strings like "g+w", and it's as usefull as unix "chmod -R" ? ;-) <?php function chmod_R($path, $filemode) { if (!is_dir($path)) return chmod($path, $filemode); $dh = opendir($path); while ($file = readdir($dh)) { if($file != '.' && $file != '..') { $fullpath = $path.'/'.$file; if(!is_dir($fullpath)) { if (!chmod($fullpath, $filemode)) return FALSE; } else { if (!chmod_R($fullpath, $filemode)) return FALSE; } } } closedir($dh); if(chmod($path, $filemode)) return TRUE; else return FALSE; } ?> info
As you might have noticed there is a minor bug in webmaster at danopia dot 5gigs dot com's code: You have to set $ftp_root variable outside the function chmod_open() and have to set it as global within the chmod_file() function. With these patches the code really works fine. THX! Ben perfectweb
As noted by others below... 1) you cannot pass a string to chmod() as the mode, and 2) decimals work as well as octals for the mode. If you need to come up with the mode on the fly (maybe based on user input) and want to use something like: $mode = '0'.$owner.$group.$public; you can use your $mode (which is a string) with chmod like this: <?php // octal mode in a string i.e. '0755' $mode = '0'.$owner.$group.$public; $mode_dec = octdec($mode); // convert octal mode to decimal chmod($filename, $mode_dec); ?> imoldgreg
an update to 'neil at 11 out of 10's code for changing mode using FTP. changes: proper array added within the function (better for those of us who only need to connect to one ftp server) so only the mode and directory name need to be passed. the octal added, for completeness and predictable stability. function changemode($xcite) { $ftp_details = array( ftp_user_name => 'username', ftp_user_pass => 'password', ftp_user_root => '/public_html/', ftp_server => 'ftp.something.org' ); $path = "public"; $mod = intval($xcite, 8); // extract ftp details (array keys as variable names) extract ($ftp_details); // set up basic connection $conn_id = ftp_connect($ftp_server); // login with username and password $login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass); // try to chmod $path directory if (ftp_site($conn_id, 'CHMOD '.$mod.' '.$ftp_root.$path) !== false) { $success=TRUE; } else { $success=FALSE; } // close the connection ftp_close($conn_id); return $success; } then call it where required, an example: changemode(777, directory); if (@copy("$tempname", "$fullfilename")) $done = "yes"; changemode(755, directory); for those of you, like me, who were looking for a way to make an 'un-hackable' uploader, here's the closest i got, now for a field test, good luck! fernando
about chmod, Problably you have a local server to simulate your scripts before upload them to the server. No matter if you use Apache under windows or IIS , a chmod instruction like chmod($filename,O777) may not work because windows does not handle that kind of permission's format. So being in your local server, if you have a only read file and you try to erase, it will show that you dont have permissions even when you have already executed your chmod instrucction correctly. Just up the script it must work well in your internet server if it is a linux machine sobre chmod, Probablemente usas un servidor local para probar tus scripts antes de subirlos al servidor en internet. No importa si usas Apache bajo windows o IIS, una instruccion como chmod(nombre_archivo,O777) podrá no trabajar por que windows no maneja esa estructura para definir los permisos. Estando en tu servidor local, si tienes un archivo de solo lectura y tratas de borrarlo, se mostrará un error diciendo que no tienes permisos aún despúes de haber ejecutado chmod correctamente. Sube tu script, si tu servidor es una máquina linux, el script trabajará sin problemas en internet. Fernando Yepes C. ambriel_angel
<?php error_reporting(E_ERROR | E_PARSE); /* Makes is so Directories are not browseable to the public, removing only the Public = Read permission, while leaving the other chmod permissions for the file in tact. If you have exectue already on, and read off, public viewers will only be able to view files through links, but not browse around to see what's inside of directories and see what you've got laying around. */ //------------------------------------------------------- // Get file mode // Get file permissions supported by chmod function getmod($filename) { $val = 0; $perms = fileperms($filename); // Owner; User $val += (($perms & 0x0100) ? 0x0100 : 0x0000); //Read $val += (($perms & 0x0080) ? 0x0080 : 0x0000); //Write $val += (($perms & 0x0040) ? 0x0040 : 0x0000); //Execute // Group $val += (($perms & 0x0020) ? 0x0020 : 0x0000); //Read $val += (($perms & 0x0010) ? 0x0010 : 0x0000); //Write $val += (($perms & 0x0008) ? 0x0008 : 0x0000); //Execute // Global; World $val += (($perms & 0x0004) ? 0x0004 : 0x0000); //Read $val += (($perms & 0x0002) ? 0x0002 : 0x0000); //Write $val += (($perms & 0x0001) ? 0x0001 : 0x0000); //Execute // Misc $val += (($perms & 0x40000) ? 0x40000 : 0x0000); //temporary file (01000000) $val += (($perms & 0x80000) ? 0x80000 : 0x0000); //compressed file (02000000) $val += (($perms & 0x100000) ? 0x100000 : 0x0000); //sparse file (04000000) $val += (($perms & 0x0800) ? 0x0800 : 0x0000); //Hidden file (setuid bit) (04000) $val += (($perms & 0x0400) ? 0x0400 : 0x0000); //System file (setgid bit) (02000) $val += (($perms & 0x0200) ? 0x0200 : 0x0000); //Archive bit (sticky bit) (01000) return $val; } //------------------------------------------------------- // Find out if file has mode function hasmod($perms, $permission) { # User Read = 0400 (256), Write = 0200 (128), Execute = 0100 (64) # Group Read = 0040 (32), Write = 0020 (16), Execute = 0010 (8) # Public Read = 0004 (4), Write = 0002 (2), Execute = 0001 (1) return (($perms & $permission) == $permission); } //------------------------------------------------------- // Take the read option off of all the subdirectories of the included path function pathlock($dir, $listall = false, $testrun = true) { echo "START @ " . date("F j, Y, h:i:s A") . " "; echo ($testrun ? '**Test Run Activated (no changes will be made).** ' : '**Live Run Activated.** '); echo $dir . " is our directory. \n"; echo "[...IN PROGRESS...] "; $file_list = ''; $stack[] = $dir; while ($stack) { $current_dir = array_pop($stack); if ($dh = opendir($current_dir)) { while (($file = readdir($dh)) !== false) { if ($file !== '.' AND $file !== '..') { $current_file = "{$current_dir}/{$file}"; if (is_dir($current_file)) { // BEG ADD PATH $mode = getmod($current_file); //Get the mode $HasPubRead = hasmod($mode,4); if ($HasPubRead || $listall) { // Can the public read this dir? //====================================== $ch = true; $take = 0; // Change the mode: if ($HasPubRead) { $take = 4; // Value for Public Read. 4 is the same in octal and decimal. if (!$testrun) { $ch = chmod($current_file, $mode-$take); } } echo $current_file . ",current=" . decoct($mode) . (($mode!==$mode-$take) ? ",new=" . decoct($mode-$take) : '') . ($ch ? '' : ',FAILED') . " \n"; } // end if hasmod // END ADD PATH $stack[] = $current_file; } // if if_dir } //if ($file !== '.' AND $file !== '..') } //while (($file = readdir($dh)) !== false) } //if ($dh = opendir($current_dir)) } // while ($stack) echo " COMPLETE @ " . date("F j, Y, h:i:s A") . " \n"; return; //return $path_list; } // end function //------------------------------------------------------- //listall Show all folders, even one's we're not going to process? //testrun Do a test run without making any changes pathlock($_SERVER["DOCUMENT_ROOT"],false,true); // listall?=false, testrun?=true ?> |
Change Languagebasename chgrp chmod chown clearstatcache copy delete dirname disk_free_space disk_total_space diskfreespace fclose feof fflush fgetc fgetcsv fgets fgetss file_exists file_get_contents file_put_contents file fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype flock fnmatch fopen fpassthru fputcsv fputs fread fscanf fseek fstat ftell ftruncate fwrite glob is_dir is_executable is_file is_link is_readable is_uploaded_file is_writable is_writeable lchgrp lchown link linkinfo lstat mkdir move_uploaded_file parse_ini_file pathinfo pclose popen readfile readlink realpath rename rewind rmdir set_file_buffer stat symlink tempnam tmpfile touch umask unlink |