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