Issues (1751)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

lib/ar.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
	if ( !defined('ARBaseDir') ) {
3
		define('ARBaseDir', dirname( __FILE__ ) . '/ar/');
4
	}
5
	require_once(ARBaseDir.'pinp.php');
6
	require_once(ARBaseDir.'core/exception.php');
7
8
	ar_pinp::allow('ar');
9
	ar_pinp::allow('ar_error');
10
11
	class ar implements arKeyValueStoreInterface {
12
		protected static $instances;
13
		protected static $ar;
14
		protected static $context = null;
15
16
		public static function __callStatic($name, $arguments) {
17
			return self::load($name);
18
		}
19
20 1
		public function __call($name, $arguments) {
21
			return $this->load($name);
22 1
		}
23
24
		public function __get($name) {
25
			return $this->load($name);
26
		}
27
28 2
		private static function _parseClassName($className) {
29 2
			$fileName = '';
30 2
			if (strpos($className, 'ar_')===0) {
31 2
				$fileName = substr($className, 3);
32 2
				$fileName = preg_replace('/[^a-z0-9_\.\\\\\/]/i', '', $fileName);
33 2
				$fileName = str_replace(array('_','\\'), '/', $fileName);
34 2
				$fileName = str_replace('../', '', $fileName);
35 2
			}
36 2
			return $fileName;
37
		}
38
39 17
		private static function _compileClassName($className) {
40 17
			if (strpos($className, 'ar_')!==0) {
41 17
				$className = 'ar_'.$className;
42 17
			}
43 17
			$className = str_replace(array('/','\\'), '_', $className);
44 17
			$className = preg_replace('/[^a-z0-9_]/i', '', $className);
45 17
			return $className;
46
		}
47
48 17
		public static function load($name=null) {
49 17
			if (!$name) {
50
				if (!self::$ar) {
51
					self::$ar = new ar();
52
				}
53
				return self::$ar;
54
			} else {
55 17
				$fullName = self::_compileClassName($name);
56 17
				if (!class_exists($fullName)) {
57
					$fileName = self::_parseClassName($fullName);
58 View Code Duplication
					if (!file_exists(ARBaseDir.$fileName.'.php')) {
59
						error( $name . ' not found' );
60
					} else {
61
						require_once(ARBaseDir.$fileName.'.php');
62
					}
63
				}
64 17
				if (!self::$instances[$name]) {
65 1
					self::$instances[$name] = new $fullName();
66 1
				}
67 17
				return self::$instances[$name];
68
			}
69
		}
70
71 10
		public static function autoload($className) {
72 10
			if (strpos($className, 'pinp_ar_')===0) {
73
				$className = substr($className, 5);
74
			}
75 10
			if (strpos($className, 'ar_')===0) {
76 2
				$fileName = self::_parseClassName($className);
77 2
				if (file_exists(ARBaseDir.$fileName.'.php')) {
78 2
					require_once(ARBaseDir.$fileName.'.php');
79 2
				} else {
80 1
					$subFileName = preg_replace( '/[A-Z].*$/', '', $fileName );
81 1 View Code Duplication
					if ( $subFileName != $fileName && file_exists( ARBaseDir.$subFileName.'.php' ) ) {
82 1
						require_once( ARBaseDir.$subFileName.'.php' );
83 1
					}
84
				}
85 2
			}
86 10
		}
87
88
		public static function ls() {
89
			return ar_store::ls();
90
		}
91
92
		public static function find($query="") {
93
			return ar_store::find($query);
94
		}
95
96 31
		public static function get($path="") {
97 31
			return ar_store::get($path);
98
		}
99
100
		public static function parents($path = ".") {
101
			return ar_store::parents($path);
0 ignored issues
show
The call to ar_store::parents() has too many arguments starting with $path.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
102
		}
103
104
		public static function exists($path = '.') {
105
			return ar_store::exists($path);
106
		}
107
108 1
		public static function error($message, $code, $previous = null) {
109 1
			return ar_error::raiseError($message, $code, $previous);
110
		}
111
112 View Code Duplication
		public static function call( $template, $params = null ) {
113
			$context = self::context();
114
			$me = $context->getObject();
115
			if ($me) {
116
				return $me->call( $template, $params );
117
			}
118
		}
119
120 View Code Duplication
		public static function callSuper( $params = null ) {
121
			$context = self::context();
122
			$me = $context->getObject();
123
			if ($me) {
124
				return $me->_call_super( $params );
125
			}
126
		}
127
128 6
		public static function taint(&$value) {
129 6
			if ( is_numeric($value) ) {
130
				return $value;
131 6
			} else if ( is_array($value) ) {
132
				array_walk_recursive( $value, array( 'self', 'taint' ) );
133 6
			} else if ( is_string($value) && $value ) { // empty strings don't need tainting
134
				$value = new arTainted($value);
135
			}
136 6
			return $value;
137
		}
138
139
		public static function untaint(&$value, $filter = FILTER_SANITIZE_SPECIAL_CHARS, $flags = null) {
140
			if ( $value instanceof arTainted ) {
141
				$value = filter_var($value->value, $filter, $flags);
142
			} else if ( is_array($value) ) {
143
				array_walk_recursive( $value, array( 'self', 'untaintArrayItem'), array(
144
					'filter' => $filter,
145
					'flags' => $flags
146
				) );
147
			}
148
			return $value;
149
		}
150
151
		protected static function untaintArrayItem(&$value, $key, $options) {
0 ignored issues
show
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
152
			self::untaint( $value, $options['filter'], $options['flags'] );
153
		}
154
155 7
		public function getvar( $name ) {
156 7
			global $ARCurrent, $ARConfig;
157
158 7
			if ($ARCurrent->arCallStack) {
159 7
				$arCallArgs=end($ARCurrent->arCallStack);
160 7
				if ( $name == 'arCallArgs' ) {
161
					return $arCallArgs;
162
				}
163 7
				if ( isset($arCallArgs[$name]) ) {
164 1
					return $arCallArgs[$name];
165
				}
166 6
			} else if ( $name == 'arCallArgs' ) {
167
				return ar_loader::getvar();
168
			}
169 6
			if ( isset($ARCurrent->$name) ) {
170
				return $ARCurrent->$name;
171
			}
172 6
			return ar_loader::getvar( $name );
173
		}
174
175
		public function putvar( $name, $value ) {
176
			global $ARCurrent;
177
			$ARCurrent->$name = $value;
178
		}
179
180 1
		public static function listExpression( $list ) {
181 1
			return new ar_listExpression( $list );
182
		}
183
184
		public static function listPattern() {
185
			self::autoload('ar_listExpression');
186
			$params = func_get_args();
187
			return new ar_listExpression_Pattern( $params );
188
		}
189
190
		public static function url( $url ) {
191
			return new ar_url( $url );
192
		}
193
194 34
		public static function context() {
195 34
			if (!isset(self::$context)) {
196
				self::setContext( new ar_ariadneContext() );
197
			}
198 34
			return self::$context;
199
		}
200
201
		public static function setContext( $context ) {
202
			if ( !isset( self::$context ) ) {
203
				self::$context = $context;
204
			} else {
205
				return self::error( 'Context can only be set once.', ar_exceptions::ACCESS_DENIED );
206
			}
207
		}
208
209 1
		public static function acquire( $varname, $options = array() ) {
210 1
			$context = self::context();
211 1
			return $context->acquire( $varname, $options);
212
		}
213
214
	}
215
216
	class arTainted {
217
		public $value = null;
218
219
		public function __construct($value) {
220
			$this->value = $value;
221
		}
222
223
		public function __toString() {
224
			return filter_var($this->value, FILTER_SANITIZE_SPECIAL_CHARS);
225
		}
226
	}
227
228
229
	class arObject {
230
		public function __construct( $vars = '' ) {
231
			if ( is_array($vars) ) {
232
				foreach ( $vars as $key => $var ) {
233
					if ( !is_numeric($key) ) {
234
						$this->{$key} = $var;
235
					}
236
				}
237
			}
238
		}
239
	}
240
241
	class arBase {
242
243 2 View Code Duplication
		public function __call($name, $arguments) {
244 2
			if (($name[0]==='_')) {
245 2
				$realName = substr($name, 1);
246 2
				if (ar_pinp::isAllowed($this, $realName)) {
247 2
					return call_user_func_array(array($this, $realName), $arguments);
248
				} else {
249
					trigger_error("Method $realName not found in class ".get_class($this), E_USER_WARNING);
250
				}
251
			} else {
252
				trigger_error("Method $name not found in class ".get_class($this), E_USER_WARNING);
253
			}
254
		}
255
	}
256
257
	class arWrapper {
258
259
		protected $wrapped = null;
260
		protected $__class = 'arWrapper';
261
262
		public function __construct( $wrapped ) {
263
			$this->wrapped = $wrapped;
264
		}
265
266
		public function __call($name, $arguments) {
267
			if ( $name[0] === '_' ) {
268
				if ( !method_exists( $this->wrapped, $name ) || !ar_pinp::isAllowed( $this, $name ) ) {
269
					$name = substr($name, 1);
270
				}
271
			}
272
			if (ar_pinp::isAllowed($this, $name)) {
273
				try {
274
					return $this->__wrap( call_user_func_array( array( $this->wrapped, $name), $arguments) );
275
				} catch( Exception $e ) {
276
					return ar::error( $e->getMessage(), $e->getCode() );
277
				}
278
			} else {
279
				trigger_error("Method $name not found in class ".get_class($this), E_USER_WARNING);
280
			}
281
		}
282
283
		public function __wrap( $result ) {
284
			if (is_object($result)) {
285
				$class = $this->__class;
286
				return new $class($result);
287
			} else {
288
				return $result;
289
			}
290
		}
291
292
		public function __get( $name ) {
293
			return $this->wrapped->$name;
294
		}
295
296
		public function __set( $name, $value ) {
297
			$this->wrapped->$name = $value;
298
		}
299
300
	}
301
302
303
	class ar_error extends ar_exceptionDefault {
304
		protected static $throwExceptions = false;
305
306 4
		public function __construct( $message = '', $code = 0, $previous = null ) {
307 4
			if ( $previous && !($previous instanceof \Exception) ) {
308
				$previous = new ar_error( $previous );
309
			}
310 4
			parent::__construct( (string) $message, (int) $code, $previous );
311 4
			$this->code = $code;
312 4
		}
313
314 1
		public function __call($name, $arguments) {
315 1
			if (($name[0]==='_')) {
316 1
				$realName = substr($name, 1);
317 1
				if (ar_pinp::isAllowed($this, $realName)) {
318 1
					return call_user_func_array(array($this, $realName), $arguments);
319 View Code Duplication
				} else {
320
					$trace = debug_backtrace(0,2);
321
					trigger_error("Method $realName not found in class ".get_class($this)." Called from line ".$trace[1]['line']." in ".$trace[1]['file'], E_USER_WARNING);
322
				}
323 View Code Duplication
			} else {
324
				$trace = debug_backtrace(0,2);
325
				trigger_error("Method $name not found in class ".get_class($this)." Called from line ".$trace[1]['line']." in ".$trace[1]['file'], E_USER_WARNING);
326
			}
327
		}
328
329 19
		public static function isError($ob) {
330 19
			return ( is_object($ob)
331 19
				&& ( is_a($ob, 'ar_error') || is_a($ob, 'error') || is_a($ob, 'PEAR_Error') ) );
332
		}
333
334 4
		public static function raiseError($message, $code, $previous = null) {
335 4
			if (self::$throwExceptions) {
336
				throw new ar_error($message, $code, $previous);
337
			} else {
338 4
				return new ar_error($message, $code, $previous);
339
			}
340
		}
341
342
		public static function configure( $option, $value ) {
343
			switch ($option) {
344
				case 'throwExceptions' :
345
					self::$throwExceptions = $value;
346
				break;
347
			}
348
		}
349
350
		public function __toString() {
351
			$result = $this->code.": ".$this->message."\r\n";
352
			$e = $this;
353
			while ($e = $e->getPrevious()) {
354
				$result .= $e->getCode().": ".$e->getMessage()."\r\n";
355
			}
356
			return $result;
357
		}
358
	}
359
360
	// FIXME: remove pinp_ar after pinp compiler has no need for it anymore
361
	class pinp_ar extends ar {
362
		public static function __callStatic($name, $arguments) {
363
			return self::load(substr($name, 1), $arguments);
0 ignored issues
show
The call to pinp_ar::load() has too many arguments starting with $arguments.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
364
		}
365
		public function __call($name, $arguments) {
366
			return $this->load(substr($name, 1), $arguments);
0 ignored issues
show
The call to pinp_ar::load() has too many arguments starting with $arguments.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
367
		}
368
		public function __get($name) {
369
			return $this->load(substr($name, 1));
370
		}
371
		public static function _ls() {
372
			return ar_store::ls();
373
		}
374
375 1
		public static function _find($query="") {
376 1
			return ar_store::find($query);
377
		}
378
379
		public static function _get($path="") {
380
			return ar_store::get($path);
381
		}
382
383
		public static function _parents($path = ".") {
384
			return ar_store::parents($path);
0 ignored issues
show
The call to ar_store::parents() has too many arguments starting with $path.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
385
		}
386
387
		public static function _exists($path = '.') {
388
			return ar_store::exists($path);
389
		}
390
391
		public static function _error($message, $code) {
392
			return ar::error($message, $code);
393
		}
394
395
		public static function _call($template, $params = null) {
396
			return ar::call($template, $params);
397
		}
398
399
		public static function _callSuper() {
400
			return ar::callSuper();
401
		}
402
403
		public static function _taint(&$value) {
404
			ar::taint($value);
405
		}
406
407
		public static function _untaint(&$value, $filter = FILTER_SANITIZE_SPECIAL_CHARS, $flags = null) {
408
			ar::untaint($value, $filter, $flags);
409
		}
410
411 1
		public static function _getvar( $name ) {
412 1
			return ar::getvar( $name );
413
		}
414
415
		public static function _putvar( $name, $value ) {
416
			return ar::putvar( $name, $value );
417
		}
418
419
		public static function _listExpression( $list ) {
420
			return ar::listExpression( $list );
421
		}
422
423
		public static function _listPattern() {
424
			$params = func_get_args();
425
			return call_user_func_array( array( 'ar', 'listPattern'), $params);
426
		}
427
428
		public static function _url( $url ) {
429
			return ar::url( $url );
430
		}
431
432
		public static function _acquire( $varname, $options = array() ) {
433
			return ar::acquire( $varname, $options );
434
		}
435
	}
436
437
	function ar($name=null) {
438
		// this function works as an alternative to statically calling the namespaced class
439
		// this is a fallback untill namespaces work in php 5.3
440 17
		return ar::load($name);
441
	}
442
443
	interface ar_contextInterface {
444
		public static function getPath( $options = array() );
445
446
		public static function getObject( $options = array() );
447
448
		public static function getLoader( $options = array() );
449
	}
450
451
	class ar_ariadneContext implements ar_contextInterface {
452
453 34
		public static function makePath( $cwd, $path ) { //FIXME: move this method to a better place
454 34
			$result = '/';
455 34
			if ( $path[0] === '/' ) {
456 34
				$path = substr( $path, 1);
457 34
			} else {
458
				$path = substr( $cwd, 1 ) . '/' . $path;
459
			}
460 34
			if ( $path ) {
461 33
				$splitpath = explode( '/', $path );
462 33
				foreach ( $splitpath as $pathticle ) {
463
					switch( $pathticle ) {
464 33
						case ".." :
465
							$result = dirname( $result );
466
							// if second char of $result is not set, then current result is the rootNode
467
							if ( isset($result[1]) ) {
468
								$result .= "/";
469
							}
470
							$result[0] = "/"; // make sure that even under windows, slashes are always forward slashes.
471
						break;
472 33
						case "." : break;
473 33
						case ""	 : break;
474 33
						default:
475 33
							$result .= $pathticle . '/';
476 33
						break;
477 33
					}
478 33
				}
479 33
			}
480 34
			return $result;
481
		}
482
483 34
		public static function getPath( $options = array() ) {
484 34
			$me = self::getObject( $options );
485 34
			if ($me) {
486 2
				$path = $me->make_path( $options['path'] );
487 2
				if ($options['skipShortcuts']) {
488 1
					$me->_load('mod_keepurl.php');
489 1
					$realpath = pinp_keepurl::_make_real_path( $path );
490 1
					if ($realpath) {
491 1
						$path = $realpath;
492 1
					}
493 2
				} else if ($options['rememberShortcuts']) {
494
					$me->_load('mod_keepurl.php');
495
					$path = pinp_keepurl::_make_path( $path );
496 2
				} else if ( $options['searchObject'] ) {
497
					if (isset($me->data->path)) {
498
						$path = $me->data->path;
499
					}
500
				}
501 2
			} else {
502 34
				$path = self::makePath( '/', $options['path'] );
503
			}
504 34
			return $path;
505
		}
506
507 34
		public static function getObject( $options = array() ) {
508 34
			if ( class_exists( 'pobject' ) ) {
509 34
				$context = pobject::getContext();
510 34
				$me = $context["arCurrentObject"];
511 34
			} else {
512
				$me = null;
513
			}
514 34
			return $me;
515
		}
516
517
		public static function getQuery( $query, $options = array() ) {
518
			$me = self::getObject( $options );
519
			if ($me) {
520
				if (isset($me->data->query)) {
521
					if ( $query ) {
522
						$query = "(" . $me->data->query . ") and $query";
523
					} else {
524
						 $query = $me->data->query;
525
					}
526
					return $query;
527
				}
528
			}
529
			return $query;
530
		}
531
532
		public static function getLoader( $options = array() ) { //FIXME: move code from ar_loader to here
533
			return ar_loader::getLoader();
534
		}
535
536 1
		public static function acquire( $varname, $options = array() ) {
537 1
			$me = self::getObject( $options );
538 1
			if ($me) {
539 1
				$data = $me->loadUserConfig();
540 1
				$vars = explode('.', $varname);
541 1
				foreach( $vars as $var ) {
542 1
					$data = $data[$var];
543 1
				}
544 1
				return $data;
545
			}
546
		}
547
548 3
		public static function callAtPath( $path, $callback ) {
549 3
			$ob = current( ar_store::get($path)->call('system.get.phtml'));
550 3
			pobject::pushContext( array(
551 3
					"arCurrentObject" => $ob,
552
					"scope" => "php"
553 3
					) );
554 3
			call_user_func( $callback );
555 3
			pobject::popContext();
556 3
		}
557
558
	}
559
560
	interface arKeyValueStoreInterface {
561
562
		public function getvar( $name );
563
564
		public function putvar( $name, $value );
565
566
	}
567
568
	spl_autoload_register('ar::autoload',true,true);
569