xref: /dokuwiki/inc/io.php (revision de86255546da549b16fa2a5f17f592831b6a1931)
1ed7b5f09Sandi<?php
215fae107Sandi/**
315fae107Sandi * File IO functions
415fae107Sandi *
515fae107Sandi * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
615fae107Sandi * @author     Andreas Gohr <andi@splitbrain.org>
715fae107Sandi */
815fae107Sandi
900976812SAndreas Gohr  if(!defined('DOKU_INC')) define('DOKU_INC',fullpath(dirname(__FILE__).'/../').'/');
10ed7b5f09Sandi  require_once(DOKU_INC.'inc/common.php');
119b307a83SAndreas Gohr  require_once(DOKU_INC.'inc/HTTPClient.php');
12cc7d0c94SBen Coburn  require_once(DOKU_INC.'inc/events.php');
13cc7d0c94SBen Coburn  require_once(DOKU_INC.'inc/utf8.php');
14f3f0262cSandi
15f3f0262cSandi/**
1653d6ccfeSandi * Removes empty directories
1753d6ccfeSandi *
18cc7d0c94SBen Coburn * Sends IO_NAMESPACE_DELETED events for 'pages' and 'media' namespaces.
19cc7d0c94SBen Coburn * Event data:
20cc7d0c94SBen Coburn * $data[0]    ns: The colon separated namespace path minus the trailing page name.
21cc7d0c94SBen Coburn * $data[1]    ns_type: 'pages' or 'media' namespace tree.
22cc7d0c94SBen Coburn *
2353d6ccfeSandi * @todo use safemode hack
24d186898bSAndreas Gohr * @param string $id      - a pageid, the namespace of that id will be tried to deleted
25d186898bSAndreas Gohr * @param string $basadir - the config name of the type to delete (datadir or mediadir usally)
26d186898bSAndreas Gohr * @returns bool - true if at least one namespace was deleted
2753d6ccfeSandi * @author  Andreas Gohr <andi@splitbrain.org>
28cc7d0c94SBen Coburn * @author Ben Coburn <btcoburn@silicodon.net>
2953d6ccfeSandi */
30755f1e03SAndreas Gohrfunction io_sweepNS($id,$basedir='datadir'){
3153d6ccfeSandi  global $conf;
32cc7d0c94SBen Coburn  $types = array ('datadir'=>'pages', 'mediadir'=>'media');
33cc7d0c94SBen Coburn  $ns_type = (isset($types[$basedir])?$types[$basedir]:false);
3453d6ccfeSandi
35d186898bSAndreas Gohr  $delone = false;
36d186898bSAndreas Gohr
3753d6ccfeSandi  //scan all namespaces
3853d6ccfeSandi  while(($id = getNS($id)) !== false){
39755f1e03SAndreas Gohr    $dir = $conf[$basedir].'/'.utf8_encodeFN(str_replace(':','/',$id));
4053d6ccfeSandi
4153d6ccfeSandi    //try to delete dir else return
42cc7d0c94SBen Coburn    if(@rmdir($dir)) {
43cc7d0c94SBen Coburn      if ($ns_type!==false) {
44cc7d0c94SBen Coburn        $data = array($id, $ns_type);
45d186898bSAndreas Gohr        $delone = true; // we deleted at least one dir
46cc7d0c94SBen Coburn        trigger_event('IO_NAMESPACE_DELETED', $data);
47cc7d0c94SBen Coburn      }
48d186898bSAndreas Gohr    } else { return $delone; }
49cc7d0c94SBen Coburn  }
50d186898bSAndreas Gohr  return $delone;
51cc7d0c94SBen Coburn}
52cc7d0c94SBen Coburn
53cc7d0c94SBen Coburn/**
54cc7d0c94SBen Coburn * Used to read in a DokuWiki page from file, and send IO_WIKIPAGE_READ events.
55cc7d0c94SBen Coburn *
56cc7d0c94SBen Coburn * Generates the action event which delegates to io_readFile().
57cc7d0c94SBen Coburn * Action plugins are allowed to modify the page content in transit.
58cc7d0c94SBen Coburn * The file path should not be changed.
59cc7d0c94SBen Coburn *
60cc7d0c94SBen Coburn * Event data:
61cc7d0c94SBen Coburn * $data[0]    The raw arguments for io_readFile as an array.
62cc7d0c94SBen Coburn * $data[1]    ns: The colon separated namespace path minus the trailing page name. (false if root ns)
63cc7d0c94SBen Coburn * $data[2]    page_name: The wiki page name.
64cc7d0c94SBen Coburn * $data[3]    rev: The page revision, false for current wiki pages.
65cc7d0c94SBen Coburn *
66cc7d0c94SBen Coburn * @author Ben Coburn <btcoburn@silicodon.net>
67cc7d0c94SBen Coburn */
68cc7d0c94SBen Coburnfunction io_readWikiPage($file, $id, $rev=false) {
69cc7d0c94SBen Coburn    if (empty($rev)) { $rev = false; }
70cc7d0c94SBen Coburn    $data = array(array($file, false), getNS($id), noNS($id), $rev);
71cc7d0c94SBen Coburn    return trigger_event('IO_WIKIPAGE_READ', $data, '_io_readWikiPage_action', false);
72cc7d0c94SBen Coburn}
73cc7d0c94SBen Coburn
74cc7d0c94SBen Coburn/**
75cc7d0c94SBen Coburn * Callback adapter for io_readFile().
76cc7d0c94SBen Coburn * @author Ben Coburn <btcoburn@silicodon.net>
77cc7d0c94SBen Coburn */
78cc7d0c94SBen Coburnfunction _io_readWikiPage_action($data) {
79cc7d0c94SBen Coburn    if (is_array($data) && is_array($data[0]) && count($data[0])===2) {
80cc7d0c94SBen Coburn        return call_user_func_array('io_readFile', $data[0]);
81cc7d0c94SBen Coburn    } else {
82cc7d0c94SBen Coburn        return ''; //callback error
8353d6ccfeSandi    }
8453d6ccfeSandi}
8553d6ccfeSandi
8653d6ccfeSandi/**
8715fae107Sandi * Returns content of $file as cleaned string.
8815fae107Sandi *
8915fae107Sandi * Uses gzip if extension is .gz
9015fae107Sandi *
91ee4c4a1bSAndreas Gohr * If you want to use the returned value in unserialize
92ee4c4a1bSAndreas Gohr * be sure to set $clean to false!
93ee4c4a1bSAndreas Gohr *
9415fae107Sandi * @author  Andreas Gohr <andi@splitbrain.org>
95f3f0262cSandi */
96e34c0709SAndreas Gohrfunction io_readFile($file,$clean=true){
97f3f0262cSandi  $ret = '';
98f3f0262cSandi  if(@file_exists($file)){
99f3f0262cSandi    if(substr($file,-3) == '.gz'){
100f3f0262cSandi      $ret = join('',gzfile($file));
101ff3ed99fSmarcel    }else if(substr($file,-4) == '.bz2'){
102ff3ed99fSmarcel      $ret = bzfile($file);
103f3f0262cSandi    }else{
10443078d10SAndreas Gohr      $ret = file_get_contents($file);
105f3f0262cSandi    }
106f3f0262cSandi  }
107e34c0709SAndreas Gohr  if($clean){
108f3f0262cSandi    return cleanText($ret);
109e34c0709SAndreas Gohr  }else{
110e34c0709SAndreas Gohr    return $ret;
111e34c0709SAndreas Gohr  }
112f3f0262cSandi}
113ff3ed99fSmarcel/**
114ff3ed99fSmarcel* Returns the content of a .bz2 compressed file as string
115ff3ed99fSmarcel* @author marcel senf <marcel@rucksackreinigung.de>
116ff3ed99fSmarcel*/
117ff3ed99fSmarcel
118ff3ed99fSmarcelfunction bzfile($file){
119ff3ed99fSmarcel  $bz = bzopen($file,"r");
120ff3ed99fSmarcel  while (!feof($bz)){
121ff3ed99fSmarcel    //8192 seems to be the maximum buffersize?
122ff3ed99fSmarcel    $str = $str . bzread($bz,8192);
123ff3ed99fSmarcel  }
124ff3ed99fSmarcel  bzclose($bz);
125ff3ed99fSmarcel  return $str;
126ff3ed99fSmarcel}
127ff3ed99fSmarcel
128f3f0262cSandi
129f3f0262cSandi/**
130cc7d0c94SBen Coburn * Used to write out a DokuWiki page to file, and send IO_WIKIPAGE_WRITE events.
131cc7d0c94SBen Coburn *
132cc7d0c94SBen Coburn * This generates an action event and delegates to io_saveFile().
133cc7d0c94SBen Coburn * Action plugins are allowed to modify the page content in transit.
134cc7d0c94SBen Coburn * The file path should not be changed.
135cc7d0c94SBen Coburn * (The append parameter is set to false.)
136cc7d0c94SBen Coburn *
137cc7d0c94SBen Coburn * Event data:
138cc7d0c94SBen Coburn * $data[0]    The raw arguments for io_saveFile as an array.
139cc7d0c94SBen Coburn * $data[1]    ns: The colon separated namespace path minus the trailing page name. (false if root ns)
140cc7d0c94SBen Coburn * $data[2]    page_name: The wiki page name.
141cc7d0c94SBen Coburn * $data[3]    rev: The page revision, false for current wiki pages.
142cc7d0c94SBen Coburn *
143cc7d0c94SBen Coburn * @author Ben Coburn <btcoburn@silicodon.net>
144cc7d0c94SBen Coburn */
145cc7d0c94SBen Coburnfunction io_writeWikiPage($file, $content, $id, $rev=false) {
146cc7d0c94SBen Coburn    if (empty($rev)) { $rev = false; }
147cc7d0c94SBen Coburn    if ($rev===false) { io_createNamespace($id); } // create namespaces as needed
148cc7d0c94SBen Coburn    $data = array(array($file, $content, false), getNS($id), noNS($id), $rev);
149cc7d0c94SBen Coburn    return trigger_event('IO_WIKIPAGE_WRITE', $data, '_io_writeWikiPage_action', false);
150cc7d0c94SBen Coburn}
151cc7d0c94SBen Coburn
152cc7d0c94SBen Coburn/**
153cc7d0c94SBen Coburn * Callback adapter for io_saveFile().
154cc7d0c94SBen Coburn * @author Ben Coburn <btcoburn@silicodon.net>
155cc7d0c94SBen Coburn */
156cc7d0c94SBen Coburnfunction _io_writeWikiPage_action($data) {
157cc7d0c94SBen Coburn    if (is_array($data) && is_array($data[0]) && count($data[0])===3) {
158cc7d0c94SBen Coburn        return call_user_func_array('io_saveFile', $data[0]);
159cc7d0c94SBen Coburn    } else {
160cc7d0c94SBen Coburn        return false; //callback error
161cc7d0c94SBen Coburn    }
162cc7d0c94SBen Coburn}
163cc7d0c94SBen Coburn
164cc7d0c94SBen Coburn/**
16515fae107Sandi * Saves $content to $file.
166f3f0262cSandi *
1671380fc45SAndreas Gohr * If the third parameter is set to true the given content
1681380fc45SAndreas Gohr * will be appended.
1691380fc45SAndreas Gohr *
17015fae107Sandi * Uses gzip if extension is .gz
171ff3ed99fSmarcel * and bz2 if extension is .bz2
17215fae107Sandi *
17315fae107Sandi * @author  Andreas Gohr <andi@splitbrain.org>
17415fae107Sandi * @return bool true on success
175f3f0262cSandi */
1761380fc45SAndreas Gohrfunction io_saveFile($file,$content,$append=false){
177ac9115b0STroels Liebe Bentsen  global $conf;
1781380fc45SAndreas Gohr  $mode = ($append) ? 'ab' : 'wb';
1791380fc45SAndreas Gohr
180d8186216SBen Coburn  $fileexists = @file_exists($file);
181f3f0262cSandi  io_makeFileDir($file);
18290eb8392Sandi  io_lock($file);
183f3f0262cSandi  if(substr($file,-3) == '.gz'){
1841380fc45SAndreas Gohr    $fh = @gzopen($file,$mode.'9');
185f3f0262cSandi    if(!$fh){
186f3f0262cSandi      msg("Writing $file failed",-1);
187fb7125eeSAndreas Gohr      io_unlock($file);
188f3f0262cSandi      return false;
189f3f0262cSandi    }
190f3f0262cSandi    gzwrite($fh, $content);
191f3f0262cSandi    gzclose($fh);
192ff3ed99fSmarcel  }else if(substr($file,-4) == '.bz2'){
193ece639c7SAndreas Gohr    $fh = @bzopen($file,$mode{0});
194ff3ed99fSmarcel    if(!$fh){
195ff3ed99fSmarcel      msg("Writing $file failed", -1);
196fb7125eeSAndreas Gohr      io_unlock($file);
197ff3ed99fSmarcel      return false;
198ff3ed99fSmarcel    }
199ff3ed99fSmarcel    bzwrite($fh, $content);
200ff3ed99fSmarcel    bzclose($fh);
201f3f0262cSandi  }else{
2021380fc45SAndreas Gohr    $fh = @fopen($file,$mode);
203f3f0262cSandi    if(!$fh){
204f3f0262cSandi      msg("Writing $file failed",-1);
205fb7125eeSAndreas Gohr      io_unlock($file);
206f3f0262cSandi      return false;
207f3f0262cSandi    }
208f3f0262cSandi    fwrite($fh, $content);
209f3f0262cSandi    fclose($fh);
210f3f0262cSandi  }
211ac9115b0STroels Liebe Bentsen
212bb4866bdSchris  if(!$fileexists and !empty($conf['fperm'])) chmod($file, $conf['fperm']);
21390eb8392Sandi  io_unlock($file);
214f3f0262cSandi  return true;
215f3f0262cSandi}
216f3f0262cSandi
217f3f0262cSandi/**
2181380fc45SAndreas Gohr * Delete exact linematch for $badline from $file.
2191380fc45SAndreas Gohr *
2201380fc45SAndreas Gohr * Be sure to include the trailing newline in $badline
221b158d625SSteven Danz *
222b158d625SSteven Danz * Uses gzip if extension is .gz
223b158d625SSteven Danz *
2248b06d178Schris * 2005-10-14 : added regex option -- Christopher Smith <chris@jalakai.co.uk>
2258b06d178Schris *
226b158d625SSteven Danz * @author Steven Danz <steven-danz@kc.rr.com>
227b158d625SSteven Danz * @return bool true on success
228b158d625SSteven Danz */
2298b06d178Schrisfunction io_deleteFromFile($file,$badline,$regex=false){
2301380fc45SAndreas Gohr  if (!@file_exists($file)) return true;
2311380fc45SAndreas Gohr
232b158d625SSteven Danz  io_lock($file);
2331380fc45SAndreas Gohr
2341380fc45SAndreas Gohr  // load into array
235b158d625SSteven Danz  if(substr($file,-3) == '.gz'){
2361380fc45SAndreas Gohr    $lines = gzfile($file);
237b158d625SSteven Danz  }else{
2381380fc45SAndreas Gohr    $lines = file($file);
239b158d625SSteven Danz  }
240b158d625SSteven Danz
2411380fc45SAndreas Gohr  // remove all matching lines
2428b06d178Schris  if ($regex) {
2438b06d178Schris    $lines = preg_grep($badline,$lines,PREG_GREP_INVERT);
2448b06d178Schris  } else {
2451380fc45SAndreas Gohr    $pos = array_search($badline,$lines); //return null or false if not found
2461380fc45SAndreas Gohr    while(is_int($pos)){
2471380fc45SAndreas Gohr      unset($lines[$pos]);
2481380fc45SAndreas Gohr      $pos = array_search($badline,$lines);
249b158d625SSteven Danz    }
2508b06d178Schris  }
251b158d625SSteven Danz
2521380fc45SAndreas Gohr  if(count($lines)){
2531380fc45SAndreas Gohr    $content = join('',$lines);
254b158d625SSteven Danz    if(substr($file,-3) == '.gz'){
255b158d625SSteven Danz      $fh = @gzopen($file,'wb9');
256b158d625SSteven Danz      if(!$fh){
257b158d625SSteven Danz        msg("Removing content from $file failed",-1);
258fb7125eeSAndreas Gohr        io_unlock($file);
259b158d625SSteven Danz        return false;
260b158d625SSteven Danz      }
261b158d625SSteven Danz      gzwrite($fh, $content);
262b158d625SSteven Danz      gzclose($fh);
263b158d625SSteven Danz    }else{
264b158d625SSteven Danz      $fh = @fopen($file,'wb');
265b158d625SSteven Danz      if(!$fh){
266b158d625SSteven Danz        msg("Removing content from $file failed",-1);
267fb7125eeSAndreas Gohr        io_unlock($file);
268b158d625SSteven Danz        return false;
269b158d625SSteven Danz      }
270b158d625SSteven Danz      fwrite($fh, $content);
271b158d625SSteven Danz      fclose($fh);
272b158d625SSteven Danz    }
273b158d625SSteven Danz  }else{
274b158d625SSteven Danz    @unlink($file);
275b158d625SSteven Danz  }
276b158d625SSteven Danz
277b158d625SSteven Danz  io_unlock($file);
278b158d625SSteven Danz  return true;
279b158d625SSteven Danz}
280b158d625SSteven Danz
281b158d625SSteven Danz/**
28290eb8392Sandi * Tries to lock a file
28390eb8392Sandi *
28490eb8392Sandi * Locking is only done for io_savefile and uses directories
28590eb8392Sandi * inside $conf['lockdir']
28690eb8392Sandi *
28790eb8392Sandi * It waits maximal 3 seconds for the lock, after this time
28890eb8392Sandi * the lock is assumed to be stale and the function goes on
28990eb8392Sandi *
29090eb8392Sandi * @author Andreas Gohr <andi@splitbrain.org>
29190eb8392Sandi */
29290eb8392Sandifunction io_lock($file){
29390eb8392Sandi  global $conf;
29490eb8392Sandi  // no locking if safemode hack
29590eb8392Sandi  if($conf['safemodehack']) return;
29690eb8392Sandi
29790eb8392Sandi  $lockDir = $conf['lockdir'].'/'.md5($file);
29890eb8392Sandi  @ignore_user_abort(1);
29990eb8392Sandi
30090eb8392Sandi  $timeStart = time();
30190eb8392Sandi  do {
30290eb8392Sandi    //waited longer than 3 seconds? -> stale lock
30390eb8392Sandi    if ((time() - $timeStart) > 3) break;
30444881d27STroels Liebe Bentsen    $locked = @mkdir($lockDir, $conf['dmode']);
30577b98903SAndreas Gohr    if($locked){
306bb4866bdSchris      if(!empty($conf['dperm'])) chmod($lockDir, $conf['dperm']);
30777b98903SAndreas Gohr      break;
30877b98903SAndreas Gohr    }
30977b98903SAndreas Gohr    usleep(50);
31090eb8392Sandi  } while ($locked === false);
31190eb8392Sandi}
31290eb8392Sandi
31390eb8392Sandi/**
31490eb8392Sandi * Unlocks a file
31590eb8392Sandi *
31690eb8392Sandi * @author Andreas Gohr <andi@splitbrain.org>
31790eb8392Sandi */
31890eb8392Sandifunction io_unlock($file){
31990eb8392Sandi  global $conf;
32090eb8392Sandi  // no locking if safemode hack
32190eb8392Sandi  if($conf['safemodehack']) return;
32290eb8392Sandi
32390eb8392Sandi  $lockDir = $conf['lockdir'].'/'.md5($file);
32490eb8392Sandi  @rmdir($lockDir);
32590eb8392Sandi  @ignore_user_abort(0);
32690eb8392Sandi}
32790eb8392Sandi
32890eb8392Sandi/**
329cc7d0c94SBen Coburn * Create missing namespace directories and send the IO_NAMESPACE_CREATED events
330cc7d0c94SBen Coburn * in the order of directory creation. (Parent directories first.)
331cc7d0c94SBen Coburn *
332cc7d0c94SBen Coburn * Event data:
333cc7d0c94SBen Coburn * $data[0]    ns: The colon separated namespace path minus the trailing page name.
334cc7d0c94SBen Coburn * $data[1]    ns_type: 'pages' or 'media' namespace tree.
335cc7d0c94SBen Coburn *
336cc7d0c94SBen Coburn * @author Ben Coburn <btcoburn@silicodon.net>
337cc7d0c94SBen Coburn */
338cc7d0c94SBen Coburnfunction io_createNamespace($id, $ns_type='pages') {
339cc7d0c94SBen Coburn    // verify ns_type
340cc7d0c94SBen Coburn    $types = array('pages'=>'wikiFN', 'media'=>'mediaFN');
341cc7d0c94SBen Coburn    if (!isset($types[$ns_type])) {
342cc7d0c94SBen Coburn        trigger_error('Bad $ns_type parameter for io_createNamespace().');
343cc7d0c94SBen Coburn        return;
344cc7d0c94SBen Coburn    }
345cc7d0c94SBen Coburn    // make event list
346cc7d0c94SBen Coburn    $missing = array();
347cc7d0c94SBen Coburn    $ns_stack = explode(':', $id);
348cc7d0c94SBen Coburn    $ns = $id;
349cc7d0c94SBen Coburn    $tmp = dirname( $file = call_user_func($types[$ns_type], $ns) );
350cc7d0c94SBen Coburn    while (!@is_dir($tmp) && !(@file_exists($tmp) && !is_dir($tmp))) {
351cc7d0c94SBen Coburn        array_pop($ns_stack);
352cc7d0c94SBen Coburn        $ns = implode(':', $ns_stack);
353cc7d0c94SBen Coburn        if (strlen($ns)==0) { break; }
354cc7d0c94SBen Coburn        $missing[] = $ns;
355cc7d0c94SBen Coburn        $tmp = dirname(call_user_func($types[$ns_type], $ns));
356cc7d0c94SBen Coburn    }
357cc7d0c94SBen Coburn    // make directories
358cc7d0c94SBen Coburn    io_makeFileDir($file);
359cc7d0c94SBen Coburn    // send the events
360cc7d0c94SBen Coburn    $missing = array_reverse($missing); // inside out
361cc7d0c94SBen Coburn    foreach ($missing as $ns) {
362cc7d0c94SBen Coburn        $data = array($ns, $ns_type);
363cc7d0c94SBen Coburn        trigger_event('IO_NAMESPACE_CREATED', $data);
364cc7d0c94SBen Coburn    }
365cc7d0c94SBen Coburn}
366cc7d0c94SBen Coburn
367cc7d0c94SBen Coburn/**
368f3f0262cSandi * Create the directory needed for the given file
36915fae107Sandi *
37015fae107Sandi * @author  Andreas Gohr <andi@splitbrain.org>
371f3f0262cSandi */
372f3f0262cSandifunction io_makeFileDir($file){
373f3f0262cSandi  global $conf;
374f3f0262cSandi
375f3f0262cSandi  $dir = dirname($file);
3760d8850c4SAndreas Gohr  if(!@is_dir($dir)){
377f3f0262cSandi    io_mkdir_p($dir) || msg("Creating directory $dir failed",-1);
378f3f0262cSandi  }
379f3f0262cSandi}
380f3f0262cSandi
381f3f0262cSandi/**
382f3f0262cSandi * Creates a directory hierachy.
383f3f0262cSandi *
38415fae107Sandi * @link    http://www.php.net/manual/en/function.mkdir.php
385f3f0262cSandi * @author  <saint@corenova.com>
3863dc3a5f1Sandi * @author  Andreas Gohr <andi@splitbrain.org>
387f3f0262cSandi */
388f3f0262cSandifunction io_mkdir_p($target){
3893dc3a5f1Sandi  global $conf;
3900d8850c4SAndreas Gohr  if (@is_dir($target)||empty($target)) return 1; // best case check first
391f3f0262cSandi  if (@file_exists($target) && !is_dir($target)) return 0;
3923dc3a5f1Sandi  //recursion
3933dc3a5f1Sandi  if (io_mkdir_p(substr($target,0,strrpos($target,'/')))){
3943dc3a5f1Sandi    if($conf['safemodehack']){
39500976812SAndreas Gohr      $dir = preg_replace('/^'.preg_quote(fullpath($conf['ftp']['root']),'/').'/','', $target);
396034138e2SRainer Weinhold      return io_mkdir_ftp($dir);
3973dc3a5f1Sandi    }else{
39844881d27STroels Liebe Bentsen      $ret = @mkdir($target,$conf['dmode']); // crawl back up & create dir tree
3991ca31cfeSAndreas Gohr      if($ret && $conf['dperm']) chmod($target, $conf['dperm']);
40044881d27STroels Liebe Bentsen      return $ret;
4013dc3a5f1Sandi    }
4023dc3a5f1Sandi  }
403f3f0262cSandi  return 0;
404f3f0262cSandi}
405f3f0262cSandi
406f3f0262cSandi/**
4073dc3a5f1Sandi * Creates a directory using FTP
4083dc3a5f1Sandi *
4093dc3a5f1Sandi * This is used when the safemode workaround is enabled
4103dc3a5f1Sandi *
4113dc3a5f1Sandi * @author <andi@splitbrain.org>
4123dc3a5f1Sandi */
4133dc3a5f1Sandifunction io_mkdir_ftp($dir){
4143dc3a5f1Sandi  global $conf;
4153dc3a5f1Sandi
4163dc3a5f1Sandi  if(!function_exists('ftp_connect')){
4173dc3a5f1Sandi    msg("FTP support not found - safemode workaround not usable",-1);
4183dc3a5f1Sandi    return false;
4193dc3a5f1Sandi  }
4203dc3a5f1Sandi
4213dc3a5f1Sandi  $conn = @ftp_connect($conf['ftp']['host'],$conf['ftp']['port'],10);
4223dc3a5f1Sandi  if(!$conn){
4233dc3a5f1Sandi    msg("FTP connection failed",-1);
4243dc3a5f1Sandi    return false;
4253dc3a5f1Sandi  }
4263dc3a5f1Sandi
4273dc3a5f1Sandi  if(!@ftp_login($conn, $conf['ftp']['user'], $conf['ftp']['pass'])){
4283dc3a5f1Sandi    msg("FTP login failed",-1);
4293dc3a5f1Sandi    return false;
4303dc3a5f1Sandi  }
4313dc3a5f1Sandi
4323dc3a5f1Sandi  //create directory
433034138e2SRainer Weinhold  $ok = @ftp_mkdir($conn, $dir);
4341ca31cfeSAndreas Gohr  //set permissions
4351ca31cfeSAndreas Gohr  @ftp_site($conn,sprintf("CHMOD %04o %s",$conf['dmode'],$dir));
4363dc3a5f1Sandi
437034138e2SRainer Weinhold  @ftp_close($conn);
4383dc3a5f1Sandi  return $ok;
4393dc3a5f1Sandi}
4403dc3a5f1Sandi
4413dc3a5f1Sandi/**
442*de862555SMichael Klier * Creates a unique temporary directory and returns
443*de862555SMichael Klier * its path.
444*de862555SMichael Klier *
445*de862555SMichael Klier * @author Michael Klier <chi@chimeric.de>
446*de862555SMichael Klier */
447*de862555SMichael Klierfunction io_mktmpdir() {
448*de862555SMichael Klier    global $conf;
449*de862555SMichael Klier
450*de862555SMichael Klier    $base = $conf['savedir'].'/tmp/';
451*de862555SMichael Klier    $dir  = md5(uniqid(rand(), true));
452*de862555SMichael Klier    $tmpdir = $base.$dir;
453*de862555SMichael Klier
454*de862555SMichael Klier    if(io_mkdir_p($tmpdir)) {
455*de862555SMichael Klier        return($tmpdir);
456*de862555SMichael Klier    } else {
457*de862555SMichael Klier        return false;
458*de862555SMichael Klier    }
459*de862555SMichael Klier}
460*de862555SMichael Klier
461*de862555SMichael Klier/**
46273ccfcb9Schris * downloads a file from the net and saves it
46373ccfcb9Schris *
46473ccfcb9Schris * if $useAttachment is false,
46573ccfcb9Schris * - $file is the full filename to save the file, incl. path
46673ccfcb9Schris * - if successful will return true, false otherwise
46773ccfcb9Schris
46873ccfcb9Schris * if $useAttachment is true,
46973ccfcb9Schris * - $file is the directory where the file should be saved
47073ccfcb9Schris * - if successful will return the name used for the saved file, false otherwise
471b625487dSandi *
472b625487dSandi * @author Andreas Gohr <andi@splitbrain.org>
47373ccfcb9Schris * @author Chris Smith <chris@jalakai.co.uk>
474b625487dSandi */
475847b8298SAndreas Gohrfunction io_download($url,$file,$useAttachment=false,$defaultName='',$maxSize=2097152){
476ac9115b0STroels Liebe Bentsen  global $conf;
4779b307a83SAndreas Gohr  $http = new DokuHTTPClient();
478847b8298SAndreas Gohr  $http->max_bodysize = $maxSize;
4799b307a83SAndreas Gohr  $http->timeout = 25; //max. 25 sec
4809b307a83SAndreas Gohr
4819b307a83SAndreas Gohr  $data = $http->get($url);
4829b307a83SAndreas Gohr  if(!$data) return false;
4839b307a83SAndreas Gohr
48473ccfcb9Schris  if ($useAttachment) {
48573ccfcb9Schris    $name = '';
48673ccfcb9Schris      if (isset($http->resp_headers['content-disposition'])) {
48773ccfcb9Schris      $content_disposition = $http->resp_headers['content-disposition'];
488ce070a9fSchris      $match=array();
48973ccfcb9Schris      if (is_string($content_disposition) &&
490ce070a9fSchris          preg_match('/attachment;\s*filename\s*=\s*"([^"]*)"/i', $content_disposition, $match)) {
49173ccfcb9Schris
49273ccfcb9Schris          $name = basename($match[1]);
49373ccfcb9Schris      }
49473ccfcb9Schris
49573ccfcb9Schris    }
49673ccfcb9Schris
49773ccfcb9Schris    if (!$name) {
49873ccfcb9Schris        if (!$defaultName) return false;
49973ccfcb9Schris        $name = $defaultName;
50073ccfcb9Schris    }
50173ccfcb9Schris
50273ccfcb9Schris    $file = $file.$name;
50373ccfcb9Schris  }
50473ccfcb9Schris
505d8186216SBen Coburn  $fileexists = @file_exists($file);
5069b307a83SAndreas Gohr  $fp = @fopen($file,"w");
507b625487dSandi  if(!$fp) return false;
5089b307a83SAndreas Gohr  fwrite($fp,$data);
509b625487dSandi  fclose($fp);
5101ca31cfeSAndreas Gohr  if(!$fileexists and $conf['fperm']) chmod($file, $conf['fperm']);
51173ccfcb9Schris  if ($useAttachment) return $name;
512b625487dSandi  return true;
513b625487dSandi}
514b625487dSandi
515b625487dSandi/**
516ac9115b0STroels Liebe Bentsen * Windows compatible rename
517bf5e5a5bSAndreas Gohr *
518bf5e5a5bSAndreas Gohr * rename() can not overwrite existing files on Windows
519bf5e5a5bSAndreas Gohr * this function will use copy/unlink instead
520bf5e5a5bSAndreas Gohr */
521bf5e5a5bSAndreas Gohrfunction io_rename($from,$to){
522ac9115b0STroels Liebe Bentsen  global $conf;
523bf5e5a5bSAndreas Gohr  if(!@rename($from,$to)){
524bf5e5a5bSAndreas Gohr    if(@copy($from,$to)){
5258e0b019fSAndreas Gohr      if($conf['fperm']) chmod($to, $conf['fperm']);
526bf5e5a5bSAndreas Gohr      @unlink($from);
527bf5e5a5bSAndreas Gohr      return true;
528bf5e5a5bSAndreas Gohr    }
529bf5e5a5bSAndreas Gohr    return false;
530bf5e5a5bSAndreas Gohr  }
531bf5e5a5bSAndreas Gohr  return true;
532bf5e5a5bSAndreas Gohr}
533bf5e5a5bSAndreas Gohr
534bf5e5a5bSAndreas Gohr
535bf5e5a5bSAndreas Gohr/**
536f3f0262cSandi * Runs an external command and returns it's output as string
53715fae107Sandi *
53815fae107Sandi * @author Harry Brueckner <harry_b@eml.cc>
53915fae107Sandi * @author Andreas Gohr <andi@splitbrain.org>
5403dc3a5f1Sandi * @deprecated
541f3f0262cSandi */
542f3f0262cSandifunction io_runcmd($cmd){
543f3f0262cSandi  $fh = popen($cmd, "r");
544f3f0262cSandi  if(!$fh) return false;
545f3f0262cSandi  $ret = '';
546f3f0262cSandi  while (!feof($fh)) {
547f3f0262cSandi    $ret .= fread($fh, 8192);
548f3f0262cSandi  }
549f3f0262cSandi  pclose($fh);
550f3f0262cSandi  return $ret;
551f3f0262cSandi}
552f3f0262cSandi
5537421c3ccSAndreas Gohr/**
5547421c3ccSAndreas Gohr * Search a file for matching lines
5557421c3ccSAndreas Gohr *
5567421c3ccSAndreas Gohr * This is probably not faster than file()+preg_grep() but less
5577421c3ccSAndreas Gohr * memory intensive because not the whole file needs to be loaded
5587421c3ccSAndreas Gohr * at once.
5597421c3ccSAndreas Gohr *
5607421c3ccSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
5617421c3ccSAndreas Gohr * @param  string $file    The file to search
5627421c3ccSAndreas Gohr * @param  string $pattern PCRE pattern
5637421c3ccSAndreas Gohr * @param  int    $max     How many lines to return (0 for all)
5647421c3ccSAndreas Gohr * @param  bool   $baxkref When true returns array with backreferences instead of lines
5657421c3ccSAndreas Gohr * @return matching lines or backref, false on error
5667421c3ccSAndreas Gohr */
5677421c3ccSAndreas Gohrfunction io_grep($file,$pattern,$max=0,$backref=false){
5687421c3ccSAndreas Gohr  $fh = @fopen($file,'r');
5697421c3ccSAndreas Gohr  if(!$fh) return false;
5707421c3ccSAndreas Gohr  $matches = array();
5717421c3ccSAndreas Gohr
5727421c3ccSAndreas Gohr  $cnt  = 0;
5737421c3ccSAndreas Gohr  $line = '';
5747421c3ccSAndreas Gohr  while (!feof($fh)) {
5757421c3ccSAndreas Gohr    $line .= fgets($fh, 4096);  // read full line
5767421c3ccSAndreas Gohr    if(substr($line,-1) != "\n") continue;
5777421c3ccSAndreas Gohr
5787421c3ccSAndreas Gohr    // check if line matches
5797421c3ccSAndreas Gohr    if(preg_match($pattern,$line,$match)){
5807421c3ccSAndreas Gohr      if($backref){
5817421c3ccSAndreas Gohr        $matches[] = $match;
5827421c3ccSAndreas Gohr      }else{
5837421c3ccSAndreas Gohr        $matches[] = $line;
5847421c3ccSAndreas Gohr      }
5857421c3ccSAndreas Gohr      $cnt++;
5867421c3ccSAndreas Gohr    }
5877421c3ccSAndreas Gohr    if($max && $max == $cnt) break;
5887421c3ccSAndreas Gohr    $line = '';
5897421c3ccSAndreas Gohr  }
5907421c3ccSAndreas Gohr  fclose($fh);
5917421c3ccSAndreas Gohr  return $matches;
5927421c3ccSAndreas Gohr}
5937421c3ccSAndreas Gohr
594340756e4Sandi//Setup VIM: ex: et ts=2 enc=utf-8 :
595