1<?php 2/** 3 * File IO functions 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Andreas Gohr <andi@splitbrain.org> 7 */ 8 9 if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); 10 require_once(DOKU_INC.'inc/common.php'); 11 12/** 13 * Removes empty directories 14 * 15 * @todo use safemode hack 16 * @author Andreas Gohr <andi@splitbrain.org> 17 */ 18function io_sweepNS($id){ 19 global $conf; 20 21 //scan all namespaces 22 while(($id = getNS($id)) !== false){ 23 $dir = $conf['datadir'].'/'.str_replace(':','/',$id); 24 $dir = utf8_encodeFN($dir); 25 26 //try to delete dir else return 27 if(!@rmdir($dir)) return; 28 } 29} 30 31/** 32 * Returns content of $file as cleaned string. 33 * 34 * Uses gzip if extension is .gz 35 * 36 * @author Andreas Gohr <andi@splitbrain.org> 37 */ 38function io_readFile($file){ 39 $ret = ''; 40 if(@file_exists($file)){ 41 if(substr($file,-3) == '.gz'){ 42 $ret = join('',gzfile($file)); 43 }else{ 44 $ret = join('',file($file)); 45 } 46 } 47 return cleanText($ret); 48} 49 50/** 51 * Saves $content to $file. 52 * 53 * If the third parameter is set to true the given content 54 * will be appended. 55 * 56 * Uses gzip if extension is .gz 57 * 58 * @author Andreas Gohr <andi@splitbrain.org> 59 * @return bool true on success 60 */ 61function io_saveFile($file,$content,$append=false){ 62 $mode = ($append) ? 'ab' : 'wb'; 63 64 io_makeFileDir($file); 65 io_lock($file); 66 if(substr($file,-3) == '.gz'){ 67 $fh = @gzopen($file,$mode.'9'); 68 if(!$fh){ 69 msg("Writing $file failed",-1); 70 return false; 71 } 72 gzwrite($fh, $content); 73 gzclose($fh); 74 }else{ 75 $fh = @fopen($file,$mode); 76 if(!$fh){ 77 msg("Writing $file failed",-1); 78 return false; 79 } 80 fwrite($fh, $content); 81 fclose($fh); 82 } 83 io_unlock($file); 84 return true; 85} 86 87/** 88 * Delete exact linematch for $badline from $file. 89 * 90 * Be sure to include the trailing newline in $badline 91 * 92 * Uses gzip if extension is .gz 93 * 94 * @author Steven Danz <steven-danz@kc.rr.com> 95 * @return bool true on success 96 */ 97function io_deleteFromFile($file,$badline){ 98 if (!@file_exists($file)) return true; 99 100 io_lock($file); 101 102 // load into array 103 if(substr($file,-3) == '.gz'){ 104 $lines = gzfile($file); 105 }else{ 106 $lines = file($file); 107 } 108 109 // remove all matching lines 110 $pos = array_search($badline,$lines); //return null or false if not found 111 while(is_int($pos)){ 112 unset($lines[$pos]); 113 $pos = array_search($badline,$lines); 114 } 115 116 if(count($lines)){ 117 $content = join('',$lines); 118 if(substr($file,-3) == '.gz'){ 119 $fh = @gzopen($file,'wb9'); 120 if(!$fh){ 121 msg("Removing content from $file failed",-1); 122 return false; 123 } 124 gzwrite($fh, $content); 125 gzclose($fh); 126 }else{ 127 $fh = @fopen($file,'wb'); 128 if(!$fh){ 129 msg("Removing content from $file failed",-1); 130 return false; 131 } 132 fwrite($fh, $content); 133 fclose($fh); 134 } 135 }else{ 136 @unlink($file); 137 } 138 139 io_unlock($file); 140 return true; 141} 142 143/** 144 * Tries to lock a file 145 * 146 * Locking is only done for io_savefile and uses directories 147 * inside $conf['lockdir'] 148 * 149 * It waits maximal 3 seconds for the lock, after this time 150 * the lock is assumed to be stale and the function goes on 151 * 152 * @author Andreas Gohr <andi@splitbrain.org> 153 */ 154function io_lock($file){ 155 global $conf; 156 // no locking if safemode hack 157 if($conf['safemodehack']) return; 158 159 $lockDir = $conf['lockdir'].'/'.md5($file); 160 @ignore_user_abort(1); 161 162 163 $timeStart = time(); 164 do { 165 //waited longer than 3 seconds? -> stale lock 166 if ((time() - $timeStart) > 3) break; 167 $locked = @mkdir($lockDir); 168 } while ($locked === false); 169} 170 171/** 172 * Unlocks a file 173 * 174 * @author Andreas Gohr <andi@splitbrain.org> 175 */ 176function io_unlock($file){ 177 global $conf; 178 // no locking if safemode hack 179 if($conf['safemodehack']) return; 180 181 $lockDir = $conf['lockdir'].'/'.md5($file); 182 @rmdir($lockDir); 183 @ignore_user_abort(0); 184} 185 186/** 187 * Create the directory needed for the given file 188 * 189 * @author Andreas Gohr <andi@splitbrain.org> 190 */ 191function io_makeFileDir($file){ 192 global $conf; 193 194 $dir = dirname($file); 195 umask($conf['dmask']); 196 if(!is_dir($dir)){ 197 io_mkdir_p($dir) || msg("Creating directory $dir failed",-1); 198 } 199 umask($conf['umask']); 200} 201 202/** 203 * Creates a directory hierachy. 204 * 205 * @link http://www.php.net/manual/en/function.mkdir.php 206 * @author <saint@corenova.com> 207 * @author Andreas Gohr <andi@splitbrain.org> 208 */ 209function io_mkdir_p($target){ 210 global $conf; 211 if (is_dir($target)||empty($target)) return 1; // best case check first 212 if (@file_exists($target) && !is_dir($target)) return 0; 213 //recursion 214 if (io_mkdir_p(substr($target,0,strrpos($target,'/')))){ 215 if($conf['safemodehack']){ 216 $dir = preg_replace('/^'.preg_quote(realpath($conf['ftp']['root']),'/').'/','', $target); 217 return io_mkdir_ftp($dir); 218 }else{ 219 return @mkdir($target,0777); // crawl back up & create dir tree 220 } 221 } 222 return 0; 223} 224 225/** 226 * Creates a directory using FTP 227 * 228 * This is used when the safemode workaround is enabled 229 * 230 * @author <andi@splitbrain.org> 231 */ 232function io_mkdir_ftp($dir){ 233 global $conf; 234 235 if(!function_exists('ftp_connect')){ 236 msg("FTP support not found - safemode workaround not usable",-1); 237 return false; 238 } 239 240 $conn = @ftp_connect($conf['ftp']['host'],$conf['ftp']['port'],10); 241 if(!$conn){ 242 msg("FTP connection failed",-1); 243 return false; 244 } 245 246 if(!@ftp_login($conn, $conf['ftp']['user'], $conf['ftp']['pass'])){ 247 msg("FTP login failed",-1); 248 return false; 249 } 250 251 //create directory 252 $ok = @ftp_mkdir($conn, $dir); 253 //set permissions (using the directory umask) 254 @ftp_site($conn,sprintf("CHMOD %04o %s",(0777 - $conf['dmask']),$dir)); 255 256 @ftp_close($conn); 257 return $ok; 258} 259 260/** 261 * downloads a file from the net and saves it to the given location 262 * 263 * @author Andreas Gohr <andi@splitbrain.org> 264 * @todo Add size limit 265 */ 266function io_download($url,$file){ 267 $fp = @fopen($url,"rb"); 268 if(!$fp) return false; 269 270 $kb = 0; 271 $now = time(); 272 273 while(!feof($fp)){ 274 if($kb++ > 2048 || (time() - $now) > 45){ 275 //abort on 2 MB and timeout on 45 sec 276 return false; 277 } 278 $cont.= fread($fp,1024); 279 } 280 fclose($fp); 281 282 $fp2 = @fopen($file,"w"); 283 if(!$fp2) return false; 284 fwrite($fp2,$cont); 285 fclose($fp2); 286 return true; 287} 288 289/** 290 * Runs an external command and returns it's output as string 291 * 292 * @author Harry Brueckner <harry_b@eml.cc> 293 * @author Andreas Gohr <andi@splitbrain.org> 294 * @deprecated 295 */ 296function io_runcmd($cmd){ 297 $fh = popen($cmd, "r"); 298 if(!$fh) return false; 299 $ret = ''; 300 while (!feof($fh)) { 301 $ret .= fread($fh, 8192); 302 } 303 pclose($fh); 304 return $ret; 305} 306 307 308//Setup VIM: ex: et ts=2 enc=utf-8 : 309