1
|
|
|
<?php |
2
|
|
|
/****************************************************************************** |
3
|
|
|
* Wikipedia Account Creation Assistance tool * |
4
|
|
|
* * |
5
|
|
|
* All code in this file is released into the public domain by the ACC * |
6
|
|
|
* Development Team. Please see team.json for a list of contributors. * |
7
|
|
|
******************************************************************************/ |
8
|
|
|
|
9
|
|
|
namespace Waca; |
10
|
|
|
|
11
|
|
|
use Waca\DataObjects\User; |
12
|
|
|
use Waca\Providers\GlobalState\IGlobalStateProvider; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Holds helper functions regarding the current request. |
16
|
|
|
* |
17
|
|
|
* This is the only place where it is allowed to use super-globals, but even then access MUST be pushed through the |
18
|
|
|
* global state provider to allow for unit tests. It's strongly recommended to do sanitising of data here, especially |
19
|
|
|
* if extra logic is required to get a deterministic value, like isHttps(). |
20
|
|
|
* |
21
|
|
|
* @package Waca |
22
|
|
|
*/ |
23
|
|
|
class WebRequest |
24
|
|
|
{ |
25
|
|
|
/** |
26
|
|
|
* @var \Waca\Providers\GlobalState\IGlobalStateProvider Provides access to the global state. |
27
|
|
|
*/ |
28
|
|
|
private static $globalStateProvider; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Returns a boolean value if the request was submitted with the HTTP POST method. |
32
|
|
|
* @return bool |
33
|
|
|
*/ |
34
|
|
|
public static function wasPosted() |
35
|
|
|
{ |
36
|
|
|
return self::method() === 'POST'; |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Gets the HTTP Method used |
41
|
|
|
* @return string|null |
42
|
|
|
*/ |
43
|
|
View Code Duplication |
public static function method() |
|
|
|
|
44
|
|
|
{ |
45
|
|
|
$server = &self::$globalStateProvider->getServerSuperGlobal(); |
46
|
|
|
|
47
|
|
|
if (isset($server['REQUEST_METHOD'])) { |
48
|
|
|
return $server['REQUEST_METHOD']; |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
return null; |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* Gets a boolean value stating whether the request was served over HTTPS or not. |
56
|
|
|
* @return bool |
57
|
|
|
*/ |
58
|
|
|
public static function isHttps() |
59
|
|
|
{ |
60
|
|
|
$server = &self::$globalStateProvider->getServerSuperGlobal(); |
61
|
|
|
|
62
|
|
View Code Duplication |
if (isset($server['HTTP_X_FORWARDED_PROTO'])) { |
|
|
|
|
63
|
|
|
if ($server['HTTP_X_FORWARDED_PROTO'] === 'https') { |
|
|
|
|
64
|
|
|
// Client <=> Proxy is encrypted |
65
|
|
|
return true; |
66
|
|
|
} |
67
|
|
|
else { |
68
|
|
|
// Proxy <=> Server link unknown, Client <=> Proxy is not encrypted. |
69
|
|
|
return false; |
70
|
|
|
} |
71
|
|
|
} |
72
|
|
|
|
73
|
|
View Code Duplication |
if (isset($server['HTTPS'])) { |
|
|
|
|
74
|
|
|
if ($server['HTTPS'] === 'off') { |
75
|
|
|
// ISAPI on IIS breaks the spec. :( |
76
|
|
|
return false; |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
if ($server['HTTPS'] !== '') { |
80
|
|
|
// Set to a non-empty value |
81
|
|
|
return true; |
82
|
|
|
} |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
return false; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Gets the path info |
90
|
|
|
* |
91
|
|
|
* @return array Array of path info segments |
92
|
|
|
*/ |
93
|
|
|
public static function pathInfo() |
94
|
|
|
{ |
95
|
|
|
$server = &self::$globalStateProvider->getServerSuperGlobal(); |
96
|
|
|
if (!isset($server['PATH_INFO'])) { |
97
|
|
|
return array(); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
$exploded = explode('/', $server['PATH_INFO']); |
101
|
|
|
|
102
|
|
|
// filter out empty values, and reindex from zero. Notably, the first element is always zero, since it starts |
103
|
|
|
// with a / |
104
|
|
|
return array_values(array_filter($exploded)); |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Gets the remote address of the web request |
109
|
|
|
* @return null|string |
110
|
|
|
*/ |
111
|
|
View Code Duplication |
public static function remoteAddress() |
|
|
|
|
112
|
|
|
{ |
113
|
|
|
$server = &self::$globalStateProvider->getServerSuperGlobal(); |
114
|
|
|
|
115
|
|
|
if (isset($server['REMOTE_ADDR'])) { |
116
|
|
|
return $server['REMOTE_ADDR']; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
return null; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Gets the XFF header contents for the web request |
124
|
|
|
* @return null|string |
125
|
|
|
*/ |
126
|
|
View Code Duplication |
public static function forwardedAddress() |
|
|
|
|
127
|
|
|
{ |
128
|
|
|
$server = &self::$globalStateProvider->getServerSuperGlobal(); |
129
|
|
|
|
130
|
|
|
if (isset($server['HTTP_X_FORWARDED_FOR'])) { |
131
|
|
|
return $server['HTTP_X_FORWARDED_FOR']; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
return null; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* Sets the global state provider. |
139
|
|
|
* |
140
|
|
|
* Almost guaranteed this is not the method you want in production code. |
141
|
|
|
* |
142
|
|
|
* @param \Waca\Providers\GlobalState\IGlobalStateProvider $globalState |
143
|
|
|
*/ |
144
|
|
|
public static function setGlobalStateProvider($globalState) |
145
|
|
|
{ |
146
|
|
|
self::$globalStateProvider = $globalState; |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
#region POST variables |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* @param string $key |
153
|
|
|
* |
154
|
|
|
* @return null|string |
155
|
|
|
*/ |
156
|
|
View Code Duplication |
public static function postString($key) |
|
|
|
|
157
|
|
|
{ |
158
|
|
|
$post = &self::$globalStateProvider->getPostSuperGlobal(); |
159
|
|
|
if (!array_key_exists($key, $post)) { |
160
|
|
|
return null; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
if ($post[$key] === "") { |
164
|
|
|
return null; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
return (string)$post[$key]; |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* @param string $key |
172
|
|
|
* |
173
|
|
|
* @return null|string |
174
|
|
|
*/ |
175
|
|
View Code Duplication |
public static function postEmail($key) |
|
|
|
|
176
|
|
|
{ |
177
|
|
|
$post = &self::$globalStateProvider->getPostSuperGlobal(); |
178
|
|
|
if (!array_key_exists($key, $post)) { |
179
|
|
|
return null; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
$filteredValue = filter_var($post[$key], FILTER_SANITIZE_EMAIL); |
183
|
|
|
|
184
|
|
|
if ($filteredValue === false) { |
185
|
|
|
return null; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
return (string)$filteredValue; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* @param string $key |
193
|
|
|
* |
194
|
|
|
* @return int|null |
195
|
|
|
*/ |
196
|
|
View Code Duplication |
public static function postInt($key) |
|
|
|
|
197
|
|
|
{ |
198
|
|
|
$post = &self::$globalStateProvider->getPostSuperGlobal(); |
199
|
|
|
if (!array_key_exists($key, $post)) { |
200
|
|
|
return null; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
$filteredValue = filter_var($post[$key], FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE); |
204
|
|
|
|
205
|
|
|
if ($filteredValue === null) { |
206
|
|
|
return null; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
return (int)$filteredValue; |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* @param string $key |
214
|
|
|
* |
215
|
|
|
* @return bool |
216
|
|
|
*/ |
217
|
|
View Code Duplication |
public static function postBoolean($key) |
|
|
|
|
218
|
|
|
{ |
219
|
|
|
$get = &self::$globalStateProvider->getPostSuperGlobal(); |
220
|
|
|
if (!array_key_exists($key, $get)) { |
221
|
|
|
return false; |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
// presence of parameter only |
225
|
|
|
if ($get[$key] === "") { |
226
|
|
|
return true; |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
if (in_array($get[$key], array(false, 'no', 'off', 0, 'false'), true)) { |
|
|
|
|
230
|
|
|
return false; |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
return true; |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
#endregion |
237
|
|
|
|
238
|
|
|
#region GET variables |
239
|
|
|
|
240
|
|
|
/** |
241
|
|
|
* @param string $key |
242
|
|
|
* |
243
|
|
|
* @return bool |
244
|
|
|
*/ |
245
|
|
View Code Duplication |
public static function getBoolean($key) |
|
|
|
|
246
|
|
|
{ |
247
|
|
|
$get = &self::$globalStateProvider->getGetSuperGlobal(); |
248
|
|
|
if (!array_key_exists($key, $get)) { |
249
|
|
|
return false; |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
// presence of parameter only |
253
|
|
|
if ($get[$key] === "") { |
254
|
|
|
return true; |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
if (in_array($get[$key], array(false, 'no', 'off', 0, 'false'), true)) { |
|
|
|
|
258
|
|
|
return false; |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
return true; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
/** |
265
|
|
|
* @param string $key |
266
|
|
|
* |
267
|
|
|
* @return int|null |
268
|
|
|
*/ |
269
|
|
View Code Duplication |
public static function getInt($key) |
|
|
|
|
270
|
|
|
{ |
271
|
|
|
$get = &self::$globalStateProvider->getGetSuperGlobal(); |
272
|
|
|
if (!array_key_exists($key, $get)) { |
273
|
|
|
return null; |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
$filteredValue = filter_var($get[$key], FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE); |
277
|
|
|
|
278
|
|
|
if ($filteredValue === null) { |
279
|
|
|
return null; |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
return (int)$filteredValue; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
/** |
286
|
|
|
* @param string $key |
287
|
|
|
* |
288
|
|
|
* @return null|string |
289
|
|
|
*/ |
290
|
|
View Code Duplication |
public static function getString($key) |
|
|
|
|
291
|
|
|
{ |
292
|
|
|
$get = &self::$globalStateProvider->getGetSuperGlobal(); |
293
|
|
|
if (!array_key_exists($key, $get)) { |
294
|
|
|
return null; |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
if ($get[$key] === "") { |
298
|
|
|
return null; |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
return (string)$get[$key]; |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
#endregion |
305
|
|
|
|
306
|
|
|
/** |
307
|
|
|
* Sets the logged-in user to the specified user. |
308
|
|
|
* |
309
|
|
|
* @param User $user |
310
|
|
|
*/ |
311
|
|
|
public static function setLoggedInUser(User $user) |
312
|
|
|
{ |
313
|
|
|
$session = &self::$globalStateProvider->getSessionSuperGlobal(); |
314
|
|
|
|
315
|
|
|
$session['userID'] = $user->getId(); |
316
|
|
|
unset($session['partialLogin']); |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
/** |
320
|
|
|
* Sets the post-login redirect |
321
|
|
|
*/ |
322
|
|
|
public static function setPostLoginRedirect() |
323
|
|
|
{ |
324
|
|
|
$session = &self::$globalStateProvider->getSessionSuperGlobal(); |
325
|
|
|
$session['returnTo'] = self::requestUri(); |
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
/** |
329
|
|
|
* @return string|null |
330
|
|
|
*/ |
331
|
|
View Code Duplication |
public static function requestUri() |
|
|
|
|
332
|
|
|
{ |
333
|
|
|
$server = &self::$globalStateProvider->getServerSuperGlobal(); |
334
|
|
|
|
335
|
|
|
if (isset($server['REQUEST_URI'])) { |
336
|
|
|
return $server['REQUEST_URI']; |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
return null; |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
/** |
343
|
|
|
* Clears the post-login redirect |
344
|
|
|
* @return string |
345
|
|
|
*/ |
346
|
|
|
public static function clearPostLoginRedirect() |
347
|
|
|
{ |
348
|
|
|
$session = &self::$globalStateProvider->getSessionSuperGlobal(); |
349
|
|
|
if (array_key_exists('returnTo', $session)) { |
350
|
|
|
$path = $session['returnTo']; |
351
|
|
|
unset($session['returnTo']); |
352
|
|
|
|
353
|
|
|
return $path; |
354
|
|
|
} |
355
|
|
|
|
356
|
|
|
return null; |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
/** |
360
|
|
|
* @return string|null |
361
|
|
|
*/ |
362
|
|
View Code Duplication |
public static function serverName() |
|
|
|
|
363
|
|
|
{ |
364
|
|
|
$server = &self::$globalStateProvider->getServerSuperGlobal(); |
365
|
|
|
|
366
|
|
|
if (isset($server['SERVER_NAME'])) { |
367
|
|
|
return $server['SERVER_NAME']; |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
return null; |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
/** |
374
|
|
|
* You probably only want to deal with this through SessionAlert. |
375
|
|
|
* @return void |
376
|
|
|
*/ |
377
|
|
|
public static function clearSessionAlertData() |
378
|
|
|
{ |
379
|
|
|
$session = &self::$globalStateProvider->getSessionSuperGlobal(); |
380
|
|
|
if (array_key_exists('alerts', $session)) { |
381
|
|
|
unset($session['alerts']); |
382
|
|
|
} |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* You probably only want to deal with this through SessionAlert. |
387
|
|
|
* |
388
|
|
|
* @return string[] |
389
|
|
|
*/ |
390
|
|
|
public static function getSessionAlertData() |
391
|
|
|
{ |
392
|
|
|
$session = &self::$globalStateProvider->getSessionSuperGlobal(); |
393
|
|
|
if (array_key_exists('alerts', $session)) { |
394
|
|
|
return $session['alerts']; |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
return array(); |
398
|
|
|
} |
399
|
|
|
|
400
|
|
|
/** |
401
|
|
|
* You probably only want to deal with this through SessionAlert. |
402
|
|
|
* |
403
|
|
|
* @param string[] $data |
404
|
|
|
*/ |
405
|
|
|
public static function setSessionAlertData($data) |
406
|
|
|
{ |
407
|
|
|
$session = &self::$globalStateProvider->getSessionSuperGlobal(); |
408
|
|
|
$session['alerts'] = $data; |
409
|
|
|
} |
410
|
|
|
|
411
|
|
|
/** |
412
|
|
|
* You probably only want to deal with this through TokenManager. |
413
|
|
|
* |
414
|
|
|
* @return string[] |
415
|
|
|
*/ |
416
|
|
|
public static function getSessionTokenData() |
417
|
|
|
{ |
418
|
|
|
$session = &self::$globalStateProvider->getSessionSuperGlobal(); |
419
|
|
|
if (array_key_exists('tokens', $session)) { |
420
|
|
|
return $session['tokens']; |
421
|
|
|
} |
422
|
|
|
|
423
|
|
|
return array(); |
424
|
|
|
} |
425
|
|
|
|
426
|
|
|
/** |
427
|
|
|
* You probably only want to deal with this through TokenManager. |
428
|
|
|
* |
429
|
|
|
* @param string[] $data |
430
|
|
|
*/ |
431
|
|
|
public static function setSessionTokenData($data) |
432
|
|
|
{ |
433
|
|
|
$session = &self::$globalStateProvider->getSessionSuperGlobal(); |
434
|
|
|
$session['tokens'] = $data; |
435
|
|
|
} |
436
|
|
|
|
437
|
|
|
/** |
438
|
|
|
* @param string $key |
439
|
|
|
* |
440
|
|
|
* @return mixed |
441
|
|
|
*/ |
442
|
|
|
public static function getSessionContext($key) |
443
|
|
|
{ |
444
|
|
|
$session = &self::$globalStateProvider->getSessionSuperGlobal(); |
445
|
|
|
|
446
|
|
|
if (!isset($session['context'])) { |
447
|
|
|
$session['context'] = array(); |
448
|
|
|
} |
449
|
|
|
|
450
|
|
|
if (!isset($session['context'][$key])) { |
451
|
|
|
return null; |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
return $session['context'][$key]; |
455
|
|
|
} |
456
|
|
|
|
457
|
|
|
/** |
458
|
|
|
* @param string $key |
459
|
|
|
* @param mixed $data |
460
|
|
|
*/ |
461
|
|
|
public static function setSessionContext($key, $data) |
462
|
|
|
{ |
463
|
|
|
$session = &self::$globalStateProvider->getSessionSuperGlobal(); |
464
|
|
|
|
465
|
|
|
if (!isset($session['context'])) { |
466
|
|
|
$session['context'] = array(); |
467
|
|
|
} |
468
|
|
|
|
469
|
|
|
$session['context'][$key] = $data; |
470
|
|
|
} |
471
|
|
|
|
472
|
|
|
/** |
473
|
|
|
* @return int|null |
474
|
|
|
*/ |
475
|
|
|
public static function getSessionUserId() |
476
|
|
|
{ |
477
|
|
|
$session = &self::$globalStateProvider->getSessionSuperGlobal(); |
478
|
|
|
|
479
|
|
|
return isset($session['userID']) ? (int)$session['userID'] : null; |
480
|
|
|
} |
481
|
|
|
|
482
|
|
|
/** |
483
|
|
|
* @param User $user |
484
|
|
|
*/ |
485
|
|
|
public static function setPartialLogin(User $user) |
486
|
|
|
{ |
487
|
|
|
$session = &self::$globalStateProvider->getSessionSuperGlobal(); |
488
|
|
|
$session['partialLogin'] = $user->getId(); |
489
|
|
|
} |
490
|
|
|
|
491
|
|
|
/** |
492
|
|
|
* @return int|null |
493
|
|
|
*/ |
494
|
|
|
public static function getPartialLogin() |
495
|
|
|
{ |
496
|
|
|
$session = &self::$globalStateProvider->getSessionSuperGlobal(); |
497
|
|
|
|
498
|
|
|
return isset($session['partialLogin']) ? (int)$session['partialLogin'] : null; |
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
/** |
502
|
|
|
* @return null|string |
503
|
|
|
*/ |
504
|
|
View Code Duplication |
public static function userAgent() |
|
|
|
|
505
|
|
|
{ |
506
|
|
|
$server = &self::$globalStateProvider->getServerSuperGlobal(); |
507
|
|
|
|
508
|
|
|
if (isset($server['HTTP_USER_AGENT'])) { |
509
|
|
|
return $server['HTTP_USER_AGENT']; |
510
|
|
|
} |
511
|
|
|
|
512
|
|
|
return null; |
513
|
|
|
} |
514
|
|
|
|
515
|
|
|
/** |
516
|
|
|
* @return null|string |
517
|
|
|
*/ |
518
|
|
View Code Duplication |
public static function scriptName() |
|
|
|
|
519
|
|
|
{ |
520
|
|
|
$server = &self::$globalStateProvider->getServerSuperGlobal(); |
521
|
|
|
|
522
|
|
|
if (isset($server['SCRIPT_NAME'])) { |
523
|
|
|
return $server['SCRIPT_NAME']; |
524
|
|
|
} |
525
|
|
|
|
526
|
|
|
return null; |
527
|
|
|
} |
528
|
|
|
|
529
|
|
|
/** |
530
|
|
|
* @return null|string |
531
|
|
|
*/ |
532
|
|
View Code Duplication |
public static function origin() |
|
|
|
|
533
|
|
|
{ |
534
|
|
|
$server = &self::$globalStateProvider->getServerSuperGlobal(); |
535
|
|
|
|
536
|
|
|
if (isset($server['HTTP_ORIGIN'])) { |
537
|
|
|
return $server['HTTP_ORIGIN']; |
538
|
|
|
} |
539
|
|
|
|
540
|
|
|
return null; |
541
|
|
|
} |
542
|
|
|
} |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.