Passed
Push — master ( 028270...ec7243 )
by Nils
04:48
created

showFolderToUser()   A

Complexity

Conditions 5
Paths 2

Size

Total Lines 17
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 7
c 1
b 0
f 0
nc 2
nop 5
dl 0
loc 17
rs 9.6111
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Teampass - a collaborative passwords manager.
7
 * ---
8
 * This library is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * @project   Teampass
13
 * @file      tree.php
14
 *
15
 * @author    Nils Laumaillé ([email protected])
16
 * @copyright 2009-2022 Teampass.net
17
 * @license   https://spdx.org/licenses/GPL-3.0-only.html#licenseText GPL-3.0
18
 *
19
 * @see       https://www.teampass.net
20
 */
21
22
23
require_once 'SecureHandler.php';
24
session_name('teampass_session');
25
session_start();
26
if (
27
    isset($_SESSION['CPM']) === false
28
    || $_SESSION['CPM'] !== 1
29
    || isset($_SESSION['key']) === false
30
    || empty($_SESSION['key']) === true
31
) {
32
    die('Hacking attempt...');
33
}
34
35
// Load config
36
if (file_exists('../includes/config/tp.config.php')) {
37
    include_once '../includes/config/tp.config.php';
38
} elseif (file_exists('./includes/config/tp.config.php')) {
39
    include_once './includes/config/tp.config.php';
40
} else {
41
    throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
42
}
43
44
// includes
45
require_once $SETTINGS['cpassman_dir'] . '/includes/config/include.php';
46
require_once $SETTINGS['cpassman_dir'] . '/sources/SplClassLoader.php';
47
require_once $SETTINGS['cpassman_dir'] . '/sources/main.functions.php';
48
require_once $SETTINGS['cpassman_dir'] . '/includes/language/' . $_SESSION['user_language'] . '.php';
49
require_once $SETTINGS['cpassman_dir'] . '/includes/config/settings.php';
50
51
// header
52
header('Content-type: text/html; charset=utf-8');
53
header('Cache-Control: no-cache, must-revalidate');
54
55
// Define Timezone
56
if (isset($SETTINGS['timezone'])) {
57
    date_default_timezone_set($SETTINGS['timezone']);
58
} else {
59
    date_default_timezone_set('UTC');
60
}
61
62
// Connect to mysql server
63
require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Database/Meekrodb/db.class.php';
64
if (defined('DB_PASSWD_CLEAR') === false) {
65
    define('DB_PASSWD_CLEAR', defuseReturnDecrypted(DB_PASSWD, $SETTINGS));
66
}
67
DB::$host = DB_HOST;
68
DB::$user = DB_USER;
69
DB::$password = DB_PASSWD_CLEAR;
70
DB::$dbName = DB_NAME;
71
DB::$port = DB_PORT;
72
DB::$encoding = DB_ENCODING;
73
74
// Superglobal load
75
require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
76
$superGlobal = new protect\SuperGlobal\SuperGlobal();
77
$get = [];
78
$get['user_tree_structure'] = $superGlobal->get('user_tree_structure', 'GET');
79
$get['user_tree_last_refresh_timestamp'] = $superGlobal->get('user_tree_last_refresh_timestamp', 'GET');
80
$get['force_refresh'] = $superGlobal->get('force_refresh', 'GET');
81
$get['id'] = $superGlobal->get('id', 'GET');
82
$session = [];
83
$session['forbiden_pfs'] = $superGlobal->get('forbiden_pfs', 'SESSION');
84
$session['groupes_visibles'] = $superGlobal->get('groupes_visibles', 'SESSION');
85
$session['list_restricted_folders_for_items'] = $superGlobal->get('list_restricted_folders_for_items', 'SESSION');
86
$session['user_id'] = $superGlobal->get('user_id', 'SESSION');
87
$session['login'] = $superGlobal->get('login', 'SESSION');
88
$session['user_read_only'] = $superGlobal->get('user_read_only', 'SESSION');
89
//$session['personal_folder'] = explode(';', $superGlobal->get('personal_folder', 'SESSION'));
90
$session['list_folders_limited'] = $superGlobal->get('list_folders_limited', 'SESSION');
91
$session['read_only_folders'] = $superGlobal->get('read_only_folders', 'SESSION');
92
$session['personal_visible_groups'] = $superGlobal->get('personal_visible_groups', 'SESSION');
93
$lastFolderChange = DB::query(
94
    'SELECT * FROM ' . prefixTable('misc') . '
95
    WHERE type = %s AND intitule = %s',
96
    'timestamp',
97
    'last_folder_change'
98
);
99
if (
100
    empty($get['user_tree_structure']) === true
101
    || ($get['user_tree_last_refresh_timestamp'] !== null && strtotime($lastFolderChange) > strtotime($get['user_tree_last_refresh_timestamp']))
102
    || (isset($get['force_refresh']) === true && (int) $get['force_refresh'] === 1)
103
) {
104
    // Build tree
105
    $tree = new SplClassLoader('Tree\NestedTree', $SETTINGS['cpassman_dir'] . '/includes/libraries');
106
    $tree->register();
107
    $tree = new Tree\NestedTree\NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
108
109
    if (
110
        isset($session['list_folders_limited']) === true
111
        && is_array($session['list_folders_limited']) === true
112
        && count($session['list_folders_limited']) > 0
113
    ) {
114
        $listFoldersLimitedKeys = array_keys($session['list_folders_limited']);
115
    } else {
116
        $listFoldersLimitedKeys = array();
117
    }
118
    
119
    // list of items accessible but not in an allowed folder
120
    if (
121
        isset($session['list_restricted_folders_for_items']) === true
122
        && count($session['list_restricted_folders_for_items']) > 0
123
    ) {
124
        $listRestrictedFoldersForItemsKeys = @array_keys($session['list_restricted_folders_for_items']);
125
    } else {
126
        $listRestrictedFoldersForItemsKeys = array();
127
    }
128
    
129
    //$_SESSION['user_treeloadstrategy'] = 'sequential';
130
    $ret_json = array();
131
    $last_visible_parent = -1;
132
    $last_visible_parent_level = 1;
133
    $nodeId = isset($get['id']) === true && is_int($get['id']) === true ? $get['id'] : 0;
134
135
    // build the tree to be displayed
136
    if (showFolderToUser(
137
        $nodeId,
138
        $session['forbiden_pfs'],
139
        $session['groupes_visibles'],
140
        $listFoldersLimitedKeys,
141
        $listRestrictedFoldersForItemsKeys
142
    ) == true)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
143
    {
144
        if (isset($_SESSION['user_treeloadstrategy']) === true
145
            && $_SESSION['user_treeloadstrategy'] === 'sequential'
146
        ) {
147
            // SEQUENTIAL MODE
148
            // Is this folder visible by user
149
            $ret_json = buildNodeTree(
150
                $nodeId,
151
                $listFoldersLimitedKeys,
152
                $listRestrictedFoldersForItemsKeys,
153
                /** @scrutinizer ignore-type */ $tree,
154
                $SETTINGS,
155
                $session['forbiden_pfs'],
156
                $session['groupes_visibles'],
157
                $session['list_restricted_folders_for_items'],
158
                $session['user_id'],
159
                $session['login'],
160
                $superGlobal->get('no_access_folders', 'SESSION'),
161
                $superGlobal->get('personal_folders', 'SESSION'),
162
                $session['list_folders_limited'],
163
                $session['read_only_folders'],
164
                $superGlobal->get('personal_folders', 'SESSION'),
165
                $session['personal_visible_groups'],
166
                $session['user_read_only']
0 ignored issues
show
Unused Code introduced by
The call to buildNodeTree() has too many arguments starting with $session['user_read_only']. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

166
            $ret_json = /** @scrutinizer ignore-call */ buildNodeTree(

This check compares calls to functions or methods with their respective definitions. If the call has more 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.

Loading history...
167
            );
168
        } else {
169
            // FULL MODE
170
            $completTree = $tree->getTreeWithChildren();
171
            foreach ($completTree[0]->children as $child) {
172
                recursiveTree(
173
                    $child,
174
                    $completTree,
175
                    /** @scrutinizer ignore-type */ $tree,
176
                    $listFoldersLimitedKeys,
177
                    $listRestrictedFoldersForItemsKeys,
178
                    $last_visible_parent,
179
                    $last_visible_parent_level,
180
                    $SETTINGS,
181
                    $session['forbiden_pfs'],
182
                    $session['groupes_visibles'],
183
                    $session['list_restricted_folders_for_items'],
184
                    $session['user_id'],
185
                    $session['login'],
186
                    $session['user_read_only'],
187
                    $superGlobal->get('personal_folders', 'SESSION'),
188
                    $session['list_folders_limited'],
189
                    $session['read_only_folders'],
190
                    $session['personal_visible_groups'],
191
                    $superGlobal->get('can_create_root_folder', 'SESSION'),
192
                    $ret_json
193
                );
194
            }
195
        }
196
    }
197
198
    // Save in SESSION
199
    $superGlobal->put('user_tree_structure', $ret_json, 'SESSION');
200
    $superGlobal->put('user_tree_last_refresh_timestamp', time(), 'SESSION');
201
202
    // Send back
203
    echo json_encode($ret_json);
204
} else {
205
    echo $get['user_tree_structure'];
206
}
207
208
/**
209
 * Check if user can see this folder based upon rights
210
 *
211
 * @param integer $nodeId
212
 * @param array $session_forbiden_pfs
213
 * @param array $session_groupes_visibles
214
 * @param array $listFoldersLimitedKeys
215
 * @param array $listRestrictedFoldersForItemsKeys
216
 * @return boolean
217
 */
218
function showFolderToUser(
219
    int $nodeId,
220
    array $session_forbiden_pfs,
221
    array $session_groupes_visibles,
222
    array $listFoldersLimitedKeys,
223
    array $listRestrictedFoldersForItemsKeys,
224
): bool
225
{
226
    if (
227
        in_array($nodeId, $session_forbiden_pfs) === false
228
        || in_array($nodeId, $session_groupes_visibles) === true
229
        || in_array($nodeId, $listFoldersLimitedKeys) === true
230
        || in_array($nodeId, $listRestrictedFoldersForItemsKeys) === true
231
    ) {
232
        return true;
233
    }
234
    return false;
235
}
236
237
/**
238
 * Get through asked folders
239
 *
240
 * @param int $nodeId
241
 * @param array $listFoldersLimitedKeys
242
 * @param array $listRestrictedFoldersForItemsKeys
243
 * @param array $tree
244
 * @param array $SETTINGS
245
 * @param array $session_forbiden_pfs
246
 * @param array $session_groupes_visibles
247
 * @param array $session_list_restricted_folders_for_items
248
 * @param int $session_user_id
249
 * @param string $session_login
250
 * @param array $session_no_access_folders
251
 * @param array $session_list_folders_limited
252
 * @param array $session_read_only_folders
253
 * @param array $session_personal_folders
254
 * @param array $session_personal_visible_groups
255
 * @param int $session_user_read_only
256
 * @return array
257
 */
258
function buildNodeTree(
259
    $nodeId,
260
    $listFoldersLimitedKeys,
261
    $listRestrictedFoldersForItemsKeys,
262
    $tree,
263
    $SETTINGS,
264
    $session_forbiden_pfs,
265
    $session_groupes_visibles,
266
    $session_list_restricted_folders_for_items,
267
    $session_user_id,
268
    $session_login,
269
    $session_no_access_folders,
270
    $session_list_folders_limited,
271
    $session_read_only_folders,
272
    $session_personal_folders,
273
    $session_personal_visible_groups,
274
    $session_user_read_only
275
) {
276
    // Prepare superGlobal variables
277
    $ret_json = array();
278
279
    // Be sure that user can only see folders he/she is allowed to
280
    if (
281
        in_array($nodeId, $session_forbiden_pfs) === false
282
        || in_array($nodeId, $session_groupes_visibles) === true
283
        || in_array($nodeId, $listFoldersLimitedKeys) === true
284
        || in_array($nodeId, $listRestrictedFoldersForItemsKeys) === true
285
    ) {
286
        $nbChildrenItems = 0;
287
288
        // Check if any allowed folder is part of the descendants of this node
289
        $nodeDescendants = $tree->getDescendants($nodeId, false, true, false);
290
        foreach ($nodeDescendants as $node) {
291
            if ((in_array($node->id, $session_forbiden_pfs) === false
292
                    || in_array($node->id, $session_groupes_visibles) === true
293
                    || in_array($node->id, $listFoldersLimitedKeys) === true
294
                    || in_array($node->id, $listRestrictedFoldersForItemsKeys)) === true
295
                && (in_array(
296
                    $node->id,
297
                    array_merge($session_groupes_visibles, $session_list_restricted_folders_for_items)
298
                ) === true
299
                    || (is_array($listFoldersLimitedKeys) === true && in_array($node->id, $listFoldersLimitedKeys) === true)
300
                    || (is_array($listRestrictedFoldersForItemsKeys) === true && in_array($node->id, $listRestrictedFoldersForItemsKeys) === true)
301
                    || in_array($node->id, $session_no_access_folders) === true)
302
            ) {
303
                $nodeElements= buildNodeTreeElements(
304
                    $node,
305
                    $session_user_id,
306
                    $session_login,
307
                    $session_user_read_only,
308
                    $session_personal_folders,
309
                    $session_groupes_visibles,
310
                    $session_read_only_folders,
311
                    $session_personal_visible_groups,
312
                    $nbChildrenItems,
313
                    $nodeDescendants,
314
                    $listFoldersLimitedKeys,
315
                    $session_list_folders_limited,
316
                    $listRestrictedFoldersForItemsKeys,
317
                    $session_list_restricted_folders_for_items,
318
                    $SETTINGS,
319
                    $tree->numDescendants($node->id)
320
                );
321
322
                // json    
323
                array_push(
324
                    $ret_json,
325
                    array(
326
                        'id' => 'li_' . $node->id,
327
                        'parent' => $nodeElements['parent'],
328
                        'text' => '<i class="fas fa-folder mr-2"></i>'.($nodeElements['show_but_block'] === true ? '<i class="fas fa-times fa-xs text-danger mr-1"></i>' : '') . $nodeElements['text'],
329
                        'children' => ($nodeElements['childrenNb'] === 0 ? false : true),
330
                        'fa_icon' => 'folder',
331
                        'li_attr' => array(
332
                            'class' => ($nodeElements['show_but_block'] === true ? '' : 'jstreeopen'),
333
                            'title' => 'ID [' . $node->id . '] ' . ($nodeElements['show_but_block'] === true ? langHdl('no_access') : $nodeElements['title']),
334
                        ),
335
                        'a_attr' => $nodeElements['show_but_block'] === true ? (array(
336
                            'id' => 'fld_' . $node->id,
337
                            'class' => $nodeElements['folderClass'],
338
                            'onclick' => 'ListerItems(' . $node->id . ', ' . $nodeElements['restricted'] . ', 0, 1)',
339
                            'data-title' => $node->title,
340
                        )) : '',
341
                        'is_pf' => in_array($node->id, $session_personal_folders) === true ? 1 : 0,
342
                    )
343
                );
344
            }
345
        }
346
    }
347
    return $ret_json;
348
}
349
350
351
function buildNodeTreeElements(
352
    $node,
353
    $session_user_id,
354
    $session_login,
355
    $session_user_read_only,
356
    $session_personal_folders,
357
    $session_groupes_visibles,
358
    $session_read_only_folders,
359
    $session_personal_visible_groups,
360
    $nbChildrenItems,
361
    $nodeDescendants,
362
    $listFoldersLimitedKeys,
363
    $session_list_folders_limited,
364
    $listRestrictedFoldersForItemsKeys,
365
    $session_list_restricted_folders_for_items,
366
    $SETTINGS,
367
    $numDescendants
368
)
369
{
370
    // get count of Items in this folder
371
    DB::query(
372
        'SELECT *
373
        FROM ' . prefixTable('items') . '
374
        WHERE inactif=%i AND id_tree = %i',
375
        0,
376
        $node->id
377
    );
378
    $itemsNb = DB::count();
379
380
    // get info about current folder
381
    DB::query(
382
        'SELECT *
383
        FROM ' . prefixTable('nested_tree') . '
384
        WHERE parent_id = %i',
385
        $node->id
386
    );
387
    $childrenNb = DB::count();
388
389
    // If personal Folder, convert id into user name
390
    $node->title = $node->title === $session_user_id && (int) $node->nlevel === 1 ?
391
        $session_login :
392
        ($node->title === null ? '' : htmlspecialchars_decode($node->title, ENT_QUOTES));
393
394
    // prepare json return for current node
395
    $parent = $node->parent_id === 0 ? '#' : 'li_' . $node->parent_id;
396
397
    // special case for READ-ONLY folder
398
    $title = (bool) $session_user_read_only === true && in_array($node->id, $session_personal_folders) === false ? langHdl('read_only_account') : '';
399
    $text = str_replace('&', '&amp;', $node->title);
400
    //$restricted = 0;
401
    //$folderClass = 'folder';
402
    //$show_but_block = false;
403
404
    if (in_array($node->id, $session_groupes_visibles) === true) {
405
        if (in_array($node->id, $session_read_only_folders) === true) {
406
            return array(
407
                'text' => '<i class="far fa-eye fa-xs mr-1 ml-1"></i>' . $text
408
                    .' <span class=\'badge badge-danger ml-2 items_count\' id=\'itcount_' . $node->id . '\'>' . $itemsNb . '</span>'
409
                    .(isKeyExistingAndEqual('tree_counters', 1, $SETTINGS) === true ?
410
                        '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)
411
                        : '')
412
                    .'</span>',
413
                'title' => langHdl('read_only_account'),
414
                'restricted' => 1,
415
                'folderClass' => 'folder_not_droppable',
416
                'show_but_block' => false,
417
                'parent' => $parent,
418
                'childrenNb' => $childrenNb,
419
                'itemsNb' => $itemsNb,
420
            );
421
        }
422
        
423
        return array(
424
            'text' => ($session_user_read_only === true && in_array($node->id, $session_personal_visible_groups) === false) ?
425
                ('<i class="far fa-eye fa-xs mr-1 ml-1"></i>' . $text
426
                .' <span class=\'badge badge-danger ml-2 items_count\' id=\'itcount_' . $node->id . '\'>' . $itemsNb . '</span>'
427
                .(isKeyExistingAndEqual('tree_counters', 1, $SETTINGS) === true ?
428
                    '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  :
429
                    '')
430
                .'</span>') :
431
                (' <span class=\'badge badge-danger ml-2 items_count\' id=\'itcount_' . $node->id . '\'>' . $itemsNb . '</span>'
432
                .(isKeyExistingAndEqual('tree_counters', 1, $SETTINGS) === true ?
433
                    '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  :
434
                    '')
435
                .'</span>'),
436
            'title' => langHdl('read_only_account'),
437
            'restricted' => 1,
438
            'folderClass' => 'folder_not_droppable',
439
            'show_but_block' => false,
440
            'parent' => $parent,
441
            'childrenNb' => $childrenNb,
442
            'itemsNb' => $itemsNb,
443
        );
444
    }
445
    
446
    elseif (in_array($node->id, $listFoldersLimitedKeys) === true) {
447
        return array(
448
            'text' => $text . ($session_user_read_only === true ?
449
                '<i class="far fa-eye fa-xs mr-1 ml-1"></i>' :
450
                '<span class="badge badge-danger ml-2 items_count" id="itcount_' . $node->id . '">' . count($session_list_folders_limited[$node->id]) . '</span>'
451
            ),
452
            'title' => $title,
453
            'restricted' => 1,
454
            'folderClass' => 'folder',
455
            'show_but_block' => false,
456
            'parent' => $parent,
457
            'childrenNb' => $childrenNb,
458
            'itemsNb' => $itemsNb,
459
        );
460
    }
461
    
462
    elseif (in_array($node->id, $listRestrictedFoldersForItemsKeys) === true) {        
463
        return array(
464
            'text' => $text . ($session_user_read_only === true ? 
465
                '<i class="far fa-eye fa-xs mr-1 ml-1"></i>' :
466
                '<span class="badge badge-danger ml-2 items_count" id="itcount_' . $node->id . '">' . count($session_list_restricted_folders_for_items[$node->id]) . '</span>'
467
            ),
468
            'title' => $title,
469
            'restricted' => 1,
470
            'folderClass' => 'folder',
471
            'show_but_block' => false,
472
            'parent' => $parent,
473
            'childrenNb' => $childrenNb,
474
            'itemsNb' => $itemsNb,
475
        );
476
    }
477
478
    // default case
479
    elseif (isKeyExistingAndEqual('show_only_accessible_folders', 1, $SETTINGS) === true
480
        && (int) $numDescendants === 0)
481
    {
482
        return array();
483
    }
484
485
    return array(
486
        'text' => $text,
487
        'title' => $title,
488
        'restricted' => 1,
489
        'folderClass' => 'folder_not_droppable',
490
        'show_but_block' => true,   // folder is visible but not accessible by user
491
        'parent' => $parent,
492
        'childrenNb' => $childrenNb,
493
        'itemsNb' => $itemsNb,
494
    );
495
}
496
497
/**
498
 * Get through complete tree
499
 *
500
 * @param int     $nodeId                            Id
501
 * @param array   $completTree                       Tree info
502
 * @param array   $tree                              The tree
503
 * @param array   $listFoldersLimitedKeys            Limited
504
 * @param array   $listRestrictedFoldersForItemsKeys Restricted
505
 * @param int     $last_visible_parent               Visible parent
506
 * @param int     $last_visible_parent_level         Parent level
507
 * @param array   $SETTINGS                          Teampass settings
508
 * @param string  $session_forbiden_pfs,
509
 * @param string  $session_groupes_visibles,
510
 * @param string  $session_list_restricted_folders_for_items,
511
 * @param int     $session_user_id,
512
 * @param string  $session_login,
513
 * @param string  $session_user_read_only,
514
 * @param array   $session_personal_folder,
515
 * @param string  $session_list_folders_limited,
516
 * @param string  $session_read_only_folders,
517
 * @param string  $session_personal_visible_groups
518
 * @param int     $can_create_root_folder
519
 * @param array   $ret_json                          Array
520
 *
521
 * @return array
522
 */
523
function recursiveTree(
524
    $nodeId,
525
    $completTree,
526
    $tree,
527
    $listFoldersLimitedKeys,
528
    $listRestrictedFoldersForItemsKeys,
529
    $last_visible_parent,
530
    $last_visible_parent_level,
531
    $SETTINGS,
532
    $session_forbiden_pfs,
533
    $session_groupes_visibles,
534
    $session_list_restricted_folders_for_items,
535
    $session_user_id,
536
    $session_login,
537
    $session_user_read_only,
538
    $session_personal_folder,
539
    $session_list_folders_limited,
540
    $session_read_only_folders,
541
    $session_personal_visible_groups,
542
    $can_create_root_folder,
543
    &$ret_json = array()
544
) {
545
    $text = '';
546
    $title = '';
547
    $show_but_block = false;
548
549
    // Load config
550
    if (file_exists('../includes/config/tp.config.php')) {
551
        include '../includes/config/tp.config.php';
552
    } elseif (file_exists('./includes/config/tp.config.php')) {
553
        include './includes/config/tp.config.php';
554
    } else {
555
        throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
556
    }
557
    
558
    // Be sure that user can only see folders he/she is allowed to
559
    if (
560
        in_array($completTree[$nodeId]->id, $session_forbiden_pfs) === false
561
        || in_array($completTree[$nodeId]->id, $session_groupes_visibles) === true
562
    ) {
563
        $displayThisNode = false;
564
        $nbChildrenItems = 0;
565
        $nodeDirectDescendants = $tree->getDescendants($completTree[$nodeId]->id, false, false, true);
566
567
        // Check if any allowed folder is part of the descendants of this node
568
        $nodeDescendants = $tree->getDescendants($completTree[$nodeId]->id, true, false, true);
569
        foreach ($nodeDescendants as $node) {
570
            // manage tree counters
571
            if (
572
                isKeyExistingAndEqual('tree_counters', 1, $SETTINGS) === true
573
                && in_array(
574
                    $node,
575
                    array_merge($session_groupes_visibles, $session_list_restricted_folders_for_items)
576
                ) === true
577
            ) {
578
                DB::query(
579
                    'SELECT * FROM ' . prefixTable('items') . '
580
                    WHERE inactif=%i AND id_tree = %i',
581
                    0,
582
                    $node
583
                );
584
                $nbChildrenItems += DB::count();
585
            }
586
587
            if (
588
                in_array($node, $session_groupes_visibles) === true
589
            ) {
590
                // Final check - is PF allowed?
591
                $nodeDetails = $tree->getNode($node);
592
                if (
593
                    (int) $nodeDetails->personal_folder === 1
594
                    && (int) $SETTINGS['enable_pf_feature'] === 1
595
                    && in_array($node, $session_personal_folder) === false
596
                ) {
597
                    $displayThisNode = false;
598
                } else {
599
                    $displayThisNode = true;
600
                    // not adding a break in order to permit a correct count of items
601
                }
602
                $text = '';
603
            }
604
        }
605
        
606
        if ($displayThisNode === true) {
607
            handleNode(
608
                $nodeId,
609
                $completTree,
610
                $tree,
611
                $listFoldersLimitedKeys,
612
                $listRestrictedFoldersForItemsKeys,
613
                $last_visible_parent,
614
                $last_visible_parent_level,
615
                $SETTINGS,
616
                $session_forbiden_pfs,
617
                $session_groupes_visibles,
618
                $session_list_restricted_folders_for_items,
619
                $session_user_id,
620
                $session_login,
621
                $session_user_read_only,
622
                $session_personal_folder,
623
                $session_list_folders_limited,
624
                $session_read_only_folders,
625
                $session_personal_visible_groups,
626
                $text,
627
                $nbChildrenItems,
628
                $nodeDescendants,
629
                $nodeDirectDescendants,
630
                $can_create_root_folder,
631
                $ret_json
632
            );
633
        }
634
    }
635
    return $ret_json;
636
}
637
638
639
function handleNode(
640
    $nodeId,
641
    $completTree,
642
    $tree,
643
    $listFoldersLimitedKeys,
644
    $listRestrictedFoldersForItemsKeys,
645
    $last_visible_parent,
646
    $last_visible_parent_level,
647
    $SETTINGS,
648
    $session_forbiden_pfs,
649
    $session_groupes_visibles,
650
    $session_list_restricted_folders_for_items,
651
    $session_user_id,
652
    $session_login,
653
    $session_user_read_only,
654
    $session_personal_folder,
655
    $session_list_folders_limited,
656
    $session_read_only_folders,
657
    $session_personal_visible_groups,
658
    $text,
659
    $nbChildrenItems,
660
    $nodeDescendants,
661
    $nodeDirectDescendants,
662
    $can_create_root_folder, 
663
    &$ret_json = array()
664
)
665
{
666
    // get info about current folder
667
    DB::query(
668
        'SELECT * FROM ' . prefixTable('items') . '
669
        WHERE inactif=%i AND id_tree = %i',
670
        0,
671
        $completTree[$nodeId]->id
672
    );
673
    $itemsNb = DB::count();
674
675
    // If personal Folder, convert id into user name
676
    if ((int) $completTree[$nodeId]->title === (int) $session_user_id && (int) $completTree[$nodeId]->nlevel === 1) {
677
        $completTree[$nodeId]->title = $session_login;
678
    }
679
680
    // Decode if needed
681
    $completTree[$nodeId]->title = htmlspecialchars_decode($completTree[$nodeId]->title, ENT_QUOTES);
682
683
    $nodeData = prepareNodeData(
684
        $completTree,
685
        (int) $completTree[$nodeId]->id,
686
        $session_groupes_visibles,
687
        $session_read_only_folders,
688
        $session_personal_visible_groups,
689
        (int) $nbChildrenItems,
690
        $nodeDescendants,
691
        (int) $itemsNb,
692
        $session_list_folders_limited,
693
        (int) $SETTINGS['show_only_accessible_folders'],
694
        $nodeDirectDescendants,
695
        isset($SETTINGS['tree_counters']) === true ? (int) $SETTINGS['tree_counters'] : '',
696
        (int) $session_user_read_only,
697
        $listFoldersLimitedKeys,
698
        $listRestrictedFoldersForItemsKeys,
699
        $session_list_restricted_folders_for_items,
700
        $session_personal_folder
701
    );
702
703
    // prepare json return for current node
704
    $parent = $completTree[$nodeId]->parent_id === '0' ? '#' : 'li_' . $completTree[$nodeId]->parent_id;
705
706
    // handle displaying
707
    if (isKeyExistingAndEqual('show_only_accessible_folders', 1, $SETTINGS) === true) {
708
        if ($nodeData['hide_node'] === true) {
709
            $last_visible_parent = (int) $parent;
710
            $last_visible_parent_level = $completTree[$nodeId]->nlevel--;
711
        } elseif ($completTree[$nodeId]->nlevel < $last_visible_parent_level) {
712
            $last_visible_parent = -1;
713
        }
714
    }
715
716
    // json
717
    if ($nodeData['hide_node'] === false && $nodeData['show_but_block'] === false) {
718
        array_push(
719
            $ret_json,
720
            array(
721
                'id' => 'li_' . $completTree[$nodeId]->id,
722
                'parent' => $last_visible_parent === -1 ? $parent : $last_visible_parent,
723
                'text' => '<i class="'.$completTree[$nodeId]->fa_icon.' tree-folder mr-2" data-folder="'.$completTree[$nodeId]->fa_icon.'"  data-folder-selected="'.$completTree[$nodeId]->fa_icon_selected.'"></i>'.$text.$completTree[$nodeId]->title.$nodeData['html'],
724
                'li_attr' => array(
725
                    'class' => 'jstreeopen',
726
                    'title' => 'ID [' . $completTree[$nodeId]->id . '] ' . $nodeData['title'],
727
                ),
728
                'a_attr' => array(
729
                    'id' => 'fld_' . $completTree[$nodeId]->id,
730
                    'class' => $nodeData['folderClass'],
731
                    'onclick' => 'ListerItems(' . $completTree[$nodeId]->id . ', ' . $nodeData['restricted'] . ', 0, 1)',
732
                    'data-title' => $completTree[$nodeId]->title,
733
                ),
734
                'is_pf' => in_array($completTree[$nodeId]->id, $session_personal_folder) === true ? 1 : 0,
735
                'can_edit' => (int) $can_create_root_folder,
736
            )
737
        );
738
    } elseif ($nodeData['show_but_block'] === true) {
739
        array_push(
740
            $ret_json,
741
            array(
742
                'id' => 'li_' . $completTree[$nodeId]->id,
743
                'parent' => $last_visible_parent === -1 ? $parent : $last_visible_parent,
744
                'text' => '<i class="'.$completTree[$nodeId]->fa_icon.' tree-folder mr-2" data-folder="'.$completTree[$nodeId]->fa_icon.'"  data-folder-selected="'.$completTree[$nodeId]->fa_icon_selected.'"></i>'.'<i class="fas fa-times fa-xs text-danger mr-1 ml-1"></i>'.$text.$completTree[$nodeId]->title.$nodeData['html'],
745
                'li_attr' => array(
746
                    'class' => '',
747
                    'title' => 'ID [' . $completTree[$nodeId]->id . '] ' . langHdl('no_access'),
748
                ),
749
            )
750
        );
751
    }
752
    
753
    foreach ($completTree[$nodeId]->children as $child) {
754
        recursiveTree(
755
            $child,
756
            $completTree,
757
            /** @scrutinizer ignore-type */ $tree,
758
            $listFoldersLimitedKeys,
759
            $listRestrictedFoldersForItemsKeys,
760
            $last_visible_parent,
761
            $last_visible_parent_level,
762
            $SETTINGS,
763
            $session_forbiden_pfs,
764
            $session_groupes_visibles,
765
            $session_list_restricted_folders_for_items,
766
            $session_user_id,
767
            $session_login,
768
            $session_user_read_only,
769
            $session_personal_folder,
770
            $session_list_folders_limited,
771
            $session_read_only_folders,
772
            $session_personal_visible_groups,
773
            $can_create_root_folder,
774
            $ret_json
775
        );
776
    }
777
}
778
779
780
781
function prepareNodeData(
782
    $completTree,
783
    $nodeId,
784
    $session_groupes_visibles,
785
    $session_read_only_folders,
786
    $session_personal_visible_groups,
787
    $nbChildrenItems,
788
    $nodeDescendants,
789
    $itemsNb,
790
    $session_list_folders_limited,
791
    $show_only_accessible_folders,
792
    $nodeDirectDescendants,
793
    $tree_counters,
794
    $session_user_read_only,
795
    $listFoldersLimitedKeys,
796
    $listRestrictedFoldersForItemsKeys,
797
    $session_list_restricted_folders_for_items,
798
    $session_personal_folder
799
): array
800
{
801
    // special case for READ-ONLY folder
802
    $title = '';
803
    if (
804
        $session_user_read_only === true
805
        && in_array($completTree[$nodeId]->id, $session_user_read_only) === false
806
    ) {
807
        $title = langHdl('read_only_account');
808
    }
809
810
    if (in_array($nodeId, $session_groupes_visibles) === true) {
811
        if (in_array($nodeId, $session_read_only_folders) === true) {
812
            return [
813
                'html' => '<i class="far fa-eye fa-xs mr-1 ml-1"></i><span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $itemsNb .
814
                    ($tree_counters === 1 ? '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  : '') . '</span>',
815
                'title' => langHdl('read_only_account'),
816
                'restricted' => 1,
817
                'folderClass' => 'folder_not_droppable',
818
                'show_but_block' => false,
819
                'hide_node' => false,
820
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
821
            ];
822
        }
823
824
        elseif (
825
            $session_user_read_only === true
826
            && in_array($nodeId, $session_personal_visible_groups) === false
827
        ) {
828
            return [
829
                'html' => '<i class="far fa-eye fa-xs mr-1"></i><span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $itemsNb .
830
                    ($tree_counters === 1 ? '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  : '') . '</span>',
831
                'title' => $title,
832
                'restricted' => 0,
833
                'folderClass' => 'folder',
834
                'show_but_block' => false,
835
                'hide_node' => false,
836
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
837
            ];
838
        }
839
        
840
        return [
841
            'html' => '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $itemsNb .
842
                ($tree_counters === 1 ? '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  : '') . '</span>',
843
            'title' => $title,
844
            'restricted' => 0,
845
            'folderClass' => 'folder',
846
            'show_but_block' => false,
847
            'hide_node' => false,
848
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
849
        ];
850
    }
851
    
852
    elseif (in_array($nodeId, $listFoldersLimitedKeys) === true) {
853
        return [
854
            'html' => ($session_user_read_only === true ? '<i class="far fa-eye fa-xs mr-1"></i>' : '') .
855
                '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . count($session_list_folders_limited[$nodeId]) . '</span>',
856
            'title' => $title,
857
            'restricted' => 1,
858
            'folderClass' => 'folder',
859
            'show_but_block' => false,
860
            'hide_node' => false,
861
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
862
        ];
863
    }
864
    
865
    elseif (in_array($nodeId, $listRestrictedFoldersForItemsKeys) === true) {
866
        return [
867
            'html' => $session_user_read_only === true ? '<i class="far fa-eye fa-xs mr-1"></i>' : '' .
868
                '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . count($session_list_restricted_folders_for_items[$nodeId]) . '</span>',
869
            'title' => $title,
870
            'restricted' => 1,
871
            'folderClass' => 'folder',
872
            'show_but_block' => false,
873
            'hide_node' => false,
874
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
875
        ];
876
    }
877
    
878
    elseif ((int) $show_only_accessible_folders === 1
879
        && (int) $nbChildrenItems === 0
880
    ) {
881
        // folder should not be visible
882
        // only if it has no descendants
883
        if (
884
            count(
885
                array_diff(
886
                    $nodeDirectDescendants,
887
                    array_merge(
888
                        $session_groupes_visibles,
889
                        array_keys($session_list_restricted_folders_for_items)
890
                    )
891
                )
892
            ) !== count($nodeDirectDescendants)
893
        ) {
894
            // show it but block it
895
            return [
896
                'html' => '',
897
                'title' => $title,
898
                'restricted' => 1,
899
                'folderClass' => 'folder_not_droppable',
900
                'show_but_block' => true,
901
                'hide_node' => false,
902
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
903
            ];
904
        }
905
        
906
        // hide it
907
        return [
908
            'html' => '',
909
            'title' => $title,
910
            'restricted' => 1,
911
            'folderClass' => 'folder_not_droppable',
912
            'show_but_block' => false,
913
            'hide_node' => true,
914
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
915
        ];
916
    }
917
918
    return [
919
        'html' => '',
920
        'title' => isset($title) === true ? $title : '',
921
        'restricted' => 1,
922
        'folderClass' => 'folder_not_droppable',
923
        'show_but_block' => true,
924
        'hide_node' => false,
925
        'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
926
    ];
927
}