1ed7b5f09Sandi<?php 215fae107Sandi/** 315fae107Sandi * File IO functions 415fae107Sandi * 515fae107Sandi * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 615fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 715fae107Sandi */ 815fae107Sandi 9ed7b5f09Sandi if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); 10ed7b5f09Sandi require_once(DOKU_INC.'inc/common.php'); 11f3f0262cSandi 12f3f0262cSandi/** 1353d6ccfeSandi * Removes empty directories 1453d6ccfeSandi * 1553d6ccfeSandi * @todo use safemode hack 1653d6ccfeSandi * @author Andreas Gohr <andi@splitbrain.org> 1753d6ccfeSandi */ 1853d6ccfeSandifunction io_sweepNS($id){ 1953d6ccfeSandi global $conf; 2053d6ccfeSandi 2153d6ccfeSandi //scan all namespaces 2253d6ccfeSandi while(($id = getNS($id)) !== false){ 2353d6ccfeSandi $dir = $conf['datadir'].'/'.str_replace(':','/',$id); 2453d6ccfeSandi $dir = utf8_encodeFN($dir); 2553d6ccfeSandi 2653d6ccfeSandi //try to delete dir else return 2753d6ccfeSandi if(!@rmdir($dir)) return; 2853d6ccfeSandi } 2953d6ccfeSandi} 3053d6ccfeSandi 3153d6ccfeSandi/** 3215fae107Sandi * Returns content of $file as cleaned string. 3315fae107Sandi * 3415fae107Sandi * Uses gzip if extension is .gz 3515fae107Sandi * 3615fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 37f3f0262cSandi */ 38f3f0262cSandifunction io_readFile($file){ 39f3f0262cSandi $ret = ''; 40f3f0262cSandi if(@file_exists($file)){ 41f3f0262cSandi if(substr($file,-3) == '.gz'){ 42f3f0262cSandi $ret = join('',gzfile($file)); 43f3f0262cSandi }else{ 44f3f0262cSandi $ret = join('',file($file)); 45f3f0262cSandi } 46f3f0262cSandi } 47f3f0262cSandi return cleanText($ret); 48f3f0262cSandi} 49f3f0262cSandi 50f3f0262cSandi/** 5115fae107Sandi * Saves $content to $file. 52f3f0262cSandi * 5315fae107Sandi * Uses gzip if extension is .gz 5415fae107Sandi * 5515fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 5615fae107Sandi * @return bool true on success 57f3f0262cSandi */ 58f3f0262cSandifunction io_saveFile($file,$content){ 59f3f0262cSandi io_makeFileDir($file); 6090eb8392Sandi io_lock($file); 61f3f0262cSandi if(substr($file,-3) == '.gz'){ 62f3f0262cSandi $fh = @gzopen($file,'wb9'); 63f3f0262cSandi if(!$fh){ 64f3f0262cSandi msg("Writing $file failed",-1); 65f3f0262cSandi return false; 66f3f0262cSandi } 67f3f0262cSandi gzwrite($fh, $content); 68f3f0262cSandi gzclose($fh); 69f3f0262cSandi }else{ 70f3f0262cSandi $fh = @fopen($file,'wb'); 71f3f0262cSandi if(!$fh){ 72f3f0262cSandi msg("Writing $file failed",-1); 73f3f0262cSandi return false; 74f3f0262cSandi } 75f3f0262cSandi fwrite($fh, $content); 76f3f0262cSandi fclose($fh); 77f3f0262cSandi } 7890eb8392Sandi io_unlock($file); 79f3f0262cSandi return true; 80f3f0262cSandi} 81f3f0262cSandi 82f3f0262cSandi/** 83*b158d625SSteven Danz * Appends $content to $file. 84*b158d625SSteven Danz * 85*b158d625SSteven Danz * Uses gzip if extension is .gz 86*b158d625SSteven Danz * 87*b158d625SSteven Danz * @author Steven Danz <steven-danz@kc.rr.com> 88*b158d625SSteven Danz * @return bool true on success 89*b158d625SSteven Danz */ 90*b158d625SSteven Danzfunction io_appendFile($file,$content){ 91*b158d625SSteven Danz io_makeFileDir($file); 92*b158d625SSteven Danz io_lock($file); 93*b158d625SSteven Danz if(substr($file,-3) == '.gz'){ 94*b158d625SSteven Danz $fh = @gzopen($file,'ab9'); 95*b158d625SSteven Danz if(!$fh){ 96*b158d625SSteven Danz msg("Appending to $file failed",-1); 97*b158d625SSteven Danz return false; 98*b158d625SSteven Danz } 99*b158d625SSteven Danz gzwrite($fh, $content); 100*b158d625SSteven Danz gzclose($fh); 101*b158d625SSteven Danz }else{ 102*b158d625SSteven Danz $fh = @fopen($file,'ab'); 103*b158d625SSteven Danz if(!$fh){ 104*b158d625SSteven Danz msg("Appending to $file failed",-1); 105*b158d625SSteven Danz return false; 106*b158d625SSteven Danz } 107*b158d625SSteven Danz fwrite($fh, $content); 108*b158d625SSteven Danz fclose($fh); 109*b158d625SSteven Danz } 110*b158d625SSteven Danz io_unlock($file); 111*b158d625SSteven Danz return true; 112*b158d625SSteven Danz} 113*b158d625SSteven Danz 114*b158d625SSteven Danz/** 115*b158d625SSteven Danz * Delete exact match for $content from $file. 116*b158d625SSteven Danz * 117*b158d625SSteven Danz * Uses gzip if extension is .gz 118*b158d625SSteven Danz * 119*b158d625SSteven Danz * @author Steven Danz <steven-danz@kc.rr.com> 120*b158d625SSteven Danz * @return bool true on success 121*b158d625SSteven Danz */ 122*b158d625SSteven Danzfunction io_deleteFromFile($file,$remove){ 123*b158d625SSteven Danz if (@file_exists($file)) { 124*b158d625SSteven Danz io_lock($file); 125*b158d625SSteven Danz $content = ''; 126*b158d625SSteven Danz if(substr($file,-3) == '.gz'){ 127*b158d625SSteven Danz $mlist = gzfile($file); 128*b158d625SSteven Danz }else{ 129*b158d625SSteven Danz $mlist = file($file); 130*b158d625SSteven Danz } 131*b158d625SSteven Danz foreach ($mlist as $entry) { 132*b158d625SSteven Danz if ($entry != $remove) { 133*b158d625SSteven Danz $content = $content . $entry; 134*b158d625SSteven Danz } 135*b158d625SSteven Danz } 136*b158d625SSteven Danz 137*b158d625SSteven Danz if (!empty($content)) { 138*b158d625SSteven Danz if(substr($file,-3) == '.gz'){ 139*b158d625SSteven Danz $fh = @gzopen($file,'wb9'); 140*b158d625SSteven Danz if(!$fh){ 141*b158d625SSteven Danz msg("Removing content from $file failed",-1); 142*b158d625SSteven Danz return false; 143*b158d625SSteven Danz } 144*b158d625SSteven Danz gzwrite($fh, $content); 145*b158d625SSteven Danz gzclose($fh); 146*b158d625SSteven Danz }else{ 147*b158d625SSteven Danz $fh = @fopen($file,'wb'); 148*b158d625SSteven Danz if(!$fh){ 149*b158d625SSteven Danz msg("Removing content from $file failed",-1); 150*b158d625SSteven Danz return false; 151*b158d625SSteven Danz } 152*b158d625SSteven Danz fwrite($fh, $content); 153*b158d625SSteven Danz fclose($fh); 154*b158d625SSteven Danz } 155*b158d625SSteven Danz } else { 156*b158d625SSteven Danz @unlink($file); 157*b158d625SSteven Danz } 158*b158d625SSteven Danz 159*b158d625SSteven Danz io_unlock($file); 160*b158d625SSteven Danz } 161*b158d625SSteven Danz return true; 162*b158d625SSteven Danz} 163*b158d625SSteven Danz 164*b158d625SSteven Danz/** 16590eb8392Sandi * Tries to lock a file 16690eb8392Sandi * 16790eb8392Sandi * Locking is only done for io_savefile and uses directories 16890eb8392Sandi * inside $conf['lockdir'] 16990eb8392Sandi * 17090eb8392Sandi * It waits maximal 3 seconds for the lock, after this time 17190eb8392Sandi * the lock is assumed to be stale and the function goes on 17290eb8392Sandi * 17390eb8392Sandi * @author Andreas Gohr <andi@splitbrain.org> 17490eb8392Sandi */ 17590eb8392Sandifunction io_lock($file){ 17690eb8392Sandi global $conf; 17790eb8392Sandi // no locking if safemode hack 17890eb8392Sandi if($conf['safemodehack']) return; 17990eb8392Sandi 18090eb8392Sandi $lockDir = $conf['lockdir'].'/'.md5($file); 18190eb8392Sandi @ignore_user_abort(1); 18290eb8392Sandi 18390eb8392Sandi 18490eb8392Sandi $timeStart = time(); 18590eb8392Sandi do { 18690eb8392Sandi //waited longer than 3 seconds? -> stale lock 18790eb8392Sandi if ((time() - $timeStart) > 3) break; 18890eb8392Sandi $locked = @mkdir($lockDir); 18990eb8392Sandi } while ($locked === false); 19090eb8392Sandi} 19190eb8392Sandi 19290eb8392Sandi/** 19390eb8392Sandi * Unlocks a file 19490eb8392Sandi * 19590eb8392Sandi * @author Andreas Gohr <andi@splitbrain.org> 19690eb8392Sandi */ 19790eb8392Sandifunction io_unlock($file){ 19890eb8392Sandi global $conf; 19990eb8392Sandi // no locking if safemode hack 20090eb8392Sandi if($conf['safemodehack']) return; 20190eb8392Sandi 20290eb8392Sandi $lockDir = $conf['lockdir'].'/'.md5($file); 20390eb8392Sandi @rmdir($lockDir); 20490eb8392Sandi @ignore_user_abort(0); 20590eb8392Sandi} 20690eb8392Sandi 20790eb8392Sandi/** 208f3f0262cSandi * Create the directory needed for the given file 20915fae107Sandi * 21015fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 211f3f0262cSandi */ 212f3f0262cSandifunction io_makeFileDir($file){ 213f3f0262cSandi global $conf; 214f3f0262cSandi 215f3f0262cSandi $dir = dirname($file); 216f3f0262cSandi umask($conf['dmask']); 217f3f0262cSandi if(!is_dir($dir)){ 218f3f0262cSandi io_mkdir_p($dir) || msg("Creating directory $dir failed",-1); 219f3f0262cSandi } 220f3f0262cSandi umask($conf['umask']); 221f3f0262cSandi} 222f3f0262cSandi 223f3f0262cSandi/** 224f3f0262cSandi * Creates a directory hierachy. 225f3f0262cSandi * 22615fae107Sandi * @link http://www.php.net/manual/en/function.mkdir.php 227f3f0262cSandi * @author <saint@corenova.com> 2283dc3a5f1Sandi * @author Andreas Gohr <andi@splitbrain.org> 229f3f0262cSandi */ 230f3f0262cSandifunction io_mkdir_p($target){ 2313dc3a5f1Sandi global $conf; 232f3f0262cSandi if (is_dir($target)||empty($target)) return 1; // best case check first 233f3f0262cSandi if (@file_exists($target) && !is_dir($target)) return 0; 2343dc3a5f1Sandi //recursion 2353dc3a5f1Sandi if (io_mkdir_p(substr($target,0,strrpos($target,'/')))){ 2363dc3a5f1Sandi if($conf['safemodehack']){ 237034138e2SRainer Weinhold $dir = preg_replace('/^'.preg_quote(realpath($conf['ftp']['root']),'/').'/','', $target); 238034138e2SRainer Weinhold return io_mkdir_ftp($dir); 2393dc3a5f1Sandi }else{ 240f3f0262cSandi return @mkdir($target,0777); // crawl back up & create dir tree 2413dc3a5f1Sandi } 2423dc3a5f1Sandi } 243f3f0262cSandi return 0; 244f3f0262cSandi} 245f3f0262cSandi 246f3f0262cSandi/** 2473dc3a5f1Sandi * Creates a directory using FTP 2483dc3a5f1Sandi * 2493dc3a5f1Sandi * This is used when the safemode workaround is enabled 2503dc3a5f1Sandi * 2513dc3a5f1Sandi * @author <andi@splitbrain.org> 2523dc3a5f1Sandi */ 2533dc3a5f1Sandifunction io_mkdir_ftp($dir){ 2543dc3a5f1Sandi global $conf; 2553dc3a5f1Sandi 2563dc3a5f1Sandi if(!function_exists('ftp_connect')){ 2573dc3a5f1Sandi msg("FTP support not found - safemode workaround not usable",-1); 2583dc3a5f1Sandi return false; 2593dc3a5f1Sandi } 2603dc3a5f1Sandi 2613dc3a5f1Sandi $conn = @ftp_connect($conf['ftp']['host'],$conf['ftp']['port'],10); 2623dc3a5f1Sandi if(!$conn){ 2633dc3a5f1Sandi msg("FTP connection failed",-1); 2643dc3a5f1Sandi return false; 2653dc3a5f1Sandi } 2663dc3a5f1Sandi 2673dc3a5f1Sandi if(!@ftp_login($conn, $conf['ftp']['user'], $conf['ftp']['pass'])){ 2683dc3a5f1Sandi msg("FTP login failed",-1); 2693dc3a5f1Sandi return false; 2703dc3a5f1Sandi } 2713dc3a5f1Sandi 2723dc3a5f1Sandi //create directory 273034138e2SRainer Weinhold $ok = @ftp_mkdir($conn, $dir); 2743dc3a5f1Sandi //set permissions (using the directory umask) 275034138e2SRainer Weinhold @ftp_site($conn,sprintf("CHMOD %04o %s",(0777 - $conf['dmask']),$dir)); 2763dc3a5f1Sandi 277034138e2SRainer Weinhold @ftp_close($conn); 2783dc3a5f1Sandi return $ok; 2793dc3a5f1Sandi} 2803dc3a5f1Sandi 2813dc3a5f1Sandi/** 282b625487dSandi * downloads a file from the net and saves it to the given location 283b625487dSandi * 284b625487dSandi * @author Andreas Gohr <andi@splitbrain.org> 285b625487dSandi * @todo Add size limit 286b625487dSandi */ 287b625487dSandifunction io_download($url,$file){ 288b625487dSandi $fp = @fopen($url,"rb"); 289b625487dSandi if(!$fp) return false; 290b625487dSandi 2910e33fac4Sandi $kb = 0; 2920e33fac4Sandi $now = time(); 2930e33fac4Sandi 294b625487dSandi while(!feof($fp)){ 2950e33fac4Sandi if($kb++ > 2048 || (time() - $now) > 45){ 2960e33fac4Sandi //abort on 2 MB and timeout on 45 sec 2970e33fac4Sandi return false; 2980e33fac4Sandi } 299b625487dSandi $cont.= fread($fp,1024); 300b625487dSandi } 301b625487dSandi fclose($fp); 302b625487dSandi 303b625487dSandi $fp2 = @fopen($file,"w"); 304b625487dSandi if(!$fp2) return false; 305b625487dSandi fwrite($fp2,$cont); 306b625487dSandi fclose($fp2); 307b625487dSandi return true; 308b625487dSandi} 309b625487dSandi 310b625487dSandi/** 311f3f0262cSandi * Runs an external command and returns it's output as string 31215fae107Sandi * 31315fae107Sandi * @author Harry Brueckner <harry_b@eml.cc> 31415fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 3153dc3a5f1Sandi * @deprecated 316f3f0262cSandi */ 317f3f0262cSandifunction io_runcmd($cmd){ 318f3f0262cSandi $fh = popen($cmd, "r"); 319f3f0262cSandi if(!$fh) return false; 320f3f0262cSandi $ret = ''; 321f3f0262cSandi while (!feof($fh)) { 322f3f0262cSandi $ret .= fread($fh, 8192); 323f3f0262cSandi } 324f3f0262cSandi pclose($fh); 325f3f0262cSandi return $ret; 326f3f0262cSandi} 327f3f0262cSandi 328340756e4Sandi 329340756e4Sandi//Setup VIM: ex: et ts=2 enc=utf-8 : 330