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'); 11*9b307a83SAndreas 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 */ 1953d6ccfeSandifunction io_sweepNS($id){ 2053d6ccfeSandi global $conf; 2153d6ccfeSandi 2253d6ccfeSandi //scan all namespaces 2353d6ccfeSandi while(($id = getNS($id)) !== false){ 2453d6ccfeSandi $dir = $conf['datadir'].'/'.str_replace(':','/',$id); 2553d6ccfeSandi $dir = utf8_encodeFN($dir); 2653d6ccfeSandi 2753d6ccfeSandi //try to delete dir else return 2853d6ccfeSandi if(!@rmdir($dir)) return; 2953d6ccfeSandi } 3053d6ccfeSandi} 3153d6ccfeSandi 3253d6ccfeSandi/** 3315fae107Sandi * Returns content of $file as cleaned string. 3415fae107Sandi * 3515fae107Sandi * Uses gzip if extension is .gz 3615fae107Sandi * 3715fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 38f3f0262cSandi */ 39f3f0262cSandifunction io_readFile($file){ 40f3f0262cSandi $ret = ''; 41f3f0262cSandi if(@file_exists($file)){ 42f3f0262cSandi if(substr($file,-3) == '.gz'){ 43f3f0262cSandi $ret = join('',gzfile($file)); 44f3f0262cSandi }else{ 45f3f0262cSandi $ret = join('',file($file)); 46f3f0262cSandi } 47f3f0262cSandi } 48f3f0262cSandi return cleanText($ret); 49f3f0262cSandi} 50f3f0262cSandi 51f3f0262cSandi/** 5215fae107Sandi * Saves $content to $file. 53f3f0262cSandi * 541380fc45SAndreas Gohr * If the third parameter is set to true the given content 551380fc45SAndreas Gohr * will be appended. 561380fc45SAndreas Gohr * 5715fae107Sandi * Uses gzip if extension is .gz 5815fae107Sandi * 5915fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 6015fae107Sandi * @return bool true on success 61f3f0262cSandi */ 621380fc45SAndreas Gohrfunction io_saveFile($file,$content,$append=false){ 631380fc45SAndreas Gohr $mode = ($append) ? 'ab' : 'wb'; 641380fc45SAndreas Gohr 65f3f0262cSandi io_makeFileDir($file); 6690eb8392Sandi io_lock($file); 67f3f0262cSandi if(substr($file,-3) == '.gz'){ 681380fc45SAndreas Gohr $fh = @gzopen($file,$mode.'9'); 69f3f0262cSandi if(!$fh){ 70f3f0262cSandi msg("Writing $file failed",-1); 71f3f0262cSandi return false; 72f3f0262cSandi } 73f3f0262cSandi gzwrite($fh, $content); 74f3f0262cSandi gzclose($fh); 75f3f0262cSandi }else{ 761380fc45SAndreas Gohr $fh = @fopen($file,$mode); 77f3f0262cSandi if(!$fh){ 78f3f0262cSandi msg("Writing $file failed",-1); 79f3f0262cSandi return false; 80f3f0262cSandi } 81f3f0262cSandi fwrite($fh, $content); 82f3f0262cSandi fclose($fh); 83f3f0262cSandi } 8490eb8392Sandi io_unlock($file); 85f3f0262cSandi return true; 86f3f0262cSandi} 87f3f0262cSandi 88f3f0262cSandi/** 891380fc45SAndreas Gohr * Delete exact linematch for $badline from $file. 901380fc45SAndreas Gohr * 911380fc45SAndreas Gohr * Be sure to include the trailing newline in $badline 92b158d625SSteven Danz * 93b158d625SSteven Danz * Uses gzip if extension is .gz 94b158d625SSteven Danz * 95b158d625SSteven Danz * @author Steven Danz <steven-danz@kc.rr.com> 96b158d625SSteven Danz * @return bool true on success 97b158d625SSteven Danz */ 981380fc45SAndreas Gohrfunction io_deleteFromFile($file,$badline){ 991380fc45SAndreas Gohr if (!@file_exists($file)) return true; 1001380fc45SAndreas Gohr 101b158d625SSteven Danz io_lock($file); 1021380fc45SAndreas Gohr 1031380fc45SAndreas Gohr // load into array 104b158d625SSteven Danz if(substr($file,-3) == '.gz'){ 1051380fc45SAndreas Gohr $lines = gzfile($file); 106b158d625SSteven Danz }else{ 1071380fc45SAndreas Gohr $lines = file($file); 108b158d625SSteven Danz } 109b158d625SSteven Danz 1101380fc45SAndreas Gohr // remove all matching lines 1111380fc45SAndreas Gohr $pos = array_search($badline,$lines); //return null or false if not found 1121380fc45SAndreas Gohr while(is_int($pos)){ 1131380fc45SAndreas Gohr unset($lines[$pos]); 1141380fc45SAndreas Gohr $pos = array_search($badline,$lines); 115b158d625SSteven Danz } 116b158d625SSteven Danz 1171380fc45SAndreas Gohr if(count($lines)){ 1181380fc45SAndreas Gohr $content = join('',$lines); 119b158d625SSteven Danz if(substr($file,-3) == '.gz'){ 120b158d625SSteven Danz $fh = @gzopen($file,'wb9'); 121b158d625SSteven Danz if(!$fh){ 122b158d625SSteven Danz msg("Removing content from $file failed",-1); 123b158d625SSteven Danz return false; 124b158d625SSteven Danz } 125b158d625SSteven Danz gzwrite($fh, $content); 126b158d625SSteven Danz gzclose($fh); 127b158d625SSteven Danz }else{ 128b158d625SSteven Danz $fh = @fopen($file,'wb'); 129b158d625SSteven Danz if(!$fh){ 130b158d625SSteven Danz msg("Removing content from $file failed",-1); 131b158d625SSteven Danz return false; 132b158d625SSteven Danz } 133b158d625SSteven Danz fwrite($fh, $content); 134b158d625SSteven Danz fclose($fh); 135b158d625SSteven Danz } 136b158d625SSteven Danz }else{ 137b158d625SSteven Danz @unlink($file); 138b158d625SSteven Danz } 139b158d625SSteven Danz 140b158d625SSteven Danz io_unlock($file); 141b158d625SSteven Danz return true; 142b158d625SSteven Danz} 143b158d625SSteven Danz 144b158d625SSteven Danz/** 14590eb8392Sandi * Tries to lock a file 14690eb8392Sandi * 14790eb8392Sandi * Locking is only done for io_savefile and uses directories 14890eb8392Sandi * inside $conf['lockdir'] 14990eb8392Sandi * 15090eb8392Sandi * It waits maximal 3 seconds for the lock, after this time 15190eb8392Sandi * the lock is assumed to be stale and the function goes on 15290eb8392Sandi * 15390eb8392Sandi * @author Andreas Gohr <andi@splitbrain.org> 15490eb8392Sandi */ 15590eb8392Sandifunction io_lock($file){ 15690eb8392Sandi global $conf; 15790eb8392Sandi // no locking if safemode hack 15890eb8392Sandi if($conf['safemodehack']) return; 15990eb8392Sandi 16090eb8392Sandi $lockDir = $conf['lockdir'].'/'.md5($file); 16190eb8392Sandi @ignore_user_abort(1); 16290eb8392Sandi 16390eb8392Sandi 16490eb8392Sandi $timeStart = time(); 16590eb8392Sandi do { 16690eb8392Sandi //waited longer than 3 seconds? -> stale lock 16790eb8392Sandi if ((time() - $timeStart) > 3) break; 16890eb8392Sandi $locked = @mkdir($lockDir); 16990eb8392Sandi } while ($locked === false); 17090eb8392Sandi} 17190eb8392Sandi 17290eb8392Sandi/** 17390eb8392Sandi * Unlocks a file 17490eb8392Sandi * 17590eb8392Sandi * @author Andreas Gohr <andi@splitbrain.org> 17690eb8392Sandi */ 17790eb8392Sandifunction io_unlock($file){ 17890eb8392Sandi global $conf; 17990eb8392Sandi // no locking if safemode hack 18090eb8392Sandi if($conf['safemodehack']) return; 18190eb8392Sandi 18290eb8392Sandi $lockDir = $conf['lockdir'].'/'.md5($file); 18390eb8392Sandi @rmdir($lockDir); 18490eb8392Sandi @ignore_user_abort(0); 18590eb8392Sandi} 18690eb8392Sandi 18790eb8392Sandi/** 188f3f0262cSandi * Create the directory needed for the given file 18915fae107Sandi * 19015fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 191f3f0262cSandi */ 192f3f0262cSandifunction io_makeFileDir($file){ 193f3f0262cSandi global $conf; 194f3f0262cSandi 195f3f0262cSandi $dir = dirname($file); 196f3f0262cSandi umask($conf['dmask']); 197f3f0262cSandi if(!is_dir($dir)){ 198f3f0262cSandi io_mkdir_p($dir) || msg("Creating directory $dir failed",-1); 199f3f0262cSandi } 200f3f0262cSandi umask($conf['umask']); 201f3f0262cSandi} 202f3f0262cSandi 203f3f0262cSandi/** 204f3f0262cSandi * Creates a directory hierachy. 205f3f0262cSandi * 20615fae107Sandi * @link http://www.php.net/manual/en/function.mkdir.php 207f3f0262cSandi * @author <saint@corenova.com> 2083dc3a5f1Sandi * @author Andreas Gohr <andi@splitbrain.org> 209f3f0262cSandi */ 210f3f0262cSandifunction io_mkdir_p($target){ 2113dc3a5f1Sandi global $conf; 212f3f0262cSandi if (is_dir($target)||empty($target)) return 1; // best case check first 213f3f0262cSandi if (@file_exists($target) && !is_dir($target)) return 0; 2143dc3a5f1Sandi //recursion 2153dc3a5f1Sandi if (io_mkdir_p(substr($target,0,strrpos($target,'/')))){ 2163dc3a5f1Sandi if($conf['safemodehack']){ 217034138e2SRainer Weinhold $dir = preg_replace('/^'.preg_quote(realpath($conf['ftp']['root']),'/').'/','', $target); 218034138e2SRainer Weinhold return io_mkdir_ftp($dir); 2193dc3a5f1Sandi }else{ 220f3f0262cSandi return @mkdir($target,0777); // crawl back up & create dir tree 2213dc3a5f1Sandi } 2223dc3a5f1Sandi } 223f3f0262cSandi return 0; 224f3f0262cSandi} 225f3f0262cSandi 226f3f0262cSandi/** 2273dc3a5f1Sandi * Creates a directory using FTP 2283dc3a5f1Sandi * 2293dc3a5f1Sandi * This is used when the safemode workaround is enabled 2303dc3a5f1Sandi * 2313dc3a5f1Sandi * @author <andi@splitbrain.org> 2323dc3a5f1Sandi */ 2333dc3a5f1Sandifunction io_mkdir_ftp($dir){ 2343dc3a5f1Sandi global $conf; 2353dc3a5f1Sandi 2363dc3a5f1Sandi if(!function_exists('ftp_connect')){ 2373dc3a5f1Sandi msg("FTP support not found - safemode workaround not usable",-1); 2383dc3a5f1Sandi return false; 2393dc3a5f1Sandi } 2403dc3a5f1Sandi 2413dc3a5f1Sandi $conn = @ftp_connect($conf['ftp']['host'],$conf['ftp']['port'],10); 2423dc3a5f1Sandi if(!$conn){ 2433dc3a5f1Sandi msg("FTP connection failed",-1); 2443dc3a5f1Sandi return false; 2453dc3a5f1Sandi } 2463dc3a5f1Sandi 2473dc3a5f1Sandi if(!@ftp_login($conn, $conf['ftp']['user'], $conf['ftp']['pass'])){ 2483dc3a5f1Sandi msg("FTP login failed",-1); 2493dc3a5f1Sandi return false; 2503dc3a5f1Sandi } 2513dc3a5f1Sandi 2523dc3a5f1Sandi //create directory 253034138e2SRainer Weinhold $ok = @ftp_mkdir($conn, $dir); 2543dc3a5f1Sandi //set permissions (using the directory umask) 255034138e2SRainer Weinhold @ftp_site($conn,sprintf("CHMOD %04o %s",(0777 - $conf['dmask']),$dir)); 2563dc3a5f1Sandi 257034138e2SRainer Weinhold @ftp_close($conn); 2583dc3a5f1Sandi return $ok; 2593dc3a5f1Sandi} 2603dc3a5f1Sandi 2613dc3a5f1Sandi/** 262b625487dSandi * downloads a file from the net and saves it to the given location 263b625487dSandi * 264b625487dSandi * @author Andreas Gohr <andi@splitbrain.org> 265b625487dSandi */ 266b625487dSandifunction io_download($url,$file){ 267*9b307a83SAndreas Gohr $http = new DokuHTTPClient(); 268*9b307a83SAndreas Gohr $http->max_bodysize = 2*1024*1024; //max. 2MB 269*9b307a83SAndreas Gohr $http->timeout = 25; //max. 25 sec 270*9b307a83SAndreas Gohr 271*9b307a83SAndreas Gohr $data = $http->get($url); 272*9b307a83SAndreas Gohr if(!$data) return false; 273*9b307a83SAndreas Gohr 274*9b307a83SAndreas Gohr $fp = @fopen($file,"w"); 275b625487dSandi if(!$fp) return false; 276*9b307a83SAndreas Gohr fwrite($fp,$data); 277b625487dSandi fclose($fp); 278b625487dSandi return true; 279b625487dSandi} 280b625487dSandi 281b625487dSandi/** 282f3f0262cSandi * Runs an external command and returns it's output as string 28315fae107Sandi * 28415fae107Sandi * @author Harry Brueckner <harry_b@eml.cc> 28515fae107Sandi * @author Andreas Gohr <andi@splitbrain.org> 2863dc3a5f1Sandi * @deprecated 287f3f0262cSandi */ 288f3f0262cSandifunction io_runcmd($cmd){ 289f3f0262cSandi $fh = popen($cmd, "r"); 290f3f0262cSandi if(!$fh) return false; 291f3f0262cSandi $ret = ''; 292f3f0262cSandi while (!feof($fh)) { 293f3f0262cSandi $ret .= fread($fh, 8192); 294f3f0262cSandi } 295f3f0262cSandi pclose($fh); 296f3f0262cSandi return $ret; 297f3f0262cSandi} 298f3f0262cSandi 299340756e4Sandi 300340756e4Sandi//Setup VIM: ex: et ts=2 enc=utf-8 : 301