-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinterface.php
More file actions
138 lines (125 loc) · 3.41 KB
/
interface.php
File metadata and controls
138 lines (125 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<?php
// pour le débuggage : affichage des erreurs + formatage du JSON
define('JSON_FLAGS', 0);
define('DEBUGGING', true);
// Mute PHP to prevent any unwanted output (such as warnings from core methods) from polluting the JSON response.
// the only way out of this script should be the function `response()` which takes
// care of closing the output buffer.
// `response()` will also include the silenced content into the response (for analysis) if DEBUGGING is true.
ob_start();
$get = $_GET['get'] ?? '';
$post = $_POST['post'] ?? '';
/**
* Note sur le nommage : les fonctions préfixées par _g_ ou _p_ ne retournent rien mais renvoient une réponse JSON :
* - _g_ = 'get' (lecture d’informations en base)
* - _p_ = 'post' (modifications en base : insert, delete, update…)
*/
if (!empty($get)) {
$funcname = '_g_' . $get;
if (function_exists($funcname)) call_user_func($funcname);
if (preg_match('/^level\d+$/', $get, $m)) {
_g_level($m[0]);
}
switch ($get) {
case 'level':
if (!isset($_GET['level'])) failureResponse('Specify level (int)');
$level = $_GET['level'];
if (!preg_match('/^level\d+$/', $level)) {
failureResponse('Level must be numeric');
}
_g_level($level);
break;
default:
if (function_exists('_g_' . $get)) {
call_user_func('_g_' . $get);
} else {
__unhandled($get);
}
break;
}
} elseif (!empty($post)) {
switch ($post) {
default:
__unhandled($post);
}
}
function _g_level($levelName) {
$maxSize = 200*1024; // 200 kB
if (preg_match('#[/]|\.\.#', $levelName)) failureResponse('Invalid level name');
$mdFilename = 'assets/levels/' . $levelName . '.md';
$jsFilename = 'assets/levels/' . $levelName . '.js';
if (filesize($mdFilename) + filesize($jsFilename) > $maxSize) {
failureResponse('The requested level files are suspiciously large (>100kB)');
}
successResponse([
'text' => file_get_contents($mdFilename),
'js' => (file_exists($jsFilename) ? $jsFilename : null),
]);
}
function _g_levels() {
$dir = 'assets/levels';
$dirHandle = opendir($dir);
$levels = [];
while (($file = readdir($dirHandle)) !== false) {
if (preg_match('/^(level\d+).md$/', $file, $m)) {
$levels[] = $m[1];
}
}
sort($levels);
successResponse($levels);
}
function __unhandled($post) {
failureResponse('Unhandled');
}
/**
* Wraps the payload in a json structure, prints it out and exits.
*
* @param mixed $payload Whatever the client-side code asked for
*/
function successResponse($payload)
{
response(
array(
//'error' => null,
'payload' => $payload,
)
);
}
/**
* Wraps the error message and debugging payload in a json structure,
* prints it out and exits.
*
* @param string $errorMessage Denial details or error description
* @param mixed $debugPayload Anything that might help with debugging
*/
function failureResponse($errorMessage, $debugPayload = null)
{
response(
array(
'error' => $errorMessage,
'debugging' => $debugPayload,
//'payload' => null,
)
);
}
/**
* Single way out for the interface: takes care of:
* - closing the output buffer
* - printing out the JSON-encoded content
* - embedding debugging information
* - exiting the script
* @param array $outArray
*/
function response($outArray)
{
header('Content-Type: text/json');
if (DEBUGGING) {
$outArray['__DEBUG'] = array(
'output_buffer' => ob_get_clean()
);
} else {
ob_end_clean();
}
echo json_encode($outArray, JSON_FLAGS);
exit;
}