xref: /dokuwiki/inc/io.php (revision 55efc227eaeb2d480ff22837b78f89766b07fe5f)
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  umask($conf['dmask']);
135  if(!is_dir($dir)){
136    io_mkdir_p($dir) || msg("Creating directory $dir failed",-1);
137  }
138  umask($conf['umask']);
139}
140
141/**
142 * Creates a directory hierachy.
143 *
144 * @link    http://www.php.net/manual/en/function.mkdir.php
145 * @author  <saint@corenova.com>
146 * @author  Andreas Gohr <andi@splitbrain.org>
147 */
148function io_mkdir_p($target){
149  global $conf;
150  if (is_dir($target)||empty($target)) return 1; // best case check first
151  if (@file_exists($target) && !is_dir($target)) return 0;
152  //recursion
153  if (io_mkdir_p(substr($target,0,strrpos($target,'/')))){
154    if($conf['safemodehack']){
155      $dir = preg_replace('/^'.preg_quote(realpath($conf['ftp']['root']),'/').'/','', $target);
156      return io_mkdir_ftp($dir);
157    }else{
158      return @mkdir($target,0777); // crawl back up & create dir tree
159    }
160  }
161  return 0;
162}
163
164/**
165 * Creates a directory using FTP
166 *
167 * This is used when the safemode workaround is enabled
168 *
169 * @author <andi@splitbrain.org>
170 */
171function io_mkdir_ftp($dir){
172  global $conf;
173
174  if(!function_exists('ftp_connect')){
175    msg("FTP support not found - safemode workaround not usable",-1);
176    return false;
177  }
178
179  $conn = @ftp_connect($conf['ftp']['host'],$conf['ftp']['port'],10);
180  if(!$conn){
181    msg("FTP connection failed",-1);
182    return false;
183  }
184
185  if(!@ftp_login($conn, $conf['ftp']['user'], $conf['ftp']['pass'])){
186    msg("FTP login failed",-1);
187    return false;
188  }
189
190  //create directory
191  $ok = @ftp_mkdir($conn, $dir);
192  //set permissions (using the directory umask)
193  @ftp_site($conn,sprintf("CHMOD %04o %s",(0777 - $conf['dmask']),$dir));
194
195  @ftp_close($conn);
196  return $ok;
197}
198
199/**
200 * downloads a file from the net and saves it to the given location
201 *
202 * @author Andreas Gohr <andi@splitbrain.org>
203 * @todo   Add size limit
204 */
205function io_download($url,$file){
206  $fp = @fopen($url,"rb");
207  if(!$fp) return false;
208
209  $kb  = 0;
210  $now = time();
211
212  while(!feof($fp)){
213    if($kb++ > 2048 || (time() - $now) > 45){
214      //abort on 2 MB and timeout on 45 sec
215      return false;
216    }
217    $cont.= fread($fp,1024);
218  }
219  fclose($fp);
220
221  $fp2 = @fopen($file,"w");
222  if(!$fp2) return false;
223  fwrite($fp2,$cont);
224  fclose($fp2);
225  return true;
226}
227
228/**
229 * Runs an external command and returns it's output as string
230 *
231 * @author Harry Brueckner <harry_b@eml.cc>
232 * @author Andreas Gohr <andi@splitbrain.org>
233 * @deprecated
234 */
235function io_runcmd($cmd){
236  $fh = popen($cmd, "r");
237  if(!$fh) return false;
238  $ret = '';
239  while (!feof($fh)) {
240    $ret .= fread($fh, 8192);
241  }
242  pclose($fh);
243  return $ret;
244}
245
246
247//Setup VIM: ex: et ts=2 enc=utf-8 :
248