Passed
Push — teampass_3.0 ( 09962f...7cabaf )
by Nils
04:19
created

recursive()   D

Complexity

Conditions 21
Paths 8

Size

Total Lines 73
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 21
eloc 45
nc 8
nop 4
dl 0
loc 73
rs 4.1666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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      import.queries.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
use Goodby\CSV\Import\Standard\Lexer;
24
use Goodby\CSV\Import\Standard\Interpreter;
25
use Goodby\CSV\Import\Standard\LexerConfig;
26
27
require_once 'SecureHandler.php';
28
session_name('teampass_session');
29
session_start();
30
if (!isset($_SESSION['CPM']) || $_SESSION['CPM'] === false || !isset($_SESSION['key']) || empty($_SESSION['key'])) {
31
    die('Hacking attempt...');
32
}
33
34
// Load config
35
if (file_exists('../includes/config/tp.config.php')) {
36
    include_once '../includes/config/tp.config.php';
37
} elseif (file_exists('./includes/config/tp.config.php')) {
38
    include_once './includes/config/tp.config.php';
39
} else {
40
    throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
41
}
42
43
// Do checks
44
require_once $SETTINGS['cpassman_dir'].'/includes/config/include.php';
45
require_once $SETTINGS['cpassman_dir'].'/sources/checks.php';
46
if (checkUser($_SESSION['user_id'], $_SESSION['key'], 'items', $SETTINGS) === false) {
47
    // Not allowed page
48
    $_SESSION['error']['code'] = ERR_NOT_ALLOWED;
49
    include $SETTINGS['cpassman_dir'].'/error.php';
50
    exit();
51
}
52
53
/*
54
 * Define Timezone
55
**/
56
if (isset($SETTINGS['timezone']) === true) {
57
    date_default_timezone_set($SETTINGS['timezone']);
58
} else {
59
    date_default_timezone_set('UTC');
60
}
61
62
require_once $SETTINGS['cpassman_dir'].'/includes/language/'.$_SESSION['user_language'].'.php';
63
require_once $SETTINGS['cpassman_dir'].'/includes/config/settings.php';
64
header('Content-type: text/html; charset=utf-8');
65
header('Cache-Control: no-cache, must-revalidate');
66
require_once 'main.functions.php';
67
68
// No time limit
69
set_time_limit(0);
70
71
// Set some constants for program readability
72
define('KP_PATH', 0);
73
define('KP_GROUP', 1);
74
define('KP_TITLE', 2);
75
define('KP_PASSWORD', 3);
76
define('KP_USERNAME', 4);
77
define('KP_URL', 5);
78
define('KP_UUID', 6);
79
define('KP_NOTES', 7);
80
81
// Connect to mysql server
82
require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
83
if (defined('DB_PASSWD_CLEAR') === false) {
84
    define('DB_PASSWD_CLEAR', defuseReturnDecrypted(DB_PASSWD, $SETTINGS));
85
}
86
87
// Class loader
88
require_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php';
89
90
//Load Tree
91
$tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
92
$tree->register();
93
$tree = new Tree\NestedTree\NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
94
95
//Load AES
96
$aes = new SplClassLoader('Encryption\Crypt', '../includes/libraries');
97
$aes->register();
98
99
//User's language loading
100
require_once $SETTINGS['cpassman_dir'].'/includes/language/'.$_SESSION['user_language'].'.php';
101
102
// POST Varaibles
103
$post_key = filter_input(INPUT_POST, 'key', FILTER_SANITIZE_STRING);
104
$post_data = filter_input(INPUT_POST, 'data', FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
105
106
// Build query
107
switch (filter_input(INPUT_POST, 'type', FILTER_SANITIZE_STRING)) {
108
    //Check if import CSV file format is what expected
109
    case 'import_file_format_csv':
110
        // Check KEY and rights
111
        if ($post_key !== $_SESSION['key']) {
112
            echo prepareExchangedData(
113
    $SETTINGS['cpassman_dir'],
114
                array(
115
                    'error' => true,
116
                    'message' => langHdl('key_is_not_correct'),
117
                ),
118
                'encode'
119
            );
120
            break;
121
        }
122
123
        //load full tree
124
        $tree->rebuild();
125
        $tree = $tree->getDescendants();
126
127
        // Init post variable
128
        $post_operation_id = filter_input(INPUT_POST, 'file', FILTER_SANITIZE_NUMBER_INT);
129
130
        // Get filename from database
131
        $data = DB::queryFirstRow(
132
            'SELECT valeur
133
            FROM '.prefixTable('misc').'
134
            WHERE increment_id = %i AND type = "temp_file"',
135
            $post_operation_id
136
        );
137
138
        // Delete operation id
139
        DB::delete(
140
            prefixTable('misc'),
141
            "increment_id = %i AND type = 'temp_file'",
142
            $post_operation_id
143
        );
144
145
        // do some initializations
146
        $file = $SETTINGS['path_to_files_folder'].'/'.$data['valeur'];
147
        $importation_possible = true;
148
        $itemsArray = array();
149
        $line_number = 0;
150
        $account = $text = '';
151
        $continue_on_next_line = false;
152
153
        // Open file
154
        if ($fp = fopen($file, 'r')) {
155
            // data from CSV
156
            $valuesToImport = array();
157
            // load libraries
158
            include_once $SETTINGS['cpassman_dir'].'/includes/libraries/Goodby/CSV/Import/Standard/Lexer.php';
159
            include_once $SETTINGS['cpassman_dir'].'/includes/libraries/Goodby/CSV/Import/Standard/Interpreter.php';
160
            include_once $SETTINGS['cpassman_dir'].'/includes/libraries/Goodby/CSV/Import/Standard/LexerConfig.php';
161
162
            // Lexer configuration
163
            $config = new LexerConfig();
164
            $lexer = new Lexer($config);
165
            $config->setIgnoreHeaderLine('true');
166
            // extract data from CSV file
167
            $interpreter = new Interpreter();
168
            $interpreter->addObserver(function (array $row) use (&$valuesToImport) {
169
                $valuesToImport[] = array(
170
                    'Label' => $row[0],
171
                    'Login' => $row[1],
172
                    'Password' => $row[2],
173
                    'url' => $row[3],
174
                    'Comments' => $row[4],
175
                );
176
            });
177
            $lexer->parse($file, $interpreter);
178
179
            // extract one line
180
            foreach ($valuesToImport as $key => $row) {
181
                //increment number of lines found
182
                ++$line_number;
183
184
                //Check number of fields. MUST be 5. if not stop importation
185
                if (count($row) != 5) {
186
                    $importation_possible = false;
187
                    //Stop if file has not expected structure
188
                    if ($importation_possible === false) {
189
                        echo '[{"error":"bad_structure"}]';
190
                        break;
191
                    }
192
                }
193
194
                //If any comment is on several lines, then replace 'lf' character
195
                $row['Comments'] = str_replace(array("\r\n", "\n", "\r"), '<br>', $row['Comments']);
196
197
                // Check if current line contains a "<br>" character in order to identify an ITEM on several CSV lines
198
                if (substr_count($row['Comments'], '<br>') > 0 || substr_count($row['Label'], '<br>') > 0) {
199
                    $continue_on_next_line = true;
200
                    $comment .= addslashes($row['Label']);
201
                } else {
202
                    // Store in variable values from previous line
203
                    if (empty($account) === false) {
204
                        if ($continue_on_next_line === false) {
205
                            // Prepare listing that will be shown to user
206
                            array_push(
207
                                $itemsArray,
208
                                array(
209
                                    'label' => $account,
210
                                    'login' => $login,
211
                                    'pwd' => $pwd,
212
                                    'url' => $url,
213
                                    'comment' => $comment,
214
                                    'label' => $account,
215
                                    'label' => $account,
216
                                )
217
                            );
218
219
                            // Initialize this variable in order to restart from scratch
220
                            $account = '';
221
                        }
222
                    }
223
                }
224
225
                // Get values of current line
226
                if ($account === '' && $continue_on_next_line === false) {
227
                    $account = trim(htmlspecialchars($row['Label'], ENT_QUOTES, 'UTF-8'));
228
                    $login = trim(htmlspecialchars($row['Login'], ENT_QUOTES, 'UTF-8'));
229
                    $pwd = trim(str_replace('"', '&quot;', $row['Password']));
230
                    $url = trim($row['url']);
231
                    $to_find = array('"', "'");
232
                    $to_ins = array('&quot', '&#39;');
233
                    $comment = htmlentities(
234
                        addslashes(str_replace($to_find, $to_ins, $row['Comments'])),
235
                        ENT_QUOTES,
236
                        'UTF-8'
237
                    );
238
239
                    $continue_on_next_line = false;
240
                }
241
            }
242
            // close file
243
            fclose($fp);
244
        } else {
245
            echo prepareExchangedData(
246
    $SETTINGS['cpassman_dir'],
247
                array(
248
                    'error' => true,
249
                    'message' => langHdl('cannot_open_file'),
250
                ),
251
                'encode'
252
            );
253
254
            //delete file
255
            unlink($file);
256
            break;
257
        }
258
259
        if ($line_number > 0) {
260
            array_push(
261
                $itemsArray,
262
                array(
263
                    'label' => $account,
264
                    'login' => $login,
265
                    'pwd' => $pwd,
266
                    'url' => $url,
267
                    'comment' => $comment,
268
                    'label' => $account,
269
                    'label' => $account,
270
                )
271
            );
272
273
            // Show results to user.
274
            echo prepareExchangedData(
275
    $SETTINGS['cpassman_dir'],
276
                array(
277
                    'error' => false,
278
                    'message' => '',
279
                    'output' => $itemsArray,
280
                    'number' => $line_number++,
281
                ),
282
                'encode'
283
            );
284
        }
285
286
        //delete file
287
        unlink($file);
288
289
        break;
290
291
    //Insert into DB the items the user has selected
292
    case 'import_items':
293
        // Check KEY and rights
294
        if ($post_key !== $_SESSION['key']) {
295
            echo prepareExchangedData(
296
                $SETTINGS['cpassman_dir'],
297
                array(
298
                    'error' => true,
299
                    'message' => langHdl('key_is_not_correct'),
300
                ),
301
                'encode'
302
            );
303
            break;
304
        }
305
306
        // Init
307
        $list = [];
308
309
        // Decrypt and retreive data in JSON format
310
        $post_items = prepareExchangedData(
311
            $SETTINGS['cpassman_dir'],
312
            $post_data,
313
            'decode'
314
        );
315
316
        // Init post variable
317
        $post_folder = filter_input(INPUT_POST, 'folder', FILTER_SANITIZE_NUMBER_INT);
318
319
        // Get title for this folder
320
        $data_fld = DB::queryFirstRow(
321
            'SELECT title
322
            FROM '.prefixTable('nested_tree').'
323
            WHERE id = %i',
324
            $post_folder
325
        );
326
327
        //Get some info about personal folder
328
        if (in_array($post_folder, $_SESSION['personal_folders']) === true) {
329
            $personalFolder = 1;
330
        } else {
331
            $personalFolder = 0;
332
        }
333
334
        //Prepare variables
335
        //$listItems = json_decode($post_items, true);
336
337
        // Clean each array entry
338
        if (is_array($post_items) === true) {
339
            array_walk_recursive($post_items, 'cleanOutput');
340
        }
341
342
        // Loop on array
343
        foreach ($post_items as $item) {
344
            //For each item, insert into DB
345
346
            // Handle case where pw is empty
347
            // if not allowed then warn user
348
            if ((isset($_SESSION['user']['create_item_without_password']) === true
349
                && (int) $_SESSION['user']['create_item_without_password'] !== 1
350
                ) ||
351
                empty($item['pwd']) === false
352
            ) {
353
                // NEW ENCRYPTION
354
                $cryptedStuff = doDataEncryption($item['pwd']);
355
            } else {
356
                $cryptedStuff['encrypted'] = '';
357
            }
358
            $post_password = $cryptedStuff['encrypted'];
359
360
            // Insert new item in table ITEMS
361
            DB::insert(
362
                prefixTable('items'),
363
                array(
364
                    'label' => substr($item['label'], 0, 500),
365
                    'description' => empty($item['description']) === true ? '' : $item['description'],
366
                    'pw' => $post_password,
367
                    'pw_iv' => '',
368
                    'url' => empty($item['url']) === true ? '' : substr($item['url'], 0, 500),
369
                    'id_tree' => filter_input(INPUT_POST, 'folder', FILTER_SANITIZE_NUMBER_INT),
370
                    'login' => empty($item['login']) === true ? '' : substr($item['login'], 0, 200),
371
                    'anyone_can_modify' => filter_input(INPUT_POST, 'import_csv_anyone_can_modify', FILTER_SANITIZE_STRING) === 'true' ? 1 : 0,
372
                    'encryption_type' => 'teampass_aes',
373
                )
374
            );
375
            $newId = DB::insertId();
376
377
            // Create sharekeys for users
378
            storeUsersShareKey(
379
                prefixTable('sharekeys_items'),
380
                (int) $personalFolder,
381
                (int) filter_input(INPUT_POST, 'folder', FILTER_SANITIZE_NUMBER_INT),
382
                (int) $newId,
383
                $cryptedStuff['objectKey'],
384
                $SETTINGS
385
            );
386
387
            //if asked, anyone in role can modify
388
            if (null !== filter_input(INPUT_POST, 'import_csv_anyone_can_modify_in_role', FILTER_SANITIZE_STRING)
389
                && filter_input(INPUT_POST, 'import_csv_anyone_can_modify_in_role', FILTER_SANITIZE_STRING) === 'true'
390
            ) {
391
                foreach ($_SESSION['arr_roles'] as $role) {
392
                    DB::insert(
393
                        prefixTable('restriction_to_roles'),
394
                        array(
395
                            'role_id' => $role['id'],
396
                            'item_id' => $newId,
397
                        )
398
                    );
399
                }
400
            }
401
402
            // Insert new item in table LOGS_ITEMS
403
            DB::insert(
404
                prefixTable('log_items'),
405
                array(
406
                    'id_item' => $newId,
407
                    'date' => time(),
408
                    'id_user' => $_SESSION['user_id'],
409
                    'action' => 'at_creation',
410
                )
411
            );
412
413
            array_push($list, $item['row']);
414
415
            //Add entry to cache table
416
            DB::insert(
417
                prefixTable('cache'),
418
                array(
419
                    'id' => $newId,
420
                    'label' => substr($item['label'], 0, 500),
421
                    'description' => empty($item['description']) ? '' : $item['description'],
422
                    'id_tree' => filter_input(INPUT_POST, 'folder', FILTER_SANITIZE_NUMBER_INT),
423
                    'url' => '0',
424
                    'perso' => $personalFolder === 0 ? 0 : 1,
425
                    'login' => empty($item['login']) ? '' : substr($item['login'], 0, 500),
426
                    'folder' => $data_fld['title'],
427
                    'author' => $_SESSION['user_id'],
428
                    'timestamp' => time(),
429
                    'tags' => '',
430
                    'restricted_to' => '0',
431
                    'renewal_period' => '0',
432
                    'timestamp' => time(),
433
                )
434
            );
435
        }
436
437
        echo prepareExchangedData(
438
            $SETTINGS['cpassman_dir'],
439
            array(
440
                'error' => false,
441
                'message' => '',
442
                'items' => $list,
443
            ),
444
            'encode'
445
        );
446
        break;
447
448
    //Check if import KEEPASS file format is what expected
449
    case 'import_file_format_keepass':
450
        // Check KEY and rights
451
        if ($post_key !== $_SESSION['key']) {
452
            echo prepareExchangedData(
453
                $SETTINGS['cpassman_dir'],
454
                array(
455
                    'error' => true,
456
                    'message' => langHdl('key_is_not_correct'),
457
                ),
458
                'encode'
459
            );
460
            break;
461
        }
462
463
        // Decrypt and retreive data in JSON format
464
        $receivedParameters = prepareExchangedData(
465
            $SETTINGS['cpassman_dir'],$post_data,
466
            'decode'
467
        );
468
        $post_operation_id = filter_var($receivedParameters['file'], FILTER_SANITIZE_STRING);
469
        $post_folder_id = filter_var($receivedParameters['folder-id'], FILTER_SANITIZE_NUMBER_INT);
470
471
        // Get filename from database
472
        $data = DB::queryFirstRow(
473
            'SELECT valeur
474
            FROM '.prefixTable('misc').'
475
            WHERE increment_id = %i AND type = "temp_file"',
476
            $post_operation_id
477
        );
478
479
        // Delete operation id
480
        DB::delete(
481
            prefixTable('misc'),
482
            'increment_id = %i AND type = "temp_file"',
483
            $post_operation_id
484
        );
485
486
        // do some initializations
487
        $file = $data['valeur'];
488
489
        //read xml file
490
        if (file_exists($SETTINGS['path_to_files_folder'].'/'.$file)) {
491
            $xml = simplexml_load_file(
492
                $SETTINGS['path_to_files_folder'].'/'.$file
493
            );
494
        }
495
496
        // Convert XML to associative array
497
        $xmlfile = file_get_contents($SETTINGS['path_to_files_folder'].'/'.$file);
498
        $new = simplexml_load_string($xmlfile);
499
        $con = json_encode($new);
500
        $newArr = json_decode($con, true);
501
        
502
        /**
503
         * Undocumented function
504
         *
505
         * @param array $array
506
         * @param integer $previousFolder
507
         * @param array $newItemsToAdd
508
         * @param integer $level
509
         * @return array
510
         */
511
        function recursive($array, $previousFolder, $newItemsToAdd, $level) : array
512
        {
513
            // Manage entries
514
            if (isset($array['Entry']) === true) {
515
                foreach($array['Entry'] as $key => $value) {
516
                    if (isset($value['String']) === true) {
517
                        $itemDefinition = [];
518
                        for($i = 0; $i < count($value['String']); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
519
                            $itemDefinition[$value['String'][$i]['Key']] = is_array($value['String'][$i]['Value']) === false ? $value['String'][$i]['Value'] : '';
520
                        }
521
                        $itemDefinition['parentFolderId'] = $previousFolder;
522
                        isset($itemDefinition['Notes']) === false ? $itemDefinition['Notes'] = '' : '';
523
                        isset($itemDefinition['URL']) === false ? $itemDefinition['URL'] = '' : '';
524
                        isset($itemDefinition['Password']) === false ? $itemDefinition['Password'] = '' : '';
525
                        array_push(
526
                            $newItemsToAdd['items'],
527
                            $itemDefinition
528
                        );
529
                    } else if ($key === "String") {
530
                        array_push(
531
                            $newItemsToAdd['items'],
532
                            [
533
                                'Notes' => is_array($value[0]['Value']) === false ? $value[0]['Value'] : '',
534
                                'Title' => is_array($value[2]['Value']) === false ? $value[2]['Value'] : '',
535
                                'Password' => is_array($value[1]['Value']) === false ? $value[1]['Value'] : '',
536
                                'URL' => is_array($value[3]['Value']) === false ? $value[3]['Value'] : '',
537
                                'UserName' => is_array($value[4]['Value']) === false ? $value[4]['Value'] : '',
538
                                'parentFolderId' => $previousFolder,
539
                            ]
540
                        );
541
                    }
542
                }
543
            }
544
545
            // Manage GROUPS
546
            if (isset($array['Group']) === true) {
547
                $currentFolderId = $previousFolder;
548
                if (is_array($array['Group'])=== true) {
549
                    if (isset($array['Group']['UUID']) === true) {
550
                        // build expect array format
551
                        $array['Group'] = [$array['Group']];
552
                    }
553
                    foreach($array['Group'] as $key => $value){
554
                        // Add this new folder
555
                        array_push(
556
                            $newItemsToAdd['folders'],
557
                            [
558
                                'folderName' => $value['Name'],
559
                                'uuid' => $value['UUID'],
560
                                'parentFolderId' => $previousFolder,
561
                                'level' => $level,
562
                            ]
563
                        );
564
                        $previousFolder = $value['UUID'];
565
                        
566
                        if (isset($value['Entry']) === true) {
567
                            // recursive inside this entry
568
                            $newItemsToAdd = recursive(
569
                                array_merge(
570
                                    ['Entry' => $value['Entry']],
571
                                    ['Group' => isset($value['Group']) === true ? $value['Group'] : ''],
572
                                ),
573
                                $previousFolder,
574
                                $newItemsToAdd,
575
                                $level + 1
576
                            );
577
                        }
578
                        $previousFolder = $currentFolderId;
579
                    }
580
                }
581
            }
582
            
583
            return $newItemsToAdd;
584
        }
585
        
586
        $ret = recursive(
587
            array_merge(
588
                ['Entry' => $newArr['Root']['Group']['Entry']],
589
                ['Group' => $newArr['Root']['Group']['Group']],
590
            ),
591
            $post_folder_id,
592
            [
593
                'folders' => [],
594
                'items' => []
595
            ],
596
            1,
597
        );
598
599
        
600
        echo prepareExchangedData(
601
            $SETTINGS['cpassman_dir'],
602
            array(
603
                'error' => false,
604
                'message' => '',
605
                'data' => $ret,
606
            ),
607
            'encode'
608
        );
609
610
        break;
611
612
    // KEEPASS - CREATE FOLDERS
613
    case 'keepass_create_folders':
614
        // Check KEY and rights
615
        if ($post_key !== $_SESSION['key']) {
616
            echo prepareExchangedData(
617
                $SETTINGS['cpassman_dir'],
618
                array(
619
                    'error' => true,
620
                    'message' => langHdl('key_is_not_correct'),
621
                ),
622
                'encode'
623
            );
624
            break;
625
        }
626
627
        // Decrypt and retreive data in JSON format
628
        $receivedParameters = prepareExchangedData(
629
            $SETTINGS['cpassman_dir'],$post_data,
630
            'decode'
631
        );
632
633
        $post_folder_id = filter_var($receivedParameters['folder-id'], FILTER_SANITIZE_NUMBER_INT);
634
        $post_edit_all = filter_var($receivedParameters['edit-all'], FILTER_SANITIZE_NUMBER_INT);
635
        $post_edit_role = filter_var($receivedParameters['edit-role'], FILTER_SANITIZE_NUMBER_INT);
636
        $post_folders = filter_var_array(
637
            $receivedParameters['folders'],
638
            FILTER_SANITIZE_STRING
639
        );
640
641
        // get destination folder informations
642
        $destinationFolderInfos = getFolderComplexity($post_folder_id, $_SESSION['personal_folders']);
643
        $arrFolders[$post_folder_id] = [
644
            'id' => (int) $post_folder_id,
645
            'level' => 1,
646
            'isPF' => false,
647
        ];
648
        $startPathLevel = 1;
649
650
        foreach($post_folders as $folder) {
651
            // get parent id
652
            $parentId = $arrFolders[$folder['parentFolderId']];
653
654
            // create folder in DB
655
            $folderId = createFolder(
656
                $folder['folderName'],
657
                $parentId['id'],
658
                $folder['level'],
659
                $startPathLevel,
660
                $destinationFolderInfos['levelPwComplexity']
661
            );
662
663
            // manage parent
664
            $arrFolders[$folder['uuid']] = [
665
                'id' => (int) $folderId,
666
                'level' => (int) ($folder['level'] + $startPathLevel),
667
                'isPF' => $destinationFolderInfos['importPF'],
668
            ];
669
        }
670
        //rebuild full tree
671
        $tree->rebuild();
672
673
674
        echo prepareExchangedData(
675
            $SETTINGS['cpassman_dir'],
676
            array(
677
                'error' => false,
678
                'message' => '',
679
                'folders' => $arrFolders,
680
            ),
681
            'encode'
682
        );
683
684
        break;
685
686
    // KEEPASS - CREATE ITEMS
687
    case 'keepass_create_items':
688
        // Check KEY and rights
689
        if ($post_key !== $_SESSION['key']) {
690
            echo prepareExchangedData(
691
                $SETTINGS['cpassman_dir'],
692
                array(
693
                    'error' => true,
694
                    'message' => langHdl('key_is_not_correct'),
695
                ),
696
                'encode'
697
            );
698
            break;
699
        }
700
701
        // Decrypt and retreive data in JSON format
702
        $receivedParameters = prepareExchangedData(
703
            $SETTINGS['cpassman_dir'],$post_data,
704
            'decode'
705
        );
706
707
        $post_edit_all = filter_var($receivedParameters['edit-all'], FILTER_SANITIZE_NUMBER_INT);
708
        $post_edit_role = filter_var($receivedParameters['edit-role'], FILTER_SANITIZE_NUMBER_INT);
709
        $post_folders = filter_var_array(
710
            $receivedParameters['folders'],
711
            FILTER_SANITIZE_STRING
712
        );
713
        $post_items = filter_var_array(
714
            $receivedParameters['items'],
715
            FILTER_SANITIZE_STRING
716
        );
717
        $ret = '';
718
719
        foreach($post_items as $item) {
720
            // get info about this folder
721
            $destinationFolderMore = DB::queryFirstRow(
722
                'SELECT title FROM '.prefixTable('nested_tree').' WHERE id = %i',
723
                (int) $post_folders[$item['parentFolderId']]['id']
724
            );
725
726
            // Handle case where pw is empty
727
            // if not allowed then warn user
728
            if ((isset($_SESSION['user']['create_item_without_password']) === true
729
                && (int) $_SESSION['user']['create_item_without_password'] !== 1
730
                ) ||
731
                empty($item['Password']) === false
732
            ) {
733
                // NEW ENCRYPTION
734
                $cryptedStuff = doDataEncryption($item['Password']);
735
            } else {
736
                $cryptedStuff['encrypted'] = '';
737
            }
738
            $post_password = $cryptedStuff['encrypted'];
739
740
            //ADD item
741
            DB::insert(
742
                prefixTable('items'),
743
                array(
744
                    'label' => substr(stripslashes($item['Title']), 0, 500),
745
                    'description' => stripslashes($item['Notes']),
746
                    'pw' => $cryptedStuff['encrypted'],
747
                    'pw_iv' => '',
748
                    'url' => substr(stripslashes($item['URL']), 0, 500),
749
                    'id_tree' => $post_folders[$item['parentFolderId']]['id'],
750
                    'login' => substr(stripslashes($item['UserName']), 0, 500),
751
                    'anyone_can_modify' => $post_edit_all,
752
                    'encryption_type' => 'teampass_aes',
753
                    'inactif' => 0,
754
                    'restricted_to' => '',
755
                    'perso' => $post_folders[$item['parentFolderId']]['isPF'] === true ? 1 : 0,
756
                )
757
            );
758
            $newId = DB::insertId();
759
760
            // Create sharekeys for users
761
            storeUsersShareKey(
762
                prefixTable('sharekeys_items'),
763
                $post_folders[$item['parentFolderId']]['isPF'] === true ? 1 : 0,
764
                (int) $post_folders[$item['parentFolderId']]['id'],
765
                (int) $newId,
766
                $cryptedStuff['objectKey'],
767
                $SETTINGS
768
            );
769
770
            //if asked, anyone in role can modify
771
            if ($post_edit_role === 1) {
772
                foreach ($_SESSION['arr_roles'] as $role) {
773
                    DB::insert(
774
                        prefixTable('restriction_to_roles'),
775
                        array(
776
                            'role_id' => $role['id'],
777
                            'item_id' => $newId,
778
                        )
779
                    );
780
                }
781
            }
782
783
            //Add log
784
            DB::insert(
785
                prefixTable('log_items'),
786
                array(
787
                    'id_item' => $newId,
788
                    'date' => time(),
789
                    'id_user' => $_SESSION['user_id'],
790
                    'action' => 'at_creation',
791
                    'raison' => 'at_import',
792
                )
793
            );
794
795
            //Add entry to cache table
796
            DB::insert(
797
                prefixTable('cache'),
798
                array(
799
                    'id' => $newId,
800
                    'label' => substr(stripslashes($item['Title']), 0, 500),
801
                    'description' => stripslashes($item['Notes']),
802
                    'url' => substr(stripslashes($item['URL']), 0, 500),
803
                    'tags' => '',
804
                    'id_tree' => $post_folders[$item['parentFolderId']]['id'],
805
                    'perso' => $post_folders[$item['parentFolderId']]['isPF'] === 0 ? 0 : 1,
806
                    'login' => substr(stripslashes($item['UserName']), 0, 500),
807
                    'restricted_to' => '0',
808
                    'folder' => $destinationFolderMore['title'],
809
                    'author' => $_SESSION['user_id'],
810
                    'renewal_period' => '0',
811
                    'timestamp' => time(),
812
                )
813
            );
814
815
            // prepare return
816
            $ret .= "<li>".substr(stripslashes($item['Title']), 0, 500)." [".$destinationFolderMore['title']."]</li>";
817
        }
818
819
820
        echo prepareExchangedData(
821
            $SETTINGS['cpassman_dir'],
822
            array(
823
                'error' => false,
824
                'message' => '',
825
                'info' => "<ul>".$ret."</ul>",
826
            ),
827
            'encode'
828
        );
829
830
        break;
831
    }
832
833
834
835
/**
836
 * Create folders during importation
837
 *
838
 * @param string $folderTitle
839
 * @param integer $parentId
840
 * @param integer $folderLevel
841
 * @param integer $startPathLevel
842
 * @param integer $levelPwComplexity
843
 * @return integer
844
 */
845
function createFolder($folderTitle, $parentId, $folderLevel, $startPathLevel, $levelPwComplexity)
846
{
847
    //create folder - if not exists at the same level
848
    DB::query(
849
        'SELECT * FROM '.prefixTable('nested_tree').'
850
        WHERE nlevel = %i AND title = %s AND parent_id = %i LIMIT 1',
851
        intval($folderLevel + $startPathLevel),
852
        $folderTitle,
853
        $parentId
854
    );
855
    if (DB::count() === 0) {
856
        //do query
857
        DB::insert(
858
            prefixTable('nested_tree'),
859
            array(
860
                'parent_id' => $parentId,
861
                'title' => stripslashes($folderTitle),
862
                'nlevel' => $folderLevel,
863
            )
864
        );
865
        $id = DB::insertId();
866
        //Add complexity level => level is set to "medium" by default.
867
        DB::insert(
868
            prefixTable('misc'),
869
            array(
870
                'type' => 'complex',
871
                'intitule' => $id,
872
                'valeur' => $levelPwComplexity,
873
            )
874
        );
875
876
        //For each role to which the user depends on, add the folder just created.
877
        foreach ($_SESSION['arr_roles'] as $role) {
878
            DB::insert(
879
                prefixTable('roles_values'),
880
                array(
881
                    'role_id' => $role['id'],
882
                    'folder_id' => $id,
883
                    'type' => 'W',
884
                )
885
            );
886
        }
887
888
        //Add this new folder to the list of visible folders for the user.
889
        array_push($_SESSION['groupes_visibles'], $id);
890
891
        return $id;
892
    }
893
    
894
    //get folder actual ID
895
    $data = DB::queryFirstRow(
896
        'SELECT id FROM '.prefixTable('nested_tree').'
897
        WHERE nlevel = %i AND title = %s AND parent_id = %i',
898
        intval($folderLevel + $startPathLevel),
899
        $folderTitle,
900
        $parentId
901
    );
902
    return $data['id'];
903
}
904
905
/** 
906
 * getFolderComplexity
907
 * 
908
 * @param int $folderId
909
 * @param boolean $isFolderPF
910
 * 
911
 * @return array
912
*/
913
function getFolderComplexity($folderId, $isFolderPF)
914
{
915
    // If destination is not ROOT then get the complexity level
916
    if (in_array($folderId, $isFolderPF) === true) {
0 ignored issues
show
Bug introduced by
$isFolderPF of type boolean is incompatible with the type array expected by parameter $haystack of in_array(). ( Ignorable by Annotation )

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

916
    if (in_array($folderId, /** @scrutinizer ignore-type */ $isFolderPF) === true) {
Loading history...
917
        return [
918
            'levelPwComplexity' => 50,
919
            'startPathLevel' => 1,
920
            'importPF' => true
921
        ];
922
    } elseif ($folderId > 0) {
923
        $data = DB::queryFirstRow(
924
            'SELECT m.valeur as value, t.nlevel as nlevel
925
            FROM '.prefixTable('misc').' as m
926
            INNER JOIN '.prefixTable('nested_tree').' as t ON (m.intitule = t.id)
927
            WHERE m.type = %s AND m.intitule = %s',
928
            'complex',
929
            $folderId
930
        );
931
        return [
932
            'levelPwComplexity' => $data['value'],
933
            'startPathLevel' => $data['nlevel'],
934
            'importPF' => false
935
        ];
936
    }
937
    return [
938
        'levelPwComplexity' => 50,
939
        'startPathLevel' => 0,
940
        'importPF' => false
941
    ];
942
}
943
944
spl_autoload_register(function ($class) {
945
    $prefix = 'League\\Csv\\';
946
    $base_dir = __DIR__.'/src/';
947
    $len = strlen($prefix);
948
    if (strncmp($prefix, $class, $len) !== 0) {
949
        // no, move to the next registered autoloader
950
        return;
951
    }
952
    $relative_class = substr($class, $len);
953
    $file = $base_dir.str_replace('\\', '/', $relative_class).'.php';
954
    if (file_exists($file)) {
955
        require $file;
956
    }
957
});
958
959
/**
960
 * Used to format the string ready for insertion in to the database.
961
 *
962
 * @param string $str             String to clean
963
 * @param string $crLFReplacement Replacement
964
 *
965
 * @return string
966
 */
967
function sanitiseString($str, $crLFReplacement)
968
{
969
    $str = preg_replace('#[\r\n]#', $crLFReplacement, (string) $str);
970
    $str = str_replace('\\', '&#92;', $str);
971
    $str = str_replace('"', '&quot;', $str);
972
    if (!empty($str)) {
973
        addslashes($str);
974
    }
975
976
    return $str;
977
}
978
979
/**
980
 * Clean array values.
981
 *
982
 * @param string $value String to clean
983
 *
984
 * @return string
985
 */
986
function cleanOutput(&$value)
987
{
988
    return htmlspecialchars_decode($value);
989
}
990