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 require_once(DOKU_INC.'inc/HTTPClient.php'); 12 13/** 14 * Removes empty directories 15 * 16 * @todo use safemode hack 17 * @author Andreas Gohr <andi@splitbrain.org> 18 */ 19function io_sweepNS($id,$basedir='datadir'){ 20 global $conf; 21 22 //scan all namespaces 23 while(($id = getNS($id)) !== false){ 24 $dir = $conf[$basedir].'/'.utf8_encodeFN(str_replace(':','/',$id)); 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,$clean=true){ 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 if($clean){ 48 return cleanText($ret); 49 }else{ 50 return $ret; 51 } 52} 53 54/** 55 * Saves $content to $file. 56 * 57 * If the third parameter is set to true the given content 58 * will be appended. 59 * 60 * Uses gzip if extension is .gz 61 * 62 * @author Andreas Gohr <andi@splitbrain.org> 63 * @return bool true on success 64 */ 65function io_saveFile($file,$content,$append=false){ 66 global $conf; 67 $mode = ($append) ? 'ab' : 'wb'; 68 69 $fileexists = file_exists($file); 70 io_makeFileDir($file); 71 io_lock($file); 72 if(substr($file,-3) == '.gz'){ 73 $fh = @gzopen($file,$mode.'9'); 74 if(!$fh){ 75 msg("Writing $file failed",-1); 76 return false; 77 } 78 gzwrite($fh, $content); 79 gzclose($fh); 80 }else{ 81 $fh = @fopen($file,$mode); 82 if(!$fh){ 83 msg("Writing $file failed",-1); 84 return false; 85 } 86 fwrite($fh, $content); 87 fclose($fh); 88 } 89 90 if(!$fileexists and $conf['fperm']) chmod($file, $conf['fperm']); 91 io_unlock($file); 92 return true; 93} 94 95/** 96 * Delete exact linematch for $badline from $file. 97 * 98 * Be sure to include the trailing newline in $badline 99 * 100 * Uses gzip if extension is .gz 101 * 102 * 2005-10-14 : added regex option -- Christopher Smith <chris@jalakai.co.uk> 103 * 104 * @author Steven Danz <steven-danz@kc.rr.com> 105 * @return bool true on success 106 */ 107function io_deleteFromFile($file,$badline,$regex=false){ 108 if (!@file_exists($file)) return true; 109 110 io_lock($file); 111 112 // load into array 113 if(substr($file,-3) == '.gz'){ 114 $lines = gzfile($file); 115 }else{ 116 $lines = file($file); 117 } 118 119 // remove all matching lines 120 if ($regex) { 121 $lines = preg_grep($badline,$lines,PREG_GREP_INVERT); 122 } else { 123 $pos = array_search($badline,$lines); //return null or false if not found 124 while(is_int($pos)){ 125 unset($lines[$pos]); 126 $pos = array_search($badline,$lines); 127 } 128 } 129 130 if(count($lines)){ 131 $content = join('',$lines); 132 if(substr($file,-3) == '.gz'){ 133 $fh = @gzopen($file,'wb9'); 134 if(!$fh){ 135 msg("Removing content from $file failed",-1); 136 return false; 137 } 138 gzwrite($fh, $content); 139 gzclose($fh); 140 }else{ 141 $fh = @fopen($file,'wb'); 142 if(!$fh){ 143 msg("Removing content from $file failed",-1); 144 return false; 145 } 146 fwrite($fh, $content); 147 fclose($fh); 148 } 149 }else{ 150 @unlink($file); 151 } 152 153 io_unlock($file); 154 return true; 155} 156 157/** 158 * Tries to lock a file 159 * 160 * Locking is only done for io_savefile and uses directories 161 * inside $conf['lockdir'] 162 * 163 * It waits maximal 3 seconds for the lock, after this time 164 * the lock is assumed to be stale and the function goes on 165 * 166 * @author Andreas Gohr <andi@splitbrain.org> 167 */ 168function io_lock($file){ 169 global $conf; 170 // no locking if safemode hack 171 if($conf['safemodehack']) return; 172 173 $lockDir = $conf['lockdir'].'/'.md5($file); 174 @ignore_user_abort(1); 175 176 $timeStart = time(); 177 do { 178 //waited longer than 3 seconds? -> stale lock 179 if ((time() - $timeStart) > 3) break; 180 $locked = @mkdir($lockDir, $conf['dmode']); 181 if($locked && $conf['dperm']) chmod($lockDir, $conf['dperm']); 182 } while ($locked === false); 183} 184 185/** 186 * Unlocks a file 187 * 188 * @author Andreas Gohr <andi@splitbrain.org> 189 */ 190function io_unlock($file){ 191 global $conf; 192 // no locking if safemode hack 193 if($conf['safemodehack']) return; 194 195 $lockDir = $conf['lockdir'].'/'.md5($file); 196 @rmdir($lockDir); 197 @ignore_user_abort(0); 198} 199 200/** 201 * Create the directory needed for the given file 202 * 203 * @author Andreas Gohr <andi@splitbrain.org> 204 */ 205function io_makeFileDir($file){ 206 global $conf; 207 208 $dir = dirname($file); 209 if(!@is_dir($dir)){ 210 io_mkdir_p($dir) || msg("Creating directory $dir failed",-1); 211 } 212} 213 214/** 215 * Creates a directory hierachy. 216 * 217 * @link http://www.php.net/manual/en/function.mkdir.php 218 * @author <saint@corenova.com> 219 * @author Andreas Gohr <andi@splitbrain.org> 220 */ 221function io_mkdir_p($target){ 222 global $conf; 223 if (@is_dir($target)||empty($target)) return 1; // best case check first 224 if (@file_exists($target) && !is_dir($target)) return 0; 225 //recursion 226 if (io_mkdir_p(substr($target,0,strrpos($target,'/')))){ 227 if($conf['safemodehack']){ 228 $dir = preg_replace('/^'.preg_quote(realpath($conf['ftp']['root']),'/').'/','', $target); 229 return io_mkdir_ftp($dir); 230 }else{ 231 $ret = @mkdir($target,$conf['dmode']); // crawl back up & create dir tree 232 if($ret && $conf['dperm']) chmod($target, $conf['dperm']); 233 return $ret; 234 } 235 } 236 return 0; 237} 238 239/** 240 * Creates a directory using FTP 241 * 242 * This is used when the safemode workaround is enabled 243 * 244 * @author <andi@splitbrain.org> 245 */ 246function io_mkdir_ftp($dir){ 247 global $conf; 248 249 if(!function_exists('ftp_connect')){ 250 msg("FTP support not found - safemode workaround not usable",-1); 251 return false; 252 } 253 254 $conn = @ftp_connect($conf['ftp']['host'],$conf['ftp']['port'],10); 255 if(!$conn){ 256 msg("FTP connection failed",-1); 257 return false; 258 } 259 260 if(!@ftp_login($conn, $conf['ftp']['user'], $conf['ftp']['pass'])){ 261 msg("FTP login failed",-1); 262 return false; 263 } 264 265 //create directory 266 $ok = @ftp_mkdir($conn, $dir); 267 //set permissions 268 @ftp_site($conn,sprintf("CHMOD %04o %s",$conf['dmode'],$dir)); 269 270 @ftp_close($conn); 271 return $ok; 272} 273 274/** 275 * downloads a file from the net and saves it 276 * 277 * if $useAttachment is false, 278 * - $file is the full filename to save the file, incl. path 279 * - if successful will return true, false otherwise 280 281 * if $useAttachment is true, 282 * - $file is the directory where the file should be saved 283 * - if successful will return the name used for the saved file, false otherwise 284 * 285 * @author Andreas Gohr <andi@splitbrain.org> 286 * @author Chris Smith <chris@jalakai.co.uk> 287 */ 288function io_download($url,$file,$useAttachment=false,$defaultName=''){ 289 global $conf; 290 $http = new DokuHTTPClient(); 291 $http->max_bodysize = 2*1024*1024; //max. 2MB 292 $http->timeout = 25; //max. 25 sec 293 294 $data = $http->get($url); 295 if(!$data) return false; 296 297 if ($useAttachment) { 298 $name = ''; 299 if (isset($http->resp_headers['content-disposition'])) { 300 $content_disposition = $http->resp_headers['content-disposition']; 301 $match=array(); 302 if (is_string($content_disposition) && 303 preg_match('/attachment;\s*filename\s*=\s*"([^"]*)"/i', $content_disposition, $match)) { 304 305 $name = basename($match[1]); 306 } 307 308 } 309 310 if (!$name) { 311 if (!$defaultName) return false; 312 $name = $defaultName; 313 } 314 315 $file = $file.$name; 316 } 317 318 $fileexists = file_exists($file); 319 $fp = @fopen($file,"w"); 320 if(!$fp) return false; 321 fwrite($fp,$data); 322 fclose($fp); 323 if(!$fileexists and $conf['fperm']) chmod($file, $conf['fperm']); 324 if ($useAttachment) return $name; 325 return true; 326} 327 328/** 329 * Windows compatible rename 330 * 331 * rename() can not overwrite existing files on Windows 332 * this function will use copy/unlink instead 333 */ 334function io_rename($from,$to){ 335 global $conf; 336 if(!@rename($from,$to)){ 337 if(@copy($from,$to)){ 338 if($conf['fperm']) chmod($file, $conf['fperm']); 339 @unlink($from); 340 return true; 341 } 342 return false; 343 } 344 return true; 345} 346 347 348/** 349 * Runs an external command and returns it's output as string 350 * 351 * @author Harry Brueckner <harry_b@eml.cc> 352 * @author Andreas Gohr <andi@splitbrain.org> 353 * @deprecated 354 */ 355function io_runcmd($cmd){ 356 $fh = popen($cmd, "r"); 357 if(!$fh) return false; 358 $ret = ''; 359 while (!feof($fh)) { 360 $ret .= fread($fh, 8192); 361 } 362 pclose($fh); 363 return $ret; 364} 365 366//Setup VIM: ex: et ts=2 enc=utf-8 : 367