Issues (27)

Security Analysis    no vulnerabilities found

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

sources/folders.queries.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Teampass - a collaborative passwords manager.
7
 * ---
8
 * This file is part of the TeamPass project.
9
 * 
10
 * TeamPass is free software: you can redistribute it and/or modify it
11
 * under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation, version 3 of the License.
13
 * 
14
 * TeamPass is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU General Public License for more details.
18
 * 
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21
 * 
22
 * Certain components of this file may be under different licenses. For
23
 * details, see the `licenses` directory or individual file headers.
24
 * ---
25
 * @file      folders.queries.php
26
 * @author    Nils Laumaillé ([email protected])
27
 * @copyright 2009-2025 Teampass.net
28
 * @license   GPL-3.0
29
 * @see       https://www.teampass.net
30
 */
31
32
use TeampassClasses\NestedTree\NestedTree;
33
use TeampassClasses\SessionManager\SessionManager;
34
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
35
use TeampassClasses\Language\Language;
36
use TeampassClasses\PerformChecks\PerformChecks;
37
use TeampassClasses\ConfigManager\ConfigManager;
38
39
// Load functions
40
require_once 'main.functions.php';
41
42
// init
43
loadClasses('DB');
44
$session = SessionManager::getSession();
45
$request = SymfonyRequest::createFromGlobals();
46
$lang = new Language($session->get('user-language') ?? 'english');
47
48
// Load config
49
$configManager = new ConfigManager();
50
$SETTINGS = $configManager->getAllSettings();
51
52
// Do checks
53
// Instantiate the class with posted data
54
$checkUserAccess = new PerformChecks(
55
    dataSanitizer(
56
        [
57
            'type' => htmlspecialchars($request->request->get('type', ''), ENT_QUOTES, 'UTF-8'),
58
        ],
59
        [
60
            'type' => 'trim|escape',
61
        ],
62
    ),
63
    [
64
        'user_id' => returnIfSet($session->get('user-id'), null),
65
        'user_key' => returnIfSet($session->get('key'), null),
66
    ]
67
);
68
69
// Define Timezone
70
date_default_timezone_set($SETTINGS['timezone'] ?? 'UTC');
71
72
// Set header properties
73
header('Content-type: text/html; charset=utf-8');
74
header('Cache-Control: no-cache, no-store, must-revalidate');
75
76
// --------------------------------- //
77
78
79
// Load tree
80
$tree = new NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
81
82
// Prepare post variables
83
$post_key = filter_input(INPUT_POST, 'key', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
84
$post_type = filter_input(INPUT_POST, 'type', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
85
$post_data = filter_input(INPUT_POST, 'data', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_FLAG_NO_ENCODE_QUOTES);
86
87
// Ensure Complexity levels are translated
88
if (defined('TP_PW_COMPLEXITY') === false) {
89
    define(
90
        'TP_PW_COMPLEXITY',
91
        array(
92
            TP_PW_STRENGTH_1 => array(TP_PW_STRENGTH_1, $lang->get('complex_level1'), 'fas fa-thermometer-empty text-danger'),
93
            TP_PW_STRENGTH_2 => array(TP_PW_STRENGTH_2, $lang->get('complex_level2'), 'fas fa-thermometer-quarter text-warning'),
94
            TP_PW_STRENGTH_3 => array(TP_PW_STRENGTH_3, $lang->get('complex_level3'), 'fas fa-thermometer-half text-warning'),
95
            TP_PW_STRENGTH_4 => array(TP_PW_STRENGTH_4, $lang->get('complex_level4'), 'fas fa-thermometer-three-quarters text-success'),
96
            TP_PW_STRENGTH_5 => array(TP_PW_STRENGTH_5, $lang->get('complex_level5'), 'fas fa-thermometer-full text-success'),
97
        )
98
    );
99
}
100
101
if (null !== $post_type) {
102
    switch ($post_type) {
103
        /*
104
         * BUILD liste of folders
105
         */
106
        case 'build_matrix':
107
            // Check KEY
108
            if ($post_key !== $session->get('key')) {
109
                echo prepareExchangedData(
110
                    array(
111
                        'error' => true,
112
                        'message' => $lang->get('key_is_not_correct'),
113
                    ),
114
                    'encode'
115
                );
116
                break;
117
            } elseif ($session->get('user-read_only') === 1) {
118
                echo prepareExchangedData(
119
                    array(
120
                        'error' => true,
121
                        'message' => $lang->get('error_not_allowed_to'),
122
                    ),
123
                    'encode'
124
                );
125
                break;
126
            }
127
128
            // Prepare variables
129
            $arrData = array();
130
131
            $treeDesc = $tree->getDescendants();
132
133
            foreach ($treeDesc as $t) {
134
                if (
135
                    in_array($t->id, $session->get('user-accessible_folders')) === true
136
                    && in_array($t->id, $session->get('user-personal_visible_folders')) === false
137
                    && $t->personal_folder == 0
138
                ) {
139
                    // get $t->parent_id
140
                    $data = DB::queryFirstRow('SELECT title FROM ' . prefixTable('nested_tree') . ' WHERE id = %i', $t->parent_id);
141
                    if ($t->nlevel == 1) {
142
                        $data['title'] = $lang->get('root');
143
                    }
144
145
                    // get rights on this folder
146
                    $arrayRights = array();
147
                    $rows = DB::query('SELECT fonction_id  FROM ' . prefixTable('rights') . ' WHERE authorized=%i AND tree_id = %i', 1, $t->id);
148
                    foreach ($rows as $record) {
149
                        array_push($arrayRights, $record['fonction_id']);
150
                    }
151
152
                    $arbo = $tree->getPath($t->id, false);
153
                    $arrayPath = array();
154
                    $arrayParents = array();
155
                    foreach ($arbo as $elem) {
156
                        array_push($arrayPath, $elem->title);
157
                        array_push($arrayParents, $elem->id);
158
                    }
159
160
                    // Get some elements from DB concerning this node
161
                    $node_data = DB::queryFirstRow(
162
                        'SELECT m.valeur AS valeur, n.renewal_period AS renewal_period,
163
                        n.bloquer_creation AS bloquer_creation, n.bloquer_modification AS bloquer_modification,
164
                        n.fa_icon AS fa_icon, n.fa_icon_selected AS fa_icon_selected
165
                        FROM ' . prefixTable('misc') . ' AS m,
166
                        ' . prefixTable('nested_tree') . ' AS n
167
                        WHERE m.type=%s AND m.intitule = n.id AND m.intitule = %i',
168
                        'complex',
169
                        $t->id
170
                    );
171
172
                    // Preapre array of columns
173
                    $arrayColumns = array();
174
175
                    $arrayColumns['id'] = (int) $t->id;
176
                    $arrayColumns['numOfChildren'] = (int) $tree->numDescendants($t->id);
177
                    $arrayColumns['level'] = (int) $t->nlevel;
178
                    $arrayColumns['parentId'] = (int) $t->parent_id;
179
                    $arrayColumns['title'] = $t->title;
180
                    $arrayColumns['nbItems'] = (int) DB::count();
181
                    $arrayColumns['path'] = $arrayPath;
182
                    $arrayColumns['parents'] = $arrayParents;
183
184
                    if (is_null($node_data) === false && isset(TP_PW_COMPLEXITY[$node_data['valeur']][1]) === true) {
185
                        $arrayColumns['folderComplexity'] = array(
186
                            'text' => TP_PW_COMPLEXITY[$node_data['valeur']][1],
187
                            'value' => TP_PW_COMPLEXITY[$node_data['valeur']][0],
188
                            'class' => TP_PW_COMPLEXITY[$node_data['valeur']][2],
189
                        );
190
                    } else {
191
                        $arrayColumns['folderComplexity'] = '';
192
                    }
193
194
                    if (is_null($node_data)=== false) {
195
                        $arrayColumns['renewalPeriod'] = (int) $node_data['renewal_period'];
196
                    } else {
197
                        $arrayColumns['renewalPeriod']=0;
198
                    }
199
200
                    //col7
201
                    $data7 = DB::queryFirstRow(
202
                        'SELECT bloquer_creation,bloquer_modification
203
                        FROM ' . prefixTable('nested_tree') . '
204
                        WHERE id = %i',
205
                        intval($t->id)
206
                    );
207
                    $arrayColumns['add_is_blocked'] = (int) $data7['bloquer_creation'];
208
                    $arrayColumns['edit_is_blocked'] = (int) $data7['bloquer_modification'];
209
                    $arrayColumns['icon'] = (string) !is_null($node_data) ? $node_data['fa_icon'] : '';
210
                    $arrayColumns['iconSelected'] = (string) !is_null($node_data) ? $node_data['fa_icon_selected'] : '';
211
212
                    array_push($arrData, $arrayColumns);
213
                }
214
            }
215
216
            // Send the complexity levels
217
            $complexity = array(
218
                array('value' => TP_PW_STRENGTH_1, 'text' => $lang->get('complex_level1')),
219
                array('value' => TP_PW_STRENGTH_2, 'text' => $lang->get('complex_level2')),
220
                array('value' => TP_PW_STRENGTH_3, 'text' => $lang->get('complex_level3')),
221
                array('value' => TP_PW_STRENGTH_4, 'text' => $lang->get('complex_level4')),
222
                array('value' => TP_PW_STRENGTH_5, 'text' => $lang->get('complex_level5')),
223
            );
224
225
            echo prepareExchangedData(
226
                array(
227
                    'error' => false,
228
                    'message' => '',
229
                    'matrix' => $arrData,
230
                    'userIsAdmin' => $session->get('user-admin'),
231
                    'userCanCreateRootFolder' => (int) $session->get('user-can_create_root_folder'),
232
                    'fullComplexity' => $complexity,
233
                ),
234
                'encode'
235
            );
236
237
            break;
238
239
        // CASE where selecting/deselecting sub-folders
240
        case 'select_sub_folders':
241
            // Check KEY
242
            if ($post_key !== $session->get('key')) {
243
                echo prepareExchangedData(
244
                    array(
245
                        'error' => true,
246
                        'message' => $lang->get('key_is_not_correct'),
247
                    ),
248
                    'encode'
249
                );
250
                break;
251
            } elseif ($session->get('user-read_only') === 1) {
252
                echo prepareExchangedData(
253
                    array(
254
                        'error' => true,
255
                        'message' => $lang->get('error_not_allowed_to'),
256
                    ),
257
                    'encode'
258
                );
259
                break;
260
            }
261
262
            $post_id = filter_input(INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT);
263
264
            // get sub folders
265
            $subfolders = array();
266
267
            // Get through each subfolder
268
            $folders = $tree->getDescendants($post_id, false);
269
            foreach ($folders as $folder) {
270
                array_push($subfolders, (int) $folder->id);
271
            }
272
273
            echo prepareExchangedData(
274
                array(
275
                    'error' => false,
276
                    'subfolders' => json_encode($subfolders),
277
                ),
278
                'encode'
279
            );
280
281
            break;
282
283
            //CASE where UPDATING a new group
284
        case 'update_folder':
285
            // Check KEY
286
            if ($post_key !== $session->get('key')) {
287
                echo prepareExchangedData(
288
                    array(
289
                        'error' => true,
290
                        'message' => $lang->get('key_is_not_correct'),
291
                    ),
292
                    'encode'
293
                );
294
                break;
295
            } elseif ($session->get('user-read_only') === 1) {
296
                echo prepareExchangedData(
297
                    array(
298
                        'error' => true,
299
                        'message' => $lang->get('error_not_allowed_to'),
300
                    ),
301
                    'encode'
302
                );
303
                break;
304
            }
305
306
            // decrypt and retrieve data in JSON format
307
            $dataReceived = prepareExchangedData(
308
                $post_data,
309
                'decode'
310
            );
311
312
            // prepare variables
313
            $data = [
314
                'id' => isset($dataReceived['id']) === true ? $dataReceived['id'] : -1,
315
                'title' => isset($dataReceived['title']) === true ? $dataReceived['title'] : '',
316
                'parentId' => isset($dataReceived['parentId']) === true ? $dataReceived['parentId'] : 0,
317
                'complexity' => isset($dataReceived['complexity']) === true ? $dataReceived['complexity'] : '',
318
                'duration' => isset($dataReceived['renewalPeriod']) === true ? $dataReceived['renewalPeriod'] : 0,
319
                'create_auth_without' => isset($dataReceived['addRestriction']) === true ? $dataReceived['addRestriction'] : 0,
320
                'edit_auth_without' => isset($dataReceived['editRestriction']) === true ? $dataReceived['editRestriction'] : 0,
321
                'icon' => isset($dataReceived['icon']) === true ? $dataReceived['icon'] : '',
322
                'icon_selected' => isset($dataReceived['iconSelected']) === true ? $dataReceived['iconSelected'] : '',
323
                'access_rights' => isset($dataReceived['accessRight']) === true ? $dataReceived['accessRight'] : 'W',
324
            ];            
325
            $filters = [
326
                'id' => 'cast:integer',
327
                'title' => 'trim|escape',
328
                'parentId' => 'cast:integer',
329
                'complexity' => 'cast:integer',
330
                'duration' => 'cast:integer',
331
                'create_auth_without' => 'cast:integer',
332
                'edit_auth_without' => 'cast:integer',
333
                'icon' => 'trim|escape',
334
                'icon_selected' => 'trim|escape',
335
                'access_rights' => 'trim|escape',
336
            ];            
337
            $inputData = dataSanitizer(
338
                $data,
339
                $filters
340
            );
341
342
            // Init
343
            $error = false;
344
            $errorMessage = '';
345
346
            // check if title is numeric
347
            if (is_numeric($inputData['title']) === true) {
348
                echo prepareExchangedData(
349
                    array(
350
                        'error' => true,
351
                        'message' => $lang->get('error_only_numbers_in_folder_name'),
352
                    ),
353
                    'encode'
354
                );
355
                break;
356
            }
357
358
            // Get info about this folder
359
            $dataFolder = DB::queryFirstRow(
360
                'SELECT *
361
                FROM ' . prefixTable('nested_tree') . '
362
                WHERE id = %i',
363
                $inputData['id']
364
            );
365
            
366
            //Check if duplicate folders name are allowed
367
            if (
368
                isset($SETTINGS['duplicate_folder']) === true
369
                && (int) $SETTINGS['duplicate_folder'] === 0
370
            ) {
371
                if (
372
                    empty($dataFolder['id']) === false
373
                    && intval($dataReceived['id']) !== intval($dataFolder['id'])
374
                    && $inputData['title'] !== $dataFolder['title']
375
                ) {
376
                    echo prepareExchangedData(
377
                        array(
378
                            'error' => true,
379
                            'message' => $lang->get('error_group_exist'),
380
                        ),
381
                        'encode'
382
                    );
383
                    break;
384
                }
385
            }
386
387
            // Is the parent folder changed?
388
            if ((int) $dataFolder['parent_id'] === (int) $inputData['parentId']) {
389
                $parentChanged = false;
390
            } else {
391
                $parentChanged = true;
392
            }
393
394
            //check if parent folder is personal
395
            $dataParent = DB::queryFirstRow(
396
                'SELECT personal_folder, bloquer_creation, bloquer_modification
397
                FROM ' . prefixTable('nested_tree') . '
398
                WHERE id = %i',
399
                $inputData['parentId']
400
            );
401
402
            // inherit from parent the specific settings it has
403
            if (DB::count() > 0) {
404
                $parentBloquerCreation = $dataParent['bloquer_creation'];
405
                $parentBloquerModification = $dataParent['bloquer_modification'];
406
            } else {
407
                $parentBloquerCreation = 0;
408
                $parentBloquerModification = 0;
409
            }
410
411
            if (isset($dataParent['personal_folder']) === true && (int) $dataParent['personal_folder'] === 1) {
412
                $isPersonal = 1;
413
            } else {
414
                $isPersonal = 0;
415
416
                // check if complexity level is good
417
                // if manager or admin don't care
418
                if (
419
                    (int) $session->get('user-admin') !== 1
420
                    && ((int) $session->get('user-manager') !== 1
421
                        || (int) $session->get('user-can_manage_all_users') !== 1)
422
                ) {
423
                    // get complexity level for this folder
424
                    $data = DB::queryFirstRow(
425
                        'SELECT valeur
426
                        FROM ' . prefixTable('misc') . '
427
                        WHERE intitule = %i AND type = %s',
428
                        $inputData['parentId'],
429
                        'complex'
430
                    );
431
432
                    if (isset($data['valeur']) === true && (int) $inputData['complexity'] < (int) $data['valeur']) {
433
                        echo prepareExchangedData(
434
                            array(
435
                                'error' => true,
436
                                'message' => $lang->get('error_folder_complexity_lower_than_top_folder')
437
                                    . ' [<b>' . TP_PW_COMPLEXITY[$data['valeur']][1] . '</b>]',
438
                            ),
439
                            'encode'
440
                        );
441
                        break;
442
                    }
443
                }
444
            }
445
446
            // Check if user is allowed
447
            if (
448
                !(
449
                    (int) $isPersonal === 1
450
                    || (int) $session->get('user-admin') === 1
451
                    || (int) $session->get('user-manager') === 1
452
                    || (int) $session->get('user-can_manage_all_users') === 1
453
                    || (isset($SETTINGS['enable_user_can_create_folders']) === true
454
                        && (int) $SETTINGS['enable_user_can_create_folders'] == 1)
455
                    || (int) $session->get('user-can_create_root_folder') === 1
456
                )
457
            ) {
458
                echo prepareExchangedData(
459
                    array(
460
                        'error' => true,
461
                        'message' => $lang->get('error_not_allowed_to'),
462
                    ),
463
                    'encode'
464
                );
465
                break;
466
            }
467
468
            // Prepare update parameters
469
            $folderParameters = array(
470
                'parent_id' => $inputData['parentId'],
471
                'title' => $inputData['title'],
472
                'personal_folder' => $isPersonal,
473
                'fa_icon' => empty($inputData['icon']) === true ? TP_DEFAULT_ICON : $inputData['icon'],
474
                'fa_icon_selected' => empty($inputData['icon_selected']) === true ? TP_DEFAULT_ICON_SELECTED : $inputData['icon_selected'],
475
            );
476
            
477
            if ($inputData['duration'] !== -1 && $dataFolder['renewal_period'] !== $inputData['duration']) {
478
                $folderParameters['renewal_period'] = $inputData['duration'];
479
            }
480
            if ($inputData['create_auth_without'] !== -1 && $dataFolder['bloquer_creation'] !== $inputData['create_auth_without']) {
481
                $folderParameters['bloquer_creation'] = $inputData['create_auth_without'];
482
            }
483
            if ($inputData['edit_auth_without'] !== -1 && $dataFolder['bloquer_modification'] !== $inputData['edit_auth_without']) {
484
                $folderParameters['bloquer_modification'] = $inputData['edit_auth_without'];
485
            }
486
            
487
            // Now update
488
            DB::update(
489
                prefixTable('nested_tree'),
490
                $folderParameters,
491
                'id=%i',
492
                $dataFolder['id']
493
            );
494
495
            // Update timestamp
496
            DB::update(
497
                prefixTable('misc'),
498
                array(
499
                    'valeur' => time(),
500
                    'updated_at' => time(),
501
                ),
502
                'type = %s AND intitule = %s',
503
                'timestamp',
504
                'last_folder_change'
505
            );
506
507
            //Add complexity
508
            DB::update(
509
                prefixTable('misc'),
510
                array(
511
                    'valeur' => $inputData['complexity'],
512
                    'updated_at' => time(),
513
                ),
514
                'intitule = %s AND type = %s',
515
                $dataFolder['id'],
516
                'complex'
517
            );
518
519
            // ensure categories are set
520
            handleFoldersCategories(
521
                [$dataFolder['id']]
522
            );
523
524
            $tree->rebuild();
525
526
            echo prepareExchangedData(
527
                array(
528
                    'error' => $error,
529
                    'message' => $errorMessage,
530
                    'info_parent_changed' => $parentChanged,
531
                ),
532
                'encode'
533
            );
534
535
            break;
536
537
        //CASE where ADDING a new group
538
        case 'add_folder':
539
            // Check KEY
540
            if ($post_key !== $session->get('key')) {
541
                echo prepareExchangedData(
542
                    array(
543
                        'error' => true,
544
                        'message' => $lang->get('key_is_not_correct'),
545
                    ),
546
                    'encode'
547
                );
548
                break;
549
            } elseif ($session->get('user-read_only') === 1) {
550
                echo prepareExchangedData(
551
                    array(
552
                        'error' => true,
553
                        'message' => $lang->get('error_not_allowed_to'),
554
                    ),
555
                    'encode'
556
                );
557
                break;
558
            }
559
560
            // decrypt and retrieve data in JSON format
561
            $dataReceived = prepareExchangedData(
562
                $post_data,
563
                'decode'
564
            );
565
566
            // prepare variables
567
            $data = [
568
                'title' => isset($dataReceived['title']) === true ? $dataReceived['title'] : '',
569
                'parentId' => isset($dataReceived['parentId']) === true ? $dataReceived['parentId'] : 0,
570
                'complexity' => isset($dataReceived['complexity']) === true ? $dataReceived['complexity'] : '',
571
                'duration' => isset($dataReceived['renewalPeriod']) === true ? $dataReceived['renewalPeriod'] : 0,
572
                'create_auth_without' => isset($dataReceived['addRestriction']) === true ? $dataReceived['addRestriction'] : 0,
573
                'edit_auth_without' => isset($dataReceived['editRestriction']) === true ? $dataReceived['editRestriction'] : 0,
574
                'icon' => isset($dataReceived['icon']) === true ? $dataReceived['icon'] : '',
575
                'icon_selected' => isset($dataReceived['iconSelected']) === true ? $dataReceived['iconSelected'] : '',
576
                'access_rights' => isset($dataReceived['accessRight']) === true ? $dataReceived['accessRight'] : 'W',
577
            ];            
578
            $filters = [
579
                'title' => 'trim|escape',
580
                'parentId' => 'cast:integer',
581
                'complexity' => 'cast:integer',
582
                'duration' => 'cast:integer',
583
                'create_auth_without' => 'cast:integer',
584
                'edit_auth_without' => 'cast:integer',
585
                'icon' => 'trim|escape',
586
                'icon_selected' => 'trim|escape',
587
                'access_rights' => 'trim|escape',
588
            ];            
589
            $inputData = dataSanitizer(
590
                $data,
591
                $filters
592
            );
593
594
            // Check if parent folder is personal
595
            $dataParent = DB::queryFirstRow(
596
                'SELECT personal_folder
597
                FROM ' . prefixTable('nested_tree') . '
598
                WHERE id = %i',
599
                $inputData['parentId']
600
            );
601
602
            $isPersonal = (isset($dataParent['personal_folder']) === true && (int) $dataParent['personal_folder'] == 1) ? 1 : 0;
603
604
            // Create folder
605
            require_once 'folders.class.php';
606
            $folderManager = new FolderManager($lang);
0 ignored issues
show
The type FolderManager was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
607
            $params = [
608
                'title' => (string) $inputData['title'],
609
                'parent_id' => (int) $inputData['parentId'],
610
                'personal_folder' => (int) $isPersonal,
611
                'complexity' => (int) $inputData['complexity'],
612
                'duration' => (int) $inputData['duration'],
613
                'create_auth_without' => (int) $inputData['create_auth_without'],
614
                'edit_auth_without' => (int) $inputData['edit_auth_without'],
615
                'icon' => (string) $inputData['icon'],
616
                'icon_selected' => (string) $inputData['icon_selected'],
617
                'access_rights' => (string) $inputData['access_rights'],
618
                'user_is_admin' => (int) $session->get('user-admin'),
619
                'user_accessible_folders' => (array) $session->get('user-accessible_folders'),
620
                'user_is_manager' => (int) $session->get('user-manager'),
621
                'user_can_create_root_folder' => (int) $session->get('user-can_create_root_folder'),
622
                'user_can_manage_all_users' => (int) $session->get('user-can_manage_all_users'),
623
                'user_id' => (int) $session->get('user-id'),
624
                'user_roles' => (string) $session->get('user-roles')
625
            ];
626
            $options = [
627
                'rebuildFolderTree' => true,
628
                'setFolderCategories' => false,
629
                'manageFolderPermissions' => true,
630
                'copyCustomFieldsCategories' => false,
631
                'refreshCacheForUsersWithSimilarRoles' => true,
632
            ];
633
            $creationStatus = $folderManager->createNewFolder($params, $options);
634
635
            // User created the folder
636
            // Add new ID to list of visible ones
637
            if ((int) $session->get('user-admin') === 0 && $creationStatus['error'] === false && $creationStatus['newId'] !== 0) {
638
                SessionManager::addRemoveFromSessionArray('user-accessible_folders', [$creationStatus['newId']], 'add');
639
            }
640
641
            echo prepareExchangedData(
642
                array(
643
                    'error' => $creationStatus['error'],
644
                    'message' => $creationStatus['error'] === true ? $lang->get('error_not_allowed_to') : $lang->get('folder_created') ,
645
                    'newId' => $creationStatus['newId'],
646
                ),
647
                'encode'
648
            );
649
650
            break;
651
652
        // CASE where DELETING multiple groups
653
        case 'delete_folders':
654
            // Check KEY
655
            if ($post_key !== $session->get('key')) {
656
                echo prepareExchangedData(
657
                    array(
658
                        'error' => true,
659
                        'message' => $lang->get('key_is_not_correct'),
660
                    ),
661
                    'encode'
662
                );
663
                break;
664
            } elseif ($session->get('user-read_only') === 1) {
665
                echo prepareExchangedData(
666
                    array(
667
                        'error' => true,
668
                        'message' => $lang->get('error_not_allowed_to'),
669
                    ),
670
                    'encode'
671
                );
672
                break;
673
            }
674
675
            // decrypt and retrieve data in JSON format
676
            $dataReceived = prepareExchangedData(
677
                $post_data,
678
                'decode'
679
            );
680
681
            // prepare variables
682
            $post_folders = filter_var_array(
683
                $dataReceived['selectedFolders'],
684
                FILTER_SANITIZE_FULL_SPECIAL_CHARS
685
            );
686
687
            // Ensure that the root folder is not part of the list
688
            if (in_array(0, $post_folders, true)) {
689
                echo prepareExchangedData(
690
                    array(
691
                        'error' => true,
692
                        'message' => $lang->get('error_not_allowed_to'). " (You can't delete the root folder)",
693
                    ),
694
                    'encode'
695
                );
696
                break;
697
            }
698
            
699
            // Ensure that user has access to all folders
700
            $foldersAccessible = DB::query(
701
                'SELECT id
702
                FROM ' . prefixTable('nested_tree') . '
703
                WHERE id IN %li AND id IN %li',
704
                $post_folders,
705
                $session->get('user-accessible_folders')
706
            );
707
            // Extract found folder IDs
708
            $accessibleIds = array_column($foldersAccessible, 'id');
709
            // Identify those that are not existing in DB or not visible by user
710
            $missingFolders = array_diff($post_folders, $accessibleIds);
711
            if (!empty($missingFolders)) {
712
                // There is some issues
713
                echo prepareExchangedData(
714
                    array(
715
                        'error' => true,
716
                        'message' => $lang->get('error_not_allowed_to') . ' (The following folders are not accessible or do not exist: ' . implode(', ', $missingFolders) . ')',
717
                    ),
718
                    'encode'
719
                );
720
                break;
721
            }
722
723
            //decrypt and retreive data in JSON format
724
            $folderForDel = array();
725
726
            // Start transaction
727
            DB::startTransaction();
728
729
            foreach ($post_folders as $folderId) {
730
                // Check if parent folder is personal
731
                $dataParent = DB::queryFirstRow(
732
                    'SELECT personal_folder
733
                    FROM ' . prefixTable('nested_tree') . '
734
                    WHERE id = %i',
735
                    $folderId
736
                );
737
738
                $isPersonal = (isset($dataParent['personal_folder']) === true && (int) $dataParent['personal_folder'] === 1) ? 1 : 0;
739
740
                // Check if user is allowed
741
                if (
742
                    !(
743
                        (int) $isPersonal === 1
744
                        || (int) $session->get('user-admin') === 1
745
                        || (int) $session->get('user-manager') === 1
746
                        || (int) $session->get('user-can_manage_all_users') === 1
747
                        || (isset($SETTINGS['enable_user_can_create_folders']) === true
748
                            && (int) $SETTINGS['enable_user_can_create_folders'] == 1)
749
                        || (int) $session->get('user-can_create_root_folder') === 1
750
                    )
751
                ) {
752
                    echo prepareExchangedData(
753
                        array(
754
                            'error' => true,
755
                            'message' => $lang->get('error_not_allowed_to'),
756
                        ),
757
                        'encode'
758
                    );
759
760
                    // Rollback transaction if error
761
                    DB::rollback();
762
763
                    exit;
764
                }
765
766
                // Exclude a folder with id already in the list
767
                if (in_array($folderId, $folderForDel) === false) {
768
                    // Get through each subfolder
769
                    $subFolders = $tree->getDescendants($folderId, true);
770
                    foreach ($subFolders as $thisSubFolders) {
771
                        if ($thisSubFolders->parent_id >= 0
772
                            && $thisSubFolders->title !== $session->get('user-id')
773
                        ) {
774
                            //Store the deleted folder (recycled bin)
775
                            DB::insert(
776
                                prefixTable('misc'),
777
                                array(
778
                                    'type' => 'folder_deleted',
779
                                    'intitule' => 'f' . $thisSubFolders->id,
780
                                    'valeur' => $thisSubFolders->id . ', ' . $thisSubFolders->parent_id . ', ' .
781
                                        $thisSubFolders->title . ', ' . $thisSubFolders->nleft . ', ' . $thisSubFolders->nright . ', ' .
782
                                        $thisSubFolders->nlevel . ', 0, 0, 0, 0',
783
                                    'created_at' => time(),
784
                                )
785
                            );
786
                            //array for delete folder
787
                            $folderForDel[] = $thisSubFolders->id;
788
789
                            //delete items & logs
790
                            $itemsInSubFolder = DB::query(
791
                                'SELECT id FROM ' . prefixTable('items') . ' 
792
                                WHERE id_tree=%i', 
793
                                $thisSubFolders->id
794
                            );
795
                            foreach ($itemsInSubFolder as $item) {
796
                                DB::update(
797
                                    prefixTable('items'),
798
                                    array(
799
                                        'inactif' => '1',
800
                                    ),
801
                                    'id = %i',
802
                                    $item['id']
803
                                );
804
805
                                // log
806
                                logItems(
807
                                    $SETTINGS,
808
                                    (int) $item['id'],
809
                                    '',
810
                                    $session->get('user-id'),
811
                                    'at_delete',
812
                                    $session->get('user-login')
813
                                );
814
815
                                // delete folder from SESSION
816
                                if (array_search($item['id'], $session->get('user-accessible_folders')) !== false) {
817
                                    SessionManager::addRemoveFromSessionArray('user-accessible_folders', [$item['id']], 'remove');
818
                                }
819
820
                                //Update CACHE table
821
                                updateCacheTable('delete_value',(int) $item['id']);
822
                            }
823
824
                            //Actualize the variable
825
                            $session->set('user-nb_folders', $session->get('user-nb_folders') - 1);
826
                        }
827
                    }
828
                }
829
            }
830
831
            // Add new task for building user cache tree
832
            if ((int) $session->get('user-admin') !== 1) {
833
                DB::insert(
834
                    prefixTable('background_tasks'),
835
                    array(
836
                        'created_at' => time(),
837
                        'process_type' => 'user_build_cache_tree',
838
                        'arguments' => json_encode([
839
                            'user_id' => (int) $session->get('user-id'),
840
                        ], JSON_HEX_QUOT | JSON_HEX_TAG),
841
                        'updated_at' => null,
842
                        'finished_at' => null,
843
                        'output' => null,
844
                    )
845
                );
846
            }
847
848
            // delete folders
849
            $folderForDel = array_unique($folderForDel);
850
            foreach ($folderForDel as $fol) {
851
                DB::delete(prefixTable('nested_tree'), 'id = %i', $fol);
852
            }
853
854
            // Update timestamp
855
            DB::update(
856
                prefixTable('misc'),
857
                array(
858
                    'valeur' => time(),
859
                    'updated_at' => time(),
860
                ),
861
                'type = %s AND intitule = %s',
862
                'timestamp',
863
                'last_folder_change'
864
            );
865
866
            // Commit transaction
867
            DB::commit();
868
869
            //rebuild tree
870
            $tree->rebuild();
871
872
            echo prepareExchangedData(
873
                array(
874
                    'error' => false,
875
                    'message' => '',
876
                ),
877
                'encode'
878
            );
879
880
            break;
881
882
        case 'copy_folder':
883
            // Check KEY
884
            if ($post_key !== $session->get('key')) {
885
                echo prepareExchangedData(
886
                    array(
887
                        'error' => true,
888
                        'message' => $lang->get('key_is_not_correct'),
889
                    ),
890
                    'encode'
891
                );
892
                break;
893
            } elseif ($session->get('user-read_only') === 1) {
894
                echo prepareExchangedData(
895
                    array(
896
                        'error' => true,
897
                        'message' => $lang->get('error_not_allowed_to'),
898
                    ),
899
                    'encode'
900
                );
901
                break;
902
            }
903
904
            // decrypt and retrieve data in JSON format
905
            $dataReceived = prepareExchangedData(
906
                $post_data,
907
                'decode'
908
            );
909
910
            // Init post variables
911
            $post_source_folder_id = filter_var($dataReceived['source_folder_id'], FILTER_SANITIZE_NUMBER_INT);
912
            $post_target_folder_id = filter_var($dataReceived['target_folder_id'], FILTER_SANITIZE_NUMBER_INT);
913
            $post_folder_label = filter_var($dataReceived['folder_label'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
914
915
            // Test if target folder is Read-only
916
            // If it is then stop
917
            if (in_array($post_target_folder_id, $session->get('user-read_only_folders')) === true) {
918
                echo prepareExchangedData(
919
                    array(
920
                        'error' => true,
921
                        'message' => $lang->get('error_not_allowed_to'),
922
                    ),
923
                    'encode'
924
                );
925
                break;
926
            }
927
928
            // Check if target parent folder is personal
929
            $dataParent = DB::queryFirstRow(
930
                'SELECT personal_folder
931
                FROM ' . prefixTable('nested_tree') . '
932
                WHERE id = %i',
933
                $post_target_folder_id
934
            );
935
936
            $isPersonal = (isset($dataParent['personal_folder']) === true && (int) $dataParent['personal_folder'] === 1) ? 1 : 0;
937
938
            // Check if user is allowed
939
            if (
940
                !(
941
                    (int) $isPersonal === 1
942
                    || (int) $session->get('user-admin') === 1
943
                    || (int) $session->get('user-manager') === 1
944
                    || (int) $session->get('user-can_manage_all_users') === 1
945
                    || (isset($SETTINGS['enable_user_can_create_folders']) === true
946
                        && (int) $SETTINGS['enable_user_can_create_folders'] == 1)
947
                    || (int) $session->get('user-can_create_root_folder') === 1
948
                )
949
            ) {
950
                echo prepareExchangedData(
951
                    array(
952
                        'error' => true,
953
                        'message' => $lang->get('error_not_allowed_to'),
954
                    ),
955
                    'encode'
956
                );
957
                break;
958
            }
959
960
            // Get all allowed folders
961
            $array_all_visible_folders = array_merge(
962
                $session->get('user-accessible_folders'),
963
                $session->get('user-read_only_folders'),
964
                $session->get('user-personal_visible_folders')
965
            );
966
967
            // get list of all folders
968
            $nodeDescendants = $tree->getDescendants($post_source_folder_id, true, false, false);
969
            $parentId = '';
970
            $tabNodes = [];
971
            foreach ($nodeDescendants as $node) {
972
                // step1 - copy folder
973
974
                // Can user access this subfolder?
975
                if (in_array($node->id, $array_all_visible_folders) === false) {
976
                    continue;
977
                }
978
979
                // get info about current node
980
                $nodeInfo = $tree->getNode($node->id);
981
982
                // get complexity of current node
983
                $nodeComplexity = DB::queryFirstRow(
984
                    'SELECT valeur
985
                    FROM ' . prefixTable('misc') . '
986
                    WHERE intitule = %i AND type= %s',
987
                    $nodeInfo->id,
988
                    'complex'
989
                );
990
991
                // prepare parent Id
992
                if (empty($parentId) === true) {
993
                    $parentId = $post_target_folder_id;
994
                } else {
995
                    $parentId = $tabNodes[$nodeInfo->parent_id];
996
                }
997
998
                //create folder
999
                DB::insert(
1000
                    prefixTable('nested_tree'),
1001
                    array(
1002
                        'parent_id' => $parentId,
1003
                        'title' => count($tabNodes) === 0 ? $post_folder_label : $nodeInfo->title,
1004
                        'personal_folder' => $nodeInfo->personal_folder,
1005
                        'renewal_period' => $nodeInfo->renewal_period,
1006
                        'bloquer_creation' => $nodeInfo->bloquer_creation,
1007
                        'bloquer_modification' => $nodeInfo->bloquer_modification,
1008
                        'categories'  => '',
1009
                    )
1010
                );
1011
                $newFolderId = DB::insertId();
1012
1013
                // add to correspondance matrix
1014
                $tabNodes[$nodeInfo->id] = $newFolderId;
1015
1016
                //Add complexity
1017
                DB::insert(
1018
                    prefixTable('misc'),
1019
                    array(
1020
                        'type' => 'complex',
1021
                        'intitule' => $newFolderId,
1022
                        'valeur' => is_null($nodeComplexity['valeur']) === false ? $nodeComplexity['valeur'] : 0,
1023
                        'created_at' => time(),
1024
                    )
1025
                );
1026
1027
                // add new folder id in SESSION
1028
                $session->set('user-accessible_folders', array_unique(array_merge($session->get('user-accessible_folders'), [$newFolderId]), SORT_NUMERIC));
1029
                if ((int) $nodeInfo->personal_folder === 1) {
1030
                    SessionManager::addRemoveFromSessionArray('user-personal_folders', [$newFolderId], 'add');
1031
                    SessionManager::addRemoveFromSessionArray('user-personal_visible_folders', [$newFolderId], 'add');
1032
                }
1033
1034
                // If new folder should not heritate of parent rights
1035
                // Then use the creator ones
1036
                if (
1037
                    (int) $nodeInfo->personal_folder !== 1
1038
                    && isset($SETTINGS['subfolder_rights_as_parent']) === true
1039
                    && (int) $SETTINGS['subfolder_rights_as_parent'] === 1
1040
                    && (int) $session->get('user-admin') === 0
1041
                ) {
1042
                    //add access to this new folder
1043
                    foreach (explode(';', $session->get('user-roles')) as $role) {
1044
                        if (empty($role) === false) {
1045
                            DB::insertUpdate(
1046
                                prefixTable('roles_values'),
1047
                                array(
1048
                                    'role_id' => $role,
1049
                                    'folder_id' => $newFolderId,
1050
                                    'type' => 'W',
1051
                                )
1052
                            );
1053
                        }
1054
                    }
1055
                }
1056
1057
                // If it is a subfolder, then give access to it for all roles that allows the parent folder
1058
                $rows = DB::query(
1059
                    'SELECT role_id, type
1060
                    FROM ' . prefixTable('roles_values') . '
1061
                    WHERE folder_id = %i',
1062
                    $parentId
1063
                );
1064
                foreach ($rows as $record) {
1065
                    // Add access to this subfolder
1066
                    DB::insertUpdate(
1067
                        prefixTable('roles_values'),
1068
                        array(
1069
                            'role_id' => $record['role_id'],
1070
                            'folder_id' => $newFolderId,
1071
                            'type' => $record['type'],
1072
                        )
1073
                    );
1074
                }
1075
1076
                // if parent folder has Custom Fields Categories then add to this child one too
1077
                $rows = DB::query(
1078
                    'SELECT id_category
1079
                    FROM ' . prefixTable('categories_folders') . '
1080
                    WHERE id_folder = %i',
1081
                    $nodeInfo->id
1082
                );
1083
                foreach ($rows as $record) {
1084
                    //add CF Category to this subfolder
1085
                    DB::insert(
1086
                        prefixTable('categories_folders'),
1087
                        array(
1088
                            'id_category' => $record['id_category'],
1089
                            'id_folder' => $newFolderId,
1090
                        )
1091
                    );
1092
                }
1093
1094
                // step2 - copy items
1095
1096
                $rows = DB::query(
1097
                    'SELECT *
1098
                    FROM ' . prefixTable('items') . '
1099
                    WHERE id_tree = %i',
1100
                    $nodeInfo->id
1101
                );
1102
                foreach ($rows as $record) {
1103
                    // check if item is deleted
1104
                    // if it is then don't copy it
1105
                    $item_deleted = DB::queryFirstRow(
1106
                        'SELECT *
1107
                        FROM ' . prefixTable('log_items') . '
1108
                        WHERE id_item = %i AND action = %s
1109
                        ORDER BY date DESC
1110
                        LIMIT 0, 1',
1111
                        $record['id'],
1112
                        'at_delete'
1113
                    );
1114
                    $dataDeleted = DB::count();
1115
1116
                    $item_restored = DB::queryFirstRow(
1117
                        'SELECT *
1118
                        FROM ' . prefixTable('log_items') . '
1119
                        WHERE id_item = %i AND action = %s
1120
                        ORDER BY date DESC
1121
                        LIMIT 0, 1',
1122
                        $record['id'],
1123
                        'at_restored'
1124
                    );
1125
1126
                    if (
1127
                        (int) $dataDeleted !== 1
1128
                        || (isset($item_restored['date']) === true && (int) $item_deleted['date'] < (int) $item_restored['date'])
1129
                    ) {
1130
                        // Get the ITEM object key for the user
1131
                        $userKey = DB::queryFirstRow(
1132
                            'SELECT share_key
1133
                            FROM ' . prefixTable('sharekeys_items') . '
1134
                            WHERE user_id = %i AND object_id = %i',
1135
                            $session->get('user-id'),
1136
                            $record['id']
1137
                        );
1138
                        if (DB::count() === 0) {
1139
                            // ERROR - No sharekey found for this item and user
1140
                            echo prepareExchangedData(
1141
                                array(
1142
                                    'error' => true,
1143
                                    'message' => $lang->get('error_not_allowed_to'),
1144
                                ),
1145
                                'encode'
1146
                            );
1147
                            break;
1148
                        }
1149
                        
1150
1151
                        // Decrypt / Encrypt the password
1152
                        $cryptedStuff = doDataEncryption(
1153
                            base64_decode(
1154
                                doDataDecryption(
1155
                                    $record['pw'],
1156
                                    decryptUserObjectKey(
1157
                                        $userKey['share_key'],
1158
                                        $session->get('user-private_key')
1159
                                    )
1160
                                )
1161
                            )
1162
                        );
1163
1164
                        // Insert the new record and get the new auto_increment id
1165
                        DB::insert(
1166
                            prefixTable('items'),
1167
                            array(
1168
                                'label' => substr($record['label'], 0, 500),
1169
                                'description' => empty($record['description']) === true ? '' : $record['description'],
1170
                                'id_tree' => $newFolderId,
1171
                                'pw' => $cryptedStuff['encrypted'],
1172
                                'pw_iv' => '',
1173
                                'url' => empty($record['url']) === true ? '' : substr($record['url'], 0, 500),
1174
                                'login' => empty($record['login']) === true ? '' : substr($record['login'], 0, 200),
1175
                                'viewed_no' => 0,
1176
                                'encryption_type' => 'teampass_aes',
1177
                                'item_key' => uniqidReal(50),
1178
                                'created_at' => time(),
1179
                            )
1180
                        );
1181
                        $newItemId = DB::insertId();
1182
1183
                        // Create task for the new item
1184
                        storeTask(
1185
                            'item_copy',
1186
                            $session->get('user-id'),
1187
                            (int) $nodeInfo->personal_folder,
1188
                            (int) $newFolderId,
1189
                            (int) $newItemId,
1190
                            $cryptedStuff['objectKey'],
1191
                        );
1192
1193
                        // Add this duplicate in logs
1194
                        logItems(
1195
                            $SETTINGS,
1196
                            (int) $newItemId,
1197
                            $record['label'],
1198
                            $session->get('user-id'),
1199
                            'at_creation',
1200
                            $session->get('user-login')
1201
                        );
1202
                        // Add the fact that item has been copied in logs
1203
                        logItems(
1204
                            $SETTINGS,
1205
                            (int) $newItemId,
1206
                            $record['label'],
1207
                            $session->get('user-id'),
1208
                            'at_copy',
1209
                            $session->get('user-login')
1210
                        );
1211
1212
                        // Add item to cache table
1213
                        updateCacheTable('add_value', (int) $newItemId);
1214
                    }
1215
                }
1216
            }
1217
1218
            // rebuild tree
1219
            $tree->rebuild();
1220
1221
            // Update timestamp
1222
            DB::update(
1223
                prefixTable('misc'),
1224
                array(
1225
                    'valeur' => time(),
1226
                    'updated_at' => time(),
1227
                ),
1228
                'type = %s AND intitule = %s',
1229
                'timestamp',
1230
                'last_folder_change'
1231
            );
1232
1233
            $data = array(
1234
                'error' => '',
1235
            );
1236
1237
            // send data
1238
            echo prepareExchangedData(
1239
                $data,
1240
                'encode'
1241
            );
1242
1243
            break;
1244
1245
        // CASE where selecting/deselecting sub-folders
1246
        case 'refresh_folders_list':
1247
            // Check KEY
1248
            if ($post_key !== $session->get('key')) {
1249
                echo prepareExchangedData(
1250
                    array(
1251
                        'error' => true,
1252
                        'message' => $lang->get('key_is_not_correct'),
1253
                    ),
1254
                    'encode'
1255
                );
1256
                break;
1257
            } elseif ($session->get('user-read_only') === 1) {
1258
                echo prepareExchangedData(
1259
                    array(
1260
                        'error' => true,
1261
                        'message' => $lang->get('error_not_allowed_to'),
1262
                    ),
1263
                    'encode'
1264
                );
1265
                break;
1266
            }
1267
1268
            $subfolders = array();
1269
1270
            if ((int) $session->get('user-admin') === 1 || (int) $session->get('user-manager') === 1 || (int) $session->get('user-can_create_root_folder') === 1) {
1271
                array_push(
1272
                    $subfolders,
1273
                    array(
1274
                        'id' => 0,
1275
                        'label' => $lang->get('root'),
1276
                        'level' => 0,
1277
                        'path' => ''
1278
                    )
1279
                );
1280
            }
1281
1282
            // get sub folders
1283
1284
            // Get through each subfolder
1285
            $folders = $tree->getDescendants(0, false);
1286
            
1287
            foreach ($folders as $folder) {
1288
                if (
1289
                    in_array($folder->id, $session->get('user-accessible_folders')) === true
1290
                    && in_array($folder->id, $session->get('user-personal_visible_folders')) === false
1291
                ) {
1292
                    // Get path
1293
                    $text = '';
1294
                    foreach ($tree->getPath($folder->id, false) as $fld) {
1295
                        $text .= empty($text) === true ? '     [<i>' . $fld->title : ' > ' . $fld->title;
1296
                    }
1297
1298
                    // Save array
1299
                    array_push(
1300
                        $subfolders,
1301
                        array(
1302
                            'id' => (int) $folder->id,
1303
                            'label' => $folder->title,
1304
                            'level' => $folder->nlevel,
1305
                            'path' => empty($text) === true ? '' : $text . '</i>]'
1306
                        )
1307
                    );
1308
                }
1309
            }
1310
1311
            echo prepareExchangedData(
1312
                array(
1313
                    'error' => false,
1314
                    'subfolders' => ($subfolders),
1315
                ),
1316
                'encode'
1317
            );
1318
1319
            break;
1320
    }
1321
}
1322