Completed
Push — development ( d7057a...328c6d )
by Nils
08:10
created

import.queries.php ➔ sanitiseString()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 2
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * @file          import.queries.php
4
 * @author        Nils Laumaillé
5
 * @version       2.1.27
6
 * @copyright     (c) 2009-2017 Nils Laumaillé
7
 * @licensing     GNU AFFERO GPL 3.0
8
 * @link          http://www.teampass.net
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
 */
14
use Goodby\CSV\Import\Standard\Lexer;
15
use Goodby\CSV\Import\Standard\Interpreter;
16
use Goodby\CSV\Import\Standard\LexerConfig;
17
18
require_once 'SecureHandler.php';
19
session_start();
20
if (!isset($_SESSION['CPM']) || $_SESSION['CPM'] != 1 || !isset($_SESSION['key']) || empty($_SESSION['key'])) {
21
    die('Hacking attempt...');
22
}
23
24
// No time limit
25
set_time_limit(0);
26
27
// Set some constants for program readability
28
define('KP_PATH', 0);
29
define('KP_GROUP', 1);
30
define('KP_TITLE', 2);
31
define('KP_PASSWORD', 3);
32
define('KP_USERNAME', 4);
33
define('KP_URL', 5);
34
define('KP_UUID', 6);
35
define('KP_NOTES', 7);
36
37
/*
38
 * sanitiseString
39
 *
40
 * Used to format the string ready for insertion in to the database
41
 */
42
/**
43
 * @param string $crLFReplacement
44
 */
45
function sanitiseString($str, $crLFReplacement)
46
{
47
    $str = preg_replace('#[\r\n]#', $crLFReplacement, $str);
48
    $str = str_replace('\\', '&#92;', $str);
49
    $str = str_replace('"', "&quot;", $str);
50
    if (!empty($str)) {
51
        addslashes($str);
52
    }
53
    return $str;
54
}
55
56
global $k, $settings;
57
header("Content-type: text/html; charset=utf-8");
58
error_reporting(E_ERROR);
59
include $_SESSION['settings']['cpassman_dir'].'/includes/config/settings.php';
60
61
//Class loader
62
require_once $_SESSION['settings']['cpassman_dir'].'/sources/SplClassLoader.php';
63
64
// call needed functions
65
require_once $_SESSION['settings']['cpassman_dir'].'/sources/main.functions.php';
66
67
// connect to the server
68
require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
69
DB::$host = $server;
70
DB::$user = $user;
71
DB::$password = $pass;
72
DB::$dbName = $database;
73
DB::$port = $port;
74
DB::$encoding = $encoding;
75
DB::$error_handler = true;
76
$link = mysqli_connect($server, $user, $pass, $database, $port);
77
$link->set_charset($encoding);
78
79
//Load Tree
80
$tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
81
$tree->register();
82
$tree = new Tree\NestedTree\NestedTree($pre.'nested_tree', 'id', 'parent_id', 'title');
83
84
//Load AES
85
$aes = new SplClassLoader('Encryption\Crypt', '../includes/libraries');
86
$aes->register();
87
88
// Load AntiXSS
89
require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXss.php';
90
$antiXss = new protect\AntiXSS\AntiXSS();
91
92
//User's language loading
93
$k['langage'] = @$_SESSION['user_language'];
94
require_once $_SESSION['settings']['cpassman_dir'].'/includes/language/'.$_SESSION['user_language'].'.php';
95
96
// Build query
97
switch ($_POST['type']) {
98
    //Check if import CSV file format is what expected
99
    case "import_file_format_csv":
100
        //load full tree
101
        $tree->rebuild();
102
        $tree = $tree->getDescendants();
103
104
        // do some initializations
105
        $file = $_SESSION['settings']['path_to_files_folder']."/".$_POST['file'];
106
        $size = 4096;
107
        $separator = ",";
108
        $enclosure = '"';
109
        $fields_expected = array("Label", "Login", "Password", "URL", "Comments"); //requiered fields from CSV
110
        $importation_possible = true;
111
        $display = "<table>";
112
        $line_number = $prev_level = 0;
113
        $account = $text = "";
114
        $continue_on_next_line = false;
115
116
        // Open file
117
        if ($fp = fopen($file, "r")) {
118
            // data from CSV
119
            $valuesToImport = array();
120
            // load libraries
121
            require_once($_SESSION['settings']['cpassman_dir'].'/includes/libraries/Goodby/CSV/Import/Standard/Lexer.php');
122
            require_once($_SESSION['settings']['cpassman_dir'].'/includes/libraries/Goodby/CSV/Import/Standard/Interpreter.php');
123
            require_once($_SESSION['settings']['cpassman_dir'].'/includes/libraries/Goodby/CSV/Import/Standard/LexerConfig.php');
124
125
            // Lexer configuration
126
            $config = new LexerConfig();
127
            $lexer = new Lexer($config);
128
            $config
129
                ->setIgnoreHeaderLine("true")
130
                //->setToCharset('UTF-8')
131
                //->setFromCharset('SJIS-win')
132
            ;
133
            // extract data from CSV file
134
            $interpreter = new Interpreter();
135
            $interpreter->addObserver(function (array $row) use (&$valuesToImport) {
136
                $valuesToImport[] = array(
137
                    'Label'     => $row[0],
138
                    'Login'     => $row[1],
139
                    'Password'  => $row[2],
140
                    'url'       => $row[3],
141
                    'Comments'  => $row[4],
142
                );
143
            });
144
            $lexer->parse($file, $interpreter);
145
146
            // extract one line
147
            foreach ($valuesToImport as $key => $row) {
148
                //Check number of fields. MUST be 5. if not stop importation
149
                if (count($row) != 5) {
150
                    $importation_possible = false;
151
                    //Stop if file has not expected structure
152
                    if ($importation_possible === false) {
153
                        echo '[{"error":"bad_structure"}]';
154
                        break;
155
                    }
156
                }
157
158
                //If any comment is on several lines, then replace 'lf' character
159
                $row['Comments'] = str_replace(array("\r\n", "\n", "\r"), "<br />", $row['Comments']);
160
161
                // Check if current line contains a "<br />" character in order to identify an ITEM on several CSV lines
162
                if (substr_count('<br />', $row['Comments']) > 0 || substr_count('<br />', $row['Label']) > 0) {
163
                    $continue_on_next_line = true;
164
                    $comment .= addslashes($row['Label']);
165
                } else {
166
                    // Store in variable values from previous line
167
                    if (!empty($account)) {
168
                        if ($continue_on_next_line === false) {
169
                            // Prepare listing that will be shown to user
170
                            $display .= '<tr><td><input type=\"checkbox\" class=\"item_checkbox\" id=\"item_to_import-'.$line_number.'\" /></td><td><span id=\"item_text-'.$line_number.'\">'.$account.'</span><input type=\"hidden\" value=\"'.$account.'@|@'.$login.'@|@'.$pw.'@|@'.$url.'@|@'.$comment.'@|@'.$line_number.'\" id=\"item_to_import_values-'.$line_number.'\" /></td></tr>';
171
172
                            // Initialize this variable in order to restart from scratch
173
                            $account = "";
174
                        }
175
                    }
176
                }
177
178
                // Get values of current line
179
                if ($account == "" && $continue_on_next_line === false) {
180
                    $account = addslashes($row['Label']);
181
                    $login = addslashes($row['Login']);
182
                    $pw = str_replace('"', "&quot;", $row['Password']);
183
                    $url = addslashes($row['url']);
184
                    $to_find = array("\"", "'");
185
                    $to_ins = array("&quot", "&#39;");
186
                    $comment = htmlentities(addslashes(str_replace($to_find, $to_ins, $row['Comments'])), ENT_QUOTES, 'UTF-8');
187
188
                    $continue_on_next_line = false;
189
                }
190
191
                //increment number of lines found
192
                $line_number++;
193
            }
194
            // close file
195
            fclose($fp);
196
197
            // remove file
198
            fileDelete($file);
199
        } else {
200
            echo '[{"error":"cannot_open"}]';
201
            break;
202
        }
203
204
        if ($line_number > 0) {
205
            //add last line
206
            $display .= '<tr><td><input type=\"checkbox\" class=\"item_checkbox\" id=\"item_to_import-'.$line_number.'\" /></td><td><span id=\"item_text-'.$line_number.'\">'.$account.'</span><input type=\"hidden\" value=\"'.$account.'@|@'.$login.'@|@'.str_replace('"', "&quote;", $pw).'@|@'.$url.'@|@'.$comment.'@|@'.$line_number.'\" id=\"item_to_import_values-'.$line_number.'\" /></td></tr>';
207
208
            // Add a checkbox for select/unselect all others
209
            $display .= '<tr><td colspan=\"2\"><br><input type=\"checkbox\" id=\"item_all_selection\" />&nbsp;'.$LANG['all'].'</td></tr>';
210
211
            // Prepare a list of all folders that the user can choose
212
            $display .= '</table><div style=\"margin:10px 0 10px 0;\"><label><b>'.$LANG['import_to_folder'].'</b></label>&nbsp;<select id=\"import_items_to\" style=\"width:87%;\">';
213
            foreach ($tree as $t) {
214
                if (in_array($t->id, $_SESSION['groupes_visibles'])) {
215
                    $ident = "";
216
                    for ($x = 1; $x < $t->nlevel; $x++) {
217
                        $ident .= "&nbsp;&nbsp;";
218
                    }
219
                    if (isset($_POST['folder_id']) && $_POST['folder_id'] == $t->id) {
220
                        $selected = " selected";
221
                    } else {
222
                        $selected = "";
223
                    }
224
                    if ($prev_level != null && $prev_level < $t->nlevel) {
225
                        $display .= '<option value=\"'.$t->id.'\"'.$selected.'>'.$ident.str_replace(array("&", '"'), array("&amp;", "&quot;"), $t->title).'</option>';
226
                    } elseif ($prev_level != null && $prev_level == $t->nlevel) {
227
                        $display .= '<option value=\"'.$t->id.'\"'.$selected.'>'.$ident.str_replace(array("&", '"'), array("&amp;", "&quot;"), $t->title).'</option>';
228
                    } else {
229
                        $display .= '<option value=\"'.$t->id.'\"'.$selected.'>'.$ident.str_replace(array("&", '"'), array("&amp;", "&quot;"), $t->title).'</option>';
230
                    }
231
                    $prev_level = $t->nlevel;
232
                }
233
            }
234
            $display .= '</select></div>';
235
236
            // Show results to user.
237
            echo '[{"error":"no" , "output" : "'.$display.'"}]';
238
        }
239
        break;
240
241
    //Insert into DB the items the user has selected
242
    case "import_items":
243
        //decrypt and retreive data in JSON format
244
        $dataReceived = (Encryption\Crypt\aesctr::decrypt($_POST['data'], $_SESSION['key'], 256));
245
246
        //Get some info about personal folder
247
        if ($_POST['folder'] == $_SESSION['user_id']) {
248
            $personalFolder = 1;
249
        } else {
250
            $personalFolder = 0;
251
        }
252
        $data_fld = DB::queryFirstRow("SELECT title FROM ".prefix_table("nested_tree")." WHERE id = %i", intval($_POST['folder']));
253
254
        //Prepare variables
255
        $listItems = htmlspecialchars_decode($dataReceived);
256
        $list = "";
257
258
        foreach (explode('@_#sep#_@', mysqli_escape_string($link, stripslashes($listItems))) as $item) {
259
            //For each item, insert into DB
260
            $item = explode('@|@', $item); //explode item to get all fields
261
262
            //Encryption key
263
            if ($personalFolder == 1) {
264
                $encrypt = cryption(
265
                    $item[2],
266
                    $_SESSION['user_settings']['session_psk'],
267
                    "encrypt"
268
                );
269
            } else {
270
                $encrypt = cryption(
271
                    $item[2],
272
                    "",
273
                    "encrypt"
274
                );
275
            }
276
277
            // Insert new item in table ITEMS
278
            DB::insert(
279
                prefix_table("items"),
280
                array(
281
                    'label' => substr($item[0], 0, 500),
282
                    'description' => $item[4],
283
                    'pw' => $encrypt['string'],
284
                    'pw_iv' => $encrypt['iv'],
285
                    'url' => substr($item[3], 0, 500),
286
                    'id_tree' => $_POST['folder'],
287
                    'login' => substr($item[1], 0, 200),
288
                    'anyone_can_modify' => $_POST['import_csv_anyone_can_modify'] == "true" ? 1 : 0
289
                )
290
            );
291
            $newId = DB::insertId();
292
293
            //if asked, anyone in role can modify
294
            if (isset($_POST['import_csv_anyone_can_modify_in_role']) && $_POST['import_csv_anyone_can_modify_in_role'] == "true") {
295
                foreach ($_SESSION['arr_roles'] as $role) {
296
                    DB::insert(
297
                        prefix_table("restriction_to_roles"),
298
                        array(
299
                            'role_id' => $role['id'],
300
                            'item_id' => $newId
301
                        )
302
                    );
303
                }
304
            }
305
306
            // Insert new item in table LOGS_ITEMS
307
            DB::insert(
308
                prefix_table("log_items"),
309
                array(
310
                    'id_item' => $newId,
311
                    'date' => time(),
312
                    'id_user' => $_SESSION['user_id'],
313
                    'action' => 'at_creation'
314
                )
315
            );
316
317
            if (empty($list)) {
318
                $list = $item[5];
319
            } else {
320
                $list .= ";".$item[5];
321
            }
322
323
            //Add entry to cache table
324
            DB::insert(
325
                prefix_table("cache"),
326
                array(
327
                    'id' => $newId,
328
                    'label' => substr($item[0], 0, 500),
329
                    'description' => $item[4],
330
                    'id_tree' => $_POST['folder'],
331
                    'perso' => $personalFolder == 0 ? 0 : 1,
332
                    'login' => substr($item[1], 0, 500),
333
                    'folder' => $data_fld['title'],
334
                    'author' => $_SESSION['user_id'],
335
                    'timestamp' => time(),
336
                    'tags' => '',
337
                    'restricted_to' => ''
338
                )
339
            );
340
        }
341
        echo '[{"items":"'.$list.'"}]';
342
        break;
343
344
    //Check if import KEEPASS file format is what expected
345
    case "import_file_format_keepass":
346
        //Initialization
347
        $root = $meta = $group = $entry = $key = $title = $notes = $pw = $username = $url = $notKeepassFile = $newItem = $history = $generatorFound = false;
348
        $name = $levelInProgress = $previousLevel = $fullPath = $historyLevel = $path = $display = $keepassVersion = "";
349
        $numGroups = $numItems = 0;
350
        $temparray = $arrFolders = array();
351
        $levelMin = 2;
352
        $foldersSeparator = '@&##&@';
353
        $itemsSeparator = '<=|#|=>';
354
        $lineEndSeparator = '@*1|#9*|@';
355
356
        //prepare CACHE files
357
        $cacheFileName = $_SESSION['settings']['path_to_files_folder']."/cpassman_cache_".md5(time().mt_rand());
358
        $cacheFileNameFolder = $cacheFileName."_folders";
359
        $cacheFile = fopen($cacheFileName, "w");
360
        $cacheFileF = fopen($cacheFileNameFolder, "w");
361
        $logFileName = "/keepassImport_".date('YmdHis');
362
        $cacheLogFile = fopen($_SESSION['settings']['path_to_files_folder'].$logFileName, 'w');
363
        $_POST['file'] = $antiXss->xss_clean($_POST['file']);
364
365
        //read xml file
366
        if (file_exists("'".$_SESSION['settings']['path_to_files_folder']."/".$_POST['file'])."'") {
367
            $xml = simplexml_load_file(
368
                $_SESSION['settings']['path_to_files_folder']."/".$_POST['file']
369
            );
370
        }
371
372
        /**
373
        Recursive function that will permit to read each level of XML nodes
374
         */
375
        function recursiveKeepassXML($xmlRoot, $xmlLevel = 0)
376
        {
377
            global $meta, $root, $group, $name, $entry, $levelMin, $title, $notes, $pw, $username, $url,
378
                $newItem, $temparray, $history, $levelInProgress, $historyLevel,
379
                $path, $previousLevel, $generatorFound, $cacheFile, $cacheFileF, $numGroups,
380
                $numItems, $foldersSeparator, $itemsSeparator, $keepassVersion, $arrFolders;
381
382
            $groupsArray = array();
383
384
            // For each node, get the name and SimpleXML balise
385
            foreach ($xmlRoot as $nom => $elem) {
386
                /*
387
                * check if file is generated by keepass 1
388
                * key "pwentry" is only used in KP1.xx XML files
389
                */
390
                if ($nom == "pwentry") {
391
                    if (empty($keepassVersion)) {
392
                        $keepassVersion = 1;
393
                        $generatorFound = true;
394
                        $entry = true;
395
                    } else {
396
                        $entry = true;
397
                    }
398
399
                    //get children
400
                    $xmlChildren = $elem->children();
401
402
                    //recursive call
403
                    recursiveKeepassXML($xmlChildren, $xmlLevel + 1);
404
                }
405
                //IMPORTING KEEPASS 1 XML FILE
406
                if ($keepassVersion == 1) {
407
                    if ($entry === true && $nom == "expiretime") {
408
                        //save previous keepass entry
409
                        $tree = preg_replace('/\\\\/', $foldersSeparator, $temparray['tree']);
410
                        fputs(
411
                            $cacheFile,
412
                            $tree.$itemsSeparator.$temparray[KP_GROUP].$itemsSeparator.$temparray[KP_TITLE].
413
                            $itemsSeparator.$temparray[KP_PW].$itemsSeparator.$temparray[KP_USERNAME].
414
                            $itemsSeparator.$temparray[KP_URL].$itemsSeparator.$temparray[KP_UUID].$itemsSeparator.$temparray[KP_NOTES]."\n"
415
                        );
416
417
                        if (!in_array($temparray['tree'], $arrFolders)) {
418
                            fwrite($cacheFileF, $tree."\n");
419
                            array_push($arrFolders, $temparray['tree']);
420
                        }
421
422
                        $temparray = array();
423
                        $newItem++;
424
                    }
425
426
                    if ($entry === true && $nom == "group") {
427
                        $temparray[KP_GROUP] = addslashes(preg_replace('#[\r\n]#', '', $elem));
428
                        foreach ($elem->attributes() as $attributeskey0 => $attributesvalue1) {
429
                            if ($attributeskey0 == "tree") {
430
                                $path = explode('\\', $attributesvalue1);
431
                                if (count($path) > 1) {
432
                                    unset($path[0]);
433
                                    $temparray['tree'] = implode('\\', $path).'\\'.$temparray[KP_GROUP];
434
                                } else {
435
                                    $temparray['tree'] = $temparray[KP_GROUP];
436
                                }
437
                            }
438
                        }
439
                        $numGroups++;
440
                    } elseif ($entry === true && $nom == "title") {
441
                        $temparray[KP_TITLE] = sanitiseString($elem, '');
442
                    } elseif ($entry === true && $nom == "username") {
443
                        $temparray[KP_USERNAME] = sanitiseString($elem, '');
444
                    } elseif ($entry === true && $nom == "url") {
445
                        $temparray[KP_URL] = sanitiseString($elem, '');
446
                    } elseif ($entry === true && $nom == "uuid") {
447
                        $temparray[KP_UUID] = addslashes(preg_replace('#[\r\n]#', '', $elem));
448
                    } elseif ($entry === true && $nom == "password") {
449
                        $temparray[KP_PW] = sanitiseString($elem, '');
450
                    } elseif ($entry === true && $nom == "notes") {
451
                        $temparray[KP_NOTES] = sanitiseString($elem, '');
452
                    }
453
                }
454
455
                /*
456
                   * check if file is generated by keepass 2
457
                */
458
                if (trim($elem) == "" && $keepassVersion != 1) {
459
                    //check if file is generated by keepass 2
460
                    if ($nom == "Meta") {
461
                        $meta = true;
462
                    }
463
                    if ($nom == "Root") {
464
                        $root = true;
465
                    }
466
467
                    if ($nom == "Group") {
468
                        $group = true;
469
                        $entry = false;
470
                        $name = "";
471
472
                        // recap previous info
473
                        if (!empty($temparray[KP_TITLE])) {
474
                            //store data
475
                            fputs(
476
                                $cacheFile,
477
                                $temparray[KP_PATH].$itemsSeparator.$temparray[KP_GROUP].
478
                                $itemsSeparator.$temparray[KP_TITLE].$itemsSeparator.$temparray[KP_PW].
479
                                $itemsSeparator.$temparray[KP_USERNAME].$itemsSeparator.
480
                                $temparray[KP_URL].$itemsSeparator.$temparray[KP_UUID].$itemsSeparator.$temparray[KP_NOTES]."\n"
481
                            );
482
483
                            //Clean temp array
484
                            $temparray[KP_TITLE] = $temparray[KP_NOTES] = $temparray[KP_PW] = $temparray[KP_USERNAME] = $temparray[KP_URL] = "";
485
486
                            //increment number
487
                            $numItems++;
488
                        }
489
                        $historyLevel = 0;
490
                    }
491
492
                    //History node needs to be managed in order to not polluate final list
493
                    if ($nom == "History") {
494
                        $history = true;
495
                        $entry = false;
496
                        $historyLevel = $xmlLevel;
497
                    }
498
499
                    if ($nom == "Entry" && ($xmlLevel < $historyLevel || empty($historyLevel))) {
500
                        $entry = true;
501
                        $group = false;
502
503
                        // recap previous info
504
                        if (!empty($temparray[KP_TITLE])) {
505
                            //store data
506
                            fputs($cacheFile, $temparray[KP_PATH].$itemsSeparator.$temparray[KP_GROUP].$itemsSeparator.$temparray[KP_TITLE].$itemsSeparator.$temparray[KP_PW].$itemsSeparator.$temparray[KP_USERNAME].$itemsSeparator.$temparray[KP_URL].$itemsSeparator.$temparray[KP_UUID].$itemsSeparator.$temparray[KP_NOTES]."\n");
507
508
                            //Clean temp array
509
                            $temparray[KP_TITLE] = $temparray[KP_NOTES] = $temparray[KP_PW] = $temparray[KP_USERNAME] = $temparray[KP_URL] = $temparray[KP_UUID] = "";
510
511
                            //increment number
512
                            $numItems++;
513
                        }
514
                        $historyLevel = 0;
515
                    }
516
517
                    //get children
518
                    $xmlChildren = $elem->children();
519
520
                    //recursive call
521
                    recursiveKeepassXML($xmlChildren, $xmlLevel + 1);
522
523
                    //IMPORTING KEEPASS 2 XML FILE
524
                } elseif ($keepassVersion != 1) {
525
                    // exit if XML file not generated by KeePass
526
                    if ($meta === true && $nom == "Generator" && $elem == "KeePass") {
527
                        $generatorFound = true;
528
                        $keepassVersion = 2;
529
                        break;
530
                    } elseif ($root === true && $xmlLevel > $levelMin) {
531
                        //Check each node name and get data from some of them
532
                        if ($entry === true && $nom == "Key" && $elem == "Title") {
533
                            $title = true;
534
                            $notes = $pw = $url = $username = false;
535
                        } elseif ($entry === true && $nom == "Key" && $elem == "Notes") {
536
                            $notes = true;
537
                            $title = $pw = $url = $username = false;
538
                        } elseif ($entry === true && $nom == "UUID") {
539
                            $temparray[KP_UUID] = $elem;
540
                        } elseif ($entry === true && $nom == "Key" && $elem == "Password") {
541
                            $pw = true;
542
                            $notes = $title = $url = $username = false;
543
                        } elseif ($entry === true && $nom == "Key" && $elem == "URL") {
544
                            $url = true;
545
                            $notes = $pw = $title = $username = false;
546
                        } elseif ($entry === true && $nom == "Key" && $elem == "UserName") {
547
                            $username = true;
548
                            $notes = $pw = $url = $title = false;
549
                        } elseif ($group === true && $nom == "Name") {
550
                            $temparray[KP_GROUP] = addslashes(preg_replace('#[\r\n]#', '', $elem));
551
                            $temparray['level'] = $xmlLevel;
552
                            //build current path
553
                            if ($xmlLevel > $levelInProgress) {
554
                                if (!empty($temparray[KP_PATH])) {
555
                                    $temparray[KP_PATH] .= $foldersSeparator.$temparray[KP_GROUP];
556
                                } else {
557
                                    $temparray[KP_PATH] = $temparray[KP_GROUP];
558
                                }
559
                            } elseif ($xmlLevel == $levelInProgress) {
560
                                if ($levelInProgress == 3) {
561
                                    $temparray[KP_PATH] = $temparray[KP_GROUP];
562
                                } else {
563
                                    $temparray[KP_PATH] = substr($temparray[KP_PATH], 0, strrpos($temparray[KP_PATH], $foldersSeparator) + strlen($foldersSeparator)).$temparray[KP_GROUP];
564
                                }
565
                            } else {
566
                                $diff = abs($xmlLevel - $levelInProgress) + 1;
567
                                $tmp = explode($foldersSeparator, $temparray[KP_PATH]);
568
                                $temparray[KP_PATH] = "";
569
                                for ($x = 0; $x < (count($tmp) - $diff); $x++) {
570
                                    if (!empty($temparray[KP_PATH])) {
571
                                        $temparray[KP_PATH] = $temparray[KP_PATH].$foldersSeparator.$tmp[$x];
572
                                    } else {
573
                                        $temparray[KP_PATH] = $tmp[$x];
574
                                    }
575
                                }
576
                                if (!empty($temparray[KP_PATH])) {
577
                                    $temparray[KP_PATH] .= $foldersSeparator.$temparray[KP_GROUP];
578
                                } else {
579
                                    $temparray[KP_PATH] = $temparray[KP_GROUP];
580
                                }
581
                            }
582
583
                            //store folders
584
                            if (!in_array($temparray[KP_PATH], $groupsArray)) {
585
                                fwrite($cacheFileF, $temparray[KP_PATH]."\n");
586
                                array_push($groupsArray, $temparray[KP_PATH]);
587
                                //increment number
588
                                $numGroups++;
589
                            }
590
591
                            //Store actual level
592
                            $levelInProgress = $xmlLevel;
593
                            $previousLevel = $temparray[KP_GROUP];
594
                        } elseif ($title === true && $nom == "Value") {
595
                            $title = false;
596
                            $temparray[KP_TITLE] = sanitiseString($elem, '');
597
                        } elseif ($notes === true && $nom == "Value") {
598
                            $notes = false;
599
                            $temparray[KP_NOTES] = sanitiseString($elem, '');
600
                        } elseif ($pw === true && $nom == "Value") {
601
                            $pw = false;
602
                            $temparray[KP_PW] = sanitiseString($elem, '');
603
                        } elseif ($url === true && $nom == "Value") {
604
                            $url = false;
605
                            $temparray[KP_URL] = sanitiseString($elem, '');
606
                        } elseif ($username === true && $nom == "Value") {
607
                            $username = false;
608
                            $temparray[KP_USERNAME] = sanitiseString($elem, '');
609
                        }
610
                    }
611
                }
612
            }
613
        }
614
615
        fputs($cacheLogFile, date('H:i:s ')."Writing XML File ".filter_var($_POST['file'], FILTER_SANITIZE_STRING)."\n");
616
617
        // Go through each node of XML file
618
        recursiveKeepassXML($xml);
619
620
        //Stop if not a keepass file
621
        if ($generatorFound === false) {
622
            //Close file & delete it
623
            fclose($cacheFileF);
624
            fclose($cacheFile);
625
            unlink($cacheFileName);
626
            unlink($cacheFileNameFolder);
627
            unlink($_SESSION['settings']['url_to_files_folder']."/".filter_var($_POST['file'], FILTER_SANITIZE_STRING));
628
629
            fputs($cacheLogFile, date('H:i').$LANG['import_error_no_read_possible_kp']."\n");
630
631
            echo '[{"error":"not_kp_file" , "message":"'.$LANG['import_error_no_read_possible_kp'].'"}]';
632
            break;
633
        }
634
635
        //save last item
636
        if (!empty($temparray[KP_TITLE])) {
637
            //store data
638
            fputs(
639
                $cacheFile,
640
                $temparray[KP_PATH].$itemsSeparator.$temparray[KP_GROUP].$itemsSeparator.
641
                $temparray[KP_TITLE].$itemsSeparator.$temparray[KP_PW].$itemsSeparator.$temparray[KP_USERNAME].
642
                $itemsSeparator.$temparray[KP_URL].$itemsSeparator.$temparray[KP_UUID].$itemsSeparator.$temparray[KP_NOTES]."\n"
643
            );
644
645
            //increment number
646
            $numItems++;
647
        }
648
649
        ##################
650
        ## STARTING IMPORTING IF NO ERRORS OR NOT EMPTY
651
        ##################
652
        if ($numItems > 0 || $numGroups > 0) {
653
            // Write in file
654
            fputs($cacheLogFile, date('H:i:s ').$LANG['nb_folders'].' '.$numGroups."\n");
655
            fputs($cacheLogFile, date('H:i:s ').$LANG['nb_items'].' '.$numItems."\n");
656
657
            $import_perso = false;
658
            $itemsArray = array();
659
            $text = '<span class="fa fa-folder-open"></span>&nbsp;'.$LANG['nb_folders'].': '.
660
                $numGroups.'<br /><span class="fa fa-tag"></span>>&nbsp;'.$LANG['nb_items'].': '.
661
                $numItems.'<br /><br />';
662
663
            //if destination is not ROOT then get the complexity level
664
            if (strpos($_POST['destination'], "perso") !== 0) {
665
                $levelPwComplexity = 50;
666
                $startPathLevel = 1;
667
                $import_perso = true;
668
            } elseif ($_POST['destination'] > 0) {
669
                $data = DB::queryFirstRow(
670
                    "SELECT m.valeur as value, t.nlevel as nlevel
671
                    FROM ".prefix_table("misc")." as m
672
                    INNER JOIN ".prefix_table("nested_tree")." as t ON (m.intitule = t.id)
673
                    WHERE m.type = %s AND m.intitule = %s",
674
                    "complex",
675
                    mysqli_escape_string($link, $_POST['destination'])
676
                );
677
                $levelPwComplexity = $data['value'];
678
                $startPathLevel = $data['nlevel'];
679
            } else {
680
                $levelPwComplexity = 50;
681
                $startPathLevel = 0;
682
            }
683
684
            //Get all folders from file
685
            fclose($cacheFileF);
686
            $cacheFileF = fopen($cacheFileNameFolder, "r");
687
688
            //Create folders
689
            $i = 1;
690
            $level = 0;
691
            $foldersArray = array();
692
            $nbFoldersImported = 0;
693
694
            fputs($cacheLogFile, date('H:i:s ')."Creating Folders\n");
695
            $results = "Folders\n\n";
696
697
            while (!feof($cacheFileF)) {
698
                $folder = fgets($cacheFileF, 4096);
699
                if (!empty($folder)) {
700
                    $folder = str_replace(array("\r\n", "\n", "\r"), '', $folder);
701
                    //get number of levels in path
702
                    $path = explode($foldersSeparator, $folder);
703
                    $folderLevel = count($path);
704
705
                    //get folder name
706
                    if (strrpos($folder, $foldersSeparator) > 0) {
707
                        $fold = substr($folder, strrpos($folder, $foldersSeparator) + strlen($foldersSeparator));
708
                        $parent = implode($foldersSeparator, array_slice($path, 0, -1));
709
                        $parent_id = $foldersArray[$parent]['id'];
710
                    } else {
711
                        $fold = $folder;
712
                        $parent_id = $_POST['destination']; //permits to select the folder destination
713
                    }
714
715
                    $fold = stripslashes($fold);
716
                    //create folder - if not exists at the same level
717
                    DB::query(
718
                        "SELECT * FROM ".prefix_table("nested_tree")."
719
                        WHERE nlevel = %i AND title = %s AND parent_id = %i LIMIT 1",
720
                        intval($folderLevel + $startPathLevel),
721
                        $fold,
722
                        $parent_id
723
                    );
724
                    $results .= str_replace($foldersSeparator, '\\', $folder);
725
                    $counter = DB::count();
726
                    if ($counter == 0) {
727
                        $results .= " - Inserting\n";
728
                        //do query
729
                        DB::insert(
730
                            prefix_table("nested_tree"),
731
                            array(
732
                                'parent_id' => $parent_id,
733
                                'title' => stripslashes($fold),
734
                                'nlevel' => $folderLevel
735
                            )
736
                        );
737
                        $id = DB::insertId();
738
                        //Add complexity level => level is set to "medium" by default.
739
                        DB::insert(
740
                            prefix_table("misc"),
741
                            array(
742
                                'type' => 'complex',
743
                                'intitule' => $id,
744
                                'valeur' => $levelPwComplexity
745
                            )
746
                        );
747
748
                        //For each role to which the user depends on, add the folder just created.
749
                        foreach ($_SESSION['arr_roles'] as $role) {
750
                            DB::insert(
751
                                prefix_table("roles_values"),
752
                                array(
753
                                    'role_id' => $role['id'],
754
                                    'folder_id' => $id,
755
                                    'type' => "W"
756
                                )
757
                            );
758
                        }
759
760
                        //Add this new folder to the list of visible folders for the user.
761
                        array_push($_SESSION['groupes_visibles'], $id);
762
763
                        //increment number of imported folders
764
                        $nbFoldersImported++;
765
                    } else {
766
                        $results .= " - Skipped\n";
767
                        //get folder actual ID
768
                        $data = DB::queryFirstRow(
769
                            "SELECT id FROM ".prefix_table("nested_tree")."
770
                            WHERE nlevel = %i AND title = %s AND parent_id = %i",
771
                            intval($folderLevel + $startPathLevel),
772
                            $fold,
773
                            $parent_id
774
                        );
775
                        $id = $data['id'];
776
                    }
777
778
                    //store in array
779
                    $foldersArray[$folder] = array(
780
                        'folder' => $fold,
781
                        'nlevel' => $folderLevel,
782
                        'id' => $id
783
                    );
784
785
                    $_SESSION['nb_folders']++;
786
                    $i++;
787
                }
788
            }
789
790
            $results .= "\n\nItems\n\n";
791
            //if no new folders them inform
792
            if ($nbFoldersImported > 0) {
793
                fputs($cacheLogFile, date('H:i:s ')."Setting User Rights\n");
794
                //Refresh the rights of actual user
795
                identifyUserRights(
796
                    implode(';', $_SESSION['groupes_visibles']).';'.$newId,
797
                    $_SESSION['groupes_interdits'],
798
                    $_SESSION['is_admin'],
799
                    $_SESSION['fonction_id'],
800
                );
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected ')'
Loading history...
801
802
                fputs($cacheLogFile, date('H:i:s ')."Rebuilding Tree\n");
803
                //rebuild full tree
804
                $tree->rebuild();
805
            }
806
807
            fputs($cacheLogFile, date('H:i:s ')."Importing Items\n");
808
809
            // Now import ITEMS
810
            $nbItemsImported = 0;
811
            $count = 0;
812
813
            //Get some info about personal folder
814
            if ($_POST['destination'] == $_SESSION['user_id']) {
815
                $personalFolder = 1;
816
            } else {
817
                $personalFolder = 0;
818
            }
819
820
            //prepare file to be read
821
            fclose($cacheFile);
822
            $cacheFile = fopen($cacheFileName, "r");
823
824
            while (!feof($cacheFile)) {
825
                //prepare an array with item to import
826
                $full_item = fgets($cacheFile, 8192);
827
                $full_item = str_replace(array("\r\n", "\n", "\r"), '', $full_item);
828
                $item = explode($itemsSeparator, $full_item);
829
830
                $count++;
831
                if (!($count % 10)) {
832
                    fputs($cacheLogFile, date('H:i:s ')."  Imported $count items (".number_format(($count / $numItems) * 100, 1).")\n");
833
                }
834
835
                if (!empty($item[KP_TITLE])) {
836
                    //$count++;
837
                    //check if not exists
838
                    $results .= str_replace($foldersSeparator, "\\", $item[KP_PATH]).'\\'.$item[KP_TITLE];
839
840
                    $pw = $item[KP_PASSWORD];
841
842
                    //Get folder label
843
                    if (count($foldersArray) == 0 || empty($item[KP_PATH])) {
844
                        $folderId = $_POST['destination'];
845
                    } else {
846
                        $folderId = $foldersArray[$item[KP_PATH]]['id'];
847
                    }
848
                    $data = DB::queryFirstRow(
849
                        "SELECT title FROM ".prefix_table("nested_tree")." WHERE id = %i",
850
                        intval($folderId)
851
                    );
852
853
                    // escape if folderId is empty
854
                    if (!empty($folderId)) {
855
                        $results .= " - Inserting\n";
856
857
                        // prepare PW
858
                        if ($import_perso === true) {
859
                            $encrypt = cryption(
860
                                $pw,
861
                                $_SESSION['user_settings']['session_psk'],
862
                                "encrypt"
863
                            );
864
                        } else {
865
                            $encrypt = cryption(
866
                                $pw,
867
                                "",
868
                                "encrypt"
869
                            );
870
                        }
871
872
                        //ADD item
873
                        DB::insert(
874
                            prefix_table("items"),
875
                            array(
876
                                'label' => substr(stripslashes($item[KP_TITLE]), 0, 500),
877
                                'description' => stripslashes(str_replace($lineEndSeparator, '<br />', $item[KP_NOTES])),
878
                                'pw' => $encrypt['string'],
879
                                'pw_iv' => $encrypt['iv'],
880
                                'url' => substr(stripslashes($item[KP_URL]), 0, 500),
881
                                'id_tree' => $folderId,
882
                                'login' => substr(stripslashes($item[KP_USERNAME]), 0, 500),
883
                                'anyone_can_modify' => $_POST['import_kps_anyone_can_modify'] == "true" ? 1 : 0
884
                            )
885
                        );
886
                        $newId = DB::insertId();
887
888
                        //if asked, anyone in role can modify
889
                        if (isset($_POST['import_kps_anyone_can_modify_in_role']) && $_POST['import_kps_anyone_can_modify_in_role'] == "true") {
890
                            foreach ($_SESSION['arr_roles'] as $role) {
891
                                DB::insert(
892
                                    prefix_table("restriction_to_roles"),
893
                                    array(
894
                                        'role_id' => $role['id'],
895
                                        'item_id' => $newId
896
                                    )
897
                                );
898
                            }
899
                        }
900
901
                        //Add log
902
                        DB::insert(
903
                            prefix_table("log_items"),
904
                            array(
905
                                'id_item' => $newId,
906
                                'date' => time(),
907
                                'id_user' => $_SESSION['user_id'],
908
                                'action' => 'at_creation',
909
                                'raison' => 'at_import'
910
                            )
911
                        );
912
913
                        //Add entry to cache table
914
                        DB::insert(
915
                            prefix_table("cache"),
916
                            array(
917
                                'id' => $newId,
918
                                'label' => substr(stripslashes($item[KP_TITLE]), 0, 500),
919
                                'description' => stripslashes(str_replace($lineEndSeparator, '<br />', $item[KP_NOTES])),
920
                                'id_tree' => $folderId,
921
                                'perso' => $personalFolder == 0 ? 0 : 1,
922
                                'login' => substr(stripslashes($item[KP_USERNAME]), 0, 500),
923
                                'folder' => $data['title'],
924
                                'author' => $_SESSION['user_id'],
925
                                'timestamp' => time()
926
                            )
927
                        );
928
929
                        //increment number of imported items
930
                        $nbItemsImported++;
931
                    } else {
932
                        $results .= " - ".$item[KP_TITLE]." was not imported\n";
933
                    }
934
                }
935
            }
936
937
            //SHow finished
938
            $text .= "Folders imported: $nbFoldersImported<br />";
939
            $text .= "Items imported: $nbItemsImported<br />";
940
            $text .= '</div><br /><br /><b>'.$LANG['import_kp_finished'].'</b>';
941
            $text .= '<a href=\''.$_SESSION['settings']['url_to_files_folder'].'/'.$logFileName.'\' target=\'_blank\'>'.$LANG['pdf_download'].'</a>';
942
943
            fputs($cacheLogFile, date('H:i:s ')."Import finished\n");
944
            fputs($cacheLogFile, date('H:i:s ')."Statistics\n");
945
            fputs($cacheLogFile, date('H:i:s ')."Folders imported: $nbFoldersImported\n");
946
            fputs($cacheLogFile, date('H:i:s ')."Items imported: $nbItemsImported\n\n".$results);
947
948
            //Delete cache file
949
            fclose($cacheFileF);
950
            fclose($cacheFile);
951
            fclose($cacheLogFile);
952
            unlink($cacheFileName);
953
            unlink($cacheFileNameFolder);
954
            unlink($_SESSION['settings']['path_to_files_folder']."/".filter_var($_POST['file'], FILTER_SANITIZE_STRING));
955
956
            //Display all messages to user
957
            echo '[{"error":"no" , "message":"'.str_replace('"', "&quote;", strip_tags($text, '<br /><a><div><b><br>')).'"}]';
958
        } else {
959
            echo '[{"error":"yes" , "message":""}]';
960
        }
961
        break;
962
}
963
964
spl_autoload_register(function ($class) {
965
    $prefix = 'League\\Csv\\';
966
    $base_dir = __DIR__.'/src/';
967
    $len = strlen($prefix);
968
    if (strncmp($prefix, $class, $len) !== 0) {
969
        // no, move to the next registered autoloader
970
        echo "ici";
971
        return;
972
    }
973
    $relative_class = substr($class, $len);
974
    $file = $base_dir.str_replace('\\', '/', $relative_class).'.php';
975
    if (file_exists($file)) {
976
        require $file;
977
    }
978
});
979