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