This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* usage |
||
4 | |||
5 | simple: |
||
6 | |||
7 | if ( !$image = ar('cache')->getIfFresh( $name ) ) { |
||
8 | $image = expensiveOperation(); |
||
9 | ar('cache')->set( $naam, $image ); |
||
10 | } |
||
11 | echo $image; |
||
12 | |||
13 | with locking: |
||
14 | |||
15 | if ( !$image = ar('cache')->getIfFresh( $naam ) ) { |
||
16 | if ( ar('cache')->lock( $naam ) ) { |
||
17 | $image = expensiveOperation(); |
||
18 | ar('cache')->set( $naam, $image, '2 hours' ); |
||
19 | } else if ( ar('cache')->wait( $naam ) ) { // lock failed, another process is generating the cache |
||
20 | // continues here when the lock to be lifted |
||
21 | $image = ar('cache')->get($naam); |
||
22 | } else { |
||
23 | // couldn't lock the file in a reasonable time, you could generate an error here |
||
24 | // or just go with a stale image, or simply do the calculation: |
||
25 | $image = expensiveOperation(); |
||
26 | } |
||
27 | } |
||
28 | echo $image; |
||
29 | |||
30 | */ |
||
31 | |||
32 | ar_pinp::allow('ar_cache'); |
||
33 | ar_pinp::allow('ar_cacheStore'); |
||
34 | ar_pinp::allow('ar_cacheProxy'); |
||
35 | |||
36 | class ar_cache extends arBase { |
||
37 | |||
38 | public static $cacheStore = null; |
||
39 | |||
40 | public static function config( $options ) { |
||
41 | if ( $options['cacheStore'] ) { |
||
42 | self::$cacheStore = $options['cacheStore']; |
||
43 | } |
||
44 | } |
||
45 | |||
46 | public static function create( $prefix = null, $timeout = 7200 ) { |
||
47 | // this method is used by pinp scripts to create a specific cache |
||
48 | // so it must be more restrictive than the constructor of the cacheStore |
||
49 | // which must be able to clear any and all caches |
||
50 | if ( !$prefix ) { // make sure you have a default prefix, so you won't clear other prefixes unintended |
||
51 | $prefix = 'default'; |
||
52 | } |
||
53 | $prefix = 'pinp/'.$prefix; // make sure the pinp scripts have their own top level |
||
54 | $prefix = $prefix . ar::context()->getPath(); // make sure the cache store is limited to the current path in the context stack |
||
55 | try { |
||
56 | return new ar_cacheStore( $prefix, $timeout ); |
||
57 | } catch( Exception $e ) { |
||
58 | return ar_error::raiseError( $e->getMessage(), $e->getCode() ); |
||
59 | } |
||
60 | } |
||
61 | |||
62 | public static function get( $name ) { |
||
63 | if ( !self::$cacheStore ) { |
||
64 | self::$cacheStore = self::create(); |
||
65 | } |
||
66 | return self::$cacheStore->get( $name ); |
||
67 | } |
||
68 | |||
69 | public static function getIfFresh( $name, $freshness=0 ) { |
||
70 | if ( !self::$cacheStore ) { |
||
71 | self::$cacheStore = self::create(); |
||
72 | } |
||
73 | return self::$cacheStore->getIfFresh( $name, $freshness ); |
||
0 ignored issues
–
show
|
|||
74 | } |
||
75 | |||
76 | public static function lock( $name ) { |
||
77 | if ( !self::$cacheStore ) { |
||
78 | self::$cacheStore = self::create(); |
||
79 | } |
||
80 | return self::$cacheStore->lock( $name ); |
||
0 ignored issues
–
show
The method
lock does only exist in ar_cacheStore , but not in ar_error .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
81 | } |
||
82 | |||
83 | public static function wait( $name ) { |
||
84 | if ( !self::$cacheStore ) { |
||
85 | self::$cacheStore = self::create(); |
||
86 | } |
||
87 | return self::$cacheStore->wait( $name ); |
||
0 ignored issues
–
show
The method
wait does only exist in ar_cacheStore , but not in ar_error .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
88 | } |
||
89 | |||
90 | public static function set( $name, $value, $timeout = 7200 ) { |
||
91 | if ( !self::$cacheStore ) { |
||
92 | self::$cacheStore = self::create(); |
||
93 | } |
||
94 | return self::$cacheStore->set( $name, $value, $timeout ); |
||
0 ignored issues
–
show
The method
set does only exist in ar_cacheStore , but not in ar_error .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
95 | } |
||
96 | |||
97 | public static function info( $name ) { |
||
98 | if ( !self::$cacheStore ) { |
||
99 | self::$cacheStore = self::create(); |
||
100 | } |
||
101 | return self::$cacheStore->info( $name ); |
||
0 ignored issues
–
show
The method
info does only exist in ar_cacheStore , but not in ar_error .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
102 | } |
||
103 | |||
104 | public static function clear( $name = null ) { |
||
105 | if ( !self::$cacheStore ) { |
||
106 | self::$cacheStore = self::create(); |
||
107 | } |
||
108 | return self::$cacheStore->clear( $name ); |
||
0 ignored issues
–
show
The method
clear does only exist in ar_cacheStore , but not in ar_error .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
109 | } |
||
110 | |||
111 | public static function purge( $name = null ) { |
||
112 | if ( !self::$cacheStore ) { |
||
113 | self::$cacheStore = self::create(); |
||
114 | } |
||
115 | return self::$cacheStore->purge( $name ); |
||
0 ignored issues
–
show
The method
purge does only exist in ar_cacheStore , but not in ar_error .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
116 | } |
||
117 | |||
118 | public static function proxy( $object, $timeout = null ) { |
||
119 | if ( !self::$cacheStore ) { |
||
120 | self::$cacheStore = self::create(); |
||
121 | } |
||
122 | return new ar_cacheProxy( $object, self::$cacheStore, $timeout ); |
||
123 | } |
||
124 | |||
125 | } |
||
126 | |||
127 | class ar_cacheProxy extends arWrapper { |
||
128 | // TODO: allow more control on retrieval: |
||
129 | // - get contents from cache even though cache may be stale |
||
130 | // perhaps through an extra option in __construct? |
||
131 | public $cacheStore = null; |
||
132 | public $cacheController = null; |
||
133 | public $cacheTimeout = '2 hours'; |
||
134 | |||
135 | public function __construct( $object, $cacheStore, $cacheTimeout = null, $cacheController = null ) { |
||
136 | parent::__construct( $object ); |
||
137 | $this->cacheStore = $cacheStore; |
||
138 | $this->cacheController = $cacheController; |
||
139 | if ( isset($cacheTimeout) ) { |
||
140 | $this->cacheTimeout = $cacheTimeout; |
||
141 | } |
||
142 | } |
||
143 | |||
144 | protected function __callCatch( $method, $args ) { |
||
145 | ob_start(); |
||
146 | $result = parent::__call( $method, $args ); |
||
147 | $output = ob_get_contents(); |
||
148 | ob_end_clean(); |
||
149 | return array( |
||
150 | 'output' => $output, |
||
151 | 'result' => $result |
||
152 | ); |
||
153 | } |
||
154 | |||
155 | protected function __callCached( $method, $args, $path ) { |
||
156 | if ( !$cacheData = $this->cacheStore->getIfFresh( $path ) ) { |
||
157 | if ( $this->cacheStore->lock( $path ) ) { |
||
158 | $cacheData = $this->__callCatch( $method, $args ); |
||
159 | $this->cacheStore->set( $path, $cacheData, $this->cacheTimeout ); |
||
160 | } else if ( $this->cacheStore->wait( $path ) ){ |
||
161 | $cacheData = $this->cacheStore->get( $path ); |
||
162 | } else { |
||
163 | $cacheData = $this->__callCatch( $method, $args ); // just get the result and return it |
||
164 | } |
||
165 | } |
||
166 | return $cacheData; |
||
167 | } |
||
168 | |||
169 | public function __call( $method, $args ) { |
||
170 | $path = $method . '(' . md5( serialize($args) ) . ')'; |
||
171 | $cacheData = $this->__callCached( $method, $args, $path ); |
||
172 | echo $cacheData['output']; |
||
173 | $result = $cacheData['result']; |
||
174 | if ( is_object( $result ) ) { |
||
175 | $result = new ar_cacheProxy( $result, $this->cacheStore->subStore( $path ) ); |
||
176 | } |
||
177 | return $result; |
||
178 | } |
||
179 | |||
180 | public function __get( $name ) { |
||
181 | $result = parent::__get( $name ); |
||
182 | if ( is_object( $result ) ) { |
||
183 | $result = new ar_cacheProxy( $result, $this->cacheStore->subStore( $name ) ); |
||
184 | } |
||
185 | return $result; |
||
186 | } |
||
187 | |||
188 | } |
||
189 | |||
190 | interface ar_cacheStoreInterface { |
||
191 | public function get( $path ); |
||
192 | public function set( $path, $value, $timeout = 7200 ); |
||
193 | public function info( $path ); |
||
194 | public function clear( $path = null ); |
||
195 | public function subStore( $path ); |
||
196 | public function isFresh( $path ); |
||
197 | public function purge( $name = null ); |
||
198 | public function getIfFresh( $name, $freshness=0 ); |
||
199 | } |
||
200 | |||
201 | class ar_cacheStore implements ar_cacheStoreInterface, arKeyValueStoreInterface { |
||
202 | |||
203 | protected $basePath = ''; |
||
204 | protected $timeout = 7200; |
||
205 | protected $mode = 0777; |
||
206 | |||
207 | public function __construct( $basePath, $timeout = 7200, $mode = 0777 ) { |
||
208 | $this->basePath = preg_replace('/\.\./', '', $basePath); |
||
209 | |||
210 | if ( is_string($timeout) ) { |
||
211 | $timeout = strtotime( $timeout, 0); |
||
212 | } |
||
213 | $this->timeout = $timeout; |
||
214 | $this->mode = $mode; |
||
215 | |||
216 | if ( !defined("ARCacheDir") ) { |
||
217 | define( "ARCacheDir", sys_get_temp_dir().'/ar_cache/' ); |
||
218 | } |
||
219 | if ( !file_exists( ARCacheDir ) ) { |
||
220 | mkdir( ARCacheDir, $this->mode ); |
||
221 | } |
||
222 | if ( !file_exists( ARCacheDir ) ) { |
||
223 | throw new ar_error("Cache Directory does not exist ( ".ARCacheDir." )", 1); |
||
224 | } |
||
225 | if ( !is_dir( ARCacheDir ) ) { |
||
226 | throw new ar_error("Cache Directory is not a directory ( ".ARCacheDir." )", 1); |
||
227 | } |
||
228 | if ( !is_writable( ARCacheDir ) ) { |
||
229 | throw new ar_error("Cache Directory is not writable ( ".ARCacheDir." )", 1); |
||
230 | } |
||
231 | } |
||
232 | |||
233 | protected function cachePath( $path ) { |
||
234 | // last '=' is added to prevent conflicts between subdirectories and cache images |
||
235 | // images always end in a '=', directories never end in a '=' |
||
236 | return ARCacheDir . $this->basePath . preg_replace('/(\.\.|\=)/', '', $path) . '='; |
||
237 | } |
||
238 | |||
239 | public function subStore( $path ) { |
||
240 | return new ar_cacheStore( $this->basePath . preg_replace('/(\.\.|\=)/', '', $path) ); |
||
241 | } |
||
242 | |||
243 | public function get( $path ) { |
||
244 | $cachePath = $this->cachePath( $path ); |
||
245 | if ( file_exists( $cachePath ) ) { |
||
246 | return unserialize( file_get_contents( $cachePath ) ); |
||
247 | } else { |
||
248 | return null; |
||
249 | } |
||
250 | } |
||
251 | |||
252 | public function getvar( $name ) { |
||
253 | return $this->get( $name ); |
||
254 | } |
||
255 | |||
256 | public function isFresh( $path ) { |
||
257 | $cachePath = $this->cachePath( $path ); |
||
258 | if ( file_exists( $cachePath ) ) { |
||
259 | return ( filemtime( $cachePath ) > time() ); |
||
260 | } else { |
||
261 | return false; |
||
262 | } |
||
263 | } |
||
264 | |||
265 | public function getIfFresh( $path, $freshness = 0 ) { |
||
266 | $info = $this->info( $path ); |
||
267 | if ( $info && $info['timeout'] >= $freshness ) { |
||
268 | return $this->get( $path ); |
||
269 | } else { |
||
270 | return false; |
||
271 | } |
||
272 | } |
||
273 | |||
274 | public function lock( $path, $blocking = false ) { |
||
275 | // locks the file against writing by other processes, so generation of time or resource expensive images |
||
276 | // will not happen by multiple processes simultaneously |
||
277 | $cachePath = $this->cachePath( $path ); |
||
278 | $dir = dirname( $cachePath ); |
||
279 | if ( !file_exists( $dir ) ) { |
||
280 | mkdir( $dir, $this->mode, true ); //recursive |
||
281 | } |
||
282 | $lockFile = fopen( $cachePath, 'c' ); |
||
283 | $lockMode = LOCK_EX; |
||
284 | if ( !$blocking ) { |
||
285 | $lockMode = $lockMode|LOCK_NB; |
||
286 | } |
||
287 | return flock( $lockFile, $lockMode ); |
||
288 | } |
||
289 | |||
290 | public function wait( $path ) { |
||
291 | $cachePath = $this->cachePath( $path ); |
||
292 | $lockFile = fopen( $cachePath, 'c' ); |
||
293 | $result = flock( $lockFile, LOCK_EX ); |
||
294 | fclose( $lockFile ); |
||
295 | return $result; |
||
296 | } |
||
297 | |||
298 | public function putvar( $name, $value ) { |
||
299 | return $this->set( $name, $value ); |
||
300 | } |
||
301 | |||
302 | public function set( $path, $value, $timeout = null ) { |
||
303 | $cachePath = $this->cachePath( $path ); |
||
304 | if ( !isset( $timeout ) ) { |
||
305 | $timeout = $this->timeout; |
||
306 | } |
||
307 | if ( is_string( $timeout ) ) { |
||
308 | $timeout = strtotime( $timeout, 0); |
||
309 | } |
||
310 | $dir = dirname( $cachePath ); |
||
311 | if ( !file_exists( $dir ) ) { |
||
312 | mkdir( $dir, $this->mode, true ); //recursive |
||
313 | } |
||
314 | if ( false !== file_put_contents( $cachePath, serialize( $value ), LOCK_EX ) ) { |
||
315 | // FIXME: check dat de lock gemaakt met lock() weg is na file_put_contents |
||
316 | touch( $cachePath, time() + $timeout ); |
||
317 | } else { |
||
318 | return false; |
||
319 | } |
||
320 | } |
||
321 | |||
322 | public function info( $path ) { |
||
323 | $cachePath = $this->cachePath( $path ); |
||
324 | if ( file_exists( $cachePath ) && is_readable( $cachePath ) ) { |
||
325 | return array( |
||
326 | 'size' => filesize($cachePath), |
||
327 | 'fresh' => $this->isFresh( $path ), |
||
328 | 'ctime' => filectime( $cachePath ), |
||
329 | 'timeout' => filemtime( $cachePath ) - time() |
||
330 | ); |
||
331 | } else { |
||
332 | return false; |
||
333 | } |
||
334 | } |
||
335 | |||
336 | public function clear( $path = null ) { |
||
337 | $cachePath = $this->cachePath( $path ); |
||
338 | if ( file_exists( $cachePath ) ) { |
||
339 | return unlink( $cachePath ); |
||
340 | } else { |
||
341 | return true; |
||
342 | } |
||
343 | } |
||
344 | |||
345 | public function purge( $path = null ) { |
||
346 | $this->clear( $path ); |
||
347 | $cachePath = substr( $this->cachePath( $path ), 0, -1 ); // remove last '=' |
||
348 | if ( file_exists( $cachePath ) ) { |
||
349 | if ( is_dir( $cachePath ) ){ |
||
350 | $cacheDir = dir( $cachePath ); |
||
351 | while (false !== ($entry = $cacheDir->read())) { |
||
352 | if ( $entry != '.' && $entry != '..' ) { |
||
353 | $this->purge( $path . '/' . $entry ); |
||
354 | } |
||
355 | } |
||
356 | return rmdir( $cachePath ); |
||
357 | } else { |
||
358 | return unlink( $cachePath ); |
||
359 | } |
||
360 | } else { |
||
361 | return true; |
||
362 | } |
||
363 | } |
||
364 | } |
||
365 |
It seems like the method you are trying to call exists only in some of the possible types.
Let’s take a look at an example:
Available Fixes
Add an additional type-check:
Only allow a single type to be passed if the variable comes from a parameter: