Ariadne-CMS /
ariadne
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
Loading history...
|
|||
| 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
Loading history...
|
|||
| 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
Loading history...
|
|||
| 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
Loading history...
|
|||
| 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
Loading history...
|
|||
| 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
Loading history...
|
|||
| 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: