xref: /dokuwiki/inc/io.php (revision ee33a34725046a56589daea1b2957f357d1836aa)
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 * Uses gzip if extension is .gz
54 *
55 * @author  Andreas Gohr <andi@splitbrain.org>
56 * @return bool true on success
57 */
58function io_saveFile($file,$content){
59  io_makeFileDir($file);
60  io_lock($file);
61  if(substr($file,-3) == '.gz'){
62    $fh = @gzopen($file,'wb9');
63    if(!$fh){
64      msg("Writing $file failed",-1);
65      return false;
66    }
67    gzwrite($fh, $content);
68    gzclose($fh);
69  }else{
70    $fh = @fopen($file,'wb');
71    if(!$fh){
72      msg("Writing $file failed",-1);
73      return false;
74    }
75    fwrite($fh, $content);
76    fclose($fh);
77  }
78  io_unlock($file);
79  return true;
80}
81
82/**
83 * Tries to lock a file
84 *
85 * Locking is only done for io_savefile and uses directories
86 * inside $conf['lockdir']
87 *
88 * It waits maximal 3 seconds for the lock, after this time
89 * the lock is assumed to be stale and the function goes on
90 *
91 * @author Andreas Gohr <andi@splitbrain.org>
92 */
93function io_lock($file){
94  global $conf;
95  // no locking if safemode hack
96  if($conf['safemodehack']) return;
97
98  $lockDir = $conf['lockdir'].'/'.md5($file);
99  @ignore_user_abort(1);
100
101
102  $timeStart = time();
103  do {
104    //waited longer than 3 seconds? -> stale lock
105    if ((time() - $timeStart) > 3) break;
106    $locked = @mkdir($lockDir);
107  } while ($locked === false);
108}
109
110/**
111 * Unlocks a file
112 *
113 * @author Andreas Gohr <andi@splitbrain.org>
114 */
115function io_unlock($file){
116  global $conf;
117  // no locking if safemode hack
118  if($conf['safemodehack']) return;
119
120  $lockDir = $conf['lockdir'].'/'.md5($file);
121  @rmdir($lockDir);
122  @ignore_user_abort(0);
123}
124
125/**
126 * Create the directory needed for the given file
127 *
128 * @author  Andreas Gohr <andi@splitbrain.org>
129 */
130function io_makeFileDir($file){
131  global $conf;
132
133  $dir = dirname($file);
134  if($conf['safemodehack']){
135    $dir = preg_replace('/^'.preg_quote(realpath($conf['ftp']['root']),'/').'/','',$dir);
136  }
137  umask($conf['dmask']);
138  if(!is_dir($dir)){
139    io_mkdir_p($dir) || msg("Creating directory $dir failed",-1);
140  }
141  umask($conf['umask']);
142}
143
144/**
145 * Creates a directory hierachy.
146 *
147 * @link    http://www.php.net/manual/en/function.mkdir.php
148 * @author  <saint@corenova.com>
149 * @author  Andreas Gohr <andi@splitbrain.org>
150 */
151function io_mkdir_p($target){
152  global $conf;
153  if (is_dir($target)||empty($target)) return 1; // best case check first
154  if (@file_exists($target) && !is_dir($target)) return 0;
155  //recursion
156  if (io_mkdir_p(substr($target,0,strrpos($target,'/')))){
157    if($conf['safemodehack']){
158      return io_mkdir_ftp($target);
159    }else{
160      return @mkdir($target,0777); // crawl back up & create dir tree
161    }
162  }
163  return 0;
164}
165
166/**
167 * Creates a directory using FTP
168 *
169 * This is used when the safemode workaround is enabled
170 *
171 * @author <andi@splitbrain.org>
172 */
173function io_mkdir_ftp($dir){
174  global $conf;
175
176  if(!function_exists('ftp_connect')){
177    msg("FTP support not found - safemode workaround not usable",-1);
178    return false;
179  }
180
181  $conn = @ftp_connect($conf['ftp']['host'],$conf['ftp']['port'],10);
182  if(!$conn){
183    msg("FTP connection failed",-1);
184    return false;
185  }
186
187  if(!@ftp_login($conn, $conf['ftp']['user'], $conf['ftp']['pass'])){
188    msg("FTP login failed",-1);
189    return false;
190  }
191
192//FIXME silence those commands again!
193  //create directory
194  $ok = ftp_mkdir($conn, $dir);
195  //set permissions (using the directory umask)
196  ftp_site($conn,sprintf("CHMOD %04o %s",(0777 - $conf['dmask']),$dir));
197
198  ftp_close($conn);
199  return $ok;
200}
201
202/**
203 * downloads a file from the net and saves it to the given location
204 *
205 * @author Andreas Gohr <andi@splitbrain.org>
206 * @todo   Add size limit
207 */
208function io_download($url,$file){
209  $fp = @fopen($url,"rb");
210  if(!$fp) return false;
211
212  $kb  = 0;
213  $now = time();
214
215  while(!feof($fp)){
216    if($kb++ > 2048 || (time() - $now) > 45){
217      //abort on 2 MB and timeout on 45 sec
218      return false;
219    }
220    $cont.= fread($fp,1024);
221  }
222  fclose($fp);
223
224  $fp2 = @fopen($file,"w");
225  if(!$fp2) return false;
226  fwrite($fp2,$cont);
227  fclose($fp2);
228  return true;
229}
230
231/**
232 * Runs an external command and returns it's output as string
233 *
234 * @author Harry Brueckner <harry_b@eml.cc>
235 * @author Andreas Gohr <andi@splitbrain.org>
236 * @deprecated
237 */
238function io_runcmd($cmd){
239  $fh = popen($cmd, "r");
240  if(!$fh) return false;
241  $ret = '';
242  while (!feof($fh)) {
243    $ret .= fread($fh, 8192);
244  }
245  pclose($fh);
246  return $ret;
247}
248
249
250//Setup VIM: ex: et ts=2 enc=utf-8 :
251