1<?php
2if(!defined('DOKU_INC')) die();
3class plugin_cache{
4  var $namespace  ='';
5  var $mediaDir   ='';
6  var $mediaFormat='';
7  var $linkFormat ='';
8  var $prefix     ='';
9  var $extension  ='';
10  var $tmpdir     ='';
11  function __construct($_name='plugin_cache',$_prefix='noname',$_ext='txt'){
12    global $conf;
13    $this->namespace = strtolower($_name);
14    $this->prefix    = strtolower($_prefix);
15    $this->extension = strtolower($_ext);
16    if (empty($_prefix)){
17      $this->prefix = $_prefix;
18    }else{
19      $this->prefix = $_prefix.'_';
20    }
21    $delimiter = ($conf['useslash'])?'/':':';
22    $this->mediaDir    = $conf['mediadir'].'/'.$this->namespace;
23    $this->mediaFormat = $this->mediaDir.'/'.$this->prefix.'%s.'.$this->extension;
24    $this->linkFormat  = $this->namespace.$delimiter.$this->prefix.'%s.'.$this->extension;
25
26    $this->useTmpDir   = false;
27    $this->tmpDir      = '/var/tmp';
28    $this->tmpFormat   = $this->tmpDir.'/'.$this->namespace.'_'.$this->prefix.'%s.'.$this->extension;
29
30    $this->CheckDir();
31  }
32
33 /**
34  * Get media file path
35  */
36  function GetMediaPath($id){
37    $id = strtolower($id);
38    if($this->useTmpDir===false){
39      return sprintf($this->mediaFormat,$id);
40    }else{
41      return sprintf($this->tmpFormat,$id);
42    }
43  }
44
45 /**
46  * Get all media file paths array
47  * array(ID,filepath)
48  */
49  function GetAllMediaPaths(){
50    $dir = $this->mediaDir;
51    $dirhandle = opendir($dir);
52    $files = array();
53
54    $patten = array($this->prefix,'.'.$this->extension);
55    $replace = array('','');
56    while($name = readdir($dirhandle)){
57      if (strpos($name,$this->extension)!==false){
58        $path = $dir.'/'.$name;
59        $id = str_replace($patten,$replace,$name);
60        $files[$id] = $path;
61      }
62    }
63    closedir();
64    return $files;
65  }
66
67 /**
68  * Get media link
69  */
70  function GetMediaLink($id){
71    return ml(sprintf($this->linkFormat,$id),'',true,'',true);
72  }
73
74 /**
75  * Get text from cache. If none, return false
76  *
77  * Uses gzip if extension is .gz
78  * and bz2 if extension is .bz2
79  */
80  function GetMediaText($id){
81    $filepath = $this->GetMediaPath($id);
82    if (@file_exists($filepath)){
83      @touch($filepath);
84      return io_readFile($filepath);
85    }
86    return false;
87  }
88 /**
89  * Save string to cache with a permission of $conf['fmode'].
90  *
91  * Uses gzip if extension is .gz
92  * and bz2 if extension is .bz2
93  */
94  function PutMediaText($id,$text){
95    global $conf;
96    $path = $this->GetMediaPath($id);
97    if(io_saveFile($path,$text)){
98        @chmod($path,$conf['fmode']);
99        return true;
100    }
101    return false;
102  }
103 /**
104  * Check cache directories
105  */
106  function CheckDir(){
107    global $conf;
108    $dummyFN=mediaFN($this->namespace.':_dummy');
109    $tmp = dirname($dummyFN);
110    if (!@is_dir($tmp)){
111      io_makeFileDir($dummyFN);
112      @chmod($tmp,$conf['dmode']);
113    }
114    if (auth_aclcheck($this->namespace.":*","","@ALL")==0){
115       global $AUTH_ACL;
116       $acl = join("",file(DOKU_CONF.'acl.auth.php'));
117       $p_acl = $this->namespace.":*\t@ALL\t1\n";
118       $new_acl = $acl.$p_acl;
119       io_saveFile(DOKU_CONF.'acl.auth.php', $new_acl);
120       $AUTH_ACL = file(DOKU_CONF.'acl.auth.php'); // Reload ACL
121    }
122  }
123 /**
124  * Return true if the file exists
125  */
126  function Exists($id){
127    $path = $this->GetMediaPath($id);
128    if(@file_exists($path)!==false){
129      @touch($path);
130      return true;
131    }
132    return false;
133  }
134
135 /**
136  * Clear all media files in a plugin's media directory
137  */
138  function ClearCache(){
139    global $conf;
140    $handle = @opendir($this->mediaDir);
141    if ($handle === false)
142      return;
143    while (($entry = readdir($handle))){
144      $path = $this->mediaDir.'/'.$entry;
145      if(is_file($path))
146          @unlink($path);
147    }
148    closedir($handle);
149  }
150 /**
151  * Remove cache and directory
152  */
153  function RemoveDir(){
154    $this->ClearCache();
155    @rmdir($this->mediaDir);
156  }
157 /**
158  * save array as tab-text
159  */
160  function _save_array($id,$ar=''){
161    $_st = _microtime();
162    if(empty($id)) return false;
163    global $conf;
164    if (empty($ar)){
165    }else{
166      $rep_pair = array("\n"=>"","\t"=>"");
167      $values = array_values($ar);
168      $keys = array_keys($ar);
169      $sz = count($values);
170      for($i=0;$i<$sz;$i++){
171        $k = $keys[$i];
172        if(empty($k)) $k=$i;
173        $v=strtr($ar[$k],$rep_pair);
174        $file.= $k."\t".$v."\n";
175      }
176    }
177    if (empty($file)){$file='#not found';}
178    $path = $this->GetMediaPath($id);
179    if(io_saveFile($path,$file)){
180      @chmod($path,$conf['fmode']);
181      _stopwatch('save_array',$_st);
182      return true;
183    }else{
184      _stopwatch('save_array',$_st);
185    return false;
186    }
187  }
188
189 /**
190  * read array from tab-text
191  */
192  function _read_array($id){
193    $_st = _microtime();
194    if (empty($id) || !$this->Exists($id)) return NULL;
195    $path = $this->GetMediaPath($id);
196    $lines = split("\n",io_readFile($path));
197    $a = array();
198    $sz = count($lines);
199    for($i=0;$i<$sz;$i++){
200      if ($line=='#not found') return null;
201      $line = chop($lines[$i]);
202      if (empty($line)) continue;
203      $items = explode("\t",$line);
204      if (count($items)!=2)continue;
205      $a[$items[0]] = $items[1];
206    }
207      _stopwatch('read_array',$_st);
208    @touch($path);
209    return $a;
210  }
211
212}
213