|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* Teampass - a collaborative passwords manager. |
|
4
|
|
|
* --- |
|
5
|
|
|
* This library is distributed in the hope that it will be useful, |
|
6
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
7
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
8
|
|
|
* --- |
|
9
|
|
|
* @project Teampass |
|
10
|
|
|
* @file upgrade_operations.php |
|
11
|
|
|
* --- |
|
12
|
|
|
* @author Nils Laumaillé ([email protected]) |
|
13
|
|
|
* @copyright 2009-2023 Teampass.net |
|
14
|
|
|
* @license https://spdx.org/licenses/GPL-3.0-only.html#licenseText GPL-3.0 |
|
15
|
|
|
* --- |
|
16
|
|
|
* @see https://www.teampass.net |
|
17
|
|
|
*/ |
|
18
|
|
|
|
|
19
|
|
|
use EZimuel\PHPSecureSession; |
|
20
|
|
|
use TeampassClasses\SuperGlobal\SuperGlobal; |
|
21
|
|
|
use TeampassClasses\Language\Language; |
|
22
|
|
|
use PasswordLib\PasswordLib; |
|
23
|
|
|
|
|
24
|
|
|
// Load functions |
|
25
|
|
|
require_once __DIR__.'/../sources/main.functions.php'; |
|
26
|
|
|
|
|
27
|
|
|
// init |
|
28
|
|
|
loadClasses('DB'); |
|
29
|
|
|
$superGlobal = new SuperGlobal(); |
|
30
|
|
|
$lang = new Language(); |
|
31
|
|
|
session_name('teampass_session'); |
|
32
|
|
|
session_start(); |
|
33
|
|
|
error_reporting(E_ERROR | E_PARSE); |
|
34
|
|
|
set_time_limit(600); |
|
35
|
|
|
$_SESSION['CPM'] = 1; |
|
36
|
|
|
|
|
37
|
|
|
//include librairies |
|
38
|
|
|
require_once __DIR__.'/../includes/language/english.php'; |
|
39
|
|
|
require_once __DIR__.'/../includes/config/include.php'; |
|
40
|
|
|
require_once __DIR__.'/../includes/config/settings.php'; |
|
41
|
|
|
require_once __DIR__.'/tp.functions.php'; |
|
42
|
|
|
require_once __DIR__.'/libs/aesctr.php'; |
|
43
|
|
|
require_once __DIR__.'/../includes/config/tp.config.php'; |
|
44
|
|
|
|
|
45
|
|
|
// Prepare POST variables |
|
46
|
|
|
$post_nb = filter_input(INPUT_POST, 'nb', FILTER_SANITIZE_NUMBER_INT); |
|
47
|
|
|
$post_start = filter_input(INPUT_POST, 'start', FILTER_SANITIZE_NUMBER_INT); |
|
48
|
|
|
|
|
49
|
|
|
// Load libraries |
|
50
|
|
|
$superGlobal = new SuperGlobal(); |
|
51
|
|
|
$lang = new Language(); |
|
52
|
|
|
|
|
53
|
|
|
// Some init |
|
54
|
|
|
$_SESSION['settings']['loaded'] = ''; |
|
55
|
|
|
$finish = true; |
|
56
|
|
|
|
|
57
|
|
|
// Get the encrypted password |
|
58
|
|
|
define('DB_PASSWD_CLEAR', defuse_return_decrypted(DB_PASSWD)); |
|
59
|
|
|
|
|
60
|
|
|
// DataBase |
|
61
|
|
|
// Test DB connexion |
|
62
|
|
|
$pass = DB_PASSWD_CLEAR; |
|
63
|
|
|
$server = DB_HOST; |
|
64
|
|
|
$pre = DB_PREFIX; |
|
65
|
|
|
$database = DB_NAME; |
|
66
|
|
|
$port = DB_PORT; |
|
67
|
|
|
$user = DB_USER; |
|
68
|
|
|
|
|
69
|
|
|
if (mysqli_connect( |
|
|
|
|
|
|
70
|
|
|
$server, |
|
71
|
|
|
$user, |
|
72
|
|
|
$pass, |
|
73
|
|
|
$database, |
|
74
|
|
|
$port |
|
|
|
|
|
|
75
|
|
|
)) { |
|
76
|
|
|
$db_link = mysqli_connect( |
|
77
|
|
|
$server, |
|
78
|
|
|
$user, |
|
79
|
|
|
$pass, |
|
80
|
|
|
$database, |
|
81
|
|
|
$port |
|
82
|
|
|
); |
|
83
|
|
|
} else { |
|
84
|
|
|
$res = 'Impossible to get connected to server. Error is: ' . addslashes(mysqli_connect_error()); |
|
85
|
|
|
echo '[{"finish":"1", "msg":"", "error":"Impossible to get connected to server. Error is: ' . addslashes(mysqli_connect_error()) . '!"}]'; |
|
86
|
|
|
mysqli_close($db_link); |
|
87
|
|
|
exit(); |
|
88
|
|
|
} |
|
89
|
|
|
|
|
90
|
|
|
// Get POST with operation to perform |
|
91
|
|
|
$post_operation = filter_input(INPUT_POST, 'type', FILTER_SANITIZE_FULL_SPECIAL_CHARS); |
|
92
|
|
|
|
|
93
|
|
|
if (isset($post_operation) === true && empty($post_operation) === false && strpos($post_operation, 'step') === false) { |
|
94
|
|
|
if ($post_operation === '20230604_1') { |
|
95
|
|
|
// ----> |
|
96
|
|
|
// OPERATION - 20230604_1 - generate key for item_key |
|
97
|
|
|
|
|
98
|
|
|
// Get items to treat |
|
99
|
|
|
$rows = mysqli_query( |
|
100
|
|
|
$db_link, |
|
101
|
|
|
"SELECT id FROM ".$pre."items |
|
102
|
|
|
WHERE item_key = '-1' |
|
103
|
|
|
ORDER BY id |
|
104
|
|
|
LIMIT ".$post_nb.";" |
|
105
|
|
|
); |
|
106
|
|
|
// Handle error on query |
|
107
|
|
|
if (!$rows) { |
|
108
|
|
|
echo '[{"finish":"1" , "error":"'.mysqli_error($db_link).'"}]'; |
|
109
|
|
|
exit(); |
|
110
|
|
|
} |
|
111
|
|
|
|
|
112
|
|
|
// Get total of items to treat |
|
113
|
|
|
$total = mysqli_num_rows($rows); |
|
|
|
|
|
|
114
|
|
|
|
|
115
|
|
|
// Loop on items and update for requested ones |
|
116
|
|
|
if ((int) $total > 0) { |
|
117
|
|
|
while ($row = mysqli_fetch_array($rows, MYSQLI_ASSOC)) { |
|
|
|
|
|
|
118
|
|
|
// Gererate a key and update |
|
119
|
|
|
mysqli_query( |
|
120
|
|
|
$db_link, |
|
121
|
|
|
"UPDATE `".$pre."items` |
|
122
|
|
|
SET `item_key` = '".uniqidReal(50)."' |
|
123
|
|
|
WHERE `id` = ".$row['id'].";" |
|
124
|
|
|
); |
|
125
|
|
|
if (mysqli_error($db_link)) { |
|
126
|
|
|
echo '[{"finish":"1", "next":"", "error":"MySQL Error! '.addslashes(mysqli_error($db_link)).'"}]'; |
|
127
|
|
|
exit(); |
|
128
|
|
|
} |
|
129
|
|
|
} |
|
130
|
|
|
} |
|
131
|
|
|
|
|
132
|
|
|
// Manage end of operation |
|
133
|
|
|
if ($total === 0) { |
|
134
|
|
|
$finish = 1; |
|
135
|
|
|
} else { |
|
136
|
|
|
$finish = 0; |
|
137
|
|
|
} |
|
138
|
|
|
// ----< |
|
139
|
|
|
} elseif ($post_operation === 'populateItemsTable_CreatedAt') { |
|
140
|
|
|
$finish = populateItemsTable_CreatedAt($pre, $post_nb); |
|
141
|
|
|
} elseif ($post_operation === 'populateItemsTable_UpdatedAt') { |
|
142
|
|
|
$finish = populateItemsTable_UpdatedAt($pre); |
|
143
|
|
|
} elseif ($post_operation === 'populateItemsTable_DeletedAt') { |
|
144
|
|
|
$finish = populateItemsTable_DeletedAt($pre); |
|
145
|
|
|
} elseif ($post_operation === '20231017_1') { |
|
146
|
|
|
// ----> |
|
147
|
|
|
// OPERATION - 20231017_1 - remove all existing keys |
|
148
|
|
|
// if item is personal and user is not owner |
|
149
|
|
|
|
|
150
|
|
|
installPurgeUnnecessaryKeys(true, 0,$pre); |
|
151
|
|
|
} |
|
152
|
|
|
// Return back |
|
153
|
|
|
echo '[{"finish":"'.$finish.'" , "next":"", "error":"", "total":"'.$total.'"}]'; |
|
|
|
|
|
|
154
|
|
|
} |
|
155
|
|
|
|
|
156
|
|
|
|
|
157
|
|
|
function populateItemsTable_CreatedAt($pre, $post_nb) |
|
158
|
|
|
{ |
|
159
|
|
|
global $db_link; |
|
160
|
|
|
// loop on items - created_at |
|
161
|
|
|
$items = mysqli_query( |
|
162
|
|
|
$db_link, |
|
163
|
|
|
"select i.id as id, ls.date as datetime |
|
164
|
|
|
from `" . $pre . "items` as i |
|
165
|
|
|
inner join `" . $pre . "log_items` as ls on ls.id_item = i.id |
|
166
|
|
|
WHERE ls.action = 'at_creation' AND i.created_at IS NULL |
|
167
|
|
|
LIMIT " . $post_nb.";" |
|
168
|
|
|
); |
|
169
|
|
|
while ($item = mysqli_fetch_assoc($items)) { |
|
|
|
|
|
|
170
|
|
|
if (empty((string) $item['datetime']) === false && is_null($item['datetime']) === false) { |
|
171
|
|
|
// update created_at field |
|
172
|
|
|
mysqli_query( |
|
173
|
|
|
$db_link, |
|
174
|
|
|
"UPDATE `" . $pre . "items` SET created_at = '".$item['datetime']."' WHERE id = ".$item['id'] |
|
175
|
|
|
); |
|
176
|
|
|
} |
|
177
|
|
|
} |
|
178
|
|
|
|
|
179
|
|
|
// Is it finished? |
|
180
|
|
|
$remainingItems = mysqli_num_rows( |
|
181
|
|
|
mysqli_query( |
|
|
|
|
|
|
182
|
|
|
$db_link, |
|
183
|
|
|
"SELECT * FROM `" . $pre . "items` WHERE created_at IS NULL" |
|
184
|
|
|
) |
|
185
|
|
|
); |
|
186
|
|
|
return $remainingItems > 0 ? 0 : 1; |
|
187
|
|
|
} |
|
188
|
|
|
|
|
189
|
|
|
function populateItemsTable_UpdatedAt($pre) |
|
190
|
|
|
{ |
|
191
|
|
|
global $db_link; |
|
192
|
|
|
// loop on items - updated_at |
|
193
|
|
|
$items = mysqli_query( |
|
194
|
|
|
$db_link, |
|
195
|
|
|
"select i.id as id, (select date from " . $pre . "log_items where action = 'at_modification' and id_item=id order by date DESC limit 1) as datetime |
|
196
|
|
|
from `" . $pre . "items` as i;" |
|
197
|
|
|
); |
|
198
|
|
|
while ($item = mysqli_fetch_assoc($items)) { |
|
|
|
|
|
|
199
|
|
|
if (is_null($item['datetime']) === false) { |
|
200
|
|
|
// update updated_at field |
|
201
|
|
|
mysqli_query( |
|
202
|
|
|
$db_link, |
|
203
|
|
|
"UPDATE `" . $pre . "items` SET updated_at = '".$item['datetime']."' WHERE id = ".$item['id'] |
|
204
|
|
|
); |
|
205
|
|
|
} |
|
206
|
|
|
} |
|
207
|
|
|
|
|
208
|
|
|
return 1; |
|
209
|
|
|
} |
|
210
|
|
|
|
|
211
|
|
|
function populateItemsTable_DeletedAt($pre) |
|
212
|
|
|
{ |
|
213
|
|
|
global $db_link; |
|
214
|
|
|
// loop on items - deleted_at |
|
215
|
|
|
$items = mysqli_query( |
|
216
|
|
|
$db_link, |
|
217
|
|
|
"select i.id as id, (select date from " . $pre . "log_items where action = 'at_deleted' and id_item=id order by date DESC limit 1) as datetime |
|
218
|
|
|
from `" . $pre . "items` as i;" |
|
219
|
|
|
); |
|
220
|
|
|
while ($item = mysqli_fetch_assoc($items)) { |
|
|
|
|
|
|
221
|
|
|
if (is_null($item['datetime']) === false) { |
|
222
|
|
|
// update updated_at field |
|
223
|
|
|
mysqli_query( |
|
224
|
|
|
$db_link, |
|
225
|
|
|
"UPDATE `" . $pre . "items` SET deleted_at = '".$item['datetime']."' WHERE id = ".$item['id'] |
|
226
|
|
|
); |
|
227
|
|
|
} |
|
228
|
|
|
} |
|
229
|
|
|
|
|
230
|
|
|
return 1; |
|
231
|
|
|
} |
|
232
|
|
|
|
|
233
|
|
|
|
|
234
|
|
|
/** |
|
235
|
|
|
* Delete unnecessary keys for personal items |
|
236
|
|
|
* |
|
237
|
|
|
* @param boolean $allUsers |
|
238
|
|
|
* @param integer $user_id |
|
239
|
|
|
* @return void |
|
240
|
|
|
*/ |
|
241
|
|
|
function installPurgeUnnecessaryKeys(bool $allUsers = true, int $user_id=0, string $pre) |
|
242
|
|
|
{ |
|
243
|
|
|
global $db_link; |
|
244
|
|
|
if ($allUsers === true) { |
|
245
|
|
|
$users = mysqli_query( |
|
246
|
|
|
$db_link, |
|
247
|
|
|
'SELECT id |
|
248
|
|
|
FROM ' . $pre . 'users |
|
249
|
|
|
WHERE id NOT IN ('.OTV_USER_ID.', '.TP_USER_ID.', '.SSH_USER_ID.', '.API_USER_ID.') |
|
250
|
|
|
ORDER BY login ASC' |
|
251
|
|
|
); |
|
252
|
|
|
while ($user = mysqli_fetch_assoc($users)) { |
|
|
|
|
|
|
253
|
|
|
installPurgeUnnecessaryKeysForUser((int) $user['id'], $pre); |
|
254
|
|
|
} |
|
255
|
|
|
} else { |
|
256
|
|
|
installPurgeUnnecessaryKeysForUser((int) $user_id, $pre); |
|
257
|
|
|
} |
|
258
|
|
|
} |
|
259
|
|
|
|
|
260
|
|
|
/** |
|
261
|
|
|
* Delete unnecessary keys for personal items |
|
262
|
|
|
* |
|
263
|
|
|
* @param integer $user_id |
|
264
|
|
|
* @return void |
|
265
|
|
|
*/ |
|
266
|
|
|
function installPurgeUnnecessaryKeysForUser(int $user_id=0, string $pre) |
|
267
|
|
|
{ |
|
268
|
|
|
global $db_link; |
|
269
|
|
|
if ($user_id === 0) { |
|
270
|
|
|
return; |
|
271
|
|
|
} |
|
272
|
|
|
|
|
273
|
|
|
$result = mysqli_query( |
|
274
|
|
|
$db_link, |
|
275
|
|
|
'SELECT id |
|
276
|
|
|
FROM ' . $pre . 'items AS i |
|
277
|
|
|
INNER JOIN ' . $pre . 'log_items AS li ON li.id_item = i.id |
|
278
|
|
|
WHERE i.perso = 1 AND li.action = "at_creation" AND li.id_user IN ('.TP_USER_ID.', '.$user_id.')', |
|
279
|
|
|
); |
|
280
|
|
|
$rowcount = mysqli_num_rows($result); |
|
|
|
|
|
|
281
|
|
|
if ($rowcount > 0) { |
|
282
|
|
|
// Build list of items id |
|
283
|
|
|
$pfItemsList = []; |
|
284
|
|
|
while ($row = mysqli_fetch_assoc($result)) { |
|
|
|
|
|
|
285
|
|
|
array_push($pfItemsList, $row['id']); |
|
286
|
|
|
} |
|
287
|
|
|
|
|
288
|
|
|
/*$personalItem = mysqli_fetch_column($result, 0);*/ |
|
289
|
|
|
$pfItemsList = implode(',', $pfItemsList); |
|
290
|
|
|
// Item keys |
|
291
|
|
|
mysqli_query( |
|
292
|
|
|
$db_link, |
|
293
|
|
|
'DELETE FROM ' . $pre . 'sharekeys_items |
|
294
|
|
|
WHERE object_id IN ('.$pfItemsList.') AND user_id NOT IN ('.TP_USER_ID.', '.$user_id.')' |
|
295
|
|
|
); |
|
296
|
|
|
// Files keys |
|
297
|
|
|
mysqli_query( |
|
298
|
|
|
$db_link, |
|
299
|
|
|
'DELETE FROM ' . $pre . 'sharekeys_files |
|
300
|
|
|
WHERE object_id IN ('.$pfItemsList.') AND user_id NOT IN ('.TP_USER_ID.', '.$user_id.')' |
|
301
|
|
|
); |
|
302
|
|
|
// Fields keys |
|
303
|
|
|
mysqli_query( |
|
304
|
|
|
$db_link, |
|
305
|
|
|
'DELETE FROM ' . $pre . 'sharekeys_fields |
|
306
|
|
|
WHERE object_id IN ('.$pfItemsList.') AND user_id NOT IN ('.TP_USER_ID.', '.$user_id.')' |
|
307
|
|
|
); |
|
308
|
|
|
// Logs keys |
|
309
|
|
|
mysqli_query( |
|
310
|
|
|
$db_link, |
|
311
|
|
|
'DELETE FROM ' . $pre . 'sharekeys_logs |
|
312
|
|
|
WHERE object_id IN ('.$pfItemsList.') AND user_id NOT IN ('.TP_USER_ID.', '.$user_id.')' |
|
313
|
|
|
); |
|
314
|
|
|
} |
|
315
|
|
|
} |
|
316
|
|
|
|
|
317
|
|
|
|
|
318
|
|
|
/** |
|
319
|
|
|
* Permits to refresh the categories of folders |
|
320
|
|
|
* |
|
321
|
|
|
* @param array $folderIds |
|
322
|
|
|
* @return void |
|
323
|
|
|
*/ |
|
324
|
|
|
function installHandleFoldersCategories( |
|
325
|
|
|
array $folderIds, $pre |
|
|
|
|
|
|
326
|
|
|
) |
|
327
|
|
|
{ |
|
328
|
|
|
global $db_link; |
|
329
|
|
|
$filename = '../includes/config/settings.php'; |
|
|
|
|
|
|
330
|
|
|
include_once '../sources/main.functions.php'; |
|
331
|
|
|
$pass = defuse_return_decrypted(DB_PASSWD); |
|
332
|
|
|
$server = DB_HOST; |
|
333
|
|
|
$pre = DB_PREFIX; |
|
334
|
|
|
$database = DB_NAME; |
|
335
|
|
|
$port = intval(DB_PORT); |
|
336
|
|
|
$user = DB_USER; |
|
337
|
|
|
$arr_data = array(); |
|
338
|
|
|
$mysqli2 = new mysqli($server, $user, $pass, $database, $port); |
|
339
|
|
|
|
|
340
|
|
|
// force full list of folders |
|
341
|
|
|
if (count($folderIds) === 0) { |
|
342
|
|
|
$result = $mysqli2->query('SELECT id |
|
343
|
|
|
FROM ' . $pre . 'nested_tree |
|
344
|
|
|
WHERE personal_folder = 0', |
|
345
|
|
|
); |
|
346
|
|
|
$rowcount = $result->num_rows; |
|
347
|
|
|
if ($rowcount > 0) { |
|
348
|
|
|
while ($row = $result->fetch_assoc()) { |
|
349
|
|
|
array_push($folderIds, $row['id']); |
|
350
|
|
|
} |
|
351
|
|
|
} |
|
352
|
|
|
} |
|
353
|
|
|
|
|
354
|
|
|
// Get complexity |
|
355
|
|
|
defineComplexity(); |
|
356
|
|
|
|
|
357
|
|
|
// update |
|
358
|
|
|
foreach ($folderIds as $folder) { |
|
359
|
|
|
// Do we have Categories |
|
360
|
|
|
// get list of associated Categories |
|
361
|
|
|
$arrCatList = array(); |
|
362
|
|
|
$result = $mysqli2->query('SELECT c.id, c.title, c.level, c.type, c.masked, c.order, c.encrypted_data, c.role_visibility, c.is_mandatory, |
|
363
|
|
|
f.id_category AS category_id |
|
364
|
|
|
FROM ' . $pre . 'categories_folders AS f |
|
365
|
|
|
INNER JOIN ' . $pre . 'categories AS c ON (f.id_category = c.parent_id) |
|
366
|
|
|
WHERE id_folder = '.$folder |
|
367
|
|
|
); |
|
368
|
|
|
$rowcount = $result->num_rows; |
|
369
|
|
|
if ($rowcount > 0) { |
|
370
|
|
|
while ($row = $result->fetch_assoc()) { |
|
371
|
|
|
$arrCatList[$row['id']] = array( |
|
372
|
|
|
'id' => $row['id'], |
|
373
|
|
|
'title' => $row['title'], |
|
374
|
|
|
'level' => $row['level'], |
|
375
|
|
|
'type' => $row['type'], |
|
376
|
|
|
'masked' => $row['masked'], |
|
377
|
|
|
'order' => $row['order'], |
|
378
|
|
|
'encrypted_data' => $row['encrypted_data'], |
|
379
|
|
|
'role_visibility' => $row['role_visibility'], |
|
380
|
|
|
'is_mandatory' => $row['is_mandatory'], |
|
381
|
|
|
'category_id' => $row['category_id'], |
|
382
|
|
|
); |
|
383
|
|
|
} |
|
384
|
|
|
} |
|
385
|
|
|
$arr_data['categories'] = $arrCatList; |
|
386
|
|
|
|
|
387
|
|
|
// Now get complexity |
|
388
|
|
|
$valTemp = ''; |
|
389
|
|
|
$result = $mysqli2->query('SELECT valeur |
|
390
|
|
|
FROM ' . $pre . 'misc |
|
391
|
|
|
WHERE type = "complex" AND intitule = '.$folder |
|
392
|
|
|
); |
|
393
|
|
|
$rowcount = $result->num_rows; |
|
394
|
|
|
if ($rowcount > 0) { |
|
395
|
|
|
while ($row = $result->fetch_assoc()) { |
|
396
|
|
|
$valTemp = array( |
|
397
|
|
|
'value' => $row['valeur'], |
|
398
|
|
|
'text' => TP_PW_COMPLEXITY[$row['valeur']][1], |
|
399
|
|
|
); |
|
400
|
|
|
} |
|
401
|
|
|
} |
|
402
|
|
|
$arr_data['complexity'] = $valTemp; |
|
403
|
|
|
|
|
404
|
|
|
// Now get Roles |
|
405
|
|
|
$valTemp = ''; |
|
406
|
|
|
$result = $mysqli2->query('SELECT t.title |
|
407
|
|
|
FROM ' . $pre . 'roles_values as v |
|
408
|
|
|
INNER JOIN ' . $pre . 'roles_title as t ON (v.role_id = t.id) |
|
409
|
|
|
WHERE v.folder_id = '.$folder.' |
|
410
|
|
|
GROUP BY title' |
|
411
|
|
|
); |
|
412
|
|
|
$rowcount = $result->num_rows; |
|
413
|
|
|
if ($rowcount > 0) { |
|
414
|
|
|
while ($row = $result->fetch_assoc()) { |
|
415
|
|
|
$valTemp .= (empty($valTemp) === true ? '' : ' - ') . $row['title']; |
|
416
|
|
|
} |
|
417
|
|
|
} |
|
418
|
|
|
$arr_data['visibilityRoles'] = $valTemp; |
|
419
|
|
|
|
|
420
|
|
|
// now save in DB |
|
421
|
|
|
$mysqli2->query("UPDATE " . $pre . "nested_tree SET categories = '".json_encode($arr_data)."' WHERE id = ".$folder); |
|
422
|
|
|
} |
|
423
|
|
|
|
|
424
|
|
|
mysqli_close($mysqli2); |
|
425
|
|
|
} |
|
426
|
|
|
|
|
427
|
|
|
/** |
|
428
|
|
|
* Permits to handle the Teampass config file |
|
429
|
|
|
* $action accepts "rebuild" and "update" |
|
430
|
|
|
* |
|
431
|
|
|
* @param string $action Action to perform |
|
432
|
|
|
* @param array $SETTINGS Teampass settings |
|
433
|
|
|
* @param string $field Field to refresh |
|
434
|
|
|
* @param string $value Value to set |
|
435
|
|
|
* |
|
436
|
|
|
* @return string|bool |
|
437
|
|
|
*/ |
|
438
|
|
|
function installHandleConfigFile($action, $SETTINGS, $field = null, $value = null) |
|
439
|
|
|
{ |
|
440
|
|
|
$tp_config_file = $SETTINGS['cpassman_dir'] . '/includes/config/tp.config.php'; |
|
441
|
|
|
$filename = '../includes/config/settings.php'; |
|
|
|
|
|
|
442
|
|
|
include_once '../sources/main.functions.php'; |
|
443
|
|
|
$pass = defuse_return_decrypted(DB_PASSWD); |
|
444
|
|
|
$server = DB_HOST; |
|
445
|
|
|
$pre = DB_PREFIX; |
|
446
|
|
|
$database = DB_NAME; |
|
447
|
|
|
$port = intval(DB_PORT); |
|
448
|
|
|
$user = DB_USER; |
|
449
|
|
|
$arr_data = array(); |
|
|
|
|
|
|
450
|
|
|
$mysqli2 = new mysqli($server, $user, $pass, $database, $port); |
|
451
|
|
|
|
|
452
|
|
|
if (file_exists($tp_config_file) === false || $action === 'rebuild') { |
|
453
|
|
|
// perform a copy |
|
454
|
|
|
if (file_exists($tp_config_file)) { |
|
455
|
|
|
if (! copy($tp_config_file, $tp_config_file . '.' . date('Y_m_d_His', time()))) { |
|
456
|
|
|
return "ERROR: Could not copy file '" . $tp_config_file . "'"; |
|
457
|
|
|
} |
|
458
|
|
|
} |
|
459
|
|
|
|
|
460
|
|
|
// regenerate |
|
461
|
|
|
$data = []; |
|
462
|
|
|
$data[0] = "<?php\n"; |
|
463
|
|
|
$data[1] = "global \$SETTINGS;\n"; |
|
464
|
|
|
$data[2] = "\$SETTINGS = array (\n"; |
|
465
|
|
|
|
|
466
|
|
|
$result = $mysqli2->query('SELECT * |
|
467
|
|
|
FROM ' . $pre . 'misc |
|
468
|
|
|
WHERE type = "admin"' |
|
469
|
|
|
); |
|
470
|
|
|
$rowcount = $result->num_rows; |
|
471
|
|
|
if ($rowcount > 0) { |
|
472
|
|
|
while ($row = $result->fetch_assoc()) { |
|
473
|
|
|
array_push($data, " '" . $row['intitule'] . "' => '" . htmlspecialchars_decode($row['valeur'], ENT_COMPAT) . "',\n"); |
|
474
|
|
|
} |
|
475
|
|
|
} |
|
476
|
|
|
array_push($data, ");\n"); |
|
477
|
|
|
$data = array_unique($data); |
|
478
|
|
|
// --- |
|
479
|
|
|
} elseif ($action === 'update' && empty($field) === false) { |
|
480
|
|
|
$data = file($tp_config_file); |
|
481
|
|
|
$inc = 0; |
|
482
|
|
|
$bFound = false; |
|
483
|
|
|
foreach ($data as $line) { |
|
484
|
|
|
if (stristr($line, ');')) { |
|
485
|
|
|
break; |
|
486
|
|
|
} |
|
487
|
|
|
|
|
488
|
|
|
if (stristr($line, "'" . $field . "' => '")) { |
|
489
|
|
|
$data[$inc] = " '" . $field . "' => '" . htmlspecialchars_decode($value ?? '', ENT_COMPAT) . "',\n"; |
|
490
|
|
|
$bFound = true; |
|
491
|
|
|
break; |
|
492
|
|
|
} |
|
493
|
|
|
++$inc; |
|
494
|
|
|
} |
|
495
|
|
|
if ($bFound === false) { |
|
496
|
|
|
$data[$inc] = " '" . $field . "' => '" . htmlspecialchars_decode($value ?? '', ENT_COMPAT). "',\n);\n"; |
|
497
|
|
|
} |
|
498
|
|
|
} |
|
499
|
|
|
mysqli_close($mysqli2); |
|
500
|
|
|
|
|
501
|
|
|
// update file |
|
502
|
|
|
file_put_contents($tp_config_file, implode('', $data ?? [])); |
|
503
|
|
|
return true; |
|
504
|
|
|
} |
This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.