Issues (2473)

Branch: master

Security Analysis    no vulnerabilities found

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

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

engine/classes/ElggSite.php (9 issues)

Upgrade to new PHP Analysis Engine

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

1
<?php
2
/**
3
 * A Site entity.
4
 *
5
 * \ElggSite represents a single site entity.
6
 *
7
 * An \ElggSite object is an \ElggEntity child class with the subtype
8
 * of "site."  It is created upon installation and holds information about a site:
9
 *  - name
10
 *  - description
11
 *  - url
12
 *
13
 * Every \ElggEntity belongs to a site.
14
 *
15
 * @note Internal: \ElggSite represents a single row from the sites_entity
16
 * table, as well as the corresponding \ElggEntity row from the entities table.
17
 *
18
 * @warning Multiple site support isn't fully developed.
19
 *
20
 * @package    Elgg.Core
21
 * @subpackage DataMode.Site
22
 * @link       http://learn.elgg.org/en/stable/design/database.html
23
 *
24
 * @property string $name        The name or title of the website
25
 * @property string $description A motto, mission statement, or description of the website
26
 * @property string $url         The root web address for the site, including trailing slash
27
 */
28
class ElggSite extends \ElggEntity {
29
30
	/**
31
	 * Initialize the attributes array.
32
	 * This is vital to distinguish between metadata and base attributes.
33
	 *
34
	 * @return void
35
	 */
36 1 View Code Duplication
	protected function initializeAttributes() {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
37 1
		parent::initializeAttributes();
38
39 1
		$this->attributes['type'] = "site";
40 1
		$this->attributes += self::getExternalAttributes();
41 1
		$this->tables_split = 2;
42 1
	}
43
44
	/**
45
	 * Get default values for attributes stored in a separate table
46
	 *
47
	 * @return array
48
	 * @access private
49
	 *
50
	 * @see \Elgg\Database\EntityTable::getEntities
51
	 */
52 1
	final public static function getExternalAttributes() {
53
		return [
54 1
			'name' => null,
55 1
			'description' => null,
56 1
			'url' => null,
57 1
		];
58
	}
59
60
	/**
61
	 * Create a new \ElggSite.
62
	 *
63
	 * Plugin developers should only use the constructor to create a new entity.
64
	 * To retrieve entities, use get_entity() and the elgg_get_entities* functions.
65
	 *
66
	 * @param \stdClass $row Database row result. Default is null to create a new site.
67
	 *
68
	 * @throws IOException If cannot load remaining data from db
69
	 * @throws InvalidParameterException If not passed a db result
70
	 */
71 1 View Code Duplication
	public function __construct($row = null) {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
72 1
		$this->initializeAttributes();
73
74
		// compatibility for 1.7 api.
75 1
		$this->initialise_attributes(false);
0 ignored issues
show
Deprecated Code introduced by
The method ElggData::initialise_attributes() has been deprecated with message: 1.8 Use initializeAttributes()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
76
77 1
		if (!empty($row)) {
78
			// Is $row is a DB entity table row
79
			if ($row instanceof \stdClass) {
80
				// Load the rest
81
				if (!$this->load($row)) {
82
					$msg = "Failed to load new " . get_class() . " for GUID:" . $row->guid;
83
					throw new \IOException($msg);
84
				}
85
			} else if ($row instanceof \ElggSite) {
86
				// $row is an \ElggSite so this is a copy constructor
87
				elgg_deprecated_notice('This type of usage of the \ElggSite constructor was deprecated. Please use the clone method.', 1.7);
88
				foreach ($row->attributes as $key => $value) {
89
					$this->attributes[$key] = $value;
90
				}
91
			} else if (strpos($row, "http") !== false) {
92
				// url so retrieve by url
93
				elgg_deprecated_notice("Passing URL to constructor is deprecated. Use get_site_by_url()", 1.9);
94
				$row = get_site_by_url($row);
95
				foreach ($row->attributes as $key => $value) {
96
					$this->attributes[$key] = $value;
97
				}
98
			} else if (is_numeric($row)) {
99
				// $row is a GUID so load
100
				elgg_deprecated_notice('Passing a GUID to constructor is deprecated. Use get_entity()', 1.9);
101
				if (!$this->load($row)) {
102
					throw new \IOException("Failed to load new " . get_class() . " from GUID:" . $row);
103
				}
104
			} else {
105
				throw new \InvalidParameterException("Unrecognized value passed to constuctor.");
106
			}
107
		}
108 1
	}
109
110
	/**
111
	 * Loads the full \ElggSite when given a guid.
112
	 *
113
	 * @param mixed $guid GUID of \ElggSite entity or database row object
114
	 *
115
	 * @return bool
116
	 * @throws InvalidClassException
117
	 */
118 View Code Duplication
	protected function load($guid) {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
119
		$attr_loader = new \Elgg\AttributeLoader(get_class(), 'site', $this->attributes);
120
		$attr_loader->requires_access_control = !($this instanceof \ElggPlugin);
121
		$attr_loader->secondary_loader = 'get_site_entity_as_row';
122
123
		$attrs = $attr_loader->getRequiredAttributes($guid);
124
		if (!$attrs) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $attrs 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...
125
			return false;
126
		}
127
128
		$this->attributes = $attrs;
129
		$this->tables_loaded = 2;
130
		$this->loadAdditionalSelectValues($attr_loader->getAdditionalSelectValues());
131
		_elgg_cache_entity($this);
132
133
		return true;
134
	}
135
136
	/**
137
	 * {@inheritdoc}
138
	 */
139
	protected function create() {
140
		global $CONFIG;
141
142
		$guid = parent::create();
143
144
		$name = sanitize_string($this->attributes['name']);
145
		$description = sanitize_string($this->attributes['description']);
146
		$url = sanitize_string($this->attributes['url']);
147
148
		$query = "INSERT into {$CONFIG->dbprefix}sites_entity
149
			(guid, name, description, url) values ($guid, '$name', '$description', '$url')";
150
151
		$result = $this->getDatabase()->insertData($query);
152
		if ($result === false) {
153
			// TODO(evan): Throw an exception here?
154
			return false;
155
		}
156
157
		// make sure the site guid is set to self if not already set
158
		if (!$this->site_guid) {
159
			$this->site_guid = $guid;
160
			$this->getDatabase()->updateData("UPDATE {$CONFIG->dbprefix}entities
161
				SET site_guid = $guid WHERE guid = $guid");
162
		}
163
164
		return $guid;
165
	}
166
167
	/**
168
	 * {@inheritdoc}
169
	 */
170 View Code Duplication
	protected function update() {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
171
		global $CONFIG;
172
173
		if (!parent::update()) {
174
			return false;
175
		}
176
177
		$guid = (int)$this->guid;
178
		$name = sanitize_string($this->name);
179
		$description = sanitize_string($this->description);
180
		$url = sanitize_string($this->url);
181
182
		$query = "UPDATE {$CONFIG->dbprefix}sites_entity
183
			SET name='$name', description='$description', url='$url' WHERE guid=$guid";
184
185
		return $this->getDatabase()->updateData($query) !== false;
186
	}
187
188
	/**
189
	 * Delete the site.
190
	 *
191
	 * @note You cannot delete the current site.
192
	 *
193
	 * @return bool
194
	 * @throws SecurityException
195
	 */
196
	public function delete() {
197
		global $CONFIG;
198
		if ($CONFIG->site->getGUID() == $this->guid) {
199
			throw new \SecurityException('You cannot delete the current site');
200
		}
201
202
		return parent::delete();
203
	}
204
205
	/**
206
	 * Disable the site
207
	 *
208
	 * @note You cannot disable the current site.
209
	 *
210
	 * @param string $reason    Optional reason for disabling
211
	 * @param bool   $recursive Recursively disable all contained entities?
212
	 *
213
	 * @return bool
214
	 * @throws SecurityException
215
	 */
216
	public function disable($reason = "", $recursive = true) {
217
		global $CONFIG;
218
219
		if ($CONFIG->site->getGUID() == $this->guid) {
220
			throw new \SecurityException('You cannot disable the current site');
221
		}
222
223
		return parent::disable($reason, $recursive);
224
	}
225
	
226
	/**
227
	 * Returns the URL for this site
228
	 *
229
	 * @return string The URL
230
	 */
231
	public function getURL() {
232
		return $this->url;
233
	}
234
235
	/**
236
	 * {@inheritdoc}
237
	 */
238
	public function getDisplayName() {
239
		return $this->name;
240
	}
241
242
	/**
243
	 * {@inheritdoc}
244
	 */
245
	public function setDisplayName($displayName) {
246
		$this->name = $displayName;
247
	}
248
249
	/**
250
	 * Gets an array of \ElggUser entities who are members of the site.
251
	 *
252
	 * @param array $options An associative array for key => value parameters
253
	 *                       accepted by elgg_get_entities(). Common parameters
254
	 *                       include 'limit', and 'offset'.
255
	 *                       Note: this was $limit before version 1.8
256
	 * @param int   $offset  Offset @deprecated parameter
257
	 *
258
	 * @return array of \ElggUsers
259
	 * @deprecated 1.9 Use \ElggSite::getEntities()
260
	 */
261
	public function getMembers($options = array(), $offset = 0) {
262
		elgg_deprecated_notice('\ElggSite::getMembers() is deprecated. Use \ElggSite::getEntities()', 1.9);
263
		if (!is_array($options)) {
264
			elgg_deprecated_notice("\ElggSite::getMembers uses different arguments!", 1.8);
265
			$options = array(
266
				'limit' => $options,
267
				'offset' => $offset,
268
			);
269
		}
270
271
		$defaults = array(
272
			'site_guids' => ELGG_ENTITIES_ANY_VALUE,
273
			'relationship' => 'member_of_site',
274
			'relationship_guid' => $this->getGUID(),
275
			'inverse_relationship' => true,
276
			'type' => 'user',
277
		);
278
279
		$options = array_merge($defaults, $options);
280
281
		return elgg_get_entities_from_relationship($options);
282
	}
283
284
	/**
285
	 * List the members of this site
286
	 *
287
	 * @param array $options An associative array for key => value parameters
288
	 *                       accepted by elgg_list_entities(). Common parameters
289
	 *                       include 'full_view', 'limit', and 'offset'.
290
	 *
291
	 * @return string
292
	 * @since 1.8.0
293
	 * @deprecated 1.9 Use elgg_list_entities_from_relationship()
294
	 */
295
	public function listMembers($options = array()) {
296
		elgg_deprecated_notice('\ElggSite::listMembers() is deprecated. Use elgg_list_entities_from_relationship()', 1.9);
297
		$defaults = array(
298
			'site_guids' => ELGG_ENTITIES_ANY_VALUE,
299
			'relationship' => 'member_of_site',
300
			'relationship_guid' => $this->getGUID(),
301
			'inverse_relationship' => true,
302
			'type' => 'user',
303
		);
304
305
		$options = array_merge($defaults, $options);
306
307
		return elgg_list_entities_from_relationship($options);
308
	}
309
310
	/**
311
	 * Adds an entity to the site.
312
	 *
313
	 * This adds a 'member_of_site' relationship between between the entity and
314
	 * the site. It does not change the site_guid of the entity.
315
	 *
316
	 * @param \ElggEntity $entity User, group, or object entity
317
	 *
318
	 * @return bool
319
	 */
320
	public function addEntity(\ElggEntity $entity) {
321
		if (elgg_instanceof($entity, 'site')) {
322
			return false;
323
		}
324
		return add_entity_relationship($entity->guid, "member_of_site", $this->guid);
325
	}
326
327
	/**
328
	 * Removes an entity from this site
329
	 *
330
	 * @param \ElggEntity $entity User, group, or object entity
331
	 *
332
	 * @return bool
333
	 */
334
	public function removeEntity($entity) {
335
		if (elgg_instanceof($entity, 'site')) {
336
			return false;
337
		}
338
		return remove_entity_relationship($entity->guid, "member_of_site", $this->guid);
339
	}
340
341
	/**
342
	 * Get an array of entities that belong to the site.
343
	 *
344
	 * This only returns entities that have been explicitly added to the
345
	 * site through addEntity().
346
	 *
347
	 * @param array $options Options array for elgg_get_entities_from_relationship()
348
	 *                       Parameters set automatically by this method:
349
	 *                       'relationship', 'relationship_guid', 'inverse_relationship'
350
	 * @return array
351
	 */
352 View Code Duplication
	public function getEntities(array $options = array()) {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
353
		$options['relationship'] = 'member_of_site';
354
		$options['relationship_guid'] = $this->guid;
355
		$options['inverse_relationship'] = true;
356
		if (!isset($options['site_guid']) || !isset($options['site_guids'])) {
357
			$options['site_guids'] = ELGG_ENTITIES_ANY_VALUE;
358
		}
359
360
		return elgg_get_entities_from_relationship($options);
361
	}
362
363
	/**
364
	 * Adds a user to the site.
365
	 *
366
	 * @param int $user_guid GUID
367
	 *
368
	 * @return bool
369
	 * @deprecated 1.9 Use \ElggSite::addEntity()
370
	 */
371
	public function addUser($user_guid) {
372
		elgg_deprecated_notice('\ElggSite::addUser() is deprecated. Use \ElggEntity::addEntity()', 1.9);
373
		return add_site_user($this->getGUID(), $user_guid);
374
	}
375
376
	/**
377
	 * Removes a user from the site.
378
	 *
379
	 * @param int $user_guid GUID
380
	 *
381
	 * @return bool
382
	 * @deprecated 1.9 Use \ElggSite::removeEntity()
383
	 */
384
	public function removeUser($user_guid) {
385
		elgg_deprecated_notice('\ElggSite::removeUser() is deprecated. Use \ElggEntity::removeEntity()', 1.9);
386
		return remove_site_user($this->getGUID(), $user_guid);
387
	}
388
389
	/**
390
	 * Returns an array of \ElggObject entities that belong to the site.
391
	 *
392
	 * @warning This only returns objects that have been explicitly added to the
393
	 * site through addObject()
394
	 *
395
	 * @param string $subtype Entity subtype
396
	 * @param int    $limit   Limit
397
	 * @param int    $offset  Offset
398
	 *
399
	 * @return array
400
	 * @deprecated 1.9 Use \ElggSite:getEntities()
401
	 */
402
	public function getObjects($subtype = "", $limit = 10, $offset = 0) {
403
		elgg_deprecated_notice('\ElggSite::getObjects() is deprecated. Use \ElggSite::getEntities()', 1.9);
404
		return get_site_objects($this->getGUID(), $subtype, $limit, $offset);
405
	}
406
407
	/**
408
	 * Adds an object to the site.
409
	 *
410
	 * @param int $object_guid GUID
411
	 *
412
	 * @return bool
413
	 * @deprecated 1.9 Use \ElggSite::addEntity()
414
	 */
415
	public function addObject($object_guid) {
416
		elgg_deprecated_notice('\ElggSite::addObject() is deprecated. Use \ElggEntity::addEntity()', 1.9);
417
		return add_site_object($this->getGUID(), $object_guid);
418
	}
419
420
	/**
421
	 * Remvoes an object from the site.
422
	 *
423
	 * @param int $object_guid GUID
424
	 *
425
	 * @return bool
426
	 * @deprecated 1.9 Use \ElggSite::removeEntity()
427
	 */
428
	public function removeObject($object_guid) {
429
		elgg_deprecated_notice('\ElggSite::removeObject() is deprecated. Use \ElggEntity::removeEntity()', 1.9);
430
		return remove_site_object($this->getGUID(), $object_guid);
431
	}
432
433
	/**
434
	 * Get the collections associated with a site.
435
	 *
436
	 * @param string $subtype Subtype
437
	 * @param int    $limit   Limit
438
	 * @param int    $offset  Offset
439
	 *
440
	 * @return mixed
441
	 * @deprecated 1.8 Was never implemented
442
	 */
443
	public function getCollections($subtype = "", $limit = 10, $offset = 0) {
444
		elgg_deprecated_notice("ElggSite::getCollections() is deprecated", 1.8);
445
		get_site_collections($this->getGUID(), $subtype, $limit, $offset);
446
	}
447
448
	/**
449
	 * {@inheritdoc}
450
	 */
451 View Code Duplication
	protected function prepareObject($object) {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
452
		$object = parent::prepareObject($object);
453
		$object->name = $this->getDisplayName();
454
		$object->description = $this->description;
455
		unset($object->read_access);
456
		return $object;
457
	}
458
459
	/*
460
	 * EXPORTABLE INTERFACE
461
	 */
462
463
	/**
464
	 * Return an array of fields which can be exported.
465
	 *
466
	 * @return array
467
	 * @deprecated 1.9 Use toObject()
468
	 */
469
	public function getExportableValues() {
470
		return array_merge(parent::getExportableValues(), array(
0 ignored issues
show
Deprecated Code introduced by
The method ElggEntity::getExportableValues() has been deprecated with message: 1.9 Use toObject()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
471
			'name',
472
			'description',
473
			'url',
474
		));
475
	}
476
477
	/**
478
	 * Get the domain for this site
479
	 *
480
	 * @return string
481
	 * @since 1.9
482
	 */
483
	public function getDomain() {
484
		$breakdown = parse_url($this->url);
485
		return $breakdown['host'];
486
	}
487
488
	/**
489
	 * Halts bootup and redirects to the site front page
490
	 * if site is in walled garden mode, no user is logged in,
491
	 * and the URL is not a public page.
492
	 *
493
	 * @return void
494
	 * @since 1.8.0
495
	 */
496
	public function checkWalledGarden() {
497
		global $CONFIG;
498
499
		// command line calls should not invoke the walled garden check
500
		if (PHP_SAPI === 'cli') {
501
			return;
502
		}
503
504
		if ($CONFIG->walled_garden) {
505
			if ($CONFIG->default_access == ACCESS_PUBLIC) {
506
				$CONFIG->default_access = ACCESS_LOGGED_IN;
507
			}
508
			_elgg_services()->hooks->registerHandler(
509
					'access:collections:write',
510
					'all',
511
					'_elgg_walled_garden_remove_public_access',
512
					9999);
513
514
			if (!_elgg_services()->session->isLoggedIn()) {
515
				// override the front page
516
				elgg_register_page_handler('', '_elgg_walled_garden_index');
517
518
				if (!$this->isPublicPage()) {
519
					if (!elgg_is_xhr()) {
520
						_elgg_services()->session->set('last_forward_from', current_page_url());
521
					}
522
					register_error(_elgg_services()->translator->translate('loggedinrequired'));
523
					forward('', 'walled_garden');
524
				}
525
			}
526
		}
527
	}
528
529
	/**
530
	 * Returns if a URL is public for this site when in Walled Garden mode.
531
	 *
532
	 * Pages are registered to be public by {@elgg_plugin_hook public_pages walled_garden}.
533
	 *
534
	 * @param string $url Defaults to the current URL.
535
	 *
536
	 * @return bool
537
	 * @since 1.8.0
538
	 */
539
	public function isPublicPage($url = '') {
540
		global $CONFIG;
541
542
		if (empty($url)) {
543
			$url = current_page_url();
544
545
			// do not check against URL queries
546
			if ($pos = strpos($url, '?')) {
547
				$url = substr($url, 0, $pos);
548
			}
549
		}
550
551
		// always allow index page
552
		if ($url == _elgg_services()->config->getSiteUrl($this->guid)) {
553
			return true;
554
		}
555
556
		// default public pages
557
		$defaults = array(
558
			'walled_garden/.*',
559
			'action/.*',
560
			'login',
561
			'register',
562
			'forgotpassword',
563
			'changepassword',
564
			'refresh_token',
565
			'ajax/view/js/languages',
566
			'upgrade\.php',
567
			'css/.*',
568
			'js/.*',
569
			'cache/[0-9]+/\w+/js|css/.*',
570
			'cron/.*',
571
			'services/.*',
572
			'robots.txt',
573
			'favicon.ico',
574
		);
575
576
		// include a hook for plugin authors to include public pages
577
		$plugins = _elgg_services()->hooks->trigger('public_pages', 'walled_garden', null, array());
578
579
		// allow public pages
580
		foreach (array_merge($defaults, $plugins) as $public) {
581
			$pattern = "`^{$CONFIG->url}$public/*$`i";
582
			if (preg_match($pattern, $url)) {
583
				return true;
584
			}
585
		}
586
587
		// non-public page
588
		return false;
589
	}
590
}
591