Completed
Push — req-comment ( 3a375d...5714fe )
by Michael
33:23 queued 30:15
created
includes/PdoDatabase.php 1 patch
Indentation   +109 added lines, -109 removed lines patch added patch discarded remove patch
@@ -15,113 +15,113 @@
 block discarded – undo
15 15
 
16 16
 class PdoDatabase extends PDO
17 17
 {
18
-    /**
19
-     * @var PdoDatabase[]
20
-     */
21
-    private static $connections = array();
22
-    /**
23
-     * @var bool True if a transaction is active
24
-     */
25
-    protected $hasActiveTransaction = false;
26
-
27
-    /**
28
-     * Unless you're doing low-level work, this is not the function you want.
29
-     *
30
-     * @param string $connectionName
31
-     *
32
-     * @return PdoDatabase
33
-     * @throws Exception
34
-     */
35
-    public static function getDatabaseConnection($connectionName)
36
-    {
37
-        if (!isset(self::$connections[$connectionName])) {
38
-            global $cDatabaseConfig;
39
-
40
-            if (!array_key_exists($connectionName, $cDatabaseConfig)) {
41
-                throw new Exception("Database configuration not found for alias $connectionName");
42
-            }
43
-
44
-            try {
45
-                $databaseObject = new PdoDatabase(
46
-                    $cDatabaseConfig[$connectionName]["dsrcname"],
47
-                    $cDatabaseConfig[$connectionName]["username"],
48
-                    $cDatabaseConfig[$connectionName]["password"],
49
-                    $cDatabaseConfig[$connectionName]["options"]
50
-                );
51
-            }
52
-            catch (PDOException $ex) {
53
-                // wrap around any potential stack traces which may include passwords
54
-                throw new EnvironmentException("Error connecting to database '$connectionName': " . $ex->getMessage());
55
-            }
56
-
57
-            $databaseObject->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
58
-
59
-            // emulating prepared statements gives a performance boost on MySQL.
60
-            //
61
-            // however, our version of PDO doesn't seem to understand parameter types when emulating
62
-            // the prepared statements, so we're forced to turn this off for now.
63
-            // -- stw 2014-02-11
64
-            $databaseObject->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
65
-
66
-            self::$connections[$connectionName] = $databaseObject;
67
-        }
68
-
69
-        return self::$connections[$connectionName];
70
-    }
71
-
72
-    /**
73
-     * Determines if this connection has a transaction in progress or not
74
-     * @return boolean true if there is a transaction in progress.
75
-     */
76
-    public function hasActiveTransaction()
77
-    {
78
-        return $this->hasActiveTransaction;
79
-    }
80
-
81
-    /**
82
-     * Summary of beginTransaction
83
-     * @return bool
84
-     */
85
-    public function beginTransaction()
86
-    {
87
-        // Override the pre-existing method, which doesn't stop you from
88
-        // starting transactions within transactions - which doesn't work and
89
-        // will throw an exception. This eliminates the need to catch exceptions
90
-        // all over the rest of the code
91
-        if ($this->hasActiveTransaction) {
92
-            return false;
93
-        }
94
-        else {
95
-            // set the transaction isolation level for every transaction.
96
-            $this->exec("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;");
97
-
98
-            // start a new transaction, and return whether or not the start was
99
-            // successful
100
-            $this->hasActiveTransaction = parent::beginTransaction();
101
-
102
-            return $this->hasActiveTransaction;
103
-        }
104
-    }
105
-
106
-    /**
107
-     * Commits the active transaction
108
-     */
109
-    public function commit()
110
-    {
111
-        if ($this->hasActiveTransaction) {
112
-            parent::commit();
113
-            $this->hasActiveTransaction = false;
114
-        }
115
-    }
116
-
117
-    /**
118
-     * Rolls back a transaction
119
-     */
120
-    public function rollBack()
121
-    {
122
-        if ($this->hasActiveTransaction) {
123
-            parent::rollback();
124
-            $this->hasActiveTransaction = false;
125
-        }
126
-    }
18
+	/**
19
+	 * @var PdoDatabase[]
20
+	 */
21
+	private static $connections = array();
22
+	/**
23
+	 * @var bool True if a transaction is active
24
+	 */
25
+	protected $hasActiveTransaction = false;
26
+
27
+	/**
28
+	 * Unless you're doing low-level work, this is not the function you want.
29
+	 *
30
+	 * @param string $connectionName
31
+	 *
32
+	 * @return PdoDatabase
33
+	 * @throws Exception
34
+	 */
35
+	public static function getDatabaseConnection($connectionName)
36
+	{
37
+		if (!isset(self::$connections[$connectionName])) {
38
+			global $cDatabaseConfig;
39
+
40
+			if (!array_key_exists($connectionName, $cDatabaseConfig)) {
41
+				throw new Exception("Database configuration not found for alias $connectionName");
42
+			}
43
+
44
+			try {
45
+				$databaseObject = new PdoDatabase(
46
+					$cDatabaseConfig[$connectionName]["dsrcname"],
47
+					$cDatabaseConfig[$connectionName]["username"],
48
+					$cDatabaseConfig[$connectionName]["password"],
49
+					$cDatabaseConfig[$connectionName]["options"]
50
+				);
51
+			}
52
+			catch (PDOException $ex) {
53
+				// wrap around any potential stack traces which may include passwords
54
+				throw new EnvironmentException("Error connecting to database '$connectionName': " . $ex->getMessage());
55
+			}
56
+
57
+			$databaseObject->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
58
+
59
+			// emulating prepared statements gives a performance boost on MySQL.
60
+			//
61
+			// however, our version of PDO doesn't seem to understand parameter types when emulating
62
+			// the prepared statements, so we're forced to turn this off for now.
63
+			// -- stw 2014-02-11
64
+			$databaseObject->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
65
+
66
+			self::$connections[$connectionName] = $databaseObject;
67
+		}
68
+
69
+		return self::$connections[$connectionName];
70
+	}
71
+
72
+	/**
73
+	 * Determines if this connection has a transaction in progress or not
74
+	 * @return boolean true if there is a transaction in progress.
75
+	 */
76
+	public function hasActiveTransaction()
77
+	{
78
+		return $this->hasActiveTransaction;
79
+	}
80
+
81
+	/**
82
+	 * Summary of beginTransaction
83
+	 * @return bool
84
+	 */
85
+	public function beginTransaction()
86
+	{
87
+		// Override the pre-existing method, which doesn't stop you from
88
+		// starting transactions within transactions - which doesn't work and
89
+		// will throw an exception. This eliminates the need to catch exceptions
90
+		// all over the rest of the code
91
+		if ($this->hasActiveTransaction) {
92
+			return false;
93
+		}
94
+		else {
95
+			// set the transaction isolation level for every transaction.
96
+			$this->exec("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;");
97
+
98
+			// start a new transaction, and return whether or not the start was
99
+			// successful
100
+			$this->hasActiveTransaction = parent::beginTransaction();
101
+
102
+			return $this->hasActiveTransaction;
103
+		}
104
+	}
105
+
106
+	/**
107
+	 * Commits the active transaction
108
+	 */
109
+	public function commit()
110
+	{
111
+		if ($this->hasActiveTransaction) {
112
+			parent::commit();
113
+			$this->hasActiveTransaction = false;
114
+		}
115
+	}
116
+
117
+	/**
118
+	 * Rolls back a transaction
119
+	 */
120
+	public function rollBack()
121
+	{
122
+		if ($this->hasActiveTransaction) {
123
+			parent::rollback();
124
+			$this->hasActiveTransaction = false;
125
+		}
126
+	}
127 127
 }
Please login to merge, or discard this patch.
includes/IdentificationVerifier.php 1 patch
Indentation   +160 added lines, -160 removed lines patch added patch discarded remove patch
@@ -26,133 +26,133 @@  discard block
 block discarded – undo
26 26
  */
27 27
 class IdentificationVerifier
28 28
 {
29
-    /**
30
-     * This field is an array of parameters, in key => value format, that should be appended to the Meta Wikimedia
31
-     * Web Service Endpoint URL to query if a user is listed on the Identification Noticeboard.  Note that URL encoding
32
-     * of these values is *not* necessary; this is done automatically.
33
-     *
34
-     * @var string[]
35
-     * @category Security-Critical
36
-     */
37
-    private static $apiQueryParameters = array(
38
-        'action'   => 'query',
39
-        'format'   => 'json',
40
-        'prop'     => 'links',
41
-        // Populated from SiteConfiguration->getIdentificationNoticeboardPage
42
-        'titles'   => '',
43
-        // Username of the user to be checked, with User: prefix, goes here!  Set in isIdentifiedOnWiki()
44
-        'pltitles' => '',
45
-    );
46
-    /** @var HttpHelper */
47
-    private $httpHelper;
48
-    /** @var SiteConfiguration */
49
-    private $siteConfiguration;
50
-    /** @var PdoDatabase */
51
-    private $dbObject;
52
-
53
-    /**
54
-     * IdentificationVerifier constructor.
55
-     *
56
-     * @param HttpHelper        $httpHelper
57
-     * @param SiteConfiguration $siteConfiguration
58
-     * @param PdoDatabase       $dbObject
59
-     */
60
-    public function __construct(HttpHelper $httpHelper, SiteConfiguration $siteConfiguration, PdoDatabase $dbObject)
61
-    {
62
-        $this->httpHelper = $httpHelper;
63
-        $this->siteConfiguration = $siteConfiguration;
64
-        $this->dbObject = $dbObject;
65
-    }
66
-
67
-    /**
68
-     * Checks if the given user is identified to the Wikimedia Foundation.
69
-     *
70
-     * @param string $onWikiName The Wikipedia username of the user
71
-     *
72
-     * @return bool
73
-     * @category Security-Critical
74
-     * @throws EnvironmentException
75
-     */
76
-    public function isUserIdentified($onWikiName)
77
-    {
78
-        if ($this->checkIdentificationCache($onWikiName)) {
79
-            return true;
80
-        }
81
-        else {
82
-            if ($this->isIdentifiedOnWiki($onWikiName)) {
83
-                $this->cacheIdentificationStatus($onWikiName);
84
-
85
-                return true;
86
-            }
87
-            else {
88
-                return false;
89
-            }
90
-        }
91
-    }
92
-
93
-    /**
94
-     * Checks if the given user has a valid entry in the idcache table.
95
-     *
96
-     * @param string $onWikiName The Wikipedia username of the user
97
-     *
98
-     * @return bool
99
-     * @category Security-Critical
100
-     */
101
-    private function checkIdentificationCache($onWikiName)
102
-    {
103
-        $interval = $this->siteConfiguration->getIdentificationCacheExpiry();
104
-
105
-        $query = <<<SQL
29
+	/**
30
+	 * This field is an array of parameters, in key => value format, that should be appended to the Meta Wikimedia
31
+	 * Web Service Endpoint URL to query if a user is listed on the Identification Noticeboard.  Note that URL encoding
32
+	 * of these values is *not* necessary; this is done automatically.
33
+	 *
34
+	 * @var string[]
35
+	 * @category Security-Critical
36
+	 */
37
+	private static $apiQueryParameters = array(
38
+		'action'   => 'query',
39
+		'format'   => 'json',
40
+		'prop'     => 'links',
41
+		// Populated from SiteConfiguration->getIdentificationNoticeboardPage
42
+		'titles'   => '',
43
+		// Username of the user to be checked, with User: prefix, goes here!  Set in isIdentifiedOnWiki()
44
+		'pltitles' => '',
45
+	);
46
+	/** @var HttpHelper */
47
+	private $httpHelper;
48
+	/** @var SiteConfiguration */
49
+	private $siteConfiguration;
50
+	/** @var PdoDatabase */
51
+	private $dbObject;
52
+
53
+	/**
54
+	 * IdentificationVerifier constructor.
55
+	 *
56
+	 * @param HttpHelper        $httpHelper
57
+	 * @param SiteConfiguration $siteConfiguration
58
+	 * @param PdoDatabase       $dbObject
59
+	 */
60
+	public function __construct(HttpHelper $httpHelper, SiteConfiguration $siteConfiguration, PdoDatabase $dbObject)
61
+	{
62
+		$this->httpHelper = $httpHelper;
63
+		$this->siteConfiguration = $siteConfiguration;
64
+		$this->dbObject = $dbObject;
65
+	}
66
+
67
+	/**
68
+	 * Checks if the given user is identified to the Wikimedia Foundation.
69
+	 *
70
+	 * @param string $onWikiName The Wikipedia username of the user
71
+	 *
72
+	 * @return bool
73
+	 * @category Security-Critical
74
+	 * @throws EnvironmentException
75
+	 */
76
+	public function isUserIdentified($onWikiName)
77
+	{
78
+		if ($this->checkIdentificationCache($onWikiName)) {
79
+			return true;
80
+		}
81
+		else {
82
+			if ($this->isIdentifiedOnWiki($onWikiName)) {
83
+				$this->cacheIdentificationStatus($onWikiName);
84
+
85
+				return true;
86
+			}
87
+			else {
88
+				return false;
89
+			}
90
+		}
91
+	}
92
+
93
+	/**
94
+	 * Checks if the given user has a valid entry in the idcache table.
95
+	 *
96
+	 * @param string $onWikiName The Wikipedia username of the user
97
+	 *
98
+	 * @return bool
99
+	 * @category Security-Critical
100
+	 */
101
+	private function checkIdentificationCache($onWikiName)
102
+	{
103
+		$interval = $this->siteConfiguration->getIdentificationCacheExpiry();
104
+
105
+		$query = <<<SQL
106 106
 			SELECT COUNT(`id`)
107 107
 			FROM `idcache`
108 108
 			WHERE `onwikiusername` = :onwikiname
109 109
 				AND DATE_ADD(`checktime`, INTERVAL {$interval}) >= NOW();
110 110
 SQL;
111
-        $stmt = $this->dbObject->prepare($query);
112
-        $stmt->bindValue(':onwikiname', $onWikiName, PDO::PARAM_STR);
113
-        $stmt->execute();
114
-
115
-        // Guaranteed by the query to only return a single row with a single column
116
-        $results = $stmt->fetch(PDO::FETCH_NUM);
117
-
118
-        // I don't expect this to ever be a value other than 0 or 1 since the `onwikiusername` column is declared as a
119
-        // unique key - but meh.
120
-        return $results[0] != 0;
121
-    }
122
-
123
-    /**
124
-     * Does pretty much exactly what it says on the label - this method will clear all expired idcache entries from the
125
-     * idcache table.  Meant to be called periodically by a maintenance script.
126
-     *
127
-     * @param SiteConfiguration $siteConfiguration
128
-     * @param PdoDatabase       $dbObject
129
-     *
130
-     * @return void
131
-     */
132
-    public static function clearExpiredCacheEntries(SiteConfiguration $siteConfiguration, PdoDatabase $dbObject)
133
-    {
134
-        $interval = $siteConfiguration->getIdentificationCacheExpiry();
135
-
136
-        $query = <<<SQL
111
+		$stmt = $this->dbObject->prepare($query);
112
+		$stmt->bindValue(':onwikiname', $onWikiName, PDO::PARAM_STR);
113
+		$stmt->execute();
114
+
115
+		// Guaranteed by the query to only return a single row with a single column
116
+		$results = $stmt->fetch(PDO::FETCH_NUM);
117
+
118
+		// I don't expect this to ever be a value other than 0 or 1 since the `onwikiusername` column is declared as a
119
+		// unique key - but meh.
120
+		return $results[0] != 0;
121
+	}
122
+
123
+	/**
124
+	 * Does pretty much exactly what it says on the label - this method will clear all expired idcache entries from the
125
+	 * idcache table.  Meant to be called periodically by a maintenance script.
126
+	 *
127
+	 * @param SiteConfiguration $siteConfiguration
128
+	 * @param PdoDatabase       $dbObject
129
+	 *
130
+	 * @return void
131
+	 */
132
+	public static function clearExpiredCacheEntries(SiteConfiguration $siteConfiguration, PdoDatabase $dbObject)
133
+	{
134
+		$interval = $siteConfiguration->getIdentificationCacheExpiry();
135
+
136
+		$query = <<<SQL
137 137
 			DELETE FROM `idcache`
138 138
 			WHERE DATE_ADD(`checktime`, INTERVAL {$interval}) < NOW();
139 139
 SQL;
140
-        $dbObject->prepare($query)->execute();
141
-    }
142
-
143
-    /**
144
-     * This method will add an entry to the idcache that the given Wikipedia user has been verified as identified.  This
145
-     * is so we don't have to hit the API every single time we check.  The cache entry is valid for as long as specified
146
-     * in the ACC configuration (validity enforced by checkIdentificationCache() and clearExpiredCacheEntries()).
147
-     *
148
-     * @param string $onWikiName The Wikipedia username of the user
149
-     *
150
-     * @return void
151
-     * @category Security-Critical
152
-     */
153
-    private function cacheIdentificationStatus($onWikiName)
154
-    {
155
-        $query = <<<SQL
140
+		$dbObject->prepare($query)->execute();
141
+	}
142
+
143
+	/**
144
+	 * This method will add an entry to the idcache that the given Wikipedia user has been verified as identified.  This
145
+	 * is so we don't have to hit the API every single time we check.  The cache entry is valid for as long as specified
146
+	 * in the ACC configuration (validity enforced by checkIdentificationCache() and clearExpiredCacheEntries()).
147
+	 *
148
+	 * @param string $onWikiName The Wikipedia username of the user
149
+	 *
150
+	 * @return void
151
+	 * @category Security-Critical
152
+	 */
153
+	private function cacheIdentificationStatus($onWikiName)
154
+	{
155
+		$query = <<<SQL
156 156
 			INSERT INTO `idcache`
157 157
 				(`onwikiusername`)
158 158
 			VALUES
@@ -161,45 +161,45 @@  discard block
 block discarded – undo
161 161
 				`onwikiusername` = VALUES(`onwikiusername`),
162 162
 				`checktime` = CURRENT_TIMESTAMP;
163 163
 SQL;
164
-        $stmt = $this->dbObject->prepare($query);
165
-        $stmt->bindValue(':onwikiname', $onWikiName, PDO::PARAM_STR);
166
-        $stmt->execute();
167
-    }
168
-
169
-    /**
170
-     * Queries the Wikimedia API to determine if the specified user is listed on the identification noticeboard.
171
-     *
172
-     * @param string $onWikiName The Wikipedia username of the user
173
-     *
174
-     * @return bool
175
-     * @throws EnvironmentException
176
-     * @category Security-Critical
177
-     */
178
-    private function isIdentifiedOnWiki($onWikiName)
179
-    {
180
-        $strings = new StringFunctions();
181
-
182
-        // First character of Wikipedia usernames is always capitalized.
183
-        $onWikiName = $strings->upperCaseFirst($onWikiName);
184
-
185
-        $parameters = self::$apiQueryParameters;
186
-        $parameters['pltitles'] = "User:" . $onWikiName;
187
-        $parameters['titles'] = $this->siteConfiguration->getIdentificationNoticeboardPage();
188
-
189
-        try {
190
-            $endpoint = $this->siteConfiguration->getMetaWikimediaWebServiceEndpoint();
191
-            $response = $this->httpHelper->get($endpoint, $parameters);
192
-            $response = json_decode($response, true);
193
-        } catch (CurlException $ex) {
194
-            // failed getting identification status, so throw a nicer error.
195
-            $message = 'Could not contact metawiki API to determine user\' identification status. '
196
-                . 'This is probably a transient error, so please try again.';
197
-
198
-            throw new EnvironmentException($message);
199
-        }
200
-
201
-        $page = @array_pop($response['query']['pages']);
202
-
203
-        return @$page['links'][0]['title'] === "User:" . $onWikiName;
204
-    }
164
+		$stmt = $this->dbObject->prepare($query);
165
+		$stmt->bindValue(':onwikiname', $onWikiName, PDO::PARAM_STR);
166
+		$stmt->execute();
167
+	}
168
+
169
+	/**
170
+	 * Queries the Wikimedia API to determine if the specified user is listed on the identification noticeboard.
171
+	 *
172
+	 * @param string $onWikiName The Wikipedia username of the user
173
+	 *
174
+	 * @return bool
175
+	 * @throws EnvironmentException
176
+	 * @category Security-Critical
177
+	 */
178
+	private function isIdentifiedOnWiki($onWikiName)
179
+	{
180
+		$strings = new StringFunctions();
181
+
182
+		// First character of Wikipedia usernames is always capitalized.
183
+		$onWikiName = $strings->upperCaseFirst($onWikiName);
184
+
185
+		$parameters = self::$apiQueryParameters;
186
+		$parameters['pltitles'] = "User:" . $onWikiName;
187
+		$parameters['titles'] = $this->siteConfiguration->getIdentificationNoticeboardPage();
188
+
189
+		try {
190
+			$endpoint = $this->siteConfiguration->getMetaWikimediaWebServiceEndpoint();
191
+			$response = $this->httpHelper->get($endpoint, $parameters);
192
+			$response = json_decode($response, true);
193
+		} catch (CurlException $ex) {
194
+			// failed getting identification status, so throw a nicer error.
195
+			$message = 'Could not contact metawiki API to determine user\' identification status. '
196
+				. 'This is probably a transient error, so please try again.';
197
+
198
+			throw new EnvironmentException($message);
199
+		}
200
+
201
+		$page = @array_pop($response['query']['pages']);
202
+
203
+		return @$page['links'][0]['title'] === "User:" . $onWikiName;
204
+	}
205 205
 }
Please login to merge, or discard this patch.
includes/SessionAlert.php 1 patch
Indentation   +137 added lines, -137 removed lines patch added patch discarded remove patch
@@ -21,141 +21,141 @@
 block discarded – undo
21 21
  */
22 22
 class SessionAlert
23 23
 {
24
-    private $message;
25
-    private $title;
26
-    private $type;
27
-    private $closable;
28
-    private $block;
29
-
30
-    /**
31
-     * @param string $message
32
-     * @param string $title
33
-     * @param string $type
34
-     * @param bool   $closable
35
-     * @param bool   $block
36
-     */
37
-    public function __construct($message, $title, $type = "alert-info", $closable = true, $block = true)
38
-    {
39
-        $this->message = $message;
40
-        $this->title = $title;
41
-        $this->type = $type;
42
-        $this->closable = $closable;
43
-        $this->block = $block;
44
-    }
45
-
46
-    /**
47
-     * Shows a quick one-liner message
48
-     *
49
-     * @param string $message
50
-     * @param string $type
51
-     */
52
-    public static function quick($message, $type = "alert-info")
53
-    {
54
-        self::append(new SessionAlert($message, "", $type, true, false));
55
-    }
56
-
57
-    /**
58
-     * @param SessionAlert $alert
59
-     */
60
-    public static function append(SessionAlert $alert)
61
-    {
62
-        $data = WebRequest::getSessionAlertData();
63
-        $data[] = serialize($alert);
64
-        WebRequest::setSessionAlertData($data);
65
-    }
66
-
67
-    /**
68
-     * Shows a quick one-liner success message
69
-     *
70
-     * @param string $message
71
-     */
72
-    public static function success($message)
73
-    {
74
-        self::append(new SessionAlert($message, "", "alert-success", true, true));
75
-    }
76
-
77
-    /**
78
-     * Shows a quick one-liner warning message
79
-     *
80
-     * @param string $message
81
-     * @param string $title
82
-     */
83
-    public static function warning($message, $title = "Warning!")
84
-    {
85
-        self::append(new SessionAlert($message, $title, "alert-warning", true, true));
86
-    }
87
-
88
-    /**
89
-     * Shows a quick one-liner error message
90
-     *
91
-     * @param string $message
92
-     * @param string $title
93
-     */
94
-    public static function error($message, $title = "Error!")
95
-    {
96
-        self::append(new SessionAlert($message, $title, "alert-danger", true, true));
97
-    }
98
-
99
-    /**
100
-     * Retrieves the alerts which have been saved to the session
101
-     * @return array
102
-     */
103
-    public static function getAlerts()
104
-    {
105
-        $alertData = array();
106
-
107
-        foreach (WebRequest::getSessionAlertData() as $a) {
108
-            $alertData[] = unserialize($a);
109
-        }
110
-
111
-        return $alertData;
112
-    }
113
-
114
-    /**
115
-     * Clears the alerts from the session
116
-     */
117
-    public static function clearAlerts()
118
-    {
119
-        WebRequest::clearSessionAlertData();
120
-    }
121
-
122
-    /**
123
-     * @return boolean
124
-     */
125
-    public function isBlock()
126
-    {
127
-        return $this->block;
128
-    }
129
-
130
-    /**
131
-     * @return boolean
132
-     */
133
-    public function isClosable()
134
-    {
135
-        return $this->closable;
136
-    }
137
-
138
-    /**
139
-     * @return string
140
-     */
141
-    public function getType()
142
-    {
143
-        return $this->type;
144
-    }
145
-
146
-    /**
147
-     * @return string
148
-     */
149
-    public function getTitle()
150
-    {
151
-        return $this->title;
152
-    }
153
-
154
-    /**
155
-     * @return string
156
-     */
157
-    public function getMessage()
158
-    {
159
-        return $this->message;
160
-    }
24
+	private $message;
25
+	private $title;
26
+	private $type;
27
+	private $closable;
28
+	private $block;
29
+
30
+	/**
31
+	 * @param string $message
32
+	 * @param string $title
33
+	 * @param string $type
34
+	 * @param bool   $closable
35
+	 * @param bool   $block
36
+	 */
37
+	public function __construct($message, $title, $type = "alert-info", $closable = true, $block = true)
38
+	{
39
+		$this->message = $message;
40
+		$this->title = $title;
41
+		$this->type = $type;
42
+		$this->closable = $closable;
43
+		$this->block = $block;
44
+	}
45
+
46
+	/**
47
+	 * Shows a quick one-liner message
48
+	 *
49
+	 * @param string $message
50
+	 * @param string $type
51
+	 */
52
+	public static function quick($message, $type = "alert-info")
53
+	{
54
+		self::append(new SessionAlert($message, "", $type, true, false));
55
+	}
56
+
57
+	/**
58
+	 * @param SessionAlert $alert
59
+	 */
60
+	public static function append(SessionAlert $alert)
61
+	{
62
+		$data = WebRequest::getSessionAlertData();
63
+		$data[] = serialize($alert);
64
+		WebRequest::setSessionAlertData($data);
65
+	}
66
+
67
+	/**
68
+	 * Shows a quick one-liner success message
69
+	 *
70
+	 * @param string $message
71
+	 */
72
+	public static function success($message)
73
+	{
74
+		self::append(new SessionAlert($message, "", "alert-success", true, true));
75
+	}
76
+
77
+	/**
78
+	 * Shows a quick one-liner warning message
79
+	 *
80
+	 * @param string $message
81
+	 * @param string $title
82
+	 */
83
+	public static function warning($message, $title = "Warning!")
84
+	{
85
+		self::append(new SessionAlert($message, $title, "alert-warning", true, true));
86
+	}
87
+
88
+	/**
89
+	 * Shows a quick one-liner error message
90
+	 *
91
+	 * @param string $message
92
+	 * @param string $title
93
+	 */
94
+	public static function error($message, $title = "Error!")
95
+	{
96
+		self::append(new SessionAlert($message, $title, "alert-danger", true, true));
97
+	}
98
+
99
+	/**
100
+	 * Retrieves the alerts which have been saved to the session
101
+	 * @return array
102
+	 */
103
+	public static function getAlerts()
104
+	{
105
+		$alertData = array();
106
+
107
+		foreach (WebRequest::getSessionAlertData() as $a) {
108
+			$alertData[] = unserialize($a);
109
+		}
110
+
111
+		return $alertData;
112
+	}
113
+
114
+	/**
115
+	 * Clears the alerts from the session
116
+	 */
117
+	public static function clearAlerts()
118
+	{
119
+		WebRequest::clearSessionAlertData();
120
+	}
121
+
122
+	/**
123
+	 * @return boolean
124
+	 */
125
+	public function isBlock()
126
+	{
127
+		return $this->block;
128
+	}
129
+
130
+	/**
131
+	 * @return boolean
132
+	 */
133
+	public function isClosable()
134
+	{
135
+		return $this->closable;
136
+	}
137
+
138
+	/**
139
+	 * @return string
140
+	 */
141
+	public function getType()
142
+	{
143
+		return $this->type;
144
+	}
145
+
146
+	/**
147
+	 * @return string
148
+	 */
149
+	public function getTitle()
150
+	{
151
+		return $this->title;
152
+	}
153
+
154
+	/**
155
+	 * @return string
156
+	 */
157
+	public function getMessage()
158
+	{
159
+		return $this->message;
160
+	}
161 161
 }
Please login to merge, or discard this patch.
includes/StringFunctions.php 1 patch
Indentation   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -10,20 +10,20 @@
 block discarded – undo
10 10
 
11 11
 class StringFunctions
12 12
 {
13
-    /**
14
-     * Make a string's first character uppercase
15
-     *
16
-     * @param string $string
17
-     *
18
-     * @return string
19
-     */
20
-    public function upperCaseFirst($string)
21
-    {
22
-        if (ord($string) < 128) {
23
-            return ucfirst($string);
24
-        }
25
-        else {
26
-            return mb_strtoupper(mb_substr($string, 0, 1)) . mb_substr($string, 1);
27
-        }
28
-    }
13
+	/**
14
+	 * Make a string's first character uppercase
15
+	 *
16
+	 * @param string $string
17
+	 *
18
+	 * @return string
19
+	 */
20
+	public function upperCaseFirst($string)
21
+	{
22
+		if (ord($string) < 128) {
23
+			return ucfirst($string);
24
+		}
25
+		else {
26
+			return mb_strtoupper(mb_substr($string, 0, 1)) . mb_substr($string, 1);
27
+		}
28
+	}
29 29
 }
Please login to merge, or discard this patch.
includes/WebRequest.php 1 patch
Indentation   +574 added lines, -574 removed lines patch added patch discarded remove patch
@@ -24,578 +24,578 @@
 block discarded – undo
24 24
  */
25 25
 class WebRequest
26 26
 {
27
-    /**
28
-     * @var IGlobalStateProvider Provides access to the global state.
29
-     */
30
-    private static $globalStateProvider;
31
-
32
-    /**
33
-     * Returns a boolean value if the request was submitted with the HTTP POST method.
34
-     * @return bool
35
-     */
36
-    public static function wasPosted()
37
-    {
38
-        return self::method() === 'POST';
39
-    }
40
-
41
-    /**
42
-     * Gets the HTTP Method used
43
-     * @return string|null
44
-     */
45
-    public static function method()
46
-    {
47
-        $server = &self::$globalStateProvider->getServerSuperGlobal();
48
-
49
-        if (isset($server['REQUEST_METHOD'])) {
50
-            return $server['REQUEST_METHOD'];
51
-        }
52
-
53
-        return null;
54
-    }
55
-
56
-    /**
57
-     * Gets a boolean value stating whether the request was served over HTTPS or not.
58
-     * @return bool
59
-     */
60
-    public static function isHttps()
61
-    {
62
-        $server = &self::$globalStateProvider->getServerSuperGlobal();
63
-
64
-        if (isset($server['HTTP_X_FORWARDED_PROTO'])) {
65
-            if ($server['HTTP_X_FORWARDED_PROTO'] === 'https') {
66
-                // Client <=> Proxy is encrypted
67
-                return true;
68
-            }
69
-            else {
70
-                // Proxy <=> Server link unknown, Client <=> Proxy is not encrypted.
71
-                return false;
72
-            }
73
-        }
74
-
75
-        if (isset($server['HTTPS'])) {
76
-            if ($server['HTTPS'] === 'off') {
77
-                // ISAPI on IIS breaks the spec. :(
78
-                return false;
79
-            }
80
-
81
-            if ($server['HTTPS'] !== '') {
82
-                // Set to a non-empty value
83
-                return true;
84
-            }
85
-        }
86
-
87
-        return false;
88
-    }
89
-
90
-    /**
91
-     * Gets the path info
92
-     *
93
-     * @return array Array of path info segments
94
-     */
95
-    public static function pathInfo()
96
-    {
97
-        $server = &self::$globalStateProvider->getServerSuperGlobal();
98
-        if (!isset($server['PATH_INFO'])) {
99
-            return array();
100
-        }
101
-
102
-        $exploded = explode('/', $server['PATH_INFO']);
103
-
104
-        // filter out empty values, and reindex from zero. Notably, the first element is always zero, since it starts
105
-        // with a /
106
-        return array_values(array_filter($exploded));
107
-    }
108
-
109
-    /**
110
-     * Gets the remote address of the web request
111
-     * @return null|string
112
-     */
113
-    public static function remoteAddress()
114
-    {
115
-        $server = &self::$globalStateProvider->getServerSuperGlobal();
116
-
117
-        if (isset($server['REMOTE_ADDR'])) {
118
-            return $server['REMOTE_ADDR'];
119
-        }
120
-
121
-        return null;
122
-    }
123
-
124
-    /**
125
-     * Gets the remote address of the web request
126
-     * @return null|string
127
-     */
128
-    public static function httpHost()
129
-    {
130
-        $server = &self::$globalStateProvider->getServerSuperGlobal();
131
-
132
-        if (isset($server['HTTP_HOST'])) {
133
-            return $server['HTTP_HOST'];
134
-        }
135
-
136
-        return null;
137
-    }
138
-
139
-    /**
140
-     * Gets the XFF header contents for the web request
141
-     * @return null|string
142
-     */
143
-    public static function forwardedAddress()
144
-    {
145
-        $server = &self::$globalStateProvider->getServerSuperGlobal();
146
-
147
-        if (isset($server['HTTP_X_FORWARDED_FOR'])) {
148
-            return $server['HTTP_X_FORWARDED_FOR'];
149
-        }
150
-
151
-        return null;
152
-    }
153
-
154
-    /**
155
-     * Sets the global state provider.
156
-     *
157
-     * Almost guaranteed this is not the method you want in production code.
158
-     *
159
-     * @param IGlobalStateProvider $globalState
160
-     */
161
-    public static function setGlobalStateProvider($globalState)
162
-    {
163
-        self::$globalStateProvider = $globalState;
164
-    }
165
-
166
-    #region POST variables
167
-
168
-    /**
169
-     * @param string $key
170
-     *
171
-     * @return null|string
172
-     */
173
-    public static function postString($key)
174
-    {
175
-        $post = &self::$globalStateProvider->getPostSuperGlobal();
176
-        if (!array_key_exists($key, $post)) {
177
-            return null;
178
-        }
179
-
180
-        if ($post[$key] === "") {
181
-            return null;
182
-        }
183
-
184
-        return (string)$post[$key];
185
-    }
186
-
187
-    /**
188
-     * @param string $key
189
-     *
190
-     * @return null|string
191
-     */
192
-    public static function postEmail($key)
193
-    {
194
-        $post = &self::$globalStateProvider->getPostSuperGlobal();
195
-        if (!array_key_exists($key, $post)) {
196
-            return null;
197
-        }
198
-
199
-        $filteredValue = filter_var($post[$key], FILTER_SANITIZE_EMAIL);
200
-
201
-        if ($filteredValue === false) {
202
-            return null;
203
-        }
204
-
205
-        return (string)$filteredValue;
206
-    }
207
-
208
-    /**
209
-     * @param string $key
210
-     *
211
-     * @return int|null
212
-     */
213
-    public static function postInt($key)
214
-    {
215
-        $post = &self::$globalStateProvider->getPostSuperGlobal();
216
-        if (!array_key_exists($key, $post)) {
217
-            return null;
218
-        }
219
-
220
-        $filteredValue = filter_var($post[$key], FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
221
-
222
-        if ($filteredValue === null) {
223
-            return null;
224
-        }
225
-
226
-        return (int)$filteredValue;
227
-    }
228
-
229
-    /**
230
-     * @param string $key
231
-     *
232
-     * @return bool
233
-     */
234
-    public static function postBoolean($key)
235
-    {
236
-        $get = &self::$globalStateProvider->getPostSuperGlobal();
237
-        if (!array_key_exists($key, $get)) {
238
-            return false;
239
-        }
240
-
241
-        // presence of parameter only
242
-        if ($get[$key] === "") {
243
-            return true;
244
-        }
245
-
246
-        if (in_array($get[$key], array(false, 'no', 'off', 0, 'false'), true)) {
247
-            return false;
248
-        }
249
-
250
-        return true;
251
-    }
252
-
253
-    #endregion
254
-
255
-    #region GET variables
256
-
257
-    /**
258
-     * @param string $key
259
-     *
260
-     * @return bool
261
-     */
262
-    public static function getBoolean($key)
263
-    {
264
-        $get = &self::$globalStateProvider->getGetSuperGlobal();
265
-        if (!array_key_exists($key, $get)) {
266
-            return false;
267
-        }
268
-
269
-        // presence of parameter only
270
-        if ($get[$key] === "") {
271
-            return true;
272
-        }
273
-
274
-        if (in_array($get[$key], array(false, 'no', 'off', 0, 'false'), true)) {
275
-            return false;
276
-        }
277
-
278
-        return true;
279
-    }
280
-
281
-    /**
282
-     * @param string $key
283
-     *
284
-     * @return int|null
285
-     */
286
-    public static function getInt($key)
287
-    {
288
-        $get = &self::$globalStateProvider->getGetSuperGlobal();
289
-        if (!array_key_exists($key, $get)) {
290
-            return null;
291
-        }
292
-
293
-        $filteredValue = filter_var($get[$key], FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
294
-
295
-        if ($filteredValue === null) {
296
-            return null;
297
-        }
298
-
299
-        return (int)$filteredValue;
300
-    }
301
-
302
-    /**
303
-     * @param string $key
304
-     *
305
-     * @return null|string
306
-     */
307
-    public static function getString($key)
308
-    {
309
-        $get = &self::$globalStateProvider->getGetSuperGlobal();
310
-        if (!array_key_exists($key, $get)) {
311
-            return null;
312
-        }
313
-
314
-        if ($get[$key] === "") {
315
-            return null;
316
-        }
317
-
318
-        return (string)$get[$key];
319
-    }
320
-
321
-    #endregion
322
-
323
-    /**
324
-     * Sets the logged-in user to the specified user.
325
-     *
326
-     * @param User $user
327
-     */
328
-    public static function setLoggedInUser(User $user)
329
-    {
330
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
331
-
332
-        $session['userID'] = $user->getId();
333
-        unset($session['partialLogin']);
334
-    }
335
-
336
-    /**
337
-     * Sets the post-login redirect
338
-     *
339
-     * @param string|null $uri The URI to redirect to
340
-     */
341
-    public static function setPostLoginRedirect($uri = null)
342
-    {
343
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
344
-
345
-        if ($uri === null) {
346
-            $uri = self::requestUri();
347
-        }
348
-
349
-        $session['returnTo'] = $uri;
350
-    }
351
-
352
-    /**
353
-     * @return string|null
354
-     */
355
-    public static function requestUri()
356
-    {
357
-        $server = &self::$globalStateProvider->getServerSuperGlobal();
358
-
359
-        if (isset($server['REQUEST_URI'])) {
360
-            return $server['REQUEST_URI'];
361
-        }
362
-
363
-        return null;
364
-    }
365
-
366
-    /**
367
-     * Clears the post-login redirect
368
-     * @return string
369
-     */
370
-    public static function clearPostLoginRedirect()
371
-    {
372
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
373
-        if (array_key_exists('returnTo', $session)) {
374
-            $path = $session['returnTo'];
375
-            unset($session['returnTo']);
376
-
377
-            return $path;
378
-        }
379
-
380
-        return null;
381
-    }
382
-
383
-    /**
384
-     * @return string|null
385
-     */
386
-    public static function serverName()
387
-    {
388
-        $server = &self::$globalStateProvider->getServerSuperGlobal();
389
-
390
-        if (isset($server['SERVER_NAME'])) {
391
-            return $server['SERVER_NAME'];
392
-        }
393
-
394
-        return null;
395
-    }
396
-
397
-    /**
398
-     * You probably only want to deal with this through SessionAlert.
399
-     * @return void
400
-     */
401
-    public static function clearSessionAlertData()
402
-    {
403
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
404
-        if (array_key_exists('alerts', $session)) {
405
-            unset($session['alerts']);
406
-        }
407
-    }
408
-
409
-    /**
410
-     * You probably only want to deal with this through SessionAlert.
411
-     *
412
-     * @return string[]
413
-     */
414
-    public static function getSessionAlertData()
415
-    {
416
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
417
-        if (array_key_exists('alerts', $session)) {
418
-            return $session['alerts'];
419
-        }
420
-
421
-        return array();
422
-    }
423
-
424
-    /**
425
-     * You probably only want to deal with this through SessionAlert.
426
-     *
427
-     * @param string[] $data
428
-     */
429
-    public static function setSessionAlertData($data)
430
-    {
431
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
432
-        $session['alerts'] = $data;
433
-    }
434
-
435
-    /**
436
-     * You probably only want to deal with this through TokenManager.
437
-     *
438
-     * @return string[]
439
-     */
440
-    public static function getSessionTokenData()
441
-    {
442
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
443
-        if (array_key_exists('tokens', $session)) {
444
-            return $session['tokens'];
445
-        }
446
-
447
-        return array();
448
-    }
449
-
450
-    /**
451
-     * You probably only want to deal with this through TokenManager.
452
-     *
453
-     * @param string[] $data
454
-     */
455
-    public static function setSessionTokenData($data)
456
-    {
457
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
458
-        $session['tokens'] = $data;
459
-    }
460
-
461
-    /**
462
-     * @param string $key
463
-     *
464
-     * @return mixed
465
-     */
466
-    public static function getSessionContext($key)
467
-    {
468
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
469
-
470
-        if (!isset($session['context'])) {
471
-            $session['context'] = array();
472
-        }
473
-
474
-        if (!isset($session['context'][$key])) {
475
-            return null;
476
-        }
477
-
478
-        return $session['context'][$key];
479
-    }
480
-
481
-    /**
482
-     * @param string $key
483
-     * @param mixed  $data
484
-     */
485
-    public static function setSessionContext($key, $data)
486
-    {
487
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
488
-
489
-        if (!isset($session['context'])) {
490
-            $session['context'] = array();
491
-        }
492
-
493
-        $session['context'][$key] = $data;
494
-    }
495
-
496
-    /**
497
-     * @return int|null
498
-     */
499
-    public static function getSessionUserId()
500
-    {
501
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
502
-
503
-        return isset($session['userID']) ? (int)$session['userID'] : null;
504
-    }
505
-
506
-    /**
507
-     * @param User $user
508
-     */
509
-    public static function setOAuthPartialLogin(User $user)
510
-    {
511
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
512
-        $session['oauthPartialLogin'] = $user->getId();
513
-    }
514
-
515
-    /**
516
-     * @return int|null
517
-     */
518
-    public static function getOAuthPartialLogin()
519
-    {
520
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
521
-
522
-        return isset($session['oauthPartialLogin']) ? (int)$session['oauthPartialLogin'] : null;
523
-    }
524
-
525
-    public static function setAuthPartialLogin($userId, $stage)
526
-    {
527
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
528
-        $session['authPartialLoginId'] = $userId;
529
-        $session['authPartialLoginStage'] = $stage;
530
-    }
531
-
532
-    public static function getAuthPartialLogin()
533
-    {
534
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
535
-
536
-        $userId = isset($session['authPartialLoginId']) ? (int)$session['authPartialLoginId'] : null;
537
-        $stage = isset($session['authPartialLoginStage']) ? (int)$session['authPartialLoginStage'] : null;
538
-
539
-        return array($userId, $stage);
540
-    }
541
-
542
-    public static function clearAuthPartialLogin()
543
-    {
544
-        $session = &self::$globalStateProvider->getSessionSuperGlobal();
545
-        unset($session['authPartialLoginId']);
546
-        unset($session['authPartialLoginStage']);
547
-    }
548
-
549
-    /**
550
-     * @return null|string
551
-     */
552
-    public static function userAgent()
553
-    {
554
-        $server = &self::$globalStateProvider->getServerSuperGlobal();
555
-
556
-        if (isset($server['HTTP_USER_AGENT'])) {
557
-            return $server['HTTP_USER_AGENT'];
558
-        }
559
-
560
-        return null;
561
-    }
562
-
563
-    /**
564
-     * @return null|string
565
-     */
566
-    public static function scriptName()
567
-    {
568
-        $server = &self::$globalStateProvider->getServerSuperGlobal();
569
-
570
-        if (isset($server['SCRIPT_NAME'])) {
571
-            return $server['SCRIPT_NAME'];
572
-        }
573
-
574
-        return null;
575
-    }
576
-
577
-    /**
578
-     * @return null|string
579
-     */
580
-    public static function origin()
581
-    {
582
-        $server = &self::$globalStateProvider->getServerSuperGlobal();
583
-
584
-        if (isset($server['HTTP_ORIGIN'])) {
585
-            return $server['HTTP_ORIGIN'];
586
-        }
587
-
588
-        return null;
589
-    }
590
-
591
-    public static function testSiteNoticeCookieValue($expectedHash)
592
-    {
593
-        $cookie = &self::$globalStateProvider->getCookieSuperGlobal();
594
-
595
-        if(isset($cookie['sitenotice'])) {
596
-            return $cookie['sitenotice'] === $expectedHash;
597
-        }
598
-
599
-        return false;
600
-    }
27
+	/**
28
+	 * @var IGlobalStateProvider Provides access to the global state.
29
+	 */
30
+	private static $globalStateProvider;
31
+
32
+	/**
33
+	 * Returns a boolean value if the request was submitted with the HTTP POST method.
34
+	 * @return bool
35
+	 */
36
+	public static function wasPosted()
37
+	{
38
+		return self::method() === 'POST';
39
+	}
40
+
41
+	/**
42
+	 * Gets the HTTP Method used
43
+	 * @return string|null
44
+	 */
45
+	public static function method()
46
+	{
47
+		$server = &self::$globalStateProvider->getServerSuperGlobal();
48
+
49
+		if (isset($server['REQUEST_METHOD'])) {
50
+			return $server['REQUEST_METHOD'];
51
+		}
52
+
53
+		return null;
54
+	}
55
+
56
+	/**
57
+	 * Gets a boolean value stating whether the request was served over HTTPS or not.
58
+	 * @return bool
59
+	 */
60
+	public static function isHttps()
61
+	{
62
+		$server = &self::$globalStateProvider->getServerSuperGlobal();
63
+
64
+		if (isset($server['HTTP_X_FORWARDED_PROTO'])) {
65
+			if ($server['HTTP_X_FORWARDED_PROTO'] === 'https') {
66
+				// Client <=> Proxy is encrypted
67
+				return true;
68
+			}
69
+			else {
70
+				// Proxy <=> Server link unknown, Client <=> Proxy is not encrypted.
71
+				return false;
72
+			}
73
+		}
74
+
75
+		if (isset($server['HTTPS'])) {
76
+			if ($server['HTTPS'] === 'off') {
77
+				// ISAPI on IIS breaks the spec. :(
78
+				return false;
79
+			}
80
+
81
+			if ($server['HTTPS'] !== '') {
82
+				// Set to a non-empty value
83
+				return true;
84
+			}
85
+		}
86
+
87
+		return false;
88
+	}
89
+
90
+	/**
91
+	 * Gets the path info
92
+	 *
93
+	 * @return array Array of path info segments
94
+	 */
95
+	public static function pathInfo()
96
+	{
97
+		$server = &self::$globalStateProvider->getServerSuperGlobal();
98
+		if (!isset($server['PATH_INFO'])) {
99
+			return array();
100
+		}
101
+
102
+		$exploded = explode('/', $server['PATH_INFO']);
103
+
104
+		// filter out empty values, and reindex from zero. Notably, the first element is always zero, since it starts
105
+		// with a /
106
+		return array_values(array_filter($exploded));
107
+	}
108
+
109
+	/**
110
+	 * Gets the remote address of the web request
111
+	 * @return null|string
112
+	 */
113
+	public static function remoteAddress()
114
+	{
115
+		$server = &self::$globalStateProvider->getServerSuperGlobal();
116
+
117
+		if (isset($server['REMOTE_ADDR'])) {
118
+			return $server['REMOTE_ADDR'];
119
+		}
120
+
121
+		return null;
122
+	}
123
+
124
+	/**
125
+	 * Gets the remote address of the web request
126
+	 * @return null|string
127
+	 */
128
+	public static function httpHost()
129
+	{
130
+		$server = &self::$globalStateProvider->getServerSuperGlobal();
131
+
132
+		if (isset($server['HTTP_HOST'])) {
133
+			return $server['HTTP_HOST'];
134
+		}
135
+
136
+		return null;
137
+	}
138
+
139
+	/**
140
+	 * Gets the XFF header contents for the web request
141
+	 * @return null|string
142
+	 */
143
+	public static function forwardedAddress()
144
+	{
145
+		$server = &self::$globalStateProvider->getServerSuperGlobal();
146
+
147
+		if (isset($server['HTTP_X_FORWARDED_FOR'])) {
148
+			return $server['HTTP_X_FORWARDED_FOR'];
149
+		}
150
+
151
+		return null;
152
+	}
153
+
154
+	/**
155
+	 * Sets the global state provider.
156
+	 *
157
+	 * Almost guaranteed this is not the method you want in production code.
158
+	 *
159
+	 * @param IGlobalStateProvider $globalState
160
+	 */
161
+	public static function setGlobalStateProvider($globalState)
162
+	{
163
+		self::$globalStateProvider = $globalState;
164
+	}
165
+
166
+	#region POST variables
167
+
168
+	/**
169
+	 * @param string $key
170
+	 *
171
+	 * @return null|string
172
+	 */
173
+	public static function postString($key)
174
+	{
175
+		$post = &self::$globalStateProvider->getPostSuperGlobal();
176
+		if (!array_key_exists($key, $post)) {
177
+			return null;
178
+		}
179
+
180
+		if ($post[$key] === "") {
181
+			return null;
182
+		}
183
+
184
+		return (string)$post[$key];
185
+	}
186
+
187
+	/**
188
+	 * @param string $key
189
+	 *
190
+	 * @return null|string
191
+	 */
192
+	public static function postEmail($key)
193
+	{
194
+		$post = &self::$globalStateProvider->getPostSuperGlobal();
195
+		if (!array_key_exists($key, $post)) {
196
+			return null;
197
+		}
198
+
199
+		$filteredValue = filter_var($post[$key], FILTER_SANITIZE_EMAIL);
200
+
201
+		if ($filteredValue === false) {
202
+			return null;
203
+		}
204
+
205
+		return (string)$filteredValue;
206
+	}
207
+
208
+	/**
209
+	 * @param string $key
210
+	 *
211
+	 * @return int|null
212
+	 */
213
+	public static function postInt($key)
214
+	{
215
+		$post = &self::$globalStateProvider->getPostSuperGlobal();
216
+		if (!array_key_exists($key, $post)) {
217
+			return null;
218
+		}
219
+
220
+		$filteredValue = filter_var($post[$key], FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
221
+
222
+		if ($filteredValue === null) {
223
+			return null;
224
+		}
225
+
226
+		return (int)$filteredValue;
227
+	}
228
+
229
+	/**
230
+	 * @param string $key
231
+	 *
232
+	 * @return bool
233
+	 */
234
+	public static function postBoolean($key)
235
+	{
236
+		$get = &self::$globalStateProvider->getPostSuperGlobal();
237
+		if (!array_key_exists($key, $get)) {
238
+			return false;
239
+		}
240
+
241
+		// presence of parameter only
242
+		if ($get[$key] === "") {
243
+			return true;
244
+		}
245
+
246
+		if (in_array($get[$key], array(false, 'no', 'off', 0, 'false'), true)) {
247
+			return false;
248
+		}
249
+
250
+		return true;
251
+	}
252
+
253
+	#endregion
254
+
255
+	#region GET variables
256
+
257
+	/**
258
+	 * @param string $key
259
+	 *
260
+	 * @return bool
261
+	 */
262
+	public static function getBoolean($key)
263
+	{
264
+		$get = &self::$globalStateProvider->getGetSuperGlobal();
265
+		if (!array_key_exists($key, $get)) {
266
+			return false;
267
+		}
268
+
269
+		// presence of parameter only
270
+		if ($get[$key] === "") {
271
+			return true;
272
+		}
273
+
274
+		if (in_array($get[$key], array(false, 'no', 'off', 0, 'false'), true)) {
275
+			return false;
276
+		}
277
+
278
+		return true;
279
+	}
280
+
281
+	/**
282
+	 * @param string $key
283
+	 *
284
+	 * @return int|null
285
+	 */
286
+	public static function getInt($key)
287
+	{
288
+		$get = &self::$globalStateProvider->getGetSuperGlobal();
289
+		if (!array_key_exists($key, $get)) {
290
+			return null;
291
+		}
292
+
293
+		$filteredValue = filter_var($get[$key], FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
294
+
295
+		if ($filteredValue === null) {
296
+			return null;
297
+		}
298
+
299
+		return (int)$filteredValue;
300
+	}
301
+
302
+	/**
303
+	 * @param string $key
304
+	 *
305
+	 * @return null|string
306
+	 */
307
+	public static function getString($key)
308
+	{
309
+		$get = &self::$globalStateProvider->getGetSuperGlobal();
310
+		if (!array_key_exists($key, $get)) {
311
+			return null;
312
+		}
313
+
314
+		if ($get[$key] === "") {
315
+			return null;
316
+		}
317
+
318
+		return (string)$get[$key];
319
+	}
320
+
321
+	#endregion
322
+
323
+	/**
324
+	 * Sets the logged-in user to the specified user.
325
+	 *
326
+	 * @param User $user
327
+	 */
328
+	public static function setLoggedInUser(User $user)
329
+	{
330
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
331
+
332
+		$session['userID'] = $user->getId();
333
+		unset($session['partialLogin']);
334
+	}
335
+
336
+	/**
337
+	 * Sets the post-login redirect
338
+	 *
339
+	 * @param string|null $uri The URI to redirect to
340
+	 */
341
+	public static function setPostLoginRedirect($uri = null)
342
+	{
343
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
344
+
345
+		if ($uri === null) {
346
+			$uri = self::requestUri();
347
+		}
348
+
349
+		$session['returnTo'] = $uri;
350
+	}
351
+
352
+	/**
353
+	 * @return string|null
354
+	 */
355
+	public static function requestUri()
356
+	{
357
+		$server = &self::$globalStateProvider->getServerSuperGlobal();
358
+
359
+		if (isset($server['REQUEST_URI'])) {
360
+			return $server['REQUEST_URI'];
361
+		}
362
+
363
+		return null;
364
+	}
365
+
366
+	/**
367
+	 * Clears the post-login redirect
368
+	 * @return string
369
+	 */
370
+	public static function clearPostLoginRedirect()
371
+	{
372
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
373
+		if (array_key_exists('returnTo', $session)) {
374
+			$path = $session['returnTo'];
375
+			unset($session['returnTo']);
376
+
377
+			return $path;
378
+		}
379
+
380
+		return null;
381
+	}
382
+
383
+	/**
384
+	 * @return string|null
385
+	 */
386
+	public static function serverName()
387
+	{
388
+		$server = &self::$globalStateProvider->getServerSuperGlobal();
389
+
390
+		if (isset($server['SERVER_NAME'])) {
391
+			return $server['SERVER_NAME'];
392
+		}
393
+
394
+		return null;
395
+	}
396
+
397
+	/**
398
+	 * You probably only want to deal with this through SessionAlert.
399
+	 * @return void
400
+	 */
401
+	public static function clearSessionAlertData()
402
+	{
403
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
404
+		if (array_key_exists('alerts', $session)) {
405
+			unset($session['alerts']);
406
+		}
407
+	}
408
+
409
+	/**
410
+	 * You probably only want to deal with this through SessionAlert.
411
+	 *
412
+	 * @return string[]
413
+	 */
414
+	public static function getSessionAlertData()
415
+	{
416
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
417
+		if (array_key_exists('alerts', $session)) {
418
+			return $session['alerts'];
419
+		}
420
+
421
+		return array();
422
+	}
423
+
424
+	/**
425
+	 * You probably only want to deal with this through SessionAlert.
426
+	 *
427
+	 * @param string[] $data
428
+	 */
429
+	public static function setSessionAlertData($data)
430
+	{
431
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
432
+		$session['alerts'] = $data;
433
+	}
434
+
435
+	/**
436
+	 * You probably only want to deal with this through TokenManager.
437
+	 *
438
+	 * @return string[]
439
+	 */
440
+	public static function getSessionTokenData()
441
+	{
442
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
443
+		if (array_key_exists('tokens', $session)) {
444
+			return $session['tokens'];
445
+		}
446
+
447
+		return array();
448
+	}
449
+
450
+	/**
451
+	 * You probably only want to deal with this through TokenManager.
452
+	 *
453
+	 * @param string[] $data
454
+	 */
455
+	public static function setSessionTokenData($data)
456
+	{
457
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
458
+		$session['tokens'] = $data;
459
+	}
460
+
461
+	/**
462
+	 * @param string $key
463
+	 *
464
+	 * @return mixed
465
+	 */
466
+	public static function getSessionContext($key)
467
+	{
468
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
469
+
470
+		if (!isset($session['context'])) {
471
+			$session['context'] = array();
472
+		}
473
+
474
+		if (!isset($session['context'][$key])) {
475
+			return null;
476
+		}
477
+
478
+		return $session['context'][$key];
479
+	}
480
+
481
+	/**
482
+	 * @param string $key
483
+	 * @param mixed  $data
484
+	 */
485
+	public static function setSessionContext($key, $data)
486
+	{
487
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
488
+
489
+		if (!isset($session['context'])) {
490
+			$session['context'] = array();
491
+		}
492
+
493
+		$session['context'][$key] = $data;
494
+	}
495
+
496
+	/**
497
+	 * @return int|null
498
+	 */
499
+	public static function getSessionUserId()
500
+	{
501
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
502
+
503
+		return isset($session['userID']) ? (int)$session['userID'] : null;
504
+	}
505
+
506
+	/**
507
+	 * @param User $user
508
+	 */
509
+	public static function setOAuthPartialLogin(User $user)
510
+	{
511
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
512
+		$session['oauthPartialLogin'] = $user->getId();
513
+	}
514
+
515
+	/**
516
+	 * @return int|null
517
+	 */
518
+	public static function getOAuthPartialLogin()
519
+	{
520
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
521
+
522
+		return isset($session['oauthPartialLogin']) ? (int)$session['oauthPartialLogin'] : null;
523
+	}
524
+
525
+	public static function setAuthPartialLogin($userId, $stage)
526
+	{
527
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
528
+		$session['authPartialLoginId'] = $userId;
529
+		$session['authPartialLoginStage'] = $stage;
530
+	}
531
+
532
+	public static function getAuthPartialLogin()
533
+	{
534
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
535
+
536
+		$userId = isset($session['authPartialLoginId']) ? (int)$session['authPartialLoginId'] : null;
537
+		$stage = isset($session['authPartialLoginStage']) ? (int)$session['authPartialLoginStage'] : null;
538
+
539
+		return array($userId, $stage);
540
+	}
541
+
542
+	public static function clearAuthPartialLogin()
543
+	{
544
+		$session = &self::$globalStateProvider->getSessionSuperGlobal();
545
+		unset($session['authPartialLoginId']);
546
+		unset($session['authPartialLoginStage']);
547
+	}
548
+
549
+	/**
550
+	 * @return null|string
551
+	 */
552
+	public static function userAgent()
553
+	{
554
+		$server = &self::$globalStateProvider->getServerSuperGlobal();
555
+
556
+		if (isset($server['HTTP_USER_AGENT'])) {
557
+			return $server['HTTP_USER_AGENT'];
558
+		}
559
+
560
+		return null;
561
+	}
562
+
563
+	/**
564
+	 * @return null|string
565
+	 */
566
+	public static function scriptName()
567
+	{
568
+		$server = &self::$globalStateProvider->getServerSuperGlobal();
569
+
570
+		if (isset($server['SCRIPT_NAME'])) {
571
+			return $server['SCRIPT_NAME'];
572
+		}
573
+
574
+		return null;
575
+	}
576
+
577
+	/**
578
+	 * @return null|string
579
+	 */
580
+	public static function origin()
581
+	{
582
+		$server = &self::$globalStateProvider->getServerSuperGlobal();
583
+
584
+		if (isset($server['HTTP_ORIGIN'])) {
585
+			return $server['HTTP_ORIGIN'];
586
+		}
587
+
588
+		return null;
589
+	}
590
+
591
+	public static function testSiteNoticeCookieValue($expectedHash)
592
+	{
593
+		$cookie = &self::$globalStateProvider->getCookieSuperGlobal();
594
+
595
+		if(isset($cookie['sitenotice'])) {
596
+			return $cookie['sitenotice'] === $expectedHash;
597
+		}
598
+
599
+		return false;
600
+	}
601 601
 }
Please login to merge, or discard this patch.
includes/RequestList.php 1 patch
Indentation   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -16,14 +16,14 @@
 block discarded – undo
16 16
  */
17 17
 class RequestList
18 18
 {
19
-    public $requests;
20
-    public $showPrivateData;
21
-    public $dataClearEmail;
22
-    public $dataClearIp;
23
-    public $relatedEmailRequests;
24
-    public $relatedIpRequests;
25
-    public $requestTrustedIp;
26
-    public $canBan;
27
-    public $canBreakReservation;
28
-    public $userList;
19
+	public $requests;
20
+	public $showPrivateData;
21
+	public $dataClearEmail;
22
+	public $dataClearIp;
23
+	public $relatedEmailRequests;
24
+	public $relatedIpRequests;
25
+	public $requestTrustedIp;
26
+	public $canBan;
27
+	public $canBreakReservation;
28
+	public $userList;
29 29
 }
Please login to merge, or discard this patch.
includes/Router/ApiRequestRouter.php 1 patch
Indentation   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -22,49 +22,49 @@
 block discarded – undo
22 22
 
23 23
 class ApiRequestRouter implements IRequestRouter
24 24
 {
25
-    /**
26
-     * @return string[]
27
-     */
28
-    public static function getActionList()
29
-    {
30
-        return array("count", "status", "stats", "help", "monitor");
31
-    }
25
+	/**
26
+	 * @return string[]
27
+	 */
28
+	public static function getActionList()
29
+	{
30
+		return array("count", "status", "stats", "help", "monitor");
31
+	}
32 32
 
33
-    /**
34
-     * @return IRoutedTask
35
-     * @throws Exception
36
-     */
37
-    public function route()
38
-    {
39
-        $requestAction = WebRequest::getString('action');
33
+	/**
34
+	 * @return IRoutedTask
35
+	 * @throws Exception
36
+	 */
37
+	public function route()
38
+	{
39
+		$requestAction = WebRequest::getString('action');
40 40
 
41
-        switch ($requestAction) {
42
-            case "count":
43
-                $result = new CountAction();
44
-                break;
45
-            case "status":
46
-                $result = new StatusAction();
47
-                break;
48
-            case "stats":
49
-                $result = new StatsAction();
50
-                break;
51
-            case "help":
52
-                $result = new HelpAction();
53
-                break;
54
-            case "monitor":
55
-                $result = new MonitorAction();
56
-                break;
57
-            case "users":
58
-                $result = new JsUsersAction();
59
-                break;
60
-            case "templates":
61
-                $result = new JsTemplateConfirmsAction();
62
-                break;
63
-            default:
64
-                $result = new UnknownAction();
65
-                break;
66
-        }
41
+		switch ($requestAction) {
42
+			case "count":
43
+				$result = new CountAction();
44
+				break;
45
+			case "status":
46
+				$result = new StatusAction();
47
+				break;
48
+			case "stats":
49
+				$result = new StatsAction();
50
+				break;
51
+			case "help":
52
+				$result = new HelpAction();
53
+				break;
54
+			case "monitor":
55
+				$result = new MonitorAction();
56
+				break;
57
+			case "users":
58
+				$result = new JsUsersAction();
59
+				break;
60
+			case "templates":
61
+				$result = new JsTemplateConfirmsAction();
62
+				break;
63
+			default:
64
+				$result = new UnknownAction();
65
+				break;
66
+		}
67 67
 
68
-        return $result;
69
-    }
68
+		return $result;
69
+	}
70 70
 }
Please login to merge, or discard this patch.
includes/Router/OAuthRequestRouter.php 1 patch
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -17,9 +17,9 @@
 block discarded – undo
17 17
  */
18 18
 class OAuthRequestRouter extends RequestRouter
19 19
 {
20
-    protected function getRouteFromPath($pathInfo)
21
-    {
22
-        // Hardcode the route for this entry point
23
-        return array(PageOAuthCallback::class, 'authorise');
24
-    }
20
+	protected function getRouteFromPath($pathInfo)
21
+	{
22
+		// Hardcode the route for this entry point
23
+		return array(PageOAuthCallback::class, 'authorise');
24
+	}
25 25
 }
26 26
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Router/RequestRouter.php 1 patch
Indentation   +441 added lines, -441 removed lines patch added patch discarded remove patch
@@ -63,445 +63,445 @@
 block discarded – undo
63 63
  */
64 64
 class RequestRouter implements IRequestRouter
65 65
 {
66
-    /**
67
-     * This is the core routing table for the application. The basic idea is:
68
-     *
69
-     *      array(
70
-     *          "foo" =>
71
-     *              array(
72
-     *                  "class"   => PageFoo::class,
73
-     *                  "actions" => array("bar", "other")
74
-     *              ),
75
-     * );
76
-     *
77
-     * Things to note:
78
-     *     - If no page is requested, we go to PageMain. PageMain can't have actions defined.
79
-     *
80
-     *     - If a page is defined and requested, but no action is requested, go to that page's main() method
81
-     *     - If a page is defined and requested, and an action is defined and requested, go to that action's method.
82
-     *     - If a page is defined and requested, and an action NOT defined and requested, go to Page404 and it's main()
83
-     *       method.
84
-     *     - If a page is NOT defined and requested, go to Page404 and it's main() method.
85
-     *
86
-     *     - Query parameters are ignored.
87
-     *
88
-     * The key point here is request routing with validation that this is allowed, before we start hitting the
89
-     * filesystem through the AutoLoader, and opening random files. Also, so that we validate the action requested
90
-     * before we start calling random methods through the web UI.
91
-     *
92
-     * Examples:
93
-     * /internal.php                => returns instance of PageMain, routed to main()
94
-     * /internal.php?query          => returns instance of PageMain, routed to main()
95
-     * /internal.php/foo            => returns instance of PageFoo, routed to main()
96
-     * /internal.php/foo?query      => returns instance of PageFoo, routed to main()
97
-     * /internal.php/foo/bar        => returns instance of PageFoo, routed to bar()
98
-     * /internal.php/foo/bar?query  => returns instance of PageFoo, routed to bar()
99
-     * /internal.php/foo/baz        => returns instance of Page404, routed to main()
100
-     * /internal.php/foo/baz?query  => returns instance of Page404, routed to main()
101
-     * /internal.php/bar            => returns instance of Page404, routed to main()
102
-     * /internal.php/bar?query      => returns instance of Page404, routed to main()
103
-     * /internal.php/bar/baz        => returns instance of Page404, routed to main()
104
-     * /internal.php/bar/baz?query  => returns instance of Page404, routed to main()
105
-     *
106
-     * Take care when changing this - a lot of places rely on the array key for redirects and other links. If you need
107
-     * to change the key, then you'll likely have to update a lot of files.
108
-     *
109
-     * @var array
110
-     */
111
-    private $routeMap = array(
112
-
113
-        //////////////////////////////////////////////////////////////////////////////////////////////////
114
-        // Login and registration
115
-        'logout'                      =>
116
-            array(
117
-                'class'   => PageLogout::class,
118
-                'actions' => array(),
119
-            ),
120
-        'login'                       =>
121
-            array(
122
-                'class'   => PagePasswordLogin::class,
123
-                'actions' => array(),
124
-            ),
125
-        'login/otp'                   =>
126
-            array(
127
-                'class'   => PageOtpLogin::class,
128
-                'actions' => array(),
129
-            ),
130
-        'login/u2f'                   =>
131
-            array(
132
-                'class'   => PageU2FLogin::class,
133
-                'actions' => array(),
134
-            ),
135
-        'forgotPassword'              =>
136
-            array(
137
-                'class'   => PageForgotPassword::class,
138
-                'actions' => array('reset'),
139
-            ),
140
-        'register'                    =>
141
-            array(
142
-                'class'   => PageRegisterOption::class,
143
-                'actions' => array(),
144
-            ),
145
-        'register/standard'           =>
146
-            array(
147
-                'class'   => PageRegisterStandard::class,
148
-                'actions' => array('done'),
149
-            ),
150
-
151
-        //////////////////////////////////////////////////////////////////////////////////////////////////
152
-        // Discovery
153
-        'search'                      =>
154
-            array(
155
-                'class'   => PageSearch::class,
156
-                'actions' => array(),
157
-            ),
158
-        'logs'                        =>
159
-            array(
160
-                'class'   => PageLog::class,
161
-                'actions' => array(),
162
-            ),
163
-
164
-        //////////////////////////////////////////////////////////////////////////////////////////////////
165
-        // Administration
166
-        'bans'                        =>
167
-            array(
168
-                'class'   => PageBan::class,
169
-                'actions' => array('set', 'remove'),
170
-            ),
171
-        'userManagement'              =>
172
-            array(
173
-                'class'   => PageUserManagement::class,
174
-                'actions' => array(
175
-                    'approve',
176
-                    'decline',
177
-                    'rename',
178
-                    'editUser',
179
-                    'suspend',
180
-                    'editRoles',
181
-                ),
182
-            ),
183
-        'siteNotice'                  =>
184
-            array(
185
-                'class'   => PageSiteNotice::class,
186
-                'actions' => array(),
187
-            ),
188
-        'emailManagement'             =>
189
-            array(
190
-                'class'   => PageEmailManagement::class,
191
-                'actions' => array('create', 'edit', 'view'),
192
-            ),
193
-        'jobQueue'                    =>
194
-            array(
195
-                'class'   => PageJobQueue::class,
196
-                'actions' => array('acknowledge', 'requeue', 'view', 'all'),
197
-            ),
198
-
199
-        //////////////////////////////////////////////////////////////////////////////////////////////////
200
-        // Personal preferences
201
-        'preferences'                 =>
202
-            array(
203
-                'class'   => PagePreferences::class,
204
-                'actions' => array(
205
-                    'refreshOAuth'
206
-                ),
207
-            ),
208
-        'changePassword'              =>
209
-            array(
210
-                'class'   => PageChangePassword::class,
211
-                'actions' => array(),
212
-            ),
213
-        'multiFactor'                 =>
214
-            array(
215
-                'class'   => PageMultiFactor::class,
216
-                'actions' => array(
217
-                    'scratch',
218
-                    'enableYubikeyOtp',
219
-                    'disableYubikeyOtp',
220
-                    'enableTotp',
221
-                    'disableTotp',
222
-                    'enableU2F',
223
-                    'disableU2F',
224
-                ),
225
-            ),
226
-        'oauth'                       =>
227
-            array(
228
-                'class'   => PageOAuth::class,
229
-                'actions' => array('detach', 'attach'),
230
-            ),
231
-        'oauth/callback'              =>
232
-            array(
233
-                'class'   => PageOAuthCallback::class,
234
-                'actions' => array('authorise', 'create'),
235
-            ),
236
-
237
-        //////////////////////////////////////////////////////////////////////////////////////////////////
238
-        // Welcomer configuration
239
-        'welcomeTemplates'            =>
240
-            array(
241
-                'class'   => PageWelcomeTemplateManagement::class,
242
-                'actions' => array('select', 'edit', 'delete', 'add', 'view'),
243
-            ),
244
-
245
-        //////////////////////////////////////////////////////////////////////////////////////////////////
246
-        // Statistics
247
-        'statistics'                  =>
248
-            array(
249
-                'class'   => StatsMain::class,
250
-                'actions' => array(),
251
-            ),
252
-        'statistics/fastCloses'       =>
253
-            array(
254
-                'class'   => StatsFastCloses::class,
255
-                'actions' => array(),
256
-            ),
257
-        'statistics/inactiveUsers'    =>
258
-            array(
259
-                'class'   => StatsInactiveUsers::class,
260
-                'actions' => array(),
261
-            ),
262
-        'statistics/monthlyStats'     =>
263
-            array(
264
-                'class'   => StatsMonthlyStats::class,
265
-                'actions' => array(),
266
-            ),
267
-        'statistics/reservedRequests' =>
268
-            array(
269
-                'class'   => StatsReservedRequests::class,
270
-                'actions' => array(),
271
-            ),
272
-        'statistics/templateStats'    =>
273
-            array(
274
-                'class'   => StatsTemplateStats::class,
275
-                'actions' => array(),
276
-            ),
277
-        'statistics/topCreators'      =>
278
-            array(
279
-                'class'   => StatsTopCreators::class,
280
-                'actions' => array(),
281
-            ),
282
-        'statistics/users'            =>
283
-            array(
284
-                'class'   => StatsUsers::class,
285
-                'actions' => array('detail'),
286
-            ),
287
-
288
-        //////////////////////////////////////////////////////////////////////////////////////////////////
289
-        // Zoom page
290
-        'viewRequest'                 =>
291
-            array(
292
-                'class'   => PageViewRequest::class,
293
-                'actions' => array(),
294
-            ),
295
-        'viewRequest/reserve'         =>
296
-            array(
297
-                'class'   => PageReservation::class,
298
-                'actions' => array(),
299
-            ),
300
-        'viewRequest/breakReserve'    =>
301
-            array(
302
-                'class'   => PageBreakReservation::class,
303
-                'actions' => array(),
304
-            ),
305
-        'viewRequest/defer'           =>
306
-            array(
307
-                'class'   => PageDeferRequest::class,
308
-                'actions' => array(),
309
-            ),
310
-        'viewRequest/comment'         =>
311
-            array(
312
-                'class'   => PageComment::class,
313
-                'actions' => array(),
314
-            ),
315
-        'viewRequest/sendToUser'      =>
316
-            array(
317
-                'class'   => PageSendToUser::class,
318
-                'actions' => array(),
319
-            ),
320
-        'viewRequest/close'           =>
321
-            array(
322
-                'class'   => PageCloseRequest::class,
323
-                'actions' => array(),
324
-            ),
325
-        'viewRequest/create'          =>
326
-            array(
327
-                'class'   => PageCreateRequest::class,
328
-                'actions' => array(),
329
-            ),
330
-        'viewRequest/drop'            =>
331
-            array(
332
-                'class'   => PageDropRequest::class,
333
-                'actions' => array(),
334
-            ),
335
-        'viewRequest/custom'          =>
336
-            array(
337
-                'class'   => PageCustomClose::class,
338
-                'actions' => array(),
339
-            ),
340
-        'editComment'                 =>
341
-            array(
342
-                'class'   => PageEditComment::class,
343
-                'actions' => array(),
344
-            ),
345
-
346
-        //////////////////////////////////////////////////////////////////////////////////////////////////
347
-        // Misc stuff
348
-        'team'                        =>
349
-            array(
350
-                'class'   => PageTeam::class,
351
-                'actions' => array(),
352
-            ),
353
-        'requestList'                 =>
354
-            array(
355
-                'class'   => PageExpandedRequestList::class,
356
-                'actions' => array(),
357
-            ),
358
-        'xffdemo'                     =>
359
-            array(
360
-                'class'   => PageXffDemo::class,
361
-                'actions' => array(),
362
-            ),
363
-    );
364
-
365
-    /**
366
-     * @return IRoutedTask
367
-     * @throws Exception
368
-     */
369
-    final public function route()
370
-    {
371
-        $pathInfo = WebRequest::pathInfo();
372
-
373
-        list($pageClass, $action) = $this->getRouteFromPath($pathInfo);
374
-
375
-        /** @var IRoutedTask $page */
376
-        $page = new $pageClass();
377
-
378
-        // Dynamic creation, so we've got to be careful here. We can't use built-in language type protection, so
379
-        // let's use our own.
380
-        if (!($page instanceof IRoutedTask)) {
381
-            throw new Exception('Expected a page, but this is not a page.');
382
-        }
383
-
384
-        // OK, I'm happy at this point that we know we're running a page, and we know it's probably what we want if it
385
-        // inherits PageBase and has been created from the routing map.
386
-        $page->setRoute($action);
387
-
388
-        return $page;
389
-    }
390
-
391
-    /**
392
-     * @param $pathInfo
393
-     *
394
-     * @return array
395
-     */
396
-    protected function getRouteFromPath($pathInfo)
397
-    {
398
-        if (count($pathInfo) === 0) {
399
-            // No pathInfo, so no page to load. Load the main page.
400
-            return $this->getDefaultRoute();
401
-        }
402
-        elseif (count($pathInfo) === 1) {
403
-            // Exactly one path info segment, it's got to be a page.
404
-            $classSegment = $pathInfo[0];
405
-
406
-            return $this->routeSinglePathSegment($classSegment);
407
-        }
408
-
409
-        // OK, we have two or more segments now.
410
-        if (count($pathInfo) > 2) {
411
-            // Let's handle more than two, and collapse it down into two.
412
-            $requestedAction = array_pop($pathInfo);
413
-            $classSegment = implode('/', $pathInfo);
414
-        }
415
-        else {
416
-            // Two path info segments.
417
-            $classSegment = $pathInfo[0];
418
-            $requestedAction = $pathInfo[1];
419
-        }
420
-
421
-        $routeMap = $this->routePathSegments($classSegment, $requestedAction);
422
-
423
-        if ($routeMap[0] === Page404::class) {
424
-            $routeMap = $this->routeSinglePathSegment($classSegment . '/' . $requestedAction);
425
-        }
426
-
427
-        return $routeMap;
428
-    }
429
-
430
-    /**
431
-     * @param $classSegment
432
-     *
433
-     * @return array
434
-     */
435
-    final protected function routeSinglePathSegment($classSegment)
436
-    {
437
-        $routeMap = $this->getRouteMap();
438
-        if (array_key_exists($classSegment, $routeMap)) {
439
-            // Route exists, but we don't have an action in path info, so default to main.
440
-            $pageClass = $routeMap[$classSegment]['class'];
441
-            $action = 'main';
442
-
443
-            return array($pageClass, $action);
444
-        }
445
-        else {
446
-            // Doesn't exist in map. Fall back to 404
447
-            $pageClass = Page404::class;
448
-            $action = "main";
449
-
450
-            return array($pageClass, $action);
451
-        }
452
-    }
453
-
454
-    /**
455
-     * @param $classSegment
456
-     * @param $requestedAction
457
-     *
458
-     * @return array
459
-     */
460
-    final protected function routePathSegments($classSegment, $requestedAction)
461
-    {
462
-        $routeMap = $this->getRouteMap();
463
-        if (array_key_exists($classSegment, $routeMap)) {
464
-            // Route exists, but we don't have an action in path info, so default to main.
465
-
466
-            if (isset($routeMap[$classSegment]['actions'])
467
-                && array_search($requestedAction, $routeMap[$classSegment]['actions']) !== false
468
-            ) {
469
-                // Action exists in allowed action list. Allow both the page and the action
470
-                $pageClass = $routeMap[$classSegment]['class'];
471
-                $action = $requestedAction;
472
-
473
-                return array($pageClass, $action);
474
-            }
475
-            else {
476
-                // Valid page, invalid action. 404 our way out.
477
-                $pageClass = Page404::class;
478
-                $action = 'main';
479
-
480
-                return array($pageClass, $action);
481
-            }
482
-        }
483
-        else {
484
-            // Class doesn't exist in map. Fall back to 404
485
-            $pageClass = Page404::class;
486
-            $action = 'main';
487
-
488
-            return array($pageClass, $action);
489
-        }
490
-    }
491
-
492
-    /**
493
-     * @return array
494
-     */
495
-    protected function getRouteMap()
496
-    {
497
-        return $this->routeMap;
498
-    }
499
-
500
-    /**
501
-     * @return array
502
-     */
503
-    protected function getDefaultRoute()
504
-    {
505
-        return array(PageMain::class, "main");
506
-    }
66
+	/**
67
+	 * This is the core routing table for the application. The basic idea is:
68
+	 *
69
+	 *      array(
70
+	 *          "foo" =>
71
+	 *              array(
72
+	 *                  "class"   => PageFoo::class,
73
+	 *                  "actions" => array("bar", "other")
74
+	 *              ),
75
+	 * );
76
+	 *
77
+	 * Things to note:
78
+	 *     - If no page is requested, we go to PageMain. PageMain can't have actions defined.
79
+	 *
80
+	 *     - If a page is defined and requested, but no action is requested, go to that page's main() method
81
+	 *     - If a page is defined and requested, and an action is defined and requested, go to that action's method.
82
+	 *     - If a page is defined and requested, and an action NOT defined and requested, go to Page404 and it's main()
83
+	 *       method.
84
+	 *     - If a page is NOT defined and requested, go to Page404 and it's main() method.
85
+	 *
86
+	 *     - Query parameters are ignored.
87
+	 *
88
+	 * The key point here is request routing with validation that this is allowed, before we start hitting the
89
+	 * filesystem through the AutoLoader, and opening random files. Also, so that we validate the action requested
90
+	 * before we start calling random methods through the web UI.
91
+	 *
92
+	 * Examples:
93
+	 * /internal.php                => returns instance of PageMain, routed to main()
94
+	 * /internal.php?query          => returns instance of PageMain, routed to main()
95
+	 * /internal.php/foo            => returns instance of PageFoo, routed to main()
96
+	 * /internal.php/foo?query      => returns instance of PageFoo, routed to main()
97
+	 * /internal.php/foo/bar        => returns instance of PageFoo, routed to bar()
98
+	 * /internal.php/foo/bar?query  => returns instance of PageFoo, routed to bar()
99
+	 * /internal.php/foo/baz        => returns instance of Page404, routed to main()
100
+	 * /internal.php/foo/baz?query  => returns instance of Page404, routed to main()
101
+	 * /internal.php/bar            => returns instance of Page404, routed to main()
102
+	 * /internal.php/bar?query      => returns instance of Page404, routed to main()
103
+	 * /internal.php/bar/baz        => returns instance of Page404, routed to main()
104
+	 * /internal.php/bar/baz?query  => returns instance of Page404, routed to main()
105
+	 *
106
+	 * Take care when changing this - a lot of places rely on the array key for redirects and other links. If you need
107
+	 * to change the key, then you'll likely have to update a lot of files.
108
+	 *
109
+	 * @var array
110
+	 */
111
+	private $routeMap = array(
112
+
113
+		//////////////////////////////////////////////////////////////////////////////////////////////////
114
+		// Login and registration
115
+		'logout'                      =>
116
+			array(
117
+				'class'   => PageLogout::class,
118
+				'actions' => array(),
119
+			),
120
+		'login'                       =>
121
+			array(
122
+				'class'   => PagePasswordLogin::class,
123
+				'actions' => array(),
124
+			),
125
+		'login/otp'                   =>
126
+			array(
127
+				'class'   => PageOtpLogin::class,
128
+				'actions' => array(),
129
+			),
130
+		'login/u2f'                   =>
131
+			array(
132
+				'class'   => PageU2FLogin::class,
133
+				'actions' => array(),
134
+			),
135
+		'forgotPassword'              =>
136
+			array(
137
+				'class'   => PageForgotPassword::class,
138
+				'actions' => array('reset'),
139
+			),
140
+		'register'                    =>
141
+			array(
142
+				'class'   => PageRegisterOption::class,
143
+				'actions' => array(),
144
+			),
145
+		'register/standard'           =>
146
+			array(
147
+				'class'   => PageRegisterStandard::class,
148
+				'actions' => array('done'),
149
+			),
150
+
151
+		//////////////////////////////////////////////////////////////////////////////////////////////////
152
+		// Discovery
153
+		'search'                      =>
154
+			array(
155
+				'class'   => PageSearch::class,
156
+				'actions' => array(),
157
+			),
158
+		'logs'                        =>
159
+			array(
160
+				'class'   => PageLog::class,
161
+				'actions' => array(),
162
+			),
163
+
164
+		//////////////////////////////////////////////////////////////////////////////////////////////////
165
+		// Administration
166
+		'bans'                        =>
167
+			array(
168
+				'class'   => PageBan::class,
169
+				'actions' => array('set', 'remove'),
170
+			),
171
+		'userManagement'              =>
172
+			array(
173
+				'class'   => PageUserManagement::class,
174
+				'actions' => array(
175
+					'approve',
176
+					'decline',
177
+					'rename',
178
+					'editUser',
179
+					'suspend',
180
+					'editRoles',
181
+				),
182
+			),
183
+		'siteNotice'                  =>
184
+			array(
185
+				'class'   => PageSiteNotice::class,
186
+				'actions' => array(),
187
+			),
188
+		'emailManagement'             =>
189
+			array(
190
+				'class'   => PageEmailManagement::class,
191
+				'actions' => array('create', 'edit', 'view'),
192
+			),
193
+		'jobQueue'                    =>
194
+			array(
195
+				'class'   => PageJobQueue::class,
196
+				'actions' => array('acknowledge', 'requeue', 'view', 'all'),
197
+			),
198
+
199
+		//////////////////////////////////////////////////////////////////////////////////////////////////
200
+		// Personal preferences
201
+		'preferences'                 =>
202
+			array(
203
+				'class'   => PagePreferences::class,
204
+				'actions' => array(
205
+					'refreshOAuth'
206
+				),
207
+			),
208
+		'changePassword'              =>
209
+			array(
210
+				'class'   => PageChangePassword::class,
211
+				'actions' => array(),
212
+			),
213
+		'multiFactor'                 =>
214
+			array(
215
+				'class'   => PageMultiFactor::class,
216
+				'actions' => array(
217
+					'scratch',
218
+					'enableYubikeyOtp',
219
+					'disableYubikeyOtp',
220
+					'enableTotp',
221
+					'disableTotp',
222
+					'enableU2F',
223
+					'disableU2F',
224
+				),
225
+			),
226
+		'oauth'                       =>
227
+			array(
228
+				'class'   => PageOAuth::class,
229
+				'actions' => array('detach', 'attach'),
230
+			),
231
+		'oauth/callback'              =>
232
+			array(
233
+				'class'   => PageOAuthCallback::class,
234
+				'actions' => array('authorise', 'create'),
235
+			),
236
+
237
+		//////////////////////////////////////////////////////////////////////////////////////////////////
238
+		// Welcomer configuration
239
+		'welcomeTemplates'            =>
240
+			array(
241
+				'class'   => PageWelcomeTemplateManagement::class,
242
+				'actions' => array('select', 'edit', 'delete', 'add', 'view'),
243
+			),
244
+
245
+		//////////////////////////////////////////////////////////////////////////////////////////////////
246
+		// Statistics
247
+		'statistics'                  =>
248
+			array(
249
+				'class'   => StatsMain::class,
250
+				'actions' => array(),
251
+			),
252
+		'statistics/fastCloses'       =>
253
+			array(
254
+				'class'   => StatsFastCloses::class,
255
+				'actions' => array(),
256
+			),
257
+		'statistics/inactiveUsers'    =>
258
+			array(
259
+				'class'   => StatsInactiveUsers::class,
260
+				'actions' => array(),
261
+			),
262
+		'statistics/monthlyStats'     =>
263
+			array(
264
+				'class'   => StatsMonthlyStats::class,
265
+				'actions' => array(),
266
+			),
267
+		'statistics/reservedRequests' =>
268
+			array(
269
+				'class'   => StatsReservedRequests::class,
270
+				'actions' => array(),
271
+			),
272
+		'statistics/templateStats'    =>
273
+			array(
274
+				'class'   => StatsTemplateStats::class,
275
+				'actions' => array(),
276
+			),
277
+		'statistics/topCreators'      =>
278
+			array(
279
+				'class'   => StatsTopCreators::class,
280
+				'actions' => array(),
281
+			),
282
+		'statistics/users'            =>
283
+			array(
284
+				'class'   => StatsUsers::class,
285
+				'actions' => array('detail'),
286
+			),
287
+
288
+		//////////////////////////////////////////////////////////////////////////////////////////////////
289
+		// Zoom page
290
+		'viewRequest'                 =>
291
+			array(
292
+				'class'   => PageViewRequest::class,
293
+				'actions' => array(),
294
+			),
295
+		'viewRequest/reserve'         =>
296
+			array(
297
+				'class'   => PageReservation::class,
298
+				'actions' => array(),
299
+			),
300
+		'viewRequest/breakReserve'    =>
301
+			array(
302
+				'class'   => PageBreakReservation::class,
303
+				'actions' => array(),
304
+			),
305
+		'viewRequest/defer'           =>
306
+			array(
307
+				'class'   => PageDeferRequest::class,
308
+				'actions' => array(),
309
+			),
310
+		'viewRequest/comment'         =>
311
+			array(
312
+				'class'   => PageComment::class,
313
+				'actions' => array(),
314
+			),
315
+		'viewRequest/sendToUser'      =>
316
+			array(
317
+				'class'   => PageSendToUser::class,
318
+				'actions' => array(),
319
+			),
320
+		'viewRequest/close'           =>
321
+			array(
322
+				'class'   => PageCloseRequest::class,
323
+				'actions' => array(),
324
+			),
325
+		'viewRequest/create'          =>
326
+			array(
327
+				'class'   => PageCreateRequest::class,
328
+				'actions' => array(),
329
+			),
330
+		'viewRequest/drop'            =>
331
+			array(
332
+				'class'   => PageDropRequest::class,
333
+				'actions' => array(),
334
+			),
335
+		'viewRequest/custom'          =>
336
+			array(
337
+				'class'   => PageCustomClose::class,
338
+				'actions' => array(),
339
+			),
340
+		'editComment'                 =>
341
+			array(
342
+				'class'   => PageEditComment::class,
343
+				'actions' => array(),
344
+			),
345
+
346
+		//////////////////////////////////////////////////////////////////////////////////////////////////
347
+		// Misc stuff
348
+		'team'                        =>
349
+			array(
350
+				'class'   => PageTeam::class,
351
+				'actions' => array(),
352
+			),
353
+		'requestList'                 =>
354
+			array(
355
+				'class'   => PageExpandedRequestList::class,
356
+				'actions' => array(),
357
+			),
358
+		'xffdemo'                     =>
359
+			array(
360
+				'class'   => PageXffDemo::class,
361
+				'actions' => array(),
362
+			),
363
+	);
364
+
365
+	/**
366
+	 * @return IRoutedTask
367
+	 * @throws Exception
368
+	 */
369
+	final public function route()
370
+	{
371
+		$pathInfo = WebRequest::pathInfo();
372
+
373
+		list($pageClass, $action) = $this->getRouteFromPath($pathInfo);
374
+
375
+		/** @var IRoutedTask $page */
376
+		$page = new $pageClass();
377
+
378
+		// Dynamic creation, so we've got to be careful here. We can't use built-in language type protection, so
379
+		// let's use our own.
380
+		if (!($page instanceof IRoutedTask)) {
381
+			throw new Exception('Expected a page, but this is not a page.');
382
+		}
383
+
384
+		// OK, I'm happy at this point that we know we're running a page, and we know it's probably what we want if it
385
+		// inherits PageBase and has been created from the routing map.
386
+		$page->setRoute($action);
387
+
388
+		return $page;
389
+	}
390
+
391
+	/**
392
+	 * @param $pathInfo
393
+	 *
394
+	 * @return array
395
+	 */
396
+	protected function getRouteFromPath($pathInfo)
397
+	{
398
+		if (count($pathInfo) === 0) {
399
+			// No pathInfo, so no page to load. Load the main page.
400
+			return $this->getDefaultRoute();
401
+		}
402
+		elseif (count($pathInfo) === 1) {
403
+			// Exactly one path info segment, it's got to be a page.
404
+			$classSegment = $pathInfo[0];
405
+
406
+			return $this->routeSinglePathSegment($classSegment);
407
+		}
408
+
409
+		// OK, we have two or more segments now.
410
+		if (count($pathInfo) > 2) {
411
+			// Let's handle more than two, and collapse it down into two.
412
+			$requestedAction = array_pop($pathInfo);
413
+			$classSegment = implode('/', $pathInfo);
414
+		}
415
+		else {
416
+			// Two path info segments.
417
+			$classSegment = $pathInfo[0];
418
+			$requestedAction = $pathInfo[1];
419
+		}
420
+
421
+		$routeMap = $this->routePathSegments($classSegment, $requestedAction);
422
+
423
+		if ($routeMap[0] === Page404::class) {
424
+			$routeMap = $this->routeSinglePathSegment($classSegment . '/' . $requestedAction);
425
+		}
426
+
427
+		return $routeMap;
428
+	}
429
+
430
+	/**
431
+	 * @param $classSegment
432
+	 *
433
+	 * @return array
434
+	 */
435
+	final protected function routeSinglePathSegment($classSegment)
436
+	{
437
+		$routeMap = $this->getRouteMap();
438
+		if (array_key_exists($classSegment, $routeMap)) {
439
+			// Route exists, but we don't have an action in path info, so default to main.
440
+			$pageClass = $routeMap[$classSegment]['class'];
441
+			$action = 'main';
442
+
443
+			return array($pageClass, $action);
444
+		}
445
+		else {
446
+			// Doesn't exist in map. Fall back to 404
447
+			$pageClass = Page404::class;
448
+			$action = "main";
449
+
450
+			return array($pageClass, $action);
451
+		}
452
+	}
453
+
454
+	/**
455
+	 * @param $classSegment
456
+	 * @param $requestedAction
457
+	 *
458
+	 * @return array
459
+	 */
460
+	final protected function routePathSegments($classSegment, $requestedAction)
461
+	{
462
+		$routeMap = $this->getRouteMap();
463
+		if (array_key_exists($classSegment, $routeMap)) {
464
+			// Route exists, but we don't have an action in path info, so default to main.
465
+
466
+			if (isset($routeMap[$classSegment]['actions'])
467
+				&& array_search($requestedAction, $routeMap[$classSegment]['actions']) !== false
468
+			) {
469
+				// Action exists in allowed action list. Allow both the page and the action
470
+				$pageClass = $routeMap[$classSegment]['class'];
471
+				$action = $requestedAction;
472
+
473
+				return array($pageClass, $action);
474
+			}
475
+			else {
476
+				// Valid page, invalid action. 404 our way out.
477
+				$pageClass = Page404::class;
478
+				$action = 'main';
479
+
480
+				return array($pageClass, $action);
481
+			}
482
+		}
483
+		else {
484
+			// Class doesn't exist in map. Fall back to 404
485
+			$pageClass = Page404::class;
486
+			$action = 'main';
487
+
488
+			return array($pageClass, $action);
489
+		}
490
+	}
491
+
492
+	/**
493
+	 * @return array
494
+	 */
495
+	protected function getRouteMap()
496
+	{
497
+		return $this->routeMap;
498
+	}
499
+
500
+	/**
501
+	 * @return array
502
+	 */
503
+	protected function getDefaultRoute()
504
+	{
505
+		return array(PageMain::class, "main");
506
+	}
507 507
 }
Please login to merge, or discard this patch.