-
-
Notifications
You must be signed in to change notification settings - Fork 419
Expand file tree
/
Copy pathutil.php
More file actions
executable file
·315 lines (255 loc) · 10.3 KB
/
Copy pathutil.php
File metadata and controls
executable file
·315 lines (255 loc) · 10.3 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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
<?php
//------------------------------------------------------------------------------
// NetAlertX
// Open Source Network Guard / WIFI & LAN intrusion detector
//
// util.php - Front module. Server side. Settings and utility functions
//------------------------------------------------------------------------------
# Puche 2021 / 2022+ jokob jokob@duck.com GNU GPLv3
//------------------------------------------------------------------------------
require dirname(__FILE__).'/../templates/globals.php';
require dirname(__FILE__).'/../templates/skinUI.php';
//------------------------------------------------------------------------------
// check if authenticated
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
$FUNCTION = [];
$SETTINGS = [];
// init request params
if(array_key_exists('function', $_REQUEST) != FALSE)
{
$FUNCTION = $_REQUEST['function'];
}
if(array_key_exists('settings', $_REQUEST) != FALSE)
{
$SETTINGS = $_REQUEST['settings'];
}
// call functions based on requested params
switch ($FUNCTION) {
case 'savesettings':
saveSettings();
break;
default:
// Handle any other cases or errors if needed
break;
}
// -------------------------------------------------------------------------------------------
function saveSettings()
{
global $SETTINGS, $FUNCTION, $config_file, $fullConfPath, $configFolderPath, $timestamp;
// save to the file
$new_name = $config_file.'_'.$timestamp.'.backup';
$new_location = $configFolderPath.'/'.$new_name;
if(file_exists( $fullConfPath) != 1)
{
displayInAppNoti('File "'.$fullConfPath.'" not found or missing read permissions. Creating a new config file.', 'warning');
}
// create a backup copy
elseif (!copy($fullConfPath, $new_location))
{
displayInAppNoti("Failed to copy file ".$fullConfPath." to ".$new_location." Check your permissions to allow read/write access to the /config folder.", 'error');
}
// generate a clean .conf file
$groups = [];
$txt = "";
$txt = $txt."#-----------------AUTOGENERATED FILE-----------------#\n";
$txt = $txt."# #\n";
$txt = $txt."# Generated: ".$timestamp." #\n";
$txt = $txt."# #\n";
$txt = $txt."# Config file for the LAN intruder detection app: #\n";
$txt = $txt."# https://github.com/netalertx/NetAlertX #\n";
$txt = $txt."# #\n";
$txt = $txt."#-----------------AUTOGENERATED FILE-----------------#\n";
// collect all groups
$decodedSettings = json_decode((string)$SETTINGS, true);
if ($decodedSettings === null) {
echo "Error: Invalid JSON in settings data.";
return;
}
foreach ($decodedSettings as $setting) {
if( in_array($setting[0] , $groups) == false) {
array_push($groups ,$setting[0]);
}
}
// go thru the groups and prepare settings to write to file
foreach ($groups as $group) {
$txt .= "\n\n# " . $group;
$txt .= "\n#---------------------------\n";
foreach ($decodedSettings as $setting) {
$settingGroup = $setting[0];
$setKey = $setting[1];
$dataType = $setting[2];
$settingValue = $setting[3];
// Sanity check
if($setKey == "UI_LANG" && $settingValue == "") {
echo "🔴 Error: important settings missing. Refresh the page with 🔃 on the top and try again.";
return;
}
if ($group == $settingGroup) {
if ($dataType == 'string' ) {
$val = encode_single_quotes($settingValue);
$txt .= $setKey . "='" . $val . "'\n";
} elseif ($dataType == 'integer') {
$txt .= $setKey . "=" . $settingValue . "\n";
} elseif ($dataType == 'none') {
$txt .= $setKey . "=''\n";
} elseif ($dataType == 'json') {
$txt .= $setKey . "=" . $settingValue . "\n";
} elseif ($dataType == 'boolean') {
$val = ($settingValue === true || $settingValue === 1 || strtolower($settingValue) === 'true') ? "True" : "False";
$txt .= $setKey . "=" . $val . "\n";
} elseif ($dataType == 'array' ) {
$temp = '';
if(is_array($settingValue) == FALSE)
{
$settingValue = json_decode($settingValue);
}
// skipping __metadata entries (?)
if (count($setting) > 3 && is_array($settingValue) == true) {
foreach ($settingValue as $val) {
$temp .= "'" . encode_single_quotes($val) . "',";
}
$temp = substr_replace($temp, "", -1); // remove last comma ','
}
$temp = '['.$temp.']'; // wrap brackets
$txt .= $setKey . "=" . $temp . "\n";
} else {
$txt .= $setKey . "='⭕Not handled⭕'\n";
}
}
}
}
$txt = $txt."\n\n";
$txt = $txt."#-------------------IMPORTANT INFO-------------------#\n";
$txt = $txt."# This file is ingested by a python script, so if #\n";
$txt = $txt."# modified it needs to use python syntax #\n";
$txt = $txt."#-------------------IMPORTANT INFO-------------------#\n";
// open new file and write the new configuration
// Backup the original file
if (file_exists($fullConfPath)) {
copy($fullConfPath, $fullConfPath . ".bak");
}
// Detect whether the frontend needs to block-wait for backend reload
$requiresReloadWait = getReloadWaitRequired($decodedSettings);
// Open the file for writing without changing permissions
$file = fopen($fullConfPath, "w") or die("Unable to open file!");
fwrite($file, $txt);
fclose($file);
echo json_encode(['success' => true, 'requiresReloadWait' => $requiresReloadWait]);
}
// -------------------------------------------------------------------------------------------
// Determines if the frontend must wait (block) for the backend to finish reloading after a
// settings save. Blocking is required when LOADED_PLUGINS changes or UI_WAIT_FOR_SETTINGS
// is explicitly enabled. Defaults to true (safe) on any parsing error.
function getReloadWaitRequired($decodedSettings) {
$newLoadedPlugins = null;
$uiWaitForSettings = false;
foreach ($decodedSettings as $setting) {
if ($setting[1] === 'LOADED_PLUGINS') {
$newLoadedPlugins = $setting[3];
}
if ($setting[1] === 'UI_WAIT_FOR_SETTINGS') {
$uiWaitForSettings = ($setting[3] === true || $setting[3] === 1
|| strtolower((string)$setting[3]) === 'true');
}
}
if ($uiWaitForSettings) {
return true;
}
$oldLoadedPlugins = getSettingValue('LOADED_PLUGINS');
// If the old value couldn't be read, default to blocking (safe).
if (strpos((string)$oldLoadedPlugins, 'Could not') !== false) {
return true;
}
return normalizePluginList($oldLoadedPlugins) !== normalizePluginList($newLoadedPlugins);
}
// -------------------------------------------------------------------------------------------
// Normalise a plugin list value (PHP array, JSON array, or Python-style list) to a sorted
// JSON string for reliable equality comparison.
function normalizePluginList($value) {
if ($value === null || $value === '') {
return '[]';
}
if (is_array($value)) {
$arr = $value;
} else {
$arr = json_decode($value, true);
if (!is_array($arr)) {
// Handle Python-style single-quoted lists: ['A','B']
$jsonStr = str_replace("'", '"', (string)$value);
$arr = json_decode($jsonStr, true);
}
if (!is_array($arr)) {
return trim((string)$value);
}
}
sort($arr);
return json_encode($arr);
}
// -------------------------------------------------------------------------------------------
// 🔺----- API ENDPOINTS SUPERSEDED -----🔺
// check server/api_server/api_server_start.py for equivalents
// equivalent: /settings/<key>
// 🔺----- API ENDPOINTS SUPERSEDED -----🔺
function getSettingValue($setKey) {
// Define the JSON endpoint URL
$apiRoot = rtrim(getenv('NETALERTX_API') ?: '/tmp/api', '/');
$url = $apiRoot . '/table_settings.json';
// Fetch the JSON data
$json = file_get_contents($url);
// Check if the JSON data was successfully fetched
if ($json === false) {
return 'Could not get json data';
}
// Decode the JSON data
$data = json_decode($json, true);
// Check if the JSON decoding was successful
if (json_last_error() !== JSON_ERROR_NONE) {
return 'Could not decode json data';
}
// Search for the setting by setKey
foreach ($data['data'] as $setting) {
if ($setting['setKey'] === $setKey) {
return $setting['setValue'];
}
}
// Return false if the setting was not found
return 'Could not find setting '.$setKey;
}
// -------------------------------------------------------------------------------------------
function encode_single_quotes ($val) {
$result = str_replace ('\'','{s-quote}',$val);
return $result;
}
// -------------------------------------------------------------------------------------------
// Helper function to send notifications via the backend API endpoint
// -------------------------------------------------------------------------------------------
function displayInAppNoti($message, $level = 'error') {
try {
$apiBase = getSettingValue('BACKEND_API_URL') ?: 'http://localhost:20212';
$apiToken = getSettingValue('API_TOKEN') ?: '';
if (empty($apiToken)) {
// If no token available, silently fail (don't break the application)
return;
}
$url = rtrim($apiBase, '/') . '/messaging/in-app/write';
$payload = json_encode([
'message' => $message,
'level' => $level
]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiToken,
'Content-Length: ' . strlen($payload)
]);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_exec($ch);
curl_close($ch);
} catch (Exception $e) {
// Silently fail if notification sending fails
}
}
?>