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'); 119b307a83SAndreas Gohr require_once(DOKU_INC.'inc/HTTPClient.php'); 12f3f0262cSandi 13f3f0262cSandi/** 1453d6ccfeSandi * Removes empty directories 1553d6ccfeSandi * 1653d6ccfeSandi * @todo use safemode hack 1753d6ccfeSandi * @author Andreas Gohr <andi@splitbrain.org> 1853d6ccfeSandi */ 19755f1e03SAndreas Gohrfunction io_sweepNS($id,$basedir='datadir'){ 2053d6ccfeSandi global $conf; 2153d6ccfeSandi 2253d6ccfeSandi //scan all namespaces 2353d6ccfeSandi while(($id = getNS($id)) !== false){ 24755f1e03SAndreas Gohr $dir = $conf[$basedir].'/'.utf8_encodeFN(str_replace(':','/',$id)); 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 * 36ee4c4a1bSAndreas Gohr * If you want to use the returned value in unserialize 37ee4c4a1bSAndreas Gohr * be sure to set $clean to false! 38ee4c4a1bSAndreas Gohr * 3915fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 40f3f0262cSandi */ 41e34c0709SAndreas Gohrfunction io_readFile($file,$clean=true){ 42f3f0262cSandi $ret = ''; 43f3f0262cSandi if(@file_exists($file)){ 44f3f0262cSandi if(substr($file,-3) == '.gz'){ 45f3f0262cSandi $ret = join('',gzfile($file)); 46f3f0262cSandi }else{ 47f3f0262cSandi $ret = join('',file($file)); 48f3f0262cSandi } 49f3f0262cSandi } 50e34c0709SAndreas Gohr if($clean){ 51f3f0262cSandi return cleanText($ret); 52e34c0709SAndreas Gohr }else{ 53e34c0709SAndreas Gohr return $ret; 54e34c0709SAndreas Gohr } 55f3f0262cSandi} 56f3f0262cSandi 57f3f0262cSandi/** 5815fae107Sandi * Saves $content to $file. 59f3f0262cSandi * 601380fc45SAndreas Gohr * If the third parameter is set to true the given content 611380fc45SAndreas Gohr * will be appended. 621380fc45SAndreas Gohr * 6315fae107Sandi * Uses gzip if extension is .gz 6415fae107Sandi * 6515fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 6615fae107Sandi * @return bool true on success 67f3f0262cSandi */ 681380fc45SAndreas Gohrfunction io_saveFile($file,$content,$append=false){ 69ac9115b0STroels Liebe Bentsen global $conf; 701380fc45SAndreas Gohr $mode = ($append) ? 'ab' : 'wb'; 711380fc45SAndreas Gohr 72ac9115b0STroels Liebe Bentsen $fileexists = file_exists($file); 73f3f0262cSandi io_makeFileDir($file); 7490eb8392Sandi io_lock($file); 75f3f0262cSandi if(substr($file,-3) == '.gz'){ 761380fc45SAndreas Gohr $fh = @gzopen($file,$mode.'9'); 77f3f0262cSandi if(!$fh){ 78f3f0262cSandi msg("Writing $file failed",-1); 79f3f0262cSandi return false; 80f3f0262cSandi } 81f3f0262cSandi gzwrite($fh, $content); 82f3f0262cSandi gzclose($fh); 83f3f0262cSandi }else{ 841380fc45SAndreas Gohr $fh = @fopen($file,$mode); 85f3f0262cSandi if(!$fh){ 86f3f0262cSandi msg("Writing $file failed",-1); 87f3f0262cSandi return false; 88f3f0262cSandi } 89f3f0262cSandi fwrite($fh, $content); 90f3f0262cSandi fclose($fh); 91f3f0262cSandi } 92ac9115b0STroels Liebe Bentsen 931ca31cfeSAndreas Gohr if(!$fileexists and $conf['fperm']) chmod($file, $conf['fperm']); 9490eb8392Sandi io_unlock($file); 95f3f0262cSandi return true; 96f3f0262cSandi} 97f3f0262cSandi 98f3f0262cSandi/** 991380fc45SAndreas Gohr * Delete exact linematch for $badline from $file. 1001380fc45SAndreas Gohr * 1011380fc45SAndreas Gohr * Be sure to include the trailing newline in $badline 102b158d625SSteven Danz * 103b158d625SSteven Danz * Uses gzip if extension is .gz 104b158d625SSteven Danz * 1058b06d178Schris * 2005-10-14 : added regex option -- Christopher Smith <chris@jalakai.co.uk> 1068b06d178Schris * 107b158d625SSteven Danz * @author Steven Danz <steven-danz@kc.rr.com> 108b158d625SSteven Danz * @return bool true on success 109b158d625SSteven Danz */ 1108b06d178Schrisfunction io_deleteFromFile($file,$badline,$regex=false){ 1111380fc45SAndreas Gohr if (!@file_exists($file)) return true; 1121380fc45SAndreas Gohr 113b158d625SSteven Danz io_lock($file); 1141380fc45SAndreas Gohr 1151380fc45SAndreas Gohr // load into array 116b158d625SSteven Danz if(substr($file,-3) == '.gz'){ 1171380fc45SAndreas Gohr $lines = gzfile($file); 118b158d625SSteven Danz }else{ 1191380fc45SAndreas Gohr $lines = file($file); 120b158d625SSteven Danz } 121b158d625SSteven Danz 1221380fc45SAndreas Gohr // remove all matching lines 1238b06d178Schris if ($regex) { 1248b06d178Schris $lines = preg_grep($badline,$lines,PREG_GREP_INVERT); 1258b06d178Schris } else { 1261380fc45SAndreas Gohr $pos = array_search($badline,$lines); //return null or false if not found 1271380fc45SAndreas Gohr while(is_int($pos)){ 1281380fc45SAndreas Gohr unset($lines[$pos]); 1291380fc45SAndreas Gohr $pos = array_search($badline,$lines); 130b158d625SSteven Danz } 1318b06d178Schris } 132b158d625SSteven Danz 1331380fc45SAndreas Gohr if(count($lines)){ 1341380fc45SAndreas Gohr $content = join('',$lines); 135b158d625SSteven Danz if(substr($file,-3) == '.gz'){ 136b158d625SSteven Danz $fh = @gzopen($file,'wb9'); 137b158d625SSteven Danz if(!$fh){ 138b158d625SSteven Danz msg("Removing content from $file failed",-1); 139b158d625SSteven Danz return false; 140b158d625SSteven Danz } 141b158d625SSteven Danz gzwrite($fh, $content); 142b158d625SSteven Danz gzclose($fh); 143b158d625SSteven Danz }else{ 144b158d625SSteven Danz $fh = @fopen($file,'wb'); 145b158d625SSteven Danz if(!$fh){ 146b158d625SSteven Danz msg("Removing content from $file failed",-1); 147b158d625SSteven Danz return false; 148b158d625SSteven Danz } 149b158d625SSteven Danz fwrite($fh, $content); 150b158d625SSteven Danz fclose($fh); 151b158d625SSteven Danz } 152b158d625SSteven Danz }else{ 153b158d625SSteven Danz @unlink($file); 154b158d625SSteven Danz } 155b158d625SSteven Danz 156b158d625SSteven Danz io_unlock($file); 157b158d625SSteven Danz return true; 158b158d625SSteven Danz} 159b158d625SSteven Danz 160b158d625SSteven Danz/** 16190eb8392Sandi * Tries to lock a file 16290eb8392Sandi * 16390eb8392Sandi * Locking is only done for io_savefile and uses directories 16490eb8392Sandi * inside $conf['lockdir'] 16590eb8392Sandi * 16690eb8392Sandi * It waits maximal 3 seconds for the lock, after this time 16790eb8392Sandi * the lock is assumed to be stale and the function goes on 16890eb8392Sandi * 16990eb8392Sandi * @author Andreas Gohr <andi@splitbrain.org> 17090eb8392Sandi */ 17190eb8392Sandifunction io_lock($file){ 17290eb8392Sandi global $conf; 17390eb8392Sandi // no locking if safemode hack 17490eb8392Sandi if($conf['safemodehack']) return; 17590eb8392Sandi 17690eb8392Sandi $lockDir = $conf['lockdir'].'/'.md5($file); 17790eb8392Sandi @ignore_user_abort(1); 17890eb8392Sandi 17990eb8392Sandi $timeStart = time(); 18090eb8392Sandi do { 18190eb8392Sandi //waited longer than 3 seconds? -> stale lock 18290eb8392Sandi if ((time() - $timeStart) > 3) break; 18344881d27STroels Liebe Bentsen $locked = @mkdir($lockDir, $conf['dmode']); 184*77b98903SAndreas Gohr if($locked){ 185*77b98903SAndreas Gohr if($conf['dperm']) chmod($lockDir, $conf['dperm']); 186*77b98903SAndreas Gohr break; 187*77b98903SAndreas Gohr } 188*77b98903SAndreas Gohr usleep(50); 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); 2160d8850c4SAndreas Gohr if(!@is_dir($dir)){ 217f3f0262cSandi io_mkdir_p($dir) || msg("Creating directory $dir failed",-1); 218f3f0262cSandi } 219f3f0262cSandi} 220f3f0262cSandi 221f3f0262cSandi/** 222f3f0262cSandi * Creates a directory hierachy. 223f3f0262cSandi * 22415fae107Sandi * @link http://www.php.net/manual/en/function.mkdir.php 225f3f0262cSandi * @author <saint@corenova.com> 2263dc3a5f1Sandi * @author Andreas Gohr <andi@splitbrain.org> 227f3f0262cSandi */ 228f3f0262cSandifunction io_mkdir_p($target){ 2293dc3a5f1Sandi global $conf; 2300d8850c4SAndreas Gohr if (@is_dir($target)||empty($target)) return 1; // best case check first 231f3f0262cSandi if (@file_exists($target) && !is_dir($target)) return 0; 2323dc3a5f1Sandi //recursion 2333dc3a5f1Sandi if (io_mkdir_p(substr($target,0,strrpos($target,'/')))){ 2343dc3a5f1Sandi if($conf['safemodehack']){ 235034138e2SRainer Weinhold $dir = preg_replace('/^'.preg_quote(realpath($conf['ftp']['root']),'/').'/','', $target); 236034138e2SRainer Weinhold return io_mkdir_ftp($dir); 2373dc3a5f1Sandi }else{ 23844881d27STroels Liebe Bentsen $ret = @mkdir($target,$conf['dmode']); // crawl back up & create dir tree 2391ca31cfeSAndreas Gohr if($ret && $conf['dperm']) chmod($target, $conf['dperm']); 24044881d27STroels Liebe Bentsen return $ret; 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); 2741ca31cfeSAndreas Gohr //set permissions 2751ca31cfeSAndreas Gohr @ftp_site($conn,sprintf("CHMOD %04o %s",$conf['dmode'],$dir)); 2763dc3a5f1Sandi 277034138e2SRainer Weinhold @ftp_close($conn); 2783dc3a5f1Sandi return $ok; 2793dc3a5f1Sandi} 2803dc3a5f1Sandi 2813dc3a5f1Sandi/** 28273ccfcb9Schris * downloads a file from the net and saves it 28373ccfcb9Schris * 28473ccfcb9Schris * if $useAttachment is false, 28573ccfcb9Schris * - $file is the full filename to save the file, incl. path 28673ccfcb9Schris * - if successful will return true, false otherwise 28773ccfcb9Schris 28873ccfcb9Schris * if $useAttachment is true, 28973ccfcb9Schris * - $file is the directory where the file should be saved 29073ccfcb9Schris * - if successful will return the name used for the saved file, false otherwise 291b625487dSandi * 292b625487dSandi * @author Andreas Gohr <andi@splitbrain.org> 29373ccfcb9Schris * @author Chris Smith <chris@jalakai.co.uk> 294b625487dSandi */ 29573ccfcb9Schrisfunction io_download($url,$file,$useAttachment=false,$defaultName=''){ 296ac9115b0STroels Liebe Bentsen global $conf; 2979b307a83SAndreas Gohr $http = new DokuHTTPClient(); 2989b307a83SAndreas Gohr $http->max_bodysize = 2*1024*1024; //max. 2MB 2999b307a83SAndreas Gohr $http->timeout = 25; //max. 25 sec 3009b307a83SAndreas Gohr 3019b307a83SAndreas Gohr $data = $http->get($url); 3029b307a83SAndreas Gohr if(!$data) return false; 3039b307a83SAndreas Gohr 30473ccfcb9Schris if ($useAttachment) { 30573ccfcb9Schris $name = ''; 30673ccfcb9Schris if (isset($http->resp_headers['content-disposition'])) { 30773ccfcb9Schris $content_disposition = $http->resp_headers['content-disposition']; 308ce070a9fSchris $match=array(); 30973ccfcb9Schris if (is_string($content_disposition) && 310ce070a9fSchris preg_match('/attachment;\s*filename\s*=\s*"([^"]*)"/i', $content_disposition, $match)) { 31173ccfcb9Schris 31273ccfcb9Schris $name = basename($match[1]); 31373ccfcb9Schris } 31473ccfcb9Schris 31573ccfcb9Schris } 31673ccfcb9Schris 31773ccfcb9Schris if (!$name) { 31873ccfcb9Schris if (!$defaultName) return false; 31973ccfcb9Schris $name = $defaultName; 32073ccfcb9Schris } 32173ccfcb9Schris 32273ccfcb9Schris $file = $file.$name; 32373ccfcb9Schris } 32473ccfcb9Schris 325ac9115b0STroels Liebe Bentsen $fileexists = file_exists($file); 3269b307a83SAndreas Gohr $fp = @fopen($file,"w"); 327b625487dSandi if(!$fp) return false; 3289b307a83SAndreas Gohr fwrite($fp,$data); 329b625487dSandi fclose($fp); 3301ca31cfeSAndreas Gohr if(!$fileexists and $conf['fperm']) chmod($file, $conf['fperm']); 33173ccfcb9Schris if ($useAttachment) return $name; 332b625487dSandi return true; 333b625487dSandi} 334b625487dSandi 335b625487dSandi/** 336ac9115b0STroels Liebe Bentsen * Windows compatible rename 337bf5e5a5bSAndreas Gohr * 338bf5e5a5bSAndreas Gohr * rename() can not overwrite existing files on Windows 339bf5e5a5bSAndreas Gohr * this function will use copy/unlink instead 340bf5e5a5bSAndreas Gohr */ 341bf5e5a5bSAndreas Gohrfunction io_rename($from,$to){ 342ac9115b0STroels Liebe Bentsen global $conf; 343bf5e5a5bSAndreas Gohr if(!@rename($from,$to)){ 344bf5e5a5bSAndreas Gohr if(@copy($from,$to)){ 3451ca31cfeSAndreas Gohr if($conf['fperm']) chmod($file, $conf['fperm']); 346bf5e5a5bSAndreas Gohr @unlink($from); 347bf5e5a5bSAndreas Gohr return true; 348bf5e5a5bSAndreas Gohr } 349bf5e5a5bSAndreas Gohr return false; 350bf5e5a5bSAndreas Gohr } 351bf5e5a5bSAndreas Gohr return true; 352bf5e5a5bSAndreas Gohr} 353bf5e5a5bSAndreas Gohr 354bf5e5a5bSAndreas Gohr 355bf5e5a5bSAndreas Gohr/** 356f3f0262cSandi * Runs an external command and returns it's output as string 35715fae107Sandi * 35815fae107Sandi * @author Harry Brueckner <harry_b@eml.cc> 35915fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 3603dc3a5f1Sandi * @deprecated 361f3f0262cSandi */ 362f3f0262cSandifunction io_runcmd($cmd){ 363f3f0262cSandi $fh = popen($cmd, "r"); 364f3f0262cSandi if(!$fh) return false; 365f3f0262cSandi $ret = ''; 366f3f0262cSandi while (!feof($fh)) { 367f3f0262cSandi $ret .= fread($fh, 8192); 368f3f0262cSandi } 369f3f0262cSandi pclose($fh); 370f3f0262cSandi return $ret; 371f3f0262cSandi} 372f3f0262cSandi 3737421c3ccSAndreas Gohr/** 3747421c3ccSAndreas Gohr * Search a file for matching lines 3757421c3ccSAndreas Gohr * 3767421c3ccSAndreas Gohr * This is probably not faster than file()+preg_grep() but less 3777421c3ccSAndreas Gohr * memory intensive because not the whole file needs to be loaded 3787421c3ccSAndreas Gohr * at once. 3797421c3ccSAndreas Gohr * 3807421c3ccSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 3817421c3ccSAndreas Gohr * @param string $file The file to search 3827421c3ccSAndreas Gohr * @param string $pattern PCRE pattern 3837421c3ccSAndreas Gohr * @param int $max How many lines to return (0 for all) 3847421c3ccSAndreas Gohr * @param bool $baxkref When true returns array with backreferences instead of lines 3857421c3ccSAndreas Gohr * @return matching lines or backref, false on error 3867421c3ccSAndreas Gohr */ 3877421c3ccSAndreas Gohrfunction io_grep($file,$pattern,$max=0,$backref=false){ 3887421c3ccSAndreas Gohr $fh = @fopen($file,'r'); 3897421c3ccSAndreas Gohr if(!$fh) return false; 3907421c3ccSAndreas Gohr $matches = array(); 3917421c3ccSAndreas Gohr 3927421c3ccSAndreas Gohr $cnt = 0; 3937421c3ccSAndreas Gohr $line = ''; 3947421c3ccSAndreas Gohr while (!feof($fh)) { 3957421c3ccSAndreas Gohr $line .= fgets($fh, 4096); // read full line 3967421c3ccSAndreas Gohr if(substr($line,-1) != "\n") continue; 3977421c3ccSAndreas Gohr 3987421c3ccSAndreas Gohr // check if line matches 3997421c3ccSAndreas Gohr if(preg_match($pattern,$line,$match)){ 4007421c3ccSAndreas Gohr if($backref){ 4017421c3ccSAndreas Gohr $matches[] = $match; 4027421c3ccSAndreas Gohr }else{ 4037421c3ccSAndreas Gohr $matches[] = $line; 4047421c3ccSAndreas Gohr } 4057421c3ccSAndreas Gohr $cnt++; 4067421c3ccSAndreas Gohr } 4077421c3ccSAndreas Gohr if($max && $max == $cnt) break; 4087421c3ccSAndreas Gohr $line = ''; 4097421c3ccSAndreas Gohr } 4107421c3ccSAndreas Gohr fclose($fh); 4117421c3ccSAndreas Gohr return $matches; 4127421c3ccSAndreas Gohr} 4137421c3ccSAndreas Gohr 414340756e4Sandi//Setup VIM: ex: et ts=2 enc=utf-8 : 415