GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Context::gets()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 0
dl 0
loc 17
rs 9.7
c 0
b 0
f 0
1
<?php
2
/* Copyright (C) XEHub <https://www.xehub.io> */
3
4
define('FOLLOW_REQUEST_SSL', 0);
5
define('ENFORCE_SSL', 1);
6
define('RELEASE_SSL', 2);
7
8
/**
9
 * Manages Context such as request arguments/environment variables
10
 * It has dual method structure, easy-to use methods which can be called as self::methodname(),and methods called with static object.
11
 *
12
 * @author XEHub ([email protected])
13
 */
14
class Context
15
{
16
17
	/**
18
	 * Allow rewrite
19
	 * @var bool TRUE: using rewrite mod, FALSE: otherwise
20
	 */
21
	public $allow_rewrite = FALSE;
22
23
	/**
24
	 * Request method
25
	 * @var string GET|POST|XMLRPC|JSON
26
	 */
27
	public $request_method = 'GET';
28
29
	/**
30
	 * js callback function name.
31
	 * @var string
32
	 */
33
	public $js_callback_func = '';
34
35
	/**
36
	 * Response method.If it's not set, it follows request method.
37
	 * @var string HTML|XMLRPC|JSON|JS_CALLBACK
38
	 */
39
	public $response_method = '';
40
41
	/**
42
	 * Conatins request parameters and environment variables
43
	 * @var object
44
	 */
45
	public $context = NULL;
46
47
	/**
48
	 * DB info
49
	 * @var object
50
	 */
51
	public $db_info = NULL;
52
53
	/**
54
	 * FTP info
55
	 * @var object
56
	 */
57
	public $ftp_info = NULL;
58
59
	/**
60
	 * ssl action cache file
61
	 * @var array
62
	 */
63
	public $sslActionCacheFile = './files/cache/sslCacheFile.php';
64
65
	/**
66
	 * List of actions to be sent via ssl (it is used by javascript xml handler for ajax)
67
	 * @var array
68
	 */
69
	public $ssl_actions = array();
70
71
	/**
72
	 * obejct oFrontEndFileHandler()
73
	 * @var object
74
	 */
75
	public $oFrontEndFileHandler;
76
77
	/**
78
	 * script codes in <head>..</head>
79
	 * @var string
80
	 */
81
	public $html_header = NULL;
82
83
	/**
84
	 * class names of <body>
85
	 * @var array
86
	 */
87
	public $body_class = array();
88
89
	/**
90
	 * codes after <body>
91
	 * @var string
92
	 */
93
	public $body_header = NULL;
94
95
	/**
96
	 * class names before </body>
97
	 * @var string
98
	 */
99
	public $html_footer = NULL;
100
101
	/**
102
	 * path of Xpress Engine
103
	 * @var string
104
	 */
105
	public $path = '';
106
	// language information - it is changed by HTTP_USER_AGENT or user's cookie
107
	/**
108
	 * language type
109
	 * @var string
110
	 */
111
	public $lang_type = '';
112
113
	/**
114
	 * contains language-specific data
115
	 * @var object
116
	 */
117
	public $lang = NULL;
118
119
	/**
120
	 * list of loaded languages (to avoid re-loading them)
121
	 * @var array
122
	 */
123
	public $loaded_lang_files = array();
124
125
	/**
126
	 * site's browser title
127
	 * @var string
128
	 */
129
	public $site_title = '';
130
131
	/**
132
	 * variables from GET or form submit
133
	 * @var mixed
134
	 */
135
	public $get_vars = NULL;
136
137
	/**
138
	 * Checks uploaded
139
	 * @var bool TRUE if attached file exists
140
	 */
141
	public $is_uploaded = FALSE;
142
	/**
143
	 * Pattern for request vars check
144
	 * @var array
145
	 */
146
	public $patterns = array(
147
			'/<\?/iUsm',
148
			'/<\%/iUsm',
149
			'/<script\s*?language\s*?=\s*?("|\')?\s*?php\s*("|\')?/iUsm'
150
			);
151
	/**
152
	 * Check init
153
	 * @var bool FALSE if init fail
154
	 */
155
	public $isSuccessInit = TRUE;
156
157
	/**
158
	 * returns static context object (Singleton). It's to use Context without declaration of an object
159
	 *
160
	 * @return object Instance
161
	 */
162
	function &getInstance()
163
	{
164
		static $theInstance = null;
165
		if(!$theInstance)
166
		{
167
			$theInstance = new Context();
168
		}
169
170
		return $theInstance;
171
	}
172
173
	/**
174
	 * Cunstructor
175
	 *
176
	 * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
177
	 */
178
	function __construct()
179
	{
180
		$this->oFrontEndFileHandler = new FrontEndFileHandler();
181
		$this->get_vars = new stdClass();
182
183
		// include ssl action cache file
184
		$this->sslActionCacheFile = FileHandler::getRealPath($this->sslActionCacheFile);
0 ignored issues
show
Documentation introduced by
$this->sslActionCacheFile is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation Bug introduced by
It seems like \FileHandler::getRealPat...is->sslActionCacheFile) of type string is incompatible with the declared type array of property $sslActionCacheFile.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
185
		if(is_readable($this->sslActionCacheFile))
186
		{
187
			require($this->sslActionCacheFile);
188
			if(isset($sslActions))
0 ignored issues
show
Bug introduced by
The variable $sslActions seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
189
			{
190
				$this->ssl_actions = $sslActions;
191
			}
192
		}
193
	}
194
195
	/**
196
	 * Initialization, it sets DB information, request arguments and so on.
197
	 *
198
	 * @see This function should be called only once
199
	 * @return void
200
	 */
201
	function init()
202
	{
203
		// fix missing HTTP_RAW_POST_DATA in PHP 5.6 and above
204
		if(!isset($GLOBALS['HTTP_RAW_POST_DATA']) && version_compare(PHP_VERSION, '5.6.0', '>=') === TRUE)
205
		{
206
			$GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents("php://input");
207
208
			// If content is not XML JSON, unset
209
			if(!preg_match('/^[\<\{\[]/', $GLOBALS['HTTP_RAW_POST_DATA']) && strpos($_SERVER['CONTENT_TYPE'], 'json') === FALSE && strpos($_SERVER['HTTP_CONTENT_TYPE'], 'json') === FALSE)
210
			{
211
				unset($GLOBALS['HTTP_RAW_POST_DATA']);
212
			}
213
		}
214
215
		// set context variables in $GLOBALS (to use in display handler)
216
		$this->context = &$GLOBALS['__Context__'];
217
		$this->context->lang = &$GLOBALS['lang'];
218
		$this->context->_COOKIE = $_COOKIE;
219
220
		// 20140429 editor/image_link
221
		$this->_checkGlobalVars();
222
223
		$this->setRequestMethod('');
224
225
		$this->_setXmlRpcArgument();
226
		$this->_setJSONRequestArgument();
227
		$this->_setRequestArgument();
228
		$this->_setUploadedArgument();
229
230
		$this->loadDBInfo();
231
		if($this->db_info->use_sitelock == 'Y')
232
		{
233
			if(is_array($this->db_info->sitelock_whitelist)) $whitelist = $this->db_info->sitelock_whitelist;
234
235
			if(!IpFilter::filter($whitelist))
0 ignored issues
show
Bug introduced by
The variable $whitelist does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
236
			{
237
				$title = ($this->db_info->sitelock_title) ? $this->db_info->sitelock_title : 'Maintenance in progress...';
238
				$message = $this->db_info->sitelock_message;
239
240
				define('_XE_SITELOCK_', TRUE);
241
				define('_XE_SITELOCK_TITLE_', $title);
242
				define('_XE_SITELOCK_MESSAGE_', $message);
243
244
				header("HTTP/1.1 403 Forbidden");
245
				if(FileHandler::exists(_XE_PATH_ . 'common/tpl/sitelock.user.html'))
0 ignored issues
show
Bug Best Practice introduced by
The expression \FileHandler::exists(_XE...pl/sitelock.user.html') of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
246
				{
247
					include _XE_PATH_ . 'common/tpl/sitelock.user.html';
248
				}
249
				else
250
				{
251
					include _XE_PATH_ . 'common/tpl/sitelock.html';
252
				}
253
				exit;
254
			}
255
		}
256
257
		// If XE is installed, get virtual site information
258
		if(self::isInstalled())
259
		{
260
			$oModuleModel = getModel('module');
261
			$site_module_info = $oModuleModel->getDefaultMid();
262
263
			if(!isset($site_module_info))
264
			{
265
				$site_module_info = new stdClass();
266
			}
267
268
			// if site_srl of site_module_info is 0 (default site), compare the domain to default_url of db_config
269
			if($site_module_info->site_srl == 0 && $site_module_info->domain != $this->db_info->default_url)
270
			{
271
				$site_module_info->domain = $this->db_info->default_url;
272
			}
273
274
			$this->set('site_module_info', $site_module_info);
275
			if($site_module_info->site_srl && isSiteID($site_module_info->domain))
276
			{
277
				$this->set('vid', $site_module_info->domain, TRUE);
0 ignored issues
show
Documentation introduced by
TRUE is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
278
			}
279
280
			if(!isset($this->db_info))
281
			{
282
				$this->db_info = new stdClass();
283
			}
284
285
			$this->db_info->lang_type = $site_module_info->default_language;
286
			if(!$this->db_info->lang_type)
287
			{
288
				$this->db_info->lang_type = 'en';
289
			}
290
			if(!$this->db_info->use_db_session)
291
			{
292
				$this->db_info->use_db_session = 'N';
293
			}
294
		}
295
296
		// Load Language File
297
		$lang_supported = $this->loadLangSelected();
298
299
		// Retrieve language type set in user's cookie
300
		if($this->lang_type = $this->get('l'))
301
		{
302
			if($_COOKIE['lang_type'] != $this->lang_type)
303
			{
304
				setcookie('lang_type', $this->lang_type, $_SERVER['REQUEST_TIME'] + 3600 * 24 * 1000);
305
			}
306
		}
307
		elseif($_COOKIE['lang_type'])
308
		{
309
			$this->lang_type = $_COOKIE['lang_type'];
310
		}
311
312
		// If it's not exists, follow default language type set in db_info
313
		if(!$this->lang_type)
314
		{
315
			$this->lang_type = $this->db_info->lang_type;
316
		}
317
318
		// if still lang_type has not been set or has not-supported type , set as English.
319
		if(!$this->lang_type)
320
		{
321
			$this->lang_type = 'en';
322
		}
323
		if(is_array($lang_supported) && !isset($lang_supported[$this->lang_type]))
324
		{
325
			$this->lang_type = 'en';
326
		}
327
328
		$this->set('lang_supported', $lang_supported);
329
		$this->setLangType($this->lang_type);
330
331
		// load module module's language file according to language setting
332
		$this->loadLang(_XE_PATH_ . 'modules/module/lang');
333
334
		// set session handler
335
		if(self::isInstalled() && $this->db_info->use_db_session == 'Y')
336
		{
337
			$oSessionModel = getModel('session');
338
			$oSessionController = getController('session');
339
			ini_set('session.serialize_handler', 'php');
340
			session_set_save_handler(
341
					array(&$oSessionController, 'open'), array(&$oSessionController, 'close'), array(&$oSessionModel, 'read'), array(&$oSessionController, 'write'), array(&$oSessionController, 'destroy'), array(&$oSessionController, 'gc')
342
			);
343
		}
344
345
		if($sess = $_POST[session_name()]) session_id($sess);
346
		session_start();
347
348
		// set authentication information in Context and session
349
		if(self::isInstalled())
350
		{
351
			$oModuleModel = getModel('module');
352
			$oModuleModel->loadModuleExtends();
353
354
			$oMemberModel = getModel('member');
355
			$oMemberController = getController('member');
356
357
			if($oMemberController && $oMemberModel)
358
			{
359
				// if signed in, validate it.
360
				if($oMemberModel->isLogged())
361
				{
362
					$oMemberController->setSessionInfo();
363
				}
364
				// check auto sign-in
365
				elseif($_COOKIE['xeak'])
366
				{
367
					$oMemberController->doAutologin();
368
				}
369
370
				$this->set('is_logged', $oMemberModel->isLogged());
371
				$this->set('logged_info', $oMemberModel->getLoggedInfo());
372
			}
373
		}
374
375
		// load common language file
376
		$this->lang = &$GLOBALS['lang'];
377
		$this->loadLang(_XE_PATH_ . 'common/lang/');
378
379
		// check if using rewrite module
380
		$this->allow_rewrite = ($this->db_info->use_rewrite == 'Y' ? TRUE : FALSE);
381
382
		// set locations for javascript use
383
		$url = array();
0 ignored issues
show
Unused Code introduced by
$url is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
384
		$current_url = self::getRequestUri();
0 ignored issues
show
Unused Code introduced by
$current_url is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
385
		if($_SERVER['REQUEST_METHOD'] == 'GET')
386
		{
387
			if($this->get_vars)
388
			{
389
				$url = array();
390 View Code Duplication
				foreach($this->get_vars as $key => $val)
391
				{
392
					if(is_array($val) && count($val) > 0)
393
					{
394
						foreach($val as $k => $v)
395
						{
396
							$url[] = $key . '[' . $k . ']=' . urlencode($v);
397
						}
398
					}
399
					elseif($val)
400
					{
401
						$url[] = $key . '=' . urlencode($val);
402
					}
403
				}
404
405
				$current_url = self::getRequestUri();
406
				if($url) $current_url .= '?' . join('&', $url);
0 ignored issues
show
Bug Best Practice introduced by
The expression $url of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
407
			}
408
			else
409
			{
410
				$current_url = $this->getUrl();
411
			}
412
		}
413
		else
414
		{
415
			$current_url = self::getRequestUri();
416
		}
417
418
		$this->set('current_url', $current_url);
419
		$this->set('request_uri', self::getRequestUri());
420
421
		if(strpos($current_url, 'xn--') !== FALSE)
422
		{
423
			$this->set('current_url', self::decodeIdna($current_url));
424
		}
425
426
		if(strpos(self::getRequestUri(), 'xn--') !== FALSE)
427
		{
428
			$this->set('request_uri', self::decodeIdna(self::getRequestUri()));
429
		}
430
	}
431
432
	/**
433
	 * Finalize using resources, such as DB connection
434
	 *
435
	 * @return void
436
	 */
437
	function close()
438
	{
439
		session_write_close();
440
	}
441
442
	/**
443
	 * Load the database information
444
	 *
445
	 * @return void
446
	 */
447
	function loadDBInfo()
448
	{
449
		$self = self::getInstance();
450
451
		if(!$self->isInstalled())
452
		{
453
			return;
454
		}
455
456
		ob_start(); // trash BOM
457
		include($self::getConfigFile());
458
		ob_end_clean();
459
460
		// If master_db information does not exist, the config file needs to be updated
461
		if(!isset($db_info->master_db))
462
		{
463
			$db_info->master_db = array();
0 ignored issues
show
Bug introduced by
The variable $db_info does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
464
			$db_info->master_db["db_type"] = $db_info->db_type;
465
			unset($db_info->db_type);
466
			$db_info->master_db["db_port"] = $db_info->db_port;
467
			unset($db_info->db_port);
468
			$db_info->master_db["db_hostname"] = $db_info->db_hostname;
469
			unset($db_info->db_hostname);
470
			$db_info->master_db["db_password"] = $db_info->db_password;
471
			unset($db_info->db_password);
472
			$db_info->master_db["db_database"] = $db_info->db_database;
473
			unset($db_info->db_database);
474
			$db_info->master_db["db_userid"] = $db_info->db_userid;
475
			unset($db_info->db_userid);
476
			$db_info->master_db["db_table_prefix"] = $db_info->db_table_prefix;
477
			unset($db_info->db_table_prefix);
478
479
			if(isset($db_info->master_db["db_table_prefix"]) && substr_compare($db_info->master_db["db_table_prefix"], '_', -1) !== 0)
480
			{
481
				$db_info->master_db["db_table_prefix"] .= '_';
482
			}
483
484
			$db_info->slave_db = array($db_info->master_db);
485
			$self->setDBInfo($db_info);
486
487
			$oInstallController = getController('install');
488
			$oInstallController->makeConfigFile();
489
		}
490
491
		if(version_compare(PHP_VERSION, '7.0', '>='))
492
		{
493
			$db_info->master_db["db_type"] = preg_replace('/^mysql(_.+)?$/', 'mysqli$1', $db_info->master_db["db_type"]);
494
			foreach($db_info->slave_db as &$slave_db_info)
495
			{
496
				$slave_db_info["db_type"] = preg_replace('/^mysql(_.+)?$/', 'mysqli$1', $slave_db_info["db_type"]);
497
			}
498
		}
499
500
		if(!$db_info->use_prepared_statements)
501
		{
502
			$db_info->use_prepared_statements = 'Y';
503
		}
504
505
		if(!$db_info->time_zone)
506
			$db_info->time_zone = date('O');
507
		$GLOBALS['_time_zone'] = $db_info->time_zone;
508
509
		if($db_info->qmail_compatibility != 'Y')
510
			$db_info->qmail_compatibility = 'N';
511
		$GLOBALS['_qmail_compatibility'] = $db_info->qmail_compatibility;
512
513
		if(!$db_info->use_db_session)
514
			$db_info->use_db_session = 'N';
515
		if(!$db_info->use_ssl)
516
			$db_info->use_ssl = 'none';
517
		$this->set('_use_ssl', $db_info->use_ssl);
518
519
		$self->set('_http_port', ($db_info->http_port) ? $db_info->http_port : NULL);
520
		$self->set('_https_port', ($db_info->https_port) ? $db_info->https_port : NULL);
521
522
		if(!$db_info->sitelock_whitelist) {
523
			$db_info->sitelock_whitelist = '127.0.0.1';
524
		}
525
526
		if(is_string($db_info->sitelock_whitelist)) {
527
			$db_info->sitelock_whitelist = explode(',', $db_info->sitelock_whitelist);
528
		}
529
530
		$self->setDBInfo($db_info);
531
	}
532
533
	/**
534
	 * Get DB's db_type
535
	 *
536
	 * @return string DB's db_type
537
	 */
538
	function getDBType()
539
	{
540
		$self = self::getInstance();
541
		return $self->db_info->master_db["db_type"];
542
	}
543
544
	/**
545
	 * Set DB information
546
	 *
547
	 * @param object $db_info DB information
548
	 * @return void
549
	 */
550
	function setDBInfo($db_info)
551
	{
552
		$self = self::getInstance();
553
		$self->db_info = $db_info;
554
	}
555
556
	/**
557
	 * Get DB information
558
	 *
559
	 * @return object DB information
560
	 */
561
	function getDBInfo()
562
	{
563
		$self = self::getInstance();
564
		return $self->db_info;
565
	}
566
567
	/**
568
	 * Return ssl status
569
	 *
570
	 * @return object SSL status (Optional - none|always|optional)
571
	 */
572
	function getSslStatus()
573
	{
574
		$dbInfo = self::getDBInfo();
575
		return $dbInfo->use_ssl;
576
	}
577
578
	/**
579
	 * Return default URL
580
	 *
581
	 * @return string Default URL
582
	 */
583
	function getDefaultUrl()
584
	{
585
		$db_info = self::getDBInfo();
586
		return $db_info->default_url;
587
	}
588
589
	/**
590
	 * Find supported languages
591
	 *
592
	 * @return array Supported languages
593
	 */
594
	function loadLangSupported()
595
	{
596
		static $lang_supported = null;
597 View Code Duplication
		if(!$lang_supported)
598
		{
599
			$langs = file(_XE_PATH_ . 'common/lang/lang.info');
600
			foreach($langs as $val)
601
			{
602
				list($lang_prefix, $lang_text) = explode(',', $val);
603
				$lang_text = trim($lang_text);
604
				$lang_supported[$lang_prefix] = $lang_text;
605
			}
606
		}
607
		return $lang_supported;
608
	}
609
610
	/**
611
	 * Find selected languages to serve in the site
612
	 *
613
	 * @return array Selected languages
614
	 */
615
	function loadLangSelected()
616
	{
617
		static $lang_selected = null;
618
		if(!$lang_selected)
619
		{
620
			$orig_lang_file = _XE_PATH_ . 'common/lang/lang.info';
621
			$selected_lang_file = _XE_PATH_ . 'files/config/lang_selected.info';
622
			if(!FileHandler::hasContent($selected_lang_file))
623
			{
624
				$old_selected_lang_file = _XE_PATH_ . 'files/cache/lang_selected.info';
625
				FileHandler::moveFile($old_selected_lang_file, $selected_lang_file);
626
			}
627
628
			if(!FileHandler::hasContent($selected_lang_file))
629
			{
630
				$buff = FileHandler::readFile($orig_lang_file);
631
				FileHandler::writeFile($selected_lang_file, $buff);
632
				$lang_selected = self::loadLangSupported();
633
			}
634 View Code Duplication
			else
635
			{
636
				$langs = file($selected_lang_file);
637
				foreach($langs as $val)
638
				{
639
					list($lang_prefix, $lang_text) = explode(',', $val);
640
					$lang_text = trim($lang_text);
641
					$lang_selected[$lang_prefix] = $lang_text;
642
				}
643
			}
644
		}
645
		return $lang_selected;
646
	}
647
648
	/**
649
	 * Single Sign On (SSO)
650
	 *
651
	 * @return bool True : Module handling is necessary in the control path of current request , False : Otherwise
652
	 */
653
	function checkSSO()
654
	{
655
		// pass if it's not GET request or XE is not yet installed
656
		if($this->db_info->use_sso != 'Y' || isCrawler())
657
		{
658
			return TRUE;
659
		}
660
		$checkActList = array('rss' => 1, 'atom' => 1);
661
		if(self::getRequestMethod() != 'GET' || !self::isInstalled() || isset($checkActList[self::get('act')]))
662
		{
663
			return TRUE;
664
		}
665
666
		// pass if default URL is not set
667
		$default_url = trim($this->db_info->default_url);
668
		if(!$default_url)
669
		{
670
			return TRUE;
671
		}
672
673
		if(substr_compare($default_url, '/', -1) !== 0)
674
		{
675
			$default_url .= '/';
676
		}
677
678
		// for sites recieving SSO valdiation
679
		if($default_url == self::getRequestUri())
680
		{
681
			if(self::get('url'))
682
			{
683
				$url = base64_decode(self::get('url'));
684
				$url_info = parse_url($url);
685 View Code Duplication
				if(!Password::checkSignature($url, self::get('sig')))
686
				{
687
					echo self::get('lang')->msg_invalid_request;
688
					return false;
689
				}
690
691
				$oModuleModel = getModel('module');
692
				$domain = $url_info['host'] . $url_info['path'];
693
				if(substr_compare($domain, '/', -1) === 0) $domain = substr($domain, 0, -1);
694
				$site_info = $oModuleModel->getSiteInfoByDomain($domain);
695
696
				if($site_info->site_srl)
697
				{
698
				$url_info['query'].= ($url_info['query'] ? '&' : '') . 'SSOID=' . urlencode(session_id()) . '&sig=' . urlencode(Password::createSignature(session_id()));
699
				$redirect_url = sprintf('%s://%s%s%s?%s', $url_info['scheme'], $url_info['host'], $url_info['port'] ? ':' . $url_info['port'] : '', $url_info['path'], $url_info['query']);
700
				}
701
				else
702
				{
703
					$redirect_url = $url;
704
				}
705
				header('location:' . $redirect_url);
706
707
				return FALSE;
708
			}
709
			// for sites requesting SSO validation
710
		}
711
		else
712
		{
713
			// result handling : set session_name()
714
			if($session_name = self::get('SSOID'))
715
			{
716 View Code Duplication
				if(!Password::checkSignature($session_name, self::get('sig')))
717
				{
718
					echo self::get('lang')->msg_invalid_request;
719
					return false;
720
				}
721
722
				setcookie(session_name(), $session_name);
723
724
				$url = preg_replace('/[\?\&]SSOID=.+$/', '', self::getRequestUrl());
725
				header('location:' . $url);
726
				return FALSE;
727
				// send SSO request
728
			}
729
			else if(!self::get('SSOID') && $_COOKIE['sso'] != md5(self::getRequestUri()))
730
			{
731
				setcookie('sso', md5(self::getRequestUri()));
732
				$origin_url = self::getRequestUrl();
733
				$origin_sig = Password::createSignature($origin_url);
734
				$url = sprintf("%s?url=%s&sig=%s", $default_url, urlencode(base64_encode($origin_url)), urlencode($origin_sig));
735
				header('location:' . $url);
736
				return FALSE;
737
			}
738
		}
739
740
		return TRUE;
741
	}
742
743
	/**
744
	 * Check if FTP info is registered
745
	 *
746
	 * @return bool True: FTP information is registered, False: otherwise
747
	 */
748
	function isFTPRegisted()
749
	{
750
		return file_exists(self::getFTPConfigFile());
751
	}
752
753
	/**
754
	 * Get FTP information
755
	 *
756
	 * @return object FTP information
757
	 */
758
	function getFTPInfo()
759
	{
760
		$self = self::getInstance();
761
762
		if(!$self->isFTPRegisted())
763
		{
764
			return null;
765
		}
766
767
		include($self->getFTPConfigFile());
768
769
		return $ftp_info;
0 ignored issues
show
Bug introduced by
The variable $ftp_info does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
770
	}
771
772
	/**
773
	 * Add string to browser title
774
	 *
775
	 * @param string $site_title Browser title to be added
776
	 * @return void
777
	 */
778
	function addBrowserTitle($site_title)
779
	{
780
		if(!$site_title)
781
		{
782
			return;
783
		}
784
		$self = self::getInstance();
785
786
		if($self->site_title)
787
		{
788
			$self->site_title .= ' - ' . $site_title;
789
		}
790
		else
791
		{
792
			$self->site_title = $site_title;
793
		}
794
	}
795
796
	/**
797
	 * Set string to browser title
798
	 *
799
	 * @param string $site_title Browser title  to be set
800
	 * @return void
801
	 */
802
	function setBrowserTitle($site_title)
803
	{
804
		if(!$site_title)
805
		{
806
			return;
807
		}
808
		$self = self::getInstance();
809
		$self->site_title = $site_title;
810
	}
811
812
	/**
813
	 * Get browser title
814
	 *
815
	 * @return string Browser title(htmlspecialchars applied)
816
	 */
817
	function getBrowserTitle()
818
	{
819
		$self = self::getInstance();
820
821
		$oModuleController = getController('module');
822
		$oModuleController->replaceDefinedLangCode($self->site_title);
823
824
		return htmlspecialchars($self->site_title, ENT_COMPAT | ENT_HTML401, 'UTF-8', FALSE);
825
	}
826
827
	/**
828
	 * Return layout's title
829
	 * @return string layout's title
830
	 */
831
	public function getSiteTitle()
832
	{
833
		$oModuleModel = getModel('module');
834
		$moduleConfig = $oModuleModel->getModuleConfig('module');
835
836
		if(isset($moduleConfig->siteTitle))
837
		{
838
			return $moduleConfig->siteTitle;
839
		}
840
		return '';
841
	}
842
843
	/**
844
	 * Get browser title
845
	 * @deprecated
846
	 */
847
	function _getBrowserTitle()
848
	{
849
		return $this->getBrowserTitle();
850
	}
851
852
	/**
853
	 * Load language file according to language type
854
	 *
855
	 * @param string $path Path of the language file
856
	 * @return void
857
	 */
858
	function loadLang($path)
859
	{
860
		global $lang;
861
862
		$self = self::getInstance();
863
		if(!$self->lang_type)
864
		{
865
			return;
866
		}
867
		if(!is_object($lang))
868
		{
869
			$lang = new stdClass;
870
		}
871
872
		if(!($filename = $self->_loadXmlLang($path)))
873
		{
874
			$filename = $self->_loadPhpLang($path);
875
		}
876
877
		if(!is_array($self->loaded_lang_files))
878
		{
879
			$self->loaded_lang_files = array();
880
		}
881
		if(in_array($filename, $self->loaded_lang_files))
882
		{
883
			return;
884
		}
885
886
		if($filename && is_readable($filename))
887
		{
888
			$self->loaded_lang_files[] = $filename;
889
			include($filename);
890
		}
891
		else
892
		{
893
			$self->_evalxmlLang($path);
894
		}
895
	}
896
897
	/**
898
	 * Evaluation of xml language file
899
	 *
900
	 * @param string Path of the language file
901
	 * @return void
902
	 */
903
	function _evalxmlLang($path)
904
	{
905
		global $lang;
906
907
		if(!$path) return;
908
909
		$_path = 'eval://' . $path;
910
911
		if(in_array($_path, $this->loaded_lang_files))
912
		{
913
			return;
914
		}
915
916
		if(substr_compare($path, '/', -1) !== 0)
917
		{
918
			$path .= '/';
919
		}
920
921
		$oXmlLangParser = new XmlLangParser($path . 'lang.xml', $this->lang_type);
922
		$content = $oXmlLangParser->getCompileContent();
923
924
		if($content)
0 ignored issues
show
Bug Best Practice introduced by
The expression $content of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
925
		{
926
			$this->loaded_lang_files[] = $_path;
927
			eval($content);
928
		}
929
	}
930
931
	/**
932
	 * Load language file of xml type
933
	 *
934
	 * @param string $path Path of the language file
935
	 * @return string file name
936
	 */
937
	function _loadXmlLang($path)
938
	{
939
		if(!$path) return;
940
941
		$oXmlLangParser = new XmlLangParser($path . ((substr_compare($path, '/', -1) !== 0) ? '/' : '') . 'lang.xml', $this->lang_type);
942
		return $oXmlLangParser->compile();
943
	}
944
945
	/**
946
	 * Load language file of php type
947
	 *
948
	 * @param string $path Path of the language file
949
	 * @return string file name
950
	 */
951
	function _loadPhpLang($path)
952
	{
953
		if(!$path) return;
954
955
		if(substr_compare($path, '/', -1) !== 0)
956
		{
957
			$path .= '/';
958
		}
959
		$path_tpl = $path . '%s.lang.php';
960
		$file = sprintf($path_tpl, $this->lang_type);
961
962
		$langs = array('ko', 'en'); // this will be configurable.
963
		while(!is_readable($file) && $langs[0])
964
		{
965
			$file = sprintf($path_tpl, array_shift($langs));
966
		}
967
968
		if(!is_readable($file))
969
		{
970
			return FALSE;
971
		}
972
		return $file;
973
	}
974
975
	/**
976
	 * Set lang_type
977
	 *
978
	 * @param string $lang_type Language type.
979
	 * @return void
980
	 */
981
	function setLangType($lang_type = 'ko')
982
	{
983
		$self = self::getInstance();
984
985
		$self->lang_type = $lang_type;
986
		$self->set('lang_type', $lang_type);
987
988
		$_SESSION['lang_type'] = $lang_type;
989
	}
990
991
	/**
992
	 * Get lang_type
993
	 *
994
	 * @return string Language type
995
	 */
996
	function getLangType()
997
	{
998
		$self = self::getInstance();
999
		return $self->lang_type;
1000
	}
1001
1002
	/**
1003
	 * Return string accoring to the inputed code
1004
	 *
1005
	 * @param string $code Language variable name
1006
	 * @return string If string for the code exists returns it, otherwise returns original code
1007
	 */
1008
	function getLang($code)
1009
	{
1010
		if(!$code)
1011
		{
1012
			return;
1013
		}
1014
		if($GLOBALS['lang']->{$code})
1015
		{
1016
			return $GLOBALS['lang']->{$code};
1017
		}
1018
		return $code;
1019
	}
1020
1021
	/**
1022
	 * Set data to lang variable
1023
	 *
1024
	 * @param string $code Language variable name
1025
	 * @param string $val `$code`s value
1026
	 * @return void
1027
	 */
1028
	function setLang($code, $val)
1029
	{
1030
		if(!isset($GLOBALS['lang']))
1031
		{
1032
			$GLOBALS['lang'] = new stdClass();
1033
		}
1034
		$GLOBALS['lang']->{$code} = $val;
1035
	}
1036
1037
	/**
1038
	 * Convert strings of variables in $source_object into UTF-8
1039
	 *
1040
	 * @param object $source_obj Conatins strings to convert
1041
	 * @return object converted object
1042
	 */
1043
	function convertEncoding($source_obj)
1044
	{
1045
		$charset_list = array(
1046
			'UTF-8', 'EUC-KR', 'CP949', 'ISO8859-1', 'EUC-JP', 'SHIFT_JIS',
1047
			'CP932', 'EUC-CN', 'HZ', 'GBK', 'GB18030', 'EUC-TW', 'BIG5',
1048
			'CP950', 'BIG5-HKSCS', 'ISO8859-6', 'ISO8859-8', 'JOHAB', 'CP1255',
1049
			'CP1256', 'CP862', 'ASCII', 'ISO8859-1', 'CP1250', 'CP1251',
1050
			'CP1252', 'CP1253', 'CP1254', 'CP1257', 'CP850', 'CP866'
1051
		);
1052
1053
		$obj = clone $source_obj;
1054
1055
		foreach($charset_list as $charset)
1056
		{
1057
			array_walk($obj,'Context::checkConvertFlag',$charset);
1058
			$flag = self::checkConvertFlag($flag = TRUE);
0 ignored issues
show
Bug introduced by
$flag = TRUE cannot be passed to checkconvertflag() as the parameter $val expects a reference.
Loading history...
1059
			if($flag)
1060
			{
1061
				if($charset == 'UTF-8')
1062
				{
1063
					return $obj;
1064
				}
1065
				array_walk($obj,'Context::doConvertEncoding',$charset);
1066
				return $obj;
1067
			}
1068
		}
1069
		return $obj;
1070
	}
1071
1072
	/**
1073
	 * Check flag
1074
	 *
1075
	 * @param mixed $val
1076
	 * @param string $key
1077
	 * @param mixed $charset charset
1078
	 * @see arrayConvWalkCallback will replaced array_walk_recursive in >=PHP5
1079
	 * @return void
1080
	 */
1081
	function checkConvertFlag(&$val, $key = null, $charset = null)
0 ignored issues
show
Unused Code introduced by
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...
1082
	{
1083
		static $flag = TRUE;
1084
		if($charset)
1085
		{
1086
			if(is_array($val))
1087
				array_walk($val,'Context::checkConvertFlag',$charset);
1088
			else if($val && iconv($charset,$charset,$val)!=$val) $flag = FALSE;
1089
			else $flag = FALSE;
1090
		}
1091
		else
1092
		{
1093
			$return = $flag;
1094
			$flag = TRUE;
1095
			return $return;
1096
		}
1097
	}
1098
1099
	/**
1100
	 * Convert array type variables into UTF-8
1101
	 *
1102
	 * @param mixed $val
1103
	 * @param string $key
1104
	 * @param string $charset character set
1105
	 * @see arrayConvWalkCallback will replaced array_walk_recursive in >=PHP5
1106
	 * @return object converted object
1107
	 */
1108
	function doConvertEncoding(&$val, $key = null, $charset)
0 ignored issues
show
Unused Code introduced by
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...
1109
	{
1110
		if (is_array($val))
1111
		{
1112
			array_walk($val,'Context::doConvertEncoding',$charset);
1113
		}
1114
		else $val = iconv($charset,'UTF-8',$val);
1115
	}
1116
1117
	/**
1118
	 * Convert strings into UTF-8
1119
	 *
1120
	 * @param string $str String to convert
1121
	 * @return string converted string
1122
	 */
1123
	function convertEncodingStr($str)
1124
	{
1125
        if(!$str) return null;
1126
		$obj = new stdClass();
1127
		$obj->str = $str;
1128
		$obj = self::convertEncoding($obj);
1129
		return $obj->str;
1130
	}
1131
1132
	function decodeIdna($domain)
1133
	{
1134
		if(strpos($domain, 'xn--') !== FALSE)
1135
		{
1136
			require_once(_XE_PATH_ . 'libs/idna_convert/idna_convert.class.php');
1137
			$IDN = new idna_convert(array('idn_version' => 2008));
1138
			$domain = $IDN->decode($domain);
1139
		}
1140
1141
		return $domain;
1142
	}
1143
1144
	/**
1145
	 * Force to set response method
1146
	 *
1147
	 * @param string $method Response method. [HTML|XMLRPC|JSON]
1148
	 * @return void
1149
	 */
1150
	function setResponseMethod($method = 'HTML')
1151
	{
1152
		$self = self::getInstance();
1153
1154
		$methods = array('HTML' => 1, 'XMLRPC' => 1, 'JSON' => 1, 'JS_CALLBACK' => 1);
1155
		$self->response_method = isset($methods[$method]) ? $method : 'HTML';
1156
	}
1157
1158
	/**
1159
	 * Get reponse method
1160
	 *
1161
	 * @return string Response method. If it's not set, returns request method.
1162
	 */
1163
	function getResponseMethod()
1164
	{
1165
		$self = self::getInstance();
1166
1167
		if($self->response_method)
1168
		{
1169
			return $self->response_method;
1170
		}
1171
1172
		$method = $self->getRequestMethod();
1173
		$methods = array('HTML' => 1, 'XMLRPC' => 1, 'JSON' => 1, 'JS_CALLBACK' => 1);
1174
1175
		return isset($methods[$method]) ? $method : 'HTML';
1176
	}
1177
1178
	/**
1179
	 * Determine request method
1180
	 *
1181
	 * @param string $type Request method. (Optional - GET|POST|XMLRPC|JSON)
1182
	 * @return void
1183
	 */
1184
	function setRequestMethod($type = '')
1185
	{
1186
		$self = self::getInstance();
1187
1188
		$self->js_callback_func = $self->getJSCallbackFunc();
1189
1190
		($type && $self->request_method = $type) or
1191
				((strpos($_SERVER['CONTENT_TYPE'], 'json') || strpos($_SERVER['HTTP_CONTENT_TYPE'], 'json')) && $self->request_method = 'JSON') or
1192
				($GLOBALS['HTTP_RAW_POST_DATA'] && $self->request_method = 'XMLRPC') or
1193
				($self->js_callback_func && $self->request_method = 'JS_CALLBACK') or
1194
				($self->request_method = $_SERVER['REQUEST_METHOD']);
1195
	}
1196
1197
	/**
1198
	 * handle global arguments
1199
	 *
1200
	 * @return void
1201
	 */
1202
	function _checkGlobalVars()
1203
	{
1204
		$this->_recursiveCheckVar($_SERVER['HTTP_HOST']);
1205
1206
		$pattern = "/[\,\"\'\{\}\[\]\(\);$]/";
1207
		if(preg_match($pattern, $_SERVER['HTTP_HOST']))
1208
		{
1209
			$this->isSuccessInit = FALSE;
1210
		}
1211
	}
1212
1213
	/**
1214
	 * handle request arguments for GET/POST
1215
	 *
1216
	 * @return void
1217
	 */
1218
	function _setRequestArgument()
1219
	{
1220
		if(!count($_REQUEST))
1221
		{
1222
			return;
1223
		}
1224
1225
		$requestMethod = $this->getRequestMethod();
1226
		foreach($_REQUEST as $key => $val)
1227
		{
1228
			if($val === '' || self::get($key))
1229
			{
1230
				continue;
1231
			}
1232
			$key = htmlentities($key);
1233
			$val = $this->_filterRequestVar($key, $val, false, ($requestMethod == 'GET'));
1234
1235
			if($requestMethod == 'GET' && isset($_GET[$key]))
1236
			{
1237
				$set_to_vars = TRUE;
1238
			}
1239
			elseif($requestMethod == 'POST' && isset($_POST[$key]))
1240
			{
1241
				$set_to_vars = TRUE;
1242
			}
1243
			elseif($requestMethod == 'JS_CALLBACK' && (isset($_GET[$key]) || isset($_POST[$key])))
1244
			{
1245
				$set_to_vars = TRUE;
1246
			}
1247
			else
1248
			{
1249
				$set_to_vars = FALSE;
1250
			}
1251
1252
			if($set_to_vars)
1253
			{
1254
				$this->_recursiveCheckVar($val);
1255
			}
1256
1257
			$this->set($key, $val, $set_to_vars);
0 ignored issues
show
Documentation introduced by
$set_to_vars is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1258
		}
1259
	}
1260
1261
	function _recursiveCheckVar($val)
1262
	{
1263
		if(is_string($val))
1264
		{
1265
			foreach($this->patterns as $pattern)
1266
			{
1267
				if(preg_match($pattern, $val))
1268
				{
1269
					$this->isSuccessInit = FALSE;
1270
					return;
1271
				}
1272
			}
1273
		}
1274
		else if(is_array($val))
1275
		{
1276
			foreach($val as $val2)
1277
			{
1278
				$this->_recursiveCheckVar($val2);
1279
			}
1280
		}
1281
	}
1282
1283
	/**
1284
	 * Handle request arguments for JSON
1285
	 *
1286
	 * @return void
1287
	 */
1288
	function _setJSONRequestArgument()
1289
	{
1290
		if($this->getRequestMethod() != 'JSON')
1291
		{
1292
			return;
1293
		}
1294
1295
		$params = array();
1296
		parse_str($GLOBALS['HTTP_RAW_POST_DATA'], $params);
1297
1298
		foreach($params as $key => $val)
0 ignored issues
show
Bug introduced by
The expression $params of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1299
		{
1300
			$key = htmlentities($key);
1301
			$this->set($key, $this->_filterRequestVar($key, $val, 1), TRUE);
0 ignored issues
show
Documentation introduced by
TRUE is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1302
		}
1303
	}
1304
1305
	/**
1306
	 * Handle request arguments for XML RPC
1307
	 *
1308
	 * @return void
1309
	 */
1310
	function _setXmlRpcArgument()
1311
	{
1312
		if($this->getRequestMethod() != 'XMLRPC')
1313
		{
1314
			return;
1315
		}
1316
1317
		$xml = $GLOBALS['HTTP_RAW_POST_DATA'];
1318
		if(Security::detectingXEE($xml))
1319
		{
1320
			header("HTTP/1.0 400 Bad Request");
1321
			exit;
1322
		}
1323
1324
		$oXml = new XmlParser();
1325
		$xml_obj = $oXml->parse($xml);
1326
1327
		$params = $xml_obj->methodcall->params;
1328
		unset($params->node_name, $params->attrs, $params->body);
1329
1330
		if(!count(get_object_vars($params)))
1331
		{
1332
			return;
1333
		}
1334
1335
		foreach($params as $key => $val)
1336
		{
1337
			$this->set($key, $this->_filterXmlVars($key, $val), TRUE);
0 ignored issues
show
Documentation introduced by
TRUE is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1338
		}
1339
	}
1340
1341
	/**
1342
	 * Filter xml variables
1343
	 *
1344
	 * @param string $key Variable key
1345
	 * @param object $val Variable value
1346
	 * @return mixed filtered value
1347
	 */
1348
	function _filterXmlVars($key, $val)
1349
	{
1350
		if(is_array($val))
1351
		{
1352
			$stack = array();
1353
			foreach($val as $k => $v)
1354
			{
1355
				$stack[$k] = $this->_filterXmlVars($k, $v);
1356
			}
1357
1358
			return $stack;
1359
		}
1360
1361
		$body = $val->body;
1362
		unset($val->node_name, $val->attrs, $val->body);
1363
		if(!count(get_object_vars($val)))
1364
		{
1365
			return $this->_filterRequestVar($key, $body, 0);
1366
		}
1367
1368
		$stack = new stdClass();
1369
		foreach($val as $k => $v)
1370
		{
1371
			$output = $this->_filterXmlVars($k, $v);
1372
			if(is_object($v) && $v->attrs->type == 'array')
1373
			{
1374
				$output = array($output);
1375
			}
1376
			if($k == 'value' && (is_array($v) || $v->attrs->type == 'array'))
1377
			{
1378
				return $output;
1379
			}
1380
1381
			$stack->{$k} = $output;
1382
		}
1383
1384
		if(!count(get_object_vars($stack)))
1385
		{
1386
			return NULL;
1387
		}
1388
1389
		return $stack;
1390
	}
1391
1392
	/**
1393
	 * Filter request variable
1394
	 *
1395
	 * @see Cast variables, such as _srl, page, and cpage, into interger
1396
	 * @param string $key Variable key
1397
	 * @param string $val Variable value
1398
	 * @param string $do_stripslashes Whether to strip slashes
1399
	 * @return mixed filtered value. Type are string or array
1400
	 */
1401
	function _filterRequestVar($key, $val, $do_stripslashes = true, $remove_hack = false)
1402
	{
1403
		if(!($isArray = is_array($val)))
1404
		{
1405
			$val = array($val);
1406
		}
1407
1408
		$result = array();
1409
		foreach($val as $k => $v)
1410
		{
1411
			$k = escape($k);
1412
			$result[$k] = $v;
1413
1414
			if($remove_hack && !is_array($result[$k])) {
1415
				if(stripos($result[$k], '<script') || stripos($result[$k], 'lt;script') || stripos($result[$k], '%3Cscript'))
1416
				{
1417
					$result[$k] = escape($result[$k]);
1418
				}
1419
			}
1420
1421
			if($key === 'page' || $key === 'cpage' || substr_compare($key, 'srl', -3) === 0)
1422
			{
1423
				$result[$k] = !preg_match('/^[0-9,]+$/', $result[$k]) ? (int) $result[$k] : $result[$k];
1424
			}
1425
			elseif(in_array($key, array('mid','search_keyword','search_target','xe_validator_id'))) {
1426
				$result[$k] = escape($result[$k], false);
1427
			}
1428
			elseif($key === 'vid')
1429
			{
1430
				$result[$k] = urlencode($result[$k]);
1431
			}
1432
			elseif(stripos($key, 'XE_VALIDATOR', 0) === 0)
1433
			{
1434
				unset($result[$k]);
1435
			}
1436
			else
1437
			{
1438
				if(in_array($k, array(
1439
					'act',
1440
					'addon',
1441
					'cur_mid',
1442
					'full_browse',
1443
					'http_status_message',
1444
					'l',
1445
					'layout',
1446
					'm',
1447
					'mid',
1448
					'module',
1449
					'selected_addon',
1450
					'selected_layout',
1451
					'selected_widget',
1452
					'widget',
1453
					'widgetstyle',
1454
				)))
1455
				{
1456
					$result[$k] = urlencode(preg_replace("/[^a-z0-9-_]+/i", '', $result[$k]));
1457
				}
1458
1459
				if($do_stripslashes && version_compare(PHP_VERSION, '5.4.0', '<') && get_magic_quotes_gpc())
1460
				{
1461 View Code Duplication
					if (is_array($result[$k]))
1462
					{
1463
						array_walk_recursive($result[$k], function(&$val) { $val = stripslashes($val); });
1464
					}
1465
					else
1466
					{
1467
						$result[$k] = stripslashes($result[$k]);
1468
					}
1469
				}
1470
1471 View Code Duplication
				if(is_array($result[$k]))
1472
				{
1473
					array_walk_recursive($result[$k], function(&$val) { $val = trim($val); });
1474
				}
1475
				else
1476
				{
1477
					$result[$k] = trim($result[$k]);
1478
				}
1479
1480
				if($remove_hack)
1481
				{
1482
					$result[$k] = escape($result[$k], false);
1483
				}
1484
			}
1485
		}
1486
1487
		return $isArray ? $result : $result[0];
1488
	}
1489
1490
	/**
1491
	 * Check if there exists uploaded file
1492
	 *
1493
	 * @return bool True: exists, False: otherwise
1494
	 */
1495
	function isUploaded()
1496
	{
1497
		$self = self::getInstance();
1498
		return $self->is_uploaded;
1499
	}
1500
1501
	/**
1502
	 * Handle uploaded file
1503
	 *
1504
	 * @return void
1505
	 */
1506
	function _setUploadedArgument()
1507
	{
1508
		if($_SERVER['REQUEST_METHOD'] != 'POST' || !$_FILES || (stripos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') === FALSE && stripos($_SERVER['HTTP_CONTENT_TYPE'], 'multipart/form-data') === FALSE))
1509
		{
1510
			return;
1511
		}
1512
1513
		foreach($_FILES as $key => $val)
1514
		{
1515
			$tmp_name = $val['tmp_name'];
1516
1517
			if(!is_array($tmp_name))
1518
			{
1519
				if(!UploadFileFilter::check($tmp_name, $val['name']))
1520
				{
1521
					unset($_FILES[$key]);
1522
					continue;
1523
				}
1524
				$val['name'] = escape($val['name'], FALSE);
1525
				$this->set($key, $val, TRUE);
0 ignored issues
show
Documentation introduced by
TRUE is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1526
				$this->is_uploaded = TRUE;
1527
			}
1528
			else
1529
			{
1530
				$files = array();
1531
				foreach ($tmp_name as $i => $j)
1532
				{
1533
					if(!UploadFileFilter::check($val['tmp_name'][$i], $val['name'][$i]))
1534
					{
1535
						$files = array();
1536
						unset($_FILES[$key]);
1537
						break;
1538
					}
1539
					$file = array();
1540
					$file['name'] = $val['name'][$i];
1541
					$file['type'] = $val['type'][$i];
1542
					$file['tmp_name'] = $val['tmp_name'][$i];
1543
					$file['error'] = $val['error'][$i];
1544
					$file['size'] = $val['size'][$i];
1545
					$files[] = $file;
1546
				}
1547
				if(count($files))
1548
				{
1549
					self::set($key, $files, true);
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1550
				}
1551
			}
1552
		}
1553
	}
1554
1555
	/**
1556
	 * Return request method
1557
	 * @return string Request method type. (Optional - GET|POST|XMLRPC|JSON)
1558
	 */
1559
	function getRequestMethod()
1560
	{
1561
		$self = self::getInstance();
1562
		return $self->request_method;
1563
	}
1564
1565
	/**
1566
	 * Return request URL
1567
	 * @return string request URL
1568
	 */
1569
	function getRequestUrl()
1570
	{
1571
		static $url = null;
1572
		if(is_null($url))
1573
		{
1574
			$url = self::getRequestUri();
1575
			if(count($_GET) > 0)
1576
			{
1577
				foreach($_GET as $key => $val)
1578
				{
1579
					$vars[] = $key . '=' . ($val ? urlencode(self::convertEncodingStr($val)) : '');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$vars was never initialized. Although not strictly required by PHP, it is generally a good practice to add $vars = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1580
				}
1581
				$url .= '?' . join('&', $vars);
0 ignored issues
show
Bug introduced by
The variable $vars does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1582
			}
1583
		}
1584
		return $url;
1585
	}
1586
1587
	/**
1588
	 * Return js callback func.
1589
	 * @return string callback func.
1590
	 */
1591
	function getJSCallbackFunc()
1592
	{
1593
		$self = self::getInstance();
0 ignored issues
show
Unused Code introduced by
$self is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1594
		$js_callback_func = isset($_GET['xe_js_callback']) ? $_GET['xe_js_callback'] : $_POST['xe_js_callback'];
1595
1596
		if(!preg_match('/^[a-z0-9\.]+$/i', $js_callback_func))
1597
		{
1598
			unset($js_callback_func);
1599
			unset($_GET['xe_js_callback']);
1600
			unset($_POST['xe_js_callback']);
1601
		}
1602
1603
		return $js_callback_func;
1604
	}
1605
1606
	/**
1607
	 * Make URL with args_list upon request URL
1608
	 *
1609
	 * @param int $num_args Arguments nums
1610
	 * @param array $args_list Argument list for set url
1611
	 * @param string $domain Domain
1612
	 * @param bool $encode If TRUE, use url encode.
1613
	 * @param bool $autoEncode If TRUE, url encode automatically, detailed. Use this option, $encode value should be TRUE
1614
	 * @return string URL
1615
	 */
1616
	function getUrl($num_args = 0, $args_list = array(), $domain = null, $encode = TRUE, $autoEncode = FALSE)
0 ignored issues
show
Unused Code introduced by
The parameter $num_args 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...
1617
	{
1618
		static $site_module_info = null;
1619
		static $current_info = null;
1620
1621
		$self = self::getInstance();
1622
1623
		// retrieve virtual site information
1624
		if(is_null($site_module_info))
1625
		{
1626
			$site_module_info = self::get('site_module_info');
1627
		}
1628
1629
		// If $domain is set, handle it (if $domain is vid type, remove $domain and handle with $vid)
1630
		if($domain && isSiteID($domain))
0 ignored issues
show
Bug Best Practice introduced by
The expression $domain of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1631
		{
1632
			$vid = $domain;
1633
			$domain = '';
1634
		}
1635
1636
		// If $domain, $vid are not set, use current site information
1637
		if(!$domain && !$vid)
0 ignored issues
show
Bug introduced by
The variable $vid does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug Best Practice introduced by
The expression $domain of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1638
		{
1639
			if($site_module_info->domain && isSiteID($site_module_info->domain))
1640
			{
1641
				$vid = $site_module_info->domain;
1642
			}
1643
			else
1644
			{
1645
				$domain = $site_module_info->domain;
1646
			}
1647
		}
1648
1649
		// if $domain is set, compare current URL. If they are same, remove the domain, otherwise link to the domain.
1650
		if($domain)
1651
		{
1652
			$domain_info = parse_url($domain);
1653
			if(is_null($current_info))
1654
			{
1655
				$current_info = parse_url(($_SERVER['HTTPS'] == 'on' ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . getScriptPath());
1656
			}
1657
			if($domain_info['host'] . $domain_info['path'] == $current_info['host'] . $current_info['path'])
1658
			{
1659
				unset($domain);
1660
			}
1661
			else
1662
			{
1663
				$domain = preg_replace('/^(http|https):\/\//i', '', trim($domain));
1664
				if(substr_compare($domain, '/', -1) !== 0)
1665
				{
1666
					$domain .= '/';
1667
				}
1668
			}
1669
		}
1670
1671
		$get_vars = array();
1672
1673
		// If there is no GET variables or first argument is '' to reset variables
1674
		if(!$self->get_vars || $args_list[0] == '')
1675
		{
1676
			// rearrange args_list
1677
			if(is_array($args_list) && $args_list[0] == '')
1678
			{
1679
				array_shift($args_list);
1680
			}
1681
		}
1682
		elseif($_SERVER['REQUEST_METHOD'] == 'GET')
1683
		{
1684
			// Otherwise, make GET variables into array
1685
			$get_vars = get_object_vars($self->get_vars);
1686
		}
1687
		else
1688
		{
1689
			if(!!$self->get_vars->module) $get_vars['module'] = $self->get_vars->module;
1690
			if(!!$self->get_vars->mid) $get_vars['mid'] = $self->get_vars->mid;
1691
			if(!!$self->get_vars->act) $get_vars['act'] = $self->get_vars->act;
1692
			if(!!$self->get_vars->page) $get_vars['page'] = $self->get_vars->page;
1693
			if(!!$self->get_vars->search_target) $get_vars['search_target'] = $self->get_vars->search_target;
1694
			if(!!$self->get_vars->search_keyword) $get_vars['search_keyword'] = $self->get_vars->search_keyword;
1695
			if($get_vars['act'] == 'IS')
1696
			{
1697
				if(!!$self->get_vars->is_keyword) $get_vars['is_keyword'] = $self->get_vars->is_keyword;
1698
			}
1699
		}
1700
1701
		// arrange args_list
1702
		for($i = 0, $c = count($args_list); $i < $c; $i += 2)
1703
		{
1704
			$key = $args_list[$i];
1705
			$val = trim($args_list[$i + 1]);
1706
1707
			// If value is not set, remove the key
1708
			if(!isset($val) || !strlen($val))
1709
			{
1710
				unset($get_vars[$key]);
1711
				continue;
1712
			}
1713
			// set new variables
1714
			$get_vars[$key] = $val;
1715
		}
1716
1717
		// remove vid, rnd
1718
		unset($get_vars['rnd']);
1719
		if($vid)
1720
		{
1721
			$get_vars['vid'] = $vid;
1722
		}
1723
		else
1724
		{
1725
			unset($get_vars['vid']);
1726
		}
1727
1728
		// for compatibility to lower versions
1729
		$act = $get_vars['act'];
1730
		$act_alias = array(
1731
			'dispMemberFriend' => 'dispCommunicationFriend',
1732
			'dispMemberMessages' => 'dispCommunicationMessages',
1733
			'dispDocumentAdminManageDocument' => 'dispDocumentManageDocument',
1734
			'dispModuleAdminSelectList' => 'dispModuleSelectList'
1735
		);
1736
		if($act_alias[$act])
1737
		{
1738
			$get_vars['act'] = $act_alias[$act];
1739
		}
1740
1741
		// organize URL
1742
		$query = '';
1743
		if(count($get_vars) > 0)
1744
		{
1745
			// if using rewrite mod
1746
			if($self->allow_rewrite)
1747
			{
1748
				$var_keys = array_keys($get_vars);
1749
				sort($var_keys);
1750
1751
				$target = join('.', $var_keys);
1752
1753
				$act = $get_vars['act'];
1754
				$vid = $get_vars['vid'];
1755
				$mid = $get_vars['mid'];
1756
				$key = $get_vars['key'];
1757
				$srl = $get_vars['document_srl'];
1758
1759
				$tmpArray = array('rss' => 1, 'atom' => 1, 'api' => 1);
1760
				$is_feed = isset($tmpArray[$act]);
1761
1762
				$target_map = array(
1763
					'vid' => $vid,
1764
					'mid' => $mid,
1765
					'mid.vid' => "$vid/$mid",
1766
					'entry.mid' => "$mid/entry/" . $get_vars['entry'],
1767
					'entry.mid.vid' => "$vid/$mid/entry/" . $get_vars['entry'],
1768
					'document_srl' => $srl,
1769
					'document_srl.mid' => "$mid/$srl",
1770
					'document_srl.vid' => "$vid/$srl",
1771
					'document_srl.mid.vid' => "$vid/$mid/$srl",
1772
					'act' => ($is_feed && $act !== 'api') ? $act : '',
1773
					'act.mid' => $is_feed ? "$mid/$act" : '',
1774
					'act.mid.vid' => $is_feed ? "$vid/$mid/$act" : '',
1775
					'act.document_srl.key' => ($act == 'trackback') ? "$srl/$key/$act" : '',
1776
					'act.document_srl.key.mid' => ($act == 'trackback') ? "$mid/$srl/$key/$act" : '',
1777
					'act.document_srl.key.vid' => ($act == 'trackback') ? "$vid/$srl/$key/$act" : '',
1778
					'act.document_srl.key.mid.vid' => ($act == 'trackback') ? "$vid/$mid/$srl/$key/$act" : ''
1779
				);
1780
1781
				$query = $target_map[$target];
1782
			}
1783
1784
			if(!$query)
1785
			{
1786
				$queries = array();
1787 View Code Duplication
				foreach($get_vars as $key => $val)
1788
				{
1789
					if(is_array($val) && count($val) > 0)
1790
					{
1791
						foreach($val as $k => $v)
1792
						{
1793
							$queries[] = $key . '[' . $k . ']=' . urlencode($v);
1794
						}
1795
					}
1796
					elseif(!is_array($val))
1797
					{
1798
						$queries[] = $key . '=' . urlencode($val);
1799
					}
1800
				}
1801
				if(count($queries) > 0)
1802
				{
1803
					$query = 'index.php?' . join('&', $queries);
1804
				}
1805
			}
1806
		}
1807
1808
		// If using SSL always
1809
		$_use_ssl = $self->get('_use_ssl');
1810
		if($_use_ssl == 'always')
1811
		{
1812
			$query = $self->getRequestUri(ENFORCE_SSL, $domain) . $query;
1813
			// optional SSL use
1814
		}
1815
		elseif($_use_ssl == 'optional')
1816
		{
1817
			$ssl_mode = (($self->get('module') === 'admin') || ($get_vars['module'] === 'admin') || (isset($get_vars['act']) && $self->isExistsSSLAction($get_vars['act']))) ? ENFORCE_SSL : RELEASE_SSL;
1818
			$query = $self->getRequestUri($ssl_mode, $domain) . $query;
1819
			// no SSL
1820
		}
1821
		else
1822
		{
1823
			// currently on SSL but target is not based on SSL
1824
			if($_SERVER['HTTPS'] == 'on')
1825
			{
1826
				$query = $self->getRequestUri(ENFORCE_SSL, $domain) . $query;
1827
			}
1828
			else if($domain) // if $domain is set
1829
			{
1830
				$query = $self->getRequestUri(FOLLOW_REQUEST_SSL, $domain) . $query;
1831
			}
1832
			else
1833
			{
1834
				$query = getScriptPath() . $query;
1835
			}
1836
		}
1837
1838
		if(!$encode)
1839
		{
1840
			return $query;
1841
		}
1842
1843
		if(!$autoEncode)
1844
		{
1845
			return htmlspecialchars($query, ENT_COMPAT | ENT_HTML401, 'UTF-8', FALSE);
1846
		}
1847
1848
		$output = array();
1849
		$encode_queries = array();
1850
		$parsedUrl = parse_url($query);
1851
		parse_str($parsedUrl['query'], $output);
1852
		foreach($output as $key => $value)
0 ignored issues
show
Bug introduced by
The expression $output of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1853
		{
1854
			if(preg_match('/&([a-z]{2,}|#\d+);/', urldecode($value)))
1855
			{
1856
				$value = urlencode(htmlspecialchars_decode(urldecode($value)));
1857
			}
1858
			$encode_queries[] = $key . '=' . $value;
1859
		}
1860
1861
		return htmlspecialchars($parsedUrl['path'] . '?' . join('&', $encode_queries), ENT_COMPAT | ENT_HTML401, 'UTF-8', FALSE);
1862
	}
1863
1864
	/**
1865
	 * Return after removing an argument on the requested URL
1866
	 *
1867
	 * @param string $ssl_mode SSL mode
1868
	 * @param string $domain Domain
1869
	 * @retrun string converted URL
1870
	 */
1871
	function getRequestUri($ssl_mode = FOLLOW_REQUEST_SSL, $domain = null)
1872
	{
1873
		static $url = array();
1874
1875
		// Check HTTP Request
1876
		if(!isset($_SERVER['SERVER_PROTOCOL']))
1877
		{
1878
			return;
1879
		}
1880
1881
		if(self::get('_use_ssl') == 'always')
1882
		{
1883
			$ssl_mode = ENFORCE_SSL;
1884
		}
1885
1886
		if($domain)
0 ignored issues
show
Bug Best Practice introduced by
The expression $domain of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1887
		{
1888
			$domain_key = md5($domain);
1889
		}
1890
		else
1891
		{
1892
			$domain_key = 'default';
1893
		}
1894
1895
		if(isset($url[$ssl_mode][$domain_key]))
1896
		{
1897
			return $url[$ssl_mode][$domain_key];
1898
		}
1899
1900
		$current_use_ssl = ($_SERVER['HTTPS'] == 'on');
1901
1902
		switch($ssl_mode)
1903
		{
1904
			case FOLLOW_REQUEST_SSL: $use_ssl = $current_use_ssl;
1905
				break;
1906
			case ENFORCE_SSL: $use_ssl = TRUE;
1907
				break;
1908
			case RELEASE_SSL: $use_ssl = FALSE;
1909
				break;
1910
		}
1911
1912
		if($domain)
0 ignored issues
show
Bug Best Practice introduced by
The expression $domain of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1913
		{
1914
			$target_url = trim($domain);
1915
			if(substr_compare($target_url, '/', -1) !== 0)
1916
			{
1917
				$target_url.= '/';
1918
			}
1919
		}
1920
		else
1921
		{
1922
			$target_url = $_SERVER['HTTP_HOST'] . getScriptPath();
1923
		}
1924
1925
		$url_info = parse_url('http://' . $target_url);
1926
1927
		if($current_use_ssl != $use_ssl)
0 ignored issues
show
Bug introduced by
The variable $use_ssl does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1928
		{
1929
			unset($url_info['port']);
1930
		}
1931
1932
		if($use_ssl)
1933
		{
1934
			$port = self::get('_https_port');
1935 View Code Duplication
			if($port && $port != 443)
1936
			{
1937
				$url_info['port'] = $port;
1938
			}
1939
			elseif($url_info['port'] == 443)
1940
			{
1941
				unset($url_info['port']);
1942
			}
1943
		}
1944 View Code Duplication
		else
1945
		{
1946
			$port = self::get('_http_port');
1947
			if($port && $port != 80)
1948
			{
1949
				$url_info['port'] = $port;
1950
			}
1951
			elseif($url_info['port'] == 80)
1952
			{
1953
				unset($url_info['port']);
1954
			}
1955
		}
1956
1957
		$url[$ssl_mode][$domain_key] = sprintf('%s://%s%s%s', $use_ssl ? 'https' : $url_info['scheme'], $url_info['host'], $url_info['port'] && $url_info['port'] != 80 ? ':' . $url_info['port'] : '', $url_info['path']);
1958
1959
		return $url[$ssl_mode][$domain_key];
1960
	}
1961
1962
	/**
1963
	 * Set a context value with a key
1964
	 *
1965
	 * @param string $key Key
1966
	 * @param mixed $val Value
1967
	 * @param mixed $set_to_get_vars If not FALSE, Set to get vars.
1968
	 * @return void
1969
	 */
1970
	function set($key, $val, $set_to_get_vars = 0)
1971
	{
1972
		$self = self::getInstance();
1973
		$self->context->{$key} = $val;
1974
		if($set_to_get_vars === FALSE)
1975
		{
1976
			return;
1977
		}
1978
		if($val === NULL || $val === '')
1979
		{
1980
			unset($self->get_vars->{$key});
1981
			return;
1982
		}
1983
		if($set_to_get_vars || $self->get_vars->{$key})
1984
		{
1985
			$self->get_vars->{$key} = $val;
1986
		}
1987
	}
1988
1989
	/**
1990
	 * Return key's value
1991
	 *
1992
	 * @param string $key Key
1993
	 * @return string Key
1994
	 */
1995
	function get($key)
1996
	{
1997
		$self = self::getInstance();
1998
1999
		if(!isset($self->context->{$key}))
2000
		{
2001
			return null;
2002
		}
2003
		return $self->context->{$key};
2004
	}
2005
2006
	/**
2007
	 * Get one more vars in object vars with given arguments(key1, key2, key3,...)
2008
	 *
2009
	 * @return object
2010
	 */
2011
	function gets()
2012
	{
2013
		$num_args = func_num_args();
2014
		if($num_args < 1)
2015
		{
2016
			return;
2017
		}
2018
		$self = self::getInstance();
2019
2020
		$args_list = func_get_args();
2021
		$output = new stdClass();
2022
		foreach($args_list as $v)
2023
		{
2024
			$output->{$v} = $self->get($v);
2025
		}
2026
		return $output;
2027
	}
2028
2029
	/**
2030
	 * Return all data
2031
	 *
2032
	 * @return object All data
2033
	 */
2034
	function getAll()
2035
	{
2036
		$self = self::getInstance();
2037
		return $self->context;
2038
	}
2039
2040
	/**
2041
	 * Return values from the GET/POST/XMLRPC
2042
	 *
2043
	 * @return BaseObject Request variables.
2044
	 */
2045
	function getRequestVars()
2046
	{
2047
		$self = self::getInstance();
2048
		if($self->get_vars)
2049
		{
2050
			return clone($self->get_vars);
2051
		}
2052
		return new stdClass;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \stdClass(); (stdClass) is incompatible with the return type documented by Context::getRequestVars of type BaseObject.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
2053
	}
2054
2055
	/**
2056
	 * Register if an action is to be encrypted by SSL. Those actions are sent to https in common/js/xml_handler.js
2057
	 *
2058
	 * @param string $action act name
2059
	 * @return void
2060
	 */
2061
	function addSSLAction($action)
2062
	{
2063
		$self = self::getInstance();
2064
2065
		if(!is_readable($self->sslActionCacheFile))
2066
		{
2067
			$buff = '<?php if(!defined("__XE__"))exit;';
2068
			FileHandler::writeFile($self->sslActionCacheFile, $buff);
0 ignored issues
show
Documentation introduced by
$self->sslActionCacheFile is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
2069
		}
2070
2071 View Code Duplication
		if(!isset($self->ssl_actions[$action]))
2072
		{
2073
			$self->ssl_actions[$action] = 1;
2074
			$sslActionCacheString = sprintf('$sslActions[\'%s\'] = 1;', $action);
2075
			FileHandler::writeFile($self->sslActionCacheFile, $sslActionCacheString, 'a');
0 ignored issues
show
Documentation introduced by
$self->sslActionCacheFile is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
2076
		}
2077
	}
2078
2079
	/**
2080
	 * Register if actions are to be encrypted by SSL. Those actions are sent to https in common/js/xml_handler.js
2081
	 *
2082
	 * @param string $action act name
0 ignored issues
show
Documentation introduced by
There is no parameter named $action. Did you maybe mean $action_array?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
2083
	 * @return void
2084
	 */
2085
	function addSSLActions($action_array)
2086
	{
2087
		$self = self::getInstance();
2088
2089
		if(!is_readable($self->sslActionCacheFile))
2090
		{
2091
			unset($self->ssl_actions);
2092
			$buff = '<?php if(!defined("__XE__"))exit;';
2093
			FileHandler::writeFile($self->sslActionCacheFile, $buff);
0 ignored issues
show
Documentation introduced by
$self->sslActionCacheFile is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
2094
		}
2095
2096
		foreach($action_array as $action)
2097
		{
2098 View Code Duplication
			if(!isset($self->ssl_actions[$action]))
2099
			{
2100
				$self->ssl_actions[$action] = 1;
2101
				$sslActionCacheString = sprintf('$sslActions[\'%s\'] = 1;', $action);
2102
				FileHandler::writeFile($self->sslActionCacheFile, $sslActionCacheString, 'a');
0 ignored issues
show
Documentation introduced by
$self->sslActionCacheFile is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
2103
			}
2104
		}
2105
	}
2106
2107
	/**
2108
	 * Delete if action is registerd to be encrypted by SSL.
2109
	 *
2110
	 * @param string $action act name
2111
	 * @return void
2112
	 */
2113
	function subtractSSLAction($action)
2114
	{
2115
		$self = self::getInstance();
2116
2117
		if($self->isExistsSSLAction($action))
2118
		{
2119
			$sslActionCacheString = sprintf('$sslActions[\'%s\'] = 1;', $action);
2120
			$buff = FileHandler::readFile($self->sslActionCacheFile);
0 ignored issues
show
Documentation introduced by
$self->sslActionCacheFile is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
2121
			$buff = str_replace($sslActionCacheString, '', $buff);
2122
			FileHandler::writeFile($self->sslActionCacheFile, $buff);
0 ignored issues
show
Documentation introduced by
$self->sslActionCacheFile is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
2123
		}
2124
	}
2125
2126
	/**
2127
	 * Get SSL Action
2128
	 *
2129
	 * @return string acts in array
2130
	 */
2131
	function getSSLActions()
2132
	{
2133
		$self = self::getInstance();
2134
		if($self->getSslStatus() == 'optional')
2135
		{
2136
			return $self->ssl_actions;
2137
		}
2138
	}
2139
2140
	/**
2141
	 * Check SSL action are existed
2142
	 *
2143
	 * @param string $action act name
2144
	 * @return bool If SSL exists, return TRUE.
2145
	 */
2146
	function isExistsSSLAction($action)
2147
	{
2148
		$self = self::getInstance();
2149
		return isset($self->ssl_actions[$action]);
2150
	}
2151
2152
	/**
2153
	 * Normalize file path
2154
	 *
2155
	 * @deprecated
2156
	 * @param string $file file path
2157
	 * @return string normalized file path
2158
	 */
2159
	function normalizeFilePath($file)
2160
	{
2161
		if($file{0} != '/' && $file{0} != '.' && strpos($file, '://') === FALSE)
2162
		{
2163
			$file = './' . $file;
2164
		}
2165
		$file = preg_replace('@/\./|(?<!:)\/\/@', '/', $file);
2166
		while(strpos($file, '/../') !== FALSE)
2167
		{
2168
			$file = preg_replace('/\/([^\/]+)\/\.\.\//s', '/', $file, 1);
2169
		}
2170
2171
		return $file;
2172
	}
2173
2174
	/**
2175
	 * Get abstract file url
2176
	 *
2177
	 * @deprecated
2178
	 * @param string $file file path
2179
	 * @return string Converted file path
2180
	 */
2181
	function getAbsFileUrl($file)
2182
	{
2183
		$file = self::normalizeFilePath($file);
0 ignored issues
show
Deprecated Code introduced by
The method Context::normalizeFilePath() has been deprecated.

This method has been deprecated.

Loading history...
2184
		$script_path = getScriptPath();
2185
		if(strpos($file, './') === 0)
2186
		{
2187
			$file = $script_path . substr($file, 2);
2188
		}
2189
		elseif(strpos($file, '../') === 0)
2190
		{
2191
			$file = self::normalizeFilePath($script_path . $file);
0 ignored issues
show
Deprecated Code introduced by
The method Context::normalizeFilePath() has been deprecated.

This method has been deprecated.

Loading history...
2192
		}
2193
2194
		return $file;
2195
	}
2196
2197
	/**
2198
	 * Load front end file
2199
	 *
2200
	 * @param array $args array
2201
	 * case js :
2202
	 * 		$args[0]: file name,
2203
	 * 		$args[1]: type (head | body),
2204
	 * 		$args[2]: target IE,
2205
	 * 		$args[3]: index
2206
	 * case css :
2207
	 * 		$args[0]: file name,
2208
	 * 		$args[1]: media,
2209
	 * 		$args[2]: target IE,
2210
	 * 		$args[3]: index
2211
	 *
2212
	 */
2213
	function loadFile($args)
2214
	{
2215
		$self = self::getInstance();
2216
2217
		$self->oFrontEndFileHandler->loadFile($args);
2218
	}
2219
2220
	/**
2221
	 * Unload front end file
2222
	 *
2223
	 * @param string $file File name with path
2224
	 * @param string $targetIe Target IE
2225
	 * @param string $media Media query
2226
	 * @return void
2227
	 */
2228
	function unloadFile($file, $targetIe = '', $media = 'all')
2229
	{
2230
		$self = self::getInstance();
2231
		$self->oFrontEndFileHandler->unloadFile($file, $targetIe, $media);
2232
	}
2233
2234
	/**
2235
	 * Unload front end file all
2236
	 *
2237
	 * @param string $type Unload target (optional - all|css|js)
2238
	 * @return void
2239
	 */
2240
	function unloadAllFiles($type = 'all')
2241
	{
2242
		$self = self::getInstance();
2243
		$self->oFrontEndFileHandler->unloadAllFiles($type);
2244
	}
2245
2246
	/**
2247
	 * Add the js file
2248
	 *
2249
	 * @deprecated
2250
	 * @param string $file File name with path
2251
	 * @param string $optimized optimized (That seems to not use)
2252
	 * @param string $targetie target IE
2253
	 * @param string $index index
2254
	 * @param string $type Added position. (head:<head>..</head>, body:<body>..</body>)
2255
	 * @param bool $isRuleset Use ruleset
2256
	 * @param string $autoPath If path not readed, set the path automatically.
2257
	 * @return void
2258
	 */
2259
	function addJsFile($file, $optimized = FALSE, $targetie = '', $index = 0, $type = 'head', $isRuleset = FALSE, $autoPath = null)
0 ignored issues
show
Unused Code introduced by
The parameter $optimized 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...
2260
	{
2261
		if($isRuleset)
2262
		{
2263
			if(strpos($file, '#') !== FALSE)
2264
			{
2265
				$file = str_replace('#', '', $file);
2266
				if(!is_readable($file))
2267
				{
2268
					$file = $autoPath;
2269
				}
2270
			}
2271
			$validator = new Validator($file);
2272
			$validator->setCacheDir('files/cache');
2273
			$file = $validator->getJsPath();
2274
		}
2275
2276
		$self = self::getInstance();
2277
		$self->oFrontEndFileHandler->loadFile(array($file, $type, $targetie, $index));
2278
	}
2279
2280
	/**
2281
	 * Remove the js file
2282
	 *
2283
	 * @deprecated
2284
	 * @param string $file File name with path
2285
	 * @param string $optimized optimized (That seems to not use)
2286
	 * @param string $targetie target IE
2287
	 * @return void
2288
	 */
2289
	function unloadJsFile($file, $optimized = FALSE, $targetie = '')
0 ignored issues
show
Unused Code introduced by
The parameter $optimized 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...
2290
	{
2291
		$self = self::getInstance();
2292
		$self->oFrontEndFileHandler->unloadFile($file, $targetie);
2293
	}
2294
2295
	/**
2296
	 * Unload all javascript files
2297
	 *
2298
	 * @return void
2299
	 */
2300
	function unloadAllJsFiles()
2301
	{
2302
		$self = self::getInstance();
2303
		$self->oFrontEndFileHandler->unloadAllFiles('js');
2304
	}
2305
2306
	/**
2307
	 * Add javascript filter
2308
	 *
2309
	 * @param string $path File path
2310
	 * @param string $filename File name
2311
	 * @return void
2312
	 */
2313
	function addJsFilter($path, $filename)
2314
	{
2315
		$oXmlFilter = new XmlJSFilter($path, $filename);
2316
		$oXmlFilter->compile();
2317
	}
2318
2319
	/**
2320
	 * Same as array_unique but works only for file subscript
2321
	 *
2322
	 * @deprecated
2323
	 * @param array $files File list
2324
	 * @return array File list
2325
	 */
2326
	function _getUniqueFileList($files)
2327
	{
2328
		ksort($files);
2329
		$files = array_values($files);
2330
		$filenames = array();
2331
		for($i = 0, $c = count($files); $i < $c; ++$i)
2332
		{
2333
			if(in_array($files[$i]['file'], $filenames))
2334
			{
2335
				unset($files[$i]);
2336
			}
2337
			$filenames[] = $files[$i]['file'];
2338
		}
2339
2340
		return $files;
2341
	}
2342
2343
	/**
2344
	 * Returns the list of javascripts that matches the given type.
2345
	 *
2346
	 * @param string $type Added position. (head:<head>..</head>, body:<body>..</body>)
2347
	 * @return array Returns javascript file list. Array contains file, targetie.
2348
	 */
2349
	function getJsFile($type = 'head')
2350
	{
2351
		$self = self::getInstance();
2352
		return $self->oFrontEndFileHandler->getJsFileList($type);
2353
	}
2354
2355
	/**
2356
	 * Add CSS file
2357
	 *
2358
	 * @deprecated
2359
	 * @param string $file File name with path
2360
	 * @param string $optimized optimized (That seems to not use)
2361
	 * @param string $media Media query
2362
	 * @param string $targetie target IE
2363
	 * @param string $index index
2364
	 * @return void
2365
	 *
2366
	 */
2367
	function addCSSFile($file, $optimized = FALSE, $media = 'all', $targetie = '', $index = 0)
0 ignored issues
show
Unused Code introduced by
The parameter $optimized 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...
2368
	{
2369
		$self = self::getInstance();
2370
		$self->oFrontEndFileHandler->loadFile(array($file, $media, $targetie, $index));
2371
	}
2372
2373
	/**
2374
	 * Remove css file
2375
	 *
2376
	 * @deprecated
2377
	 * @param string $file File name with path
2378
	 * @param string $optimized optimized (That seems to not use)
2379
	 * @param string $media Media query
2380
	 * @param string $targetie target IE
2381
	 * @return void
2382
	 */
2383
	function unloadCSSFile($file, $optimized = FALSE, $media = 'all', $targetie = '')
0 ignored issues
show
Unused Code introduced by
The parameter $optimized 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...
2384
	{
2385
		$self = self::getInstance();
2386
		$self->oFrontEndFileHandler->unloadFile($file, $targetie, $media);
2387
	}
2388
2389
	/**
2390
	 * Unload all css files
2391
	 *
2392
	 * @return void
2393
	 */
2394
	function unloadAllCSSFiles()
2395
	{
2396
		$self = self::getInstance();
2397
		$self->oFrontEndFileHandler->unloadAllFiles('css');
2398
	}
2399
2400
	/**
2401
	 * Return a list of css files
2402
	 *
2403
	 * @return array Returns css file list. Array contains file, media, targetie.
2404
	 */
2405
	function getCSSFile()
2406
	{
2407
		$self = self::getInstance();
2408
		return $self->oFrontEndFileHandler->getCssFileList();
2409
	}
2410
2411
	/**
2412
	 * Returns javascript plugin file info
2413
	 * @param string $pluginName
2414
	 * @return stdClass
2415
	 */
2416
	function getJavascriptPluginInfo($pluginName)
2417
	{
2418
		if($plugin_name == 'ui.datepicker')
0 ignored issues
show
Bug introduced by
The variable $plugin_name seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
2419
		{
2420
			$plugin_name = 'ui';
0 ignored issues
show
Unused Code introduced by
$plugin_name is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2421
		}
2422
2423
		$plugin_path = './common/js/plugins/' . $pluginName . '/';
2424
		$info_file = $plugin_path . 'plugin.load';
2425
		if(!is_readable($info_file))
2426
		{
2427
			return;
2428
		}
2429
2430
		$list = file($info_file);
2431
		$result = new stdClass();
2432
		$result->jsList = array();
2433
		$result->cssList = array();
2434
2435
		foreach($list as $filename)
2436
		{
2437
			$filename = trim($filename);
2438
			if(!$filename)
2439
			{
2440
				continue;
2441
			}
2442
2443
			if(strncasecmp('./', $filename, 2) === 0)
2444
			{
2445
				$filename = substr($filename, 2);
2446
			}
2447
2448
			if(substr_compare($filename, '.js', -3) === 0)
2449
			{
2450
				$result->jsList[] = $plugin_path . $filename;
2451
			}
2452
			elseif(substr_compare($filename, '.css', -4) === 0)
2453
			{
2454
				$result->cssList[] = $plugin_path . $filename;
2455
			}
2456
		}
2457
2458
		if(is_dir($plugin_path . 'lang'))
2459
		{
2460
			$result->langPath = $plugin_path . 'lang';
2461
		}
2462
2463
		return $result;
2464
	}
2465
	/**
2466
	 * Load javascript plugin
2467
	 *
2468
	 * @param string $plugin_name plugin name
2469
	 * @return void
2470
	 */
2471
	function loadJavascriptPlugin($plugin_name)
2472
	{
2473
		static $loaded_plugins = array();
2474
2475
		$self = self::getInstance();
2476
		if($plugin_name == 'ui.datepicker')
2477
		{
2478
			$plugin_name = 'ui';
2479
		}
2480
2481
		if($loaded_plugins[$plugin_name])
2482
		{
2483
			return;
2484
		}
2485
		$loaded_plugins[$plugin_name] = TRUE;
2486
2487
		$plugin_path = './common/js/plugins/' . $plugin_name . '/';
2488
		$info_file = $plugin_path . 'plugin.load';
2489
		if(!is_readable($info_file))
2490
		{
2491
			return;
2492
		}
2493
2494
		$list = file($info_file);
2495
		foreach($list as $filename)
2496
		{
2497
			$filename = trim($filename);
2498
			if(!$filename)
2499
			{
2500
				continue;
2501
			}
2502
2503
			if(strncasecmp('./', $filename, 2) === 0)
2504
			{
2505
				$filename = substr($filename, 2);
2506
			}
2507 View Code Duplication
			if(substr_compare($filename, '.js', -3) === 0)
2508
			{
2509
				$self->loadFile(array($plugin_path . $filename, 'body', '', 0), TRUE);
0 ignored issues
show
Unused Code introduced by
The call to Context::loadFile() has too many arguments starting with TRUE.

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...
2510
			}
2511 View Code Duplication
			if(substr_compare($filename, '.css', -4) === 0)
2512
			{
2513
				$self->loadFile(array($plugin_path . $filename, 'all', '', 0), TRUE);
0 ignored issues
show
Unused Code introduced by
The call to Context::loadFile() has too many arguments starting with TRUE.

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...
2514
			}
2515
		}
2516
2517
		if(is_dir($plugin_path . 'lang'))
2518
		{
2519
			$self->loadLang($plugin_path . 'lang');
2520
		}
2521
	}
2522
2523
	/**
2524
	 * Add html code before </head>
2525
	 *
2526
	 * @param string $header add html code before </head>.
2527
	 * @return void
2528
	 */
2529
	function addHtmlHeader($header)
2530
	{
2531
		$self = self::getInstance();
2532
		$self->html_header .= "\n" . $header;
2533
	}
2534
2535
	function clearHtmlHeader()
2536
	{
2537
		$self = self::getInstance();
2538
		$self->html_header = '';
2539
	}
2540
2541
	/**
2542
	 * Returns added html code by addHtmlHeader()
2543
	 *
2544
	 * @return string Added html code before </head>
2545
	 */
2546
	function getHtmlHeader()
2547
	{
2548
		$self = self::getInstance();
2549
		return $self->html_header;
2550
	}
2551
2552
	/**
2553
	 * Add css class to Html Body
2554
	 *
2555
	 * @param string $class_name class name
2556
	 */
2557
	function addBodyClass($class_name)
2558
	{
2559
		$self = self::getInstance();
2560
		$self->body_class[] = $class_name;
2561
	}
2562
2563
	/**
2564
	 * Return css class to Html Body
2565
	 *
2566
	 * @return string Return class to html body
2567
	 */
2568
	function getBodyClass()
2569
	{
2570
		$self = self::getInstance();
2571
		$self->body_class = array_unique($self->body_class);
2572
2573
		return (count($self->body_class) > 0) ? sprintf(' class="%s"', join(' ', $self->body_class)) : '';
2574
	}
2575
2576
	/**
2577
	 * Add html code after <body>
2578
	 *
2579
	 * @param string $header Add html code after <body>
2580
	 */
2581
	function addBodyHeader($header)
2582
	{
2583
		$self = self::getInstance();
2584
		$self->body_header .= "\n" . $header;
2585
	}
2586
2587
	/**
2588
	 * Returns added html code by addBodyHeader()
2589
	 *
2590
	 * @return string Added html code after <body>
2591
	 */
2592
	function getBodyHeader()
2593
	{
2594
		$self = self::getInstance();
2595
		return $self->body_header;
2596
	}
2597
2598
	/**
2599
	 * Add html code before </body>
2600
	 *
2601
	 * @param string $footer Add html code before </body>
2602
	 */
2603
	function addHtmlFooter($footer)
2604
	{
2605
		$self = self::getInstance();
2606
		$self->html_footer .= ($self->Htmlfooter ? "\n" : '') . $footer;
0 ignored issues
show
Bug introduced by
The property Htmlfooter does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
2607
	}
2608
2609
	/**
2610
	 * Returns added html code by addHtmlHeader()
2611
	 *
2612
	 * @return string Added html code before </body>
2613
	 */
2614
	function getHtmlFooter()
2615
	{
2616
		$self = self::getInstance();
2617
		return $self->html_footer;
2618
	}
2619
2620
	/**
2621
	 * Get config file
2622
	 *
2623
	 * @retrun string The path of the config file that contains database settings
2624
	 */
2625
	function getConfigFile()
2626
	{
2627
		return _XE_PATH_ . 'files/config/db.config.php';
2628
	}
2629
2630
	/**
2631
	 * Get FTP config file
2632
	 *
2633
	 * @return string The path of the config file that contains FTP settings
2634
	 */
2635
	function getFTPConfigFile()
2636
	{
2637
		return _XE_PATH_ . 'files/config/ftp.config.php';
2638
	}
2639
2640
	/**
2641
	 * Checks whether XE is installed
2642
	 *
2643
	 * @return bool True if the config file exists, otherwise FALSE.
2644
	 */
2645
	function isInstalled()
2646
	{
2647
		return FileHandler::hasContent(self::getConfigFile());
2648
	}
2649
2650
	/**
2651
	 * Transforms codes about widget or other features into the actual code, deprecatred
2652
	 *
2653
	 * @param string Transforms codes
2654
	 * @return string Transforms codes
2655
	 */
2656
	function transContent($content)
2657
	{
2658
		return $content;
2659
	}
2660
2661
	/**
2662
	 * Check whether it is allowed to use rewrite mod
2663
	 *
2664
	 * @return bool True if it is allowed to use rewrite mod, otherwise FALSE
2665
	 */
2666
	function isAllowRewrite()
2667
	{
2668
		$oContext = self::getInstance();
2669
		return $oContext->allow_rewrite;
2670
	}
2671
2672
	/**
2673
	 * Converts a local path into an URL
2674
	 *
2675
	 * @param string $path URL path
2676
	 * @return string Converted path
2677
	 */
2678
	function pathToUrl($path)
2679
	{
2680
		$xe = _XE_PATH_;
2681
		$path = strtr($path, "\\", "/");
2682
2683
		$base_url = preg_replace('@^https?://[^/]+/?@', '', self::getRequestUri());
2684
2685
		$_xe = explode('/', $xe);
2686
		$_path = explode('/', $path);
2687
		$_base = explode('/', $base_url);
2688
2689
		if(!$_base[count($_base) - 1])
2690
		{
2691
			array_pop($_base);
2692
		}
2693
2694
		foreach($_xe as $idx => $dir)
2695
		{
2696
			if($_path[0] != $dir)
2697
			{
2698
				break;
2699
			}
2700
			array_shift($_path);
2701
		}
2702
2703
		$idx = count($_xe) - $idx - 1;
0 ignored issues
show
Bug introduced by
The variable $idx does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2704
		while($idx--)
2705
		{
2706
			if(count($_base) > 0)
2707
			{
2708
				array_shift($_base);
2709
			}
2710
			else
2711
			{
2712
				array_unshift($_base, '..');
2713
			}
2714
		}
2715
2716
		if(count($_base) > 0)
2717
		{
2718
			array_unshift($_path, join('/', $_base));
2719
		}
2720
2721
		$path = '/' . join('/', $_path);
2722
		if(substr_compare($path, '/', -1) !== 0)
2723
		{
2724
			$path .= '/';
2725
		}
2726
		return $path;
2727
	}
2728
2729
	/**
2730
	 * Get meta tag
2731
	 * @return array The list of meta tags
2732
	 */
2733
	function getMetaTag()
2734
	{
2735
		$self = self::getInstance();
2736
2737
		if(!is_array($self->meta_tags))
2738
		{
2739
			$self->meta_tags = array();
0 ignored issues
show
Bug introduced by
The property meta_tags does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
2740
		}
2741
2742
		$ret = array();
2743
		foreach($self->meta_tags as $key => $val)
2744
		{
2745
			list($name, $is_http_equiv) = explode("\t", $key);
2746
			$ret[] = array('name' => $name, 'is_http_equiv' => $is_http_equiv, 'content' => $val);
2747
		}
2748
2749
		return $ret;
2750
	}
2751
2752
	/**
2753
	 * Add the meta tag
2754
	 *
2755
	 * @param string $name name of meta tag
2756
	 * @param string $content content of meta tag
2757
	 * @param mixed $is_http_equiv value of http_equiv
2758
	 * @return void
2759
	 */
2760
	function addMetaTag($name, $content, $is_http_equiv = FALSE)
2761
	{
2762
		$self = self::getInstance();
2763
		$self->meta_tags[$name . "\t" . ($is_http_equiv ? '1' : '0')] = $content;
2764
	}
2765
2766
}
2767
/* End of file Context.class.php */
2768
/* Location: ./classes/context/Context.class.php */
2769