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 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
|
|
|
// Load config |
25
|
|
|
if (file_exists('../includes/config/tp.config.php')) { |
26
|
|
|
require_once '../includes/config/tp.config.php'; |
27
|
|
|
} elseif (file_exists('./includes/config/tp.config.php')) { |
28
|
|
|
require_once './includes/config/tp.config.php'; |
29
|
|
|
} else { |
30
|
|
|
throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1); |
31
|
|
|
} |
32
|
|
|
|
33
|
|
|
// No time limit |
34
|
|
|
set_time_limit(0); |
35
|
|
|
|
36
|
|
|
// Set some constants for program readability |
37
|
|
|
define('KP_PATH', 0); |
38
|
|
|
define('KP_GROUP', 1); |
39
|
|
|
define('KP_TITLE', 2); |
40
|
|
|
define('KP_PASSWORD', 3); |
41
|
|
|
define('KP_USERNAME', 4); |
42
|
|
|
define('KP_URL', 5); |
43
|
|
|
define('KP_UUID', 6); |
44
|
|
|
define('KP_NOTES', 7); |
45
|
|
|
|
46
|
|
|
/* |
47
|
|
|
* sanitiseString |
48
|
|
|
* |
49
|
|
|
* Used to format the string ready for insertion in to the database |
50
|
|
|
*/ |
51
|
|
|
/** |
52
|
|
|
* @param string $crLFReplacement |
53
|
|
|
*/ |
54
|
|
|
function sanitiseString($str, $crLFReplacement) |
55
|
|
|
{ |
56
|
|
|
$str = preg_replace('#[\r\n]#', $crLFReplacement, $str); |
57
|
|
|
$str = str_replace('\\', '\', $str); |
58
|
|
|
$str = str_replace('"', """, $str); |
59
|
|
|
if (!empty($str)) { |
60
|
|
|
addslashes($str); |
61
|
|
|
} |
62
|
|
|
return $str; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
global $k, $settings; |
|
|
|
|
66
|
|
|
header("Content-type: text/html; charset=utf-8"); |
67
|
|
|
error_reporting(E_ERROR); |
68
|
|
|
include $SETTINGS['cpassman_dir'].'/includes/config/settings.php'; |
69
|
|
|
|
70
|
|
|
//Class loader |
71
|
|
|
require_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php'; |
72
|
|
|
|
73
|
|
|
// call needed functions |
74
|
|
|
require_once $SETTINGS['cpassman_dir'].'/sources/main.functions.php'; |
75
|
|
|
|
76
|
|
|
// connect to the server |
77
|
|
|
require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php'; |
78
|
|
|
$pass = defuse_return_decrypted($pass); |
79
|
|
|
DB::$host = $server; |
80
|
|
|
DB::$user = $user; |
81
|
|
|
DB::$password = $pass; |
82
|
|
|
DB::$dbName = $database; |
83
|
|
|
DB::$port = $port; |
84
|
|
|
DB::$encoding = $encoding; |
85
|
|
|
DB::$error_handler = true; |
86
|
|
|
$link = mysqli_connect($server, $user, $pass, $database, $port); |
87
|
|
|
$link->set_charset($encoding); |
88
|
|
|
|
89
|
|
|
//Load Tree |
90
|
|
|
$tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries'); |
91
|
|
|
$tree->register(); |
92
|
|
|
$tree = new Tree\NestedTree\NestedTree($pre.'nested_tree', 'id', 'parent_id', 'title'); |
93
|
|
|
|
94
|
|
|
//Load AES |
95
|
|
|
$aes = new SplClassLoader('Encryption\Crypt', '../includes/libraries'); |
96
|
|
|
$aes->register(); |
97
|
|
|
|
98
|
|
|
//User's language loading |
99
|
|
|
require_once $SETTINGS['cpassman_dir'].'/includes/language/'.$_SESSION['user_language'].'.php'; |
100
|
|
|
|
101
|
|
|
// Build query |
102
|
|
|
switch (filter_input(INPUT_POST, 'type', FILTER_SANITIZE_STRING)) { |
103
|
|
|
//Check if import CSV file format is what expected |
104
|
|
|
case "import_file_format_csv": |
105
|
|
|
//load full tree |
106
|
|
|
$tree->rebuild(); |
107
|
|
|
$tree = $tree->getDescendants(); |
108
|
|
|
// Init post variable |
109
|
|
|
$post_operation_id = filter_input(INPUT_POST, 'file', FILTER_SANITIZE_NUMBER_INT); |
110
|
|
|
|
111
|
|
|
// Get filename from database |
112
|
|
|
$data = DB::queryFirstRow( |
113
|
|
|
"SELECT valeur |
114
|
|
|
FROM ".$pre."misc |
115
|
|
|
WHERE increment_id = %i AND type = 'temp_file'", |
116
|
|
|
$post_operation_id |
117
|
|
|
); |
118
|
|
|
|
119
|
|
|
// Delete operation id |
120
|
|
|
DB::delete( |
121
|
|
|
prefix_table('misc'), |
122
|
|
|
"increment_id = %i AND type = 'temp_file'", |
123
|
|
|
$post_operation_id |
124
|
|
|
); |
125
|
|
|
|
126
|
|
|
// do some initializations |
127
|
|
|
$file = $SETTINGS['path_to_files_folder']."/".$data['valeur']; |
128
|
|
|
$size = 4096; |
129
|
|
|
$separator = ","; |
130
|
|
|
$enclosure = '"'; |
131
|
|
|
$fields_expected = array("Label", "Login", "Password", "URL", "Comments"); //requiered fields from CSV |
132
|
|
|
$importation_possible = true; |
133
|
|
|
$display = "<table>"; |
134
|
|
|
$line_number = $prev_level = 0; |
135
|
|
|
$account = $text = ""; |
136
|
|
|
$continue_on_next_line = false; |
137
|
|
|
|
138
|
|
|
// Open file |
139
|
|
|
if ($fp = fopen($file, "r")) { |
140
|
|
|
// data from CSV |
141
|
|
|
$valuesToImport = array(); |
142
|
|
|
// load libraries |
143
|
|
|
require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Goodby/CSV/Import/Standard/Lexer.php'; |
144
|
|
|
require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Goodby/CSV/Import/Standard/Interpreter.php'; |
145
|
|
|
require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Goodby/CSV/Import/Standard/LexerConfig.php'; |
146
|
|
|
|
147
|
|
|
// Lexer configuration |
148
|
|
|
$config = new LexerConfig(); |
149
|
|
|
$lexer = new Lexer($config); |
150
|
|
|
$config->setIgnoreHeaderLine("true"); |
151
|
|
|
// extract data from CSV file |
152
|
|
|
$interpreter = new Interpreter(); |
153
|
|
|
$interpreter->addObserver(function (array $row) use (&$valuesToImport) { |
154
|
|
|
$valuesToImport[] = array( |
155
|
|
|
'Label' => $row[0], |
156
|
|
|
'Login' => $row[1], |
157
|
|
|
'Password' => $row[2], |
158
|
|
|
'url' => $row[3], |
159
|
|
|
'Comments' => $row[4], |
160
|
|
|
); |
161
|
|
|
}); |
162
|
|
|
$lexer->parse($file, $interpreter); |
163
|
|
|
|
164
|
|
|
// extract one line |
165
|
|
|
foreach ($valuesToImport as $key => $row) { |
166
|
|
|
//Check number of fields. MUST be 5. if not stop importation |
167
|
|
|
if (count($row) != 5) { |
168
|
|
|
$importation_possible = false; |
169
|
|
|
//Stop if file has not expected structure |
170
|
|
|
if ($importation_possible === false) { |
171
|
|
|
echo '[{"error":"bad_structure"}]'; |
172
|
|
|
break; |
173
|
|
|
} |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
//If any comment is on several lines, then replace 'lf' character |
177
|
|
|
$row['Comments'] = str_replace(array("\r\n", "\n", "\r"), "<br />", $row['Comments']); |
178
|
|
|
|
179
|
|
|
// Check if current line contains a "<br />" character in order to identify an ITEM on several CSV lines |
180
|
|
|
if (substr_count('<br />', $row['Comments']) > 0 || substr_count('<br />', $row['Label']) > 0) { |
181
|
|
|
$continue_on_next_line = true; |
182
|
|
|
$comment .= addslashes($row['Label']); |
183
|
|
|
} else { |
184
|
|
|
// Store in variable values from previous line |
185
|
|
|
if (!empty($account)) { |
186
|
|
|
if ($continue_on_next_line === false) { |
187
|
|
|
// Prepare listing that will be shown to user |
188
|
|
|
$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.'@|@'.$pwd.'@|@'.$url.'@|@'.$comment.'@|@'.$line_number.'\" id=\"item_to_import_values-'.$line_number.'\" /></td></tr>'; |
189
|
|
|
|
190
|
|
|
// Initialize this variable in order to restart from scratch |
191
|
|
|
$account = ""; |
192
|
|
|
} |
193
|
|
|
} |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
// Get values of current line |
197
|
|
|
if ($account == "" && $continue_on_next_line === false) { |
198
|
|
|
$account = htmlspecialchars($row['Label'], ENT_QUOTES, 'UTF-8'); |
199
|
|
|
$login = htmlspecialchars($row['Login'], ENT_QUOTES, 'UTF-8'); |
200
|
|
|
$pwd = str_replace('"', """, $row['Password']); |
201
|
|
|
$url = addslashes($row['url']); |
202
|
|
|
$to_find = array("\"", "'"); |
203
|
|
|
$to_ins = array(""", "'"); |
204
|
|
|
$comment = htmlentities(addslashes(str_replace($to_find, $to_ins, $row['Comments'])), ENT_QUOTES, 'UTF-8'); |
205
|
|
|
|
206
|
|
|
$continue_on_next_line = false; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
//increment number of lines found |
210
|
|
|
$line_number++; |
211
|
|
|
} |
212
|
|
|
// close file |
213
|
|
|
fclose($fp); |
214
|
|
|
} else { |
215
|
|
|
echo '[{"error":"cannot_open"}]'; |
216
|
|
|
|
217
|
|
|
//delete file |
218
|
|
|
unlink($file); |
219
|
|
|
break; |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
if ($line_number > 0) { |
223
|
|
|
//add last line |
224
|
|
|
$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('"', ""e;", $pwd).'@|@'.$url.'@|@'.$comment.'@|@'.$line_number.'\" id=\"item_to_import_values-'.$line_number.'\" /></td></tr>'; |
225
|
|
|
|
226
|
|
|
// Add a checkbox for select/unselect all others |
227
|
|
|
$display .= '<tr><td colspan=\"2\"><br><input type=\"checkbox\" id=\"item_all_selection\" /> '.$LANG['all'].'</td></tr>'; |
228
|
|
|
|
229
|
|
|
// Prepare a list of all folders that the user can choose |
230
|
|
|
$display .= '</table><div style=\"margin:10px 0 10px 0;\"><label><b>'.$LANG['import_to_folder'].'</b></label> <select id=\"import_items_to\" style=\"width:87%;\">'; |
231
|
|
|
foreach ($tree as $t) { |
232
|
|
|
if (($_SESSION['user_read_only'] === '0' && in_array($t->id, $_SESSION['groupes_visibles'])) |
233
|
|
|
|| ($_SESSION['user_read_only'] === '1' && in_array($t->id, $_SESSION['personal_visible_groups'])) |
234
|
|
|
) { |
235
|
|
|
$ident = ""; |
236
|
|
|
for ($x = 1; $x < $t->nlevel; $x++) { |
237
|
|
|
$ident .= " "; |
238
|
|
|
} |
239
|
|
|
if (null !== filter_input(INPUT_POST, 'folder_id', FILTER_SANITIZE_NUMBER_INT) && filter_input(INPUT_POST, 'folder_id', FILTER_SANITIZE_NUMBER_INT) === $t->id) { |
240
|
|
|
$selected = " selected"; |
241
|
|
|
} else { |
242
|
|
|
$selected = ""; |
243
|
|
|
} |
244
|
|
|
// Check if folder is User id |
245
|
|
|
if (is_numeric($t->title) === true && $t->title === $_SESSION['user_id']) { |
246
|
|
|
$t->title = $_SESSION['login']; |
247
|
|
|
} |
248
|
|
|
if ($prev_level != null && $prev_level < $t->nlevel) { |
249
|
|
|
$display .= '<option value=\"'.$t->id.'\"'.$selected.'>'.$ident.str_replace(array("&", '"'), array("&", """), $t->title).'</option>'; |
250
|
|
|
} elseif ($prev_level != null && $prev_level == $t->nlevel) { |
251
|
|
|
$display .= '<option value=\"'.$t->id.'\"'.$selected.'>'.$ident.str_replace(array("&", '"'), array("&", """), $t->title).'</option>'; |
252
|
|
|
} else { |
253
|
|
|
$display .= '<option value=\"'.$t->id.'\"'.$selected.'>'.$ident.str_replace(array("&", '"'), array("&", """), $t->title).'</option>'; |
254
|
|
|
} |
255
|
|
|
$prev_level = $t->nlevel; |
256
|
|
|
} |
257
|
|
|
} |
258
|
|
|
$display .= '</select></div>'; |
259
|
|
|
|
260
|
|
|
// Show results to user. |
261
|
|
|
echo '[{"error":"no" , "output" : "'.$display.'"}]'; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
//delete file |
265
|
|
|
unlink($file); |
266
|
|
|
|
267
|
|
|
break; |
268
|
|
|
|
269
|
|
|
//Insert into DB the items the user has selected |
270
|
|
|
case "import_items": |
271
|
|
|
//decrypt and retreive data in JSON format |
272
|
|
|
$dataReceived = (Encryption\Crypt\aesctr::decrypt( |
273
|
|
|
filter_input(INPUT_POST, 'data', FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES), |
274
|
|
|
$_SESSION['key'], |
275
|
|
|
256 |
276
|
|
|
)); |
277
|
|
|
|
278
|
|
|
$post_folder = filter_input(INPUT_POST, 'folder', FILTER_SANITIZE_NUMBER_INT); |
279
|
|
|
|
280
|
|
|
// Get title for this folder |
281
|
|
|
$data_fld = DB::queryFirstRow( |
282
|
|
|
"SELECT title |
283
|
|
|
FROM ".prefix_table("nested_tree")." |
284
|
|
|
WHERE id = %i", |
285
|
|
|
$post_folder |
286
|
|
|
); |
287
|
|
|
|
288
|
|
|
//Get some info about personal folder |
289
|
|
|
if (in_array($post_folder, $_SESSION['personal_folders']) === true) { |
290
|
|
|
$personalFolder = 1; |
291
|
|
|
} else { |
292
|
|
|
$personalFolder = 0; |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
//Prepare variables |
296
|
|
|
$listItems = htmlspecialchars_decode($dataReceived); |
297
|
|
|
$list = ""; |
298
|
|
|
|
299
|
|
|
foreach (explode('@_#sep#_@', stripslashes($listItems)) as $item) { |
300
|
|
|
//For each item, insert into DB |
301
|
|
|
$item = explode('@|@', $item); //explode item to get all fields |
302
|
|
|
|
303
|
|
|
//Encryption key |
304
|
|
|
if ($personalFolder == 1) { |
305
|
|
|
$encrypt = cryption( |
306
|
|
|
$item[2], |
307
|
|
|
$_SESSION['user_settings']['session_psk'], |
308
|
|
|
"encrypt" |
309
|
|
|
); |
310
|
|
|
} else { |
311
|
|
|
$encrypt = cryption( |
312
|
|
|
$item[2], |
313
|
|
|
"", |
314
|
|
|
"encrypt" |
315
|
|
|
); |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
// Insert new item in table ITEMS |
319
|
|
|
DB::insert( |
320
|
|
|
prefix_table("items"), |
321
|
|
|
array( |
322
|
|
|
'label' => substr($item[0], 0, 500), |
323
|
|
|
'description' => empty($item[4]) ? '' : $item[4], |
324
|
|
|
'pw' => $encrypt['string'], |
325
|
|
|
'pw_iv' => $encrypt['iv'], |
326
|
|
|
'url' => empty($item[3]) ? '' : substr($item[3], 0, 500), |
327
|
|
|
'id_tree' => filter_input(INPUT_POST, 'folder', FILTER_SANITIZE_NUMBER_INT), |
328
|
|
|
'login' => empty($item[1]) ? '' : substr($item[1], 0, 200), |
329
|
|
|
'anyone_can_modify' => filter_input(INPUT_POST, 'import_csv_anyone_can_modify', FILTER_SANITIZE_STRING) === "true" ? 1 : 0 |
330
|
|
|
) |
331
|
|
|
); |
332
|
|
|
$newId = DB::insertId(); |
333
|
|
|
|
334
|
|
|
//if asked, anyone in role can modify |
335
|
|
|
if (null !== filter_input(INPUT_POST, 'import_csv_anyone_can_modify_in_role', FILTER_SANITIZE_STRING) |
336
|
|
|
&& filter_input(INPUT_POST, 'import_csv_anyone_can_modify_in_role', FILTER_SANITIZE_STRING) === "true" |
337
|
|
|
) { |
338
|
|
|
foreach ($_SESSION['arr_roles'] as $role) { |
339
|
|
|
DB::insert( |
340
|
|
|
prefix_table("restriction_to_roles"), |
341
|
|
|
array( |
342
|
|
|
'role_id' => $role['id'], |
343
|
|
|
'item_id' => $newId |
344
|
|
|
) |
345
|
|
|
); |
346
|
|
|
} |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
// Insert new item in table LOGS_ITEMS |
350
|
|
|
DB::insert( |
351
|
|
|
prefix_table("log_items"), |
352
|
|
|
array( |
353
|
|
|
'id_item' => $newId, |
354
|
|
|
'date' => time(), |
355
|
|
|
'id_user' => $_SESSION['user_id'], |
356
|
|
|
'action' => 'at_creation' |
357
|
|
|
) |
358
|
|
|
); |
359
|
|
|
|
360
|
|
|
if (empty($list)) { |
361
|
|
|
$list = $item[5]; |
362
|
|
|
} else { |
363
|
|
|
$list .= ";".$item[5]; |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
//Add entry to cache table |
367
|
|
|
DB::insert( |
368
|
|
|
prefix_table("cache"), |
369
|
|
|
array( |
370
|
|
|
'id' => $newId, |
371
|
|
|
'label' => substr($item[0], 0, 500), |
372
|
|
|
'description' => empty($item[4]) ? '' : $item[4], |
373
|
|
|
'id_tree' => filter_input(INPUT_POST, 'folder', FILTER_SANITIZE_NUMBER_INT), |
374
|
|
|
'url' => "0", |
375
|
|
|
'perso' => $personalFolder == 0 ? 0 : 1, |
376
|
|
|
'login' => empty($item[1]) ? '' : substr($item[1], 0, 500), |
377
|
|
|
'folder' => $data_fld['title'], |
378
|
|
|
'author' => $_SESSION['user_id'], |
379
|
|
|
'timestamp' => time(), |
380
|
|
|
'tags' => '', |
381
|
|
|
'restricted_to' => '0', |
382
|
|
|
'renewal_period' => "0", |
383
|
|
|
'timestamp' => time() |
384
|
|
|
) |
385
|
|
|
); |
386
|
|
|
} |
387
|
|
|
echo '[{"items":"'.$list.'"}]'; |
388
|
|
|
break; |
389
|
|
|
|
390
|
|
|
//Check if import KEEPASS file format is what expected |
391
|
|
|
case "import_file_format_keepass": |
392
|
|
|
//Initialization |
393
|
|
|
$root = $meta = $group = $entry = $key = $title = $notes = $pwd = $username = $url = $notKeepassFile = $newItem = $history = $generatorFound = false; |
394
|
|
|
$name = $levelInProgress = $previousLevel = $fullPath = $historyLevel = $path = $display = $keepassVersion = ""; |
395
|
|
|
$numGroups = $numItems = 0; |
396
|
|
|
$temparray = $arrFolders = array(); |
397
|
|
|
$levelMin = 2; |
398
|
|
|
$foldersSeparator = '@&##&@'; |
399
|
|
|
$itemsSeparator = '<=|#|=>'; |
400
|
|
|
$lineEndSeparator = '@*1|#9*|@'; |
401
|
|
|
|
402
|
|
|
//prepare CACHE files |
403
|
|
|
$cacheFileName = $SETTINGS['path_to_files_folder']."/cpassman_cache_".md5(time().mt_rand()); |
404
|
|
|
$cacheFileNameFolder = $cacheFileName."_folders"; |
405
|
|
|
$cacheFile = fopen($cacheFileName, "w"); |
406
|
|
|
$cacheFileF = fopen($cacheFileNameFolder, "w"); |
407
|
|
|
$logFileName = "/keepassImport_".date('YmdHis').".log"; |
408
|
|
|
$cacheLogFile = fopen($SETTINGS['path_to_files_folder'].$logFileName, 'w'); |
409
|
|
|
|
410
|
|
|
// Init post variable |
411
|
|
|
$post_operation_id = filter_input(INPUT_POST, 'file', FILTER_SANITIZE_STRING); |
412
|
|
|
|
413
|
|
|
// Get filename from database |
414
|
|
|
$data = DB::queryFirstRow( |
415
|
|
|
"SELECT valeur |
416
|
|
|
FROM ".$pre."misc |
417
|
|
|
WHERE increment_id = %i AND type = 'temp_file'", |
418
|
|
|
$post_operation_id |
419
|
|
|
); |
420
|
|
|
|
421
|
|
|
// Delete operation id |
422
|
|
|
DB::delete( |
423
|
|
|
prefix_table('misc'), |
424
|
|
|
"increment_id = %i AND type = 'temp_file'", |
425
|
|
|
$post_operation_id |
426
|
|
|
); |
427
|
|
|
|
428
|
|
|
// do some initializations |
429
|
|
|
$file = $data['valeur']; |
430
|
|
|
|
431
|
|
|
//read xml file |
432
|
|
|
if (file_exists($SETTINGS['path_to_files_folder']."/".$file)) { |
433
|
|
|
$xml = simplexml_load_file( |
434
|
|
|
$SETTINGS['path_to_files_folder']."/".$file |
435
|
|
|
); |
436
|
|
|
} |
437
|
|
|
|
438
|
|
|
/** |
439
|
|
|
** Recursive function that will permit to read each level of XML nodes |
440
|
|
|
*/ |
441
|
|
|
function recursiveKeepassXML($xmlRoot, $xmlLevel = 0) |
442
|
|
|
{ |
443
|
|
|
global $meta, $root, $group, $name, $entry, $levelMin, $title, $notes, $pwd, $username, $url, |
|
|
|
|
444
|
|
|
$newItem, $temparray, $history, $levelInProgress, $historyLevel, |
445
|
|
|
$path, $previousLevel, $generatorFound, $cacheFile, $cacheFileF, $numGroups, |
446
|
|
|
$numItems, $foldersSeparator, $itemsSeparator, $keepassVersion, $arrFolders; |
447
|
|
|
|
448
|
|
|
$groupsArray = array(); |
449
|
|
|
|
450
|
|
|
// For each node, get the name and SimpleXML balise |
451
|
|
|
foreach ($xmlRoot as $nom => $elem) { |
452
|
|
|
/* |
453
|
|
|
* check if file is generated by keepass 1 |
454
|
|
|
* key "pwentry" is only used in KP1.xx XML files |
455
|
|
|
*/ |
456
|
|
|
if ($nom == "pwentry") { |
457
|
|
|
if (empty($keepassVersion)) { |
458
|
|
|
$keepassVersion = 1; |
459
|
|
|
$generatorFound = true; |
460
|
|
|
$entry = true; |
461
|
|
|
} else { |
462
|
|
|
$entry = true; |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
//get children |
466
|
|
|
$xmlChildren = $elem->children(); |
467
|
|
|
|
468
|
|
|
//recursive call |
469
|
|
|
recursiveKeepassXML($xmlChildren, $xmlLevel + 1); |
470
|
|
|
} |
471
|
|
|
//IMPORTING KEEPASS 1 XML FILE |
472
|
|
|
if ($keepassVersion == 1) { |
473
|
|
|
if ($entry === true && $nom == "expiretime") { |
474
|
|
|
//save previous keepass entry |
475
|
|
|
$tree = preg_replace('/\\\\/', $foldersSeparator, $temparray['tree']); |
476
|
|
|
fputs( |
477
|
|
|
$cacheFile, |
478
|
|
|
$tree.$itemsSeparator.$temparray[KP_GROUP].$itemsSeparator.$temparray[KP_TITLE]. |
479
|
|
|
$itemsSeparator.$temparray[KP_PW].$itemsSeparator.$temparray[KP_USERNAME]. |
|
|
|
|
480
|
|
|
$itemsSeparator.$temparray[KP_URL].$itemsSeparator.$temparray[KP_UUID].$itemsSeparator.$temparray[KP_NOTES]."\n" |
481
|
|
|
); |
482
|
|
|
|
483
|
|
|
if (!in_array($temparray['tree'], $arrFolders)) { |
484
|
|
|
fwrite($cacheFileF, $tree."\n"); |
485
|
|
|
array_push($arrFolders, $temparray['tree']); |
486
|
|
|
} |
487
|
|
|
|
488
|
|
|
$temparray = array(); |
489
|
|
|
$newItem++; |
490
|
|
|
} |
491
|
|
|
|
492
|
|
|
if ($entry === true && $nom == "group") { |
493
|
|
|
$temparray[KP_GROUP] = addslashes(preg_replace('#[\r\n]#', '', $elem)); |
494
|
|
|
foreach ($elem->attributes() as $attributeskey0 => $attributesvalue1) { |
495
|
|
|
if ($attributeskey0 == "tree") { |
496
|
|
|
$path = explode('\\', $attributesvalue1); |
497
|
|
|
if (count($path) > 1) { |
498
|
|
|
unset($path[0]); |
499
|
|
|
$temparray['tree'] = implode('\\', $path).'\\'.$temparray[KP_GROUP]; |
500
|
|
|
} else { |
501
|
|
|
$temparray['tree'] = $temparray[KP_GROUP]; |
502
|
|
|
} |
503
|
|
|
} |
504
|
|
|
} |
505
|
|
|
$numGroups++; |
506
|
|
|
} elseif ($entry === true && $nom == "title") { |
507
|
|
|
$temparray[KP_TITLE] = sanitiseString($elem, ''); |
508
|
|
|
} elseif ($entry === true && $nom == "username") { |
509
|
|
|
$temparray[KP_USERNAME] = sanitiseString($elem, ''); |
510
|
|
|
} elseif ($entry === true && $nom == "url") { |
511
|
|
|
$temparray[KP_URL] = sanitiseString($elem, ''); |
512
|
|
|
} elseif ($entry === true && $nom == "uuid") { |
513
|
|
|
$temparray[KP_UUID] = addslashes(preg_replace('#[\r\n]#', '', $elem)); |
514
|
|
|
} elseif ($entry === true && $nom == "password") { |
515
|
|
|
$temparray[KP_PW] = sanitiseString($elem, ''); |
516
|
|
|
} elseif ($entry === true && $nom == "notes") { |
517
|
|
|
$temparray[KP_NOTES] = sanitiseString($elem, ''); |
518
|
|
|
} |
519
|
|
|
} |
520
|
|
|
|
521
|
|
|
/* |
522
|
|
|
* check if file is generated by keepass 2 |
523
|
|
|
*/ |
524
|
|
|
if (trim($elem) == "" && $keepassVersion != 1) { |
525
|
|
|
//check if file is generated by keepass 2 |
526
|
|
|
if ($nom == "Meta") { |
527
|
|
|
$meta = true; |
528
|
|
|
} |
529
|
|
|
if ($nom == "Root") { |
530
|
|
|
$root = true; |
531
|
|
|
} |
532
|
|
|
|
533
|
|
|
if ($nom == "Group") { |
534
|
|
|
$group = true; |
535
|
|
|
$entry = false; |
536
|
|
|
$name = ""; |
537
|
|
|
|
538
|
|
|
// recap previous info |
539
|
|
|
if (!empty($temparray[KP_TITLE])) { |
540
|
|
|
//store data |
541
|
|
|
fputs( |
542
|
|
|
$cacheFile, |
543
|
|
|
$temparray[KP_PATH].$itemsSeparator.$temparray[KP_GROUP]. |
544
|
|
|
$itemsSeparator.$temparray[KP_TITLE].$itemsSeparator.$temparray[KP_PW]. |
545
|
|
|
$itemsSeparator.$temparray[KP_USERNAME].$itemsSeparator. |
546
|
|
|
$temparray[KP_URL].$itemsSeparator.$temparray[KP_UUID].$itemsSeparator.$temparray[KP_NOTES]."\n" |
547
|
|
|
); |
548
|
|
|
|
549
|
|
|
//Clean temp array |
550
|
|
|
$temparray[KP_TITLE] = $temparray[KP_NOTES] = $temparray[KP_PW] = $temparray[KP_USERNAME] = $temparray[KP_URL] = ""; |
551
|
|
|
|
552
|
|
|
//increment number |
553
|
|
|
$numItems++; |
554
|
|
|
} |
555
|
|
|
$historyLevel = 0; |
556
|
|
|
} |
557
|
|
|
|
558
|
|
|
//History node needs to be managed in order to not polluate final list |
559
|
|
|
if ($nom == "History") { |
560
|
|
|
$history = true; |
561
|
|
|
$entry = false; |
562
|
|
|
$historyLevel = $xmlLevel; |
563
|
|
|
} |
564
|
|
|
|
565
|
|
|
if ($nom == "Entry" && ($xmlLevel < $historyLevel || empty($historyLevel))) { |
566
|
|
|
$entry = true; |
567
|
|
|
$group = false; |
568
|
|
|
$history = false; |
569
|
|
|
|
570
|
|
|
// recap previous info |
571
|
|
|
if (!empty($temparray[KP_TITLE])) { |
572
|
|
|
//store data |
573
|
|
|
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"); |
574
|
|
|
|
575
|
|
|
//Clean temp array |
576
|
|
|
$temparray[KP_TITLE] = $temparray[KP_NOTES] = $temparray[KP_PW] = $temparray[KP_USERNAME] = $temparray[KP_URL] = $temparray[KP_UUID] = ""; |
577
|
|
|
|
578
|
|
|
//increment number |
579
|
|
|
$numItems++; |
580
|
|
|
} |
581
|
|
|
$historyLevel = 0; |
582
|
|
|
} |
583
|
|
|
|
584
|
|
|
//get children |
585
|
|
|
$xmlChildren = $elem->children(); |
586
|
|
|
|
587
|
|
|
//recursive call |
588
|
|
|
if ($history !== true) { |
589
|
|
|
recursiveKeepassXML($xmlChildren, $xmlLevel + 1); |
590
|
|
|
} |
591
|
|
|
|
592
|
|
|
// Force History to false |
593
|
|
|
$history = false; |
594
|
|
|
|
595
|
|
|
//IMPORTING KEEPASS 2 XML FILE |
596
|
|
|
} elseif ($keepassVersion != 1) { |
597
|
|
|
// exit if XML file not generated by KeePass |
598
|
|
|
if ($meta === true && $nom == "Generator" && $elem == "KeePass") { |
599
|
|
|
$generatorFound = true; |
600
|
|
|
$keepassVersion = 2; |
601
|
|
|
break; |
602
|
|
|
} elseif ($root === true && $xmlLevel > $levelMin) { |
603
|
|
|
//Check each node name and get data from some of them |
604
|
|
|
if ($entry === true && $nom == "Key" && $elem == "Title") { |
605
|
|
|
$title = true; |
606
|
|
|
$notes = $pwd = $url = $username = false; |
607
|
|
|
} elseif ($entry === true && $nom == "Key" && $elem == "Notes") { |
608
|
|
|
$notes = true; |
609
|
|
|
$title = $pwd = $url = $username = false; |
610
|
|
|
} elseif ($entry === true && $nom == "UUID") { |
611
|
|
|
$temparray[KP_UUID] = $elem; |
612
|
|
|
} elseif ($entry === true && $nom == "Key" && $elem == "Password") { |
613
|
|
|
$pwd = true; |
614
|
|
|
$notes = $title = $url = $username = false; |
615
|
|
|
} elseif ($entry === true && $nom == "Key" && $elem == "URL") { |
616
|
|
|
$url = true; |
617
|
|
|
$notes = $pwd = $title = $username = false; |
618
|
|
|
} elseif ($entry === true && $nom == "Key" && $elem == "UserName") { |
619
|
|
|
$username = true; |
620
|
|
|
$notes = $pwd = $url = $title = false; |
621
|
|
|
} elseif ($group === true && $nom == "Name") { |
622
|
|
|
$temparray[KP_GROUP] = addslashes(preg_replace('#[\r\n]#', '', $elem)); |
623
|
|
|
$temparray['level'] = $xmlLevel; |
624
|
|
|
//build current path |
625
|
|
|
if ($xmlLevel > $levelInProgress) { |
626
|
|
|
if (!empty($temparray[KP_PATH])) { |
627
|
|
|
$temparray[KP_PATH] .= $foldersSeparator.$temparray[KP_GROUP]; |
628
|
|
|
} else { |
629
|
|
|
$temparray[KP_PATH] = $temparray[KP_GROUP]; |
630
|
|
|
} |
631
|
|
|
} elseif ($xmlLevel == $levelInProgress) { |
632
|
|
|
if ($levelInProgress == 3) { |
633
|
|
|
$temparray[KP_PATH] = $temparray[KP_GROUP]; |
634
|
|
|
} else { |
635
|
|
|
$temparray[KP_PATH] = substr($temparray[KP_PATH], 0, strrpos($temparray[KP_PATH], $foldersSeparator) + strlen($foldersSeparator)).$temparray[KP_GROUP]; |
636
|
|
|
} |
637
|
|
|
} else { |
638
|
|
|
$diff = abs($xmlLevel - $levelInProgress) + 1; |
639
|
|
|
$tmp = explode($foldersSeparator, $temparray[KP_PATH]); |
640
|
|
|
$temparray[KP_PATH] = ""; |
641
|
|
|
for ($x = 0; $x < (count($tmp) - $diff); $x++) { |
642
|
|
|
if (!empty($temparray[KP_PATH])) { |
643
|
|
|
$temparray[KP_PATH] = $temparray[KP_PATH].$foldersSeparator.$tmp[$x]; |
644
|
|
|
} else { |
645
|
|
|
$temparray[KP_PATH] = $tmp[$x]; |
646
|
|
|
} |
647
|
|
|
} |
648
|
|
|
if (!empty($temparray[KP_PATH])) { |
649
|
|
|
$temparray[KP_PATH] .= $foldersSeparator.$temparray[KP_GROUP]; |
650
|
|
|
} else { |
651
|
|
|
$temparray[KP_PATH] = $temparray[KP_GROUP]; |
652
|
|
|
} |
653
|
|
|
} |
654
|
|
|
|
655
|
|
|
//store folders |
656
|
|
|
if (!in_array($temparray[KP_PATH], $groupsArray)) { |
657
|
|
|
fwrite($cacheFileF, $temparray[KP_PATH]."\n"); |
658
|
|
|
array_push($groupsArray, $temparray[KP_PATH]); |
659
|
|
|
//increment number |
660
|
|
|
$numGroups++; |
661
|
|
|
} |
662
|
|
|
|
663
|
|
|
//Store actual level |
664
|
|
|
$levelInProgress = $xmlLevel; |
665
|
|
|
$previousLevel = $temparray[KP_GROUP]; |
666
|
|
|
} elseif ($title === true && $nom == "Value") { |
667
|
|
|
$title = false; |
668
|
|
|
$temparray[KP_TITLE] = sanitiseString($elem, ''); |
669
|
|
|
} elseif ($notes === true && $nom == "Value") { |
670
|
|
|
$notes = false; |
671
|
|
|
$temparray[KP_NOTES] = sanitiseString($elem, ''); |
672
|
|
|
} elseif ($pwd === true && $nom == "Value") { |
673
|
|
|
$pwd = false; |
674
|
|
|
$temparray[KP_PW] = sanitiseString($elem, ''); |
675
|
|
|
} elseif ($url === true && $nom == "Value") { |
676
|
|
|
$url = false; |
677
|
|
|
$temparray[KP_URL] = sanitiseString($elem, ''); |
678
|
|
|
} elseif ($username === true && $nom == "Value") { |
679
|
|
|
$username = false; |
680
|
|
|
$temparray[KP_USERNAME] = sanitiseString($elem, ''); |
681
|
|
|
} |
682
|
|
|
} |
683
|
|
|
} |
684
|
|
|
} |
685
|
|
|
} |
686
|
|
|
|
687
|
|
|
fputs($cacheLogFile, date('H:i:s ')."Writing XML File ".filter_input(INPUT_POST, 'file', FILTER_SANITIZE_STRING)."\n"); |
|
|
|
|
688
|
|
|
|
689
|
|
|
// Go through each node of XML file |
690
|
|
|
recursiveKeepassXML($xml); |
691
|
|
|
|
692
|
|
|
//Stop if not a keepass file |
693
|
|
|
if ($generatorFound === false) { |
|
|
|
|
694
|
|
|
//Close file & delete it |
695
|
|
|
fclose($cacheFileF); |
|
|
|
|
696
|
|
|
fclose($cacheFile); |
697
|
|
|
unlink($cacheFileName); |
698
|
|
|
unlink($cacheFileNameFolder); |
699
|
|
|
unlink($SETTINGS['url_to_files_folder']."/".filter_input(INPUT_POST, 'file', FILTER_SANITIZE_STRING)); |
700
|
|
|
|
701
|
|
|
fputs($cacheLogFile, date('H:i').$LANG['import_error_no_read_possible_kp']."\n"); |
702
|
|
|
|
703
|
|
|
echo '[{"error":"not_kp_file" , "message":"'.$LANG['import_error_no_read_possible_kp'].'"}]'; |
704
|
|
|
break; |
705
|
|
|
} |
706
|
|
|
|
707
|
|
|
//save last item |
708
|
|
|
if (!empty($temparray[KP_TITLE])) { |
709
|
|
|
//store data |
710
|
|
|
fputs( |
711
|
|
|
$cacheFile, |
712
|
|
|
$temparray[KP_PATH].$itemsSeparator.$temparray[KP_GROUP].$itemsSeparator. |
713
|
|
|
$temparray[KP_TITLE].$itemsSeparator.$temparray[KP_PW].$itemsSeparator.$temparray[KP_USERNAME]. |
|
|
|
|
714
|
|
|
$itemsSeparator.$temparray[KP_URL].$itemsSeparator.$temparray[KP_UUID].$itemsSeparator.$temparray[KP_NOTES]."\n" |
715
|
|
|
); |
716
|
|
|
|
717
|
|
|
//increment number |
718
|
|
|
$numItems++; |
719
|
|
|
} |
720
|
|
|
|
721
|
|
|
################## |
722
|
|
|
## STARTING IMPORTING IF NO ERRORS OR NOT EMPTY |
723
|
|
|
################## |
724
|
|
|
if ($numItems > 0 || $numGroups > 0) { |
725
|
|
|
// Write in file |
726
|
|
|
fputs($cacheLogFile, date('H:i:s ').$LANG['nb_folders'].' '.$numGroups."\n"); |
727
|
|
|
fputs($cacheLogFile, date('H:i:s ').$LANG['nb_items'].' '.$numItems."\n"); |
728
|
|
|
|
729
|
|
|
$import_perso = false; |
730
|
|
|
$itemsArray = array(); |
731
|
|
|
$text = '<span class="fa fa-folder-open"></span> '.$LANG['nb_folders'].': '. |
732
|
|
|
$numGroups.'<br /><span class="fa fa-tag"></span>> '.$LANG['nb_items'].': '. |
733
|
|
|
$numItems.'<br /><br />'; |
734
|
|
|
$post_destination = filter_input(INPUT_POST, 'destination', FILTER_SANITIZE_STRING); |
735
|
|
|
|
736
|
|
|
// If personal folder, then remove the suffix in ID |
737
|
|
|
if (substr_count($post_destination, '-perso') > 0) { |
738
|
|
|
$post_destination = str_replace('-perso', '', $post_destination); |
739
|
|
|
} |
740
|
|
|
|
741
|
|
|
// If destination is not ROOT then get the complexity level |
742
|
|
|
if (strpos($post_destination, "perso") !== 0) { |
743
|
|
|
$levelPwComplexity = 50; |
744
|
|
|
$startPathLevel = 1; |
745
|
|
|
$import_perso = true; |
746
|
|
|
} elseif ($post_destination > 0) { |
747
|
|
|
$data = DB::queryFirstRow( |
748
|
|
|
"SELECT m.valeur as value, t.nlevel as nlevel |
749
|
|
|
FROM ".prefix_table("misc")." as m |
750
|
|
|
INNER JOIN ".prefix_table("nested_tree")." as t ON (m.intitule = t.id) |
751
|
|
|
WHERE m.type = %s AND m.intitule = %s", |
752
|
|
|
"complex", |
753
|
|
|
mysqli_escape_string($link, $post_destination) |
754
|
|
|
); |
755
|
|
|
$levelPwComplexity = $data['value']; |
756
|
|
|
$startPathLevel = $data['nlevel']; |
757
|
|
|
} else { |
758
|
|
|
$levelPwComplexity = 50; |
759
|
|
|
$startPathLevel = 0; |
760
|
|
|
} |
761
|
|
|
|
762
|
|
|
//Get all folders from file |
763
|
|
|
fclose($cacheFileF); |
764
|
|
|
$cacheFileF = fopen($cacheFileNameFolder, "r"); |
765
|
|
|
|
766
|
|
|
//Create folders |
767
|
|
|
$i = 1; |
768
|
|
|
$level = 0; |
769
|
|
|
$foldersArray = array(); |
770
|
|
|
$nbFoldersImported = 0; |
771
|
|
|
|
772
|
|
|
fputs($cacheLogFile, date('H:i:s ')."Creating Folders\n"); |
773
|
|
|
$results = "Folders\n\n"; |
774
|
|
|
|
775
|
|
|
while (!feof($cacheFileF)) { |
776
|
|
|
$folder = fgets($cacheFileF, 4096); |
777
|
|
|
if (!empty($folder)) { |
778
|
|
|
$folder = str_replace(array("\r\n", "\n", "\r"), '', $folder); |
779
|
|
|
//get number of levels in path |
780
|
|
|
$path = explode($foldersSeparator, $folder); |
781
|
|
|
$folderLevel = count($path); |
782
|
|
|
|
783
|
|
|
//get folder name |
784
|
|
|
if (strrpos($folder, $foldersSeparator) > 0) { |
785
|
|
|
$fold = substr($folder, strrpos($folder, $foldersSeparator) + strlen($foldersSeparator)); |
786
|
|
|
$parent = implode($foldersSeparator, array_slice($path, 0, -1)); |
787
|
|
|
$parent_id = $foldersArray[$parent]['id']; |
788
|
|
|
} else { |
789
|
|
|
$fold = $folder; |
790
|
|
|
$parent_id = $post_destination; //permits to select the folder destination |
791
|
|
|
} |
792
|
|
|
|
793
|
|
|
$fold = stripslashes($fold); |
794
|
|
|
//create folder - if not exists at the same level |
795
|
|
|
DB::query( |
796
|
|
|
"SELECT * FROM ".prefix_table("nested_tree")." |
797
|
|
|
WHERE nlevel = %i AND title = %s AND parent_id = %i LIMIT 1", |
798
|
|
|
intval($folderLevel + $startPathLevel), |
799
|
|
|
$fold, |
800
|
|
|
$parent_id |
801
|
|
|
); |
802
|
|
|
$results .= str_replace($foldersSeparator, '\\', $folder); |
803
|
|
|
$counter = DB::count(); |
804
|
|
|
if ($counter == 0) { |
805
|
|
|
$results .= " - Inserting\n"; |
806
|
|
|
//do query |
807
|
|
|
DB::insert( |
808
|
|
|
prefix_table("nested_tree"), |
809
|
|
|
array( |
810
|
|
|
'parent_id' => $parent_id, |
811
|
|
|
'title' => stripslashes($fold), |
812
|
|
|
'nlevel' => $folderLevel |
813
|
|
|
) |
814
|
|
|
); |
815
|
|
|
$id = DB::insertId(); |
816
|
|
|
//Add complexity level => level is set to "medium" by default. |
817
|
|
|
DB::insert( |
818
|
|
|
prefix_table("misc"), |
819
|
|
|
array( |
820
|
|
|
'type' => 'complex', |
821
|
|
|
'intitule' => $id, |
822
|
|
|
'valeur' => $levelPwComplexity |
823
|
|
|
) |
824
|
|
|
); |
825
|
|
|
|
826
|
|
|
//For each role to which the user depends on, add the folder just created. |
827
|
|
|
foreach ($_SESSION['arr_roles'] as $role) { |
828
|
|
|
DB::insert( |
829
|
|
|
prefix_table("roles_values"), |
830
|
|
|
array( |
831
|
|
|
'role_id' => $role['id'], |
832
|
|
|
'folder_id' => $id, |
833
|
|
|
'type' => "W" |
834
|
|
|
) |
835
|
|
|
); |
836
|
|
|
} |
837
|
|
|
|
838
|
|
|
//Add this new folder to the list of visible folders for the user. |
839
|
|
|
array_push($_SESSION['groupes_visibles'], $id); |
840
|
|
|
|
841
|
|
|
//increment number of imported folders |
842
|
|
|
$nbFoldersImported++; |
843
|
|
|
} else { |
844
|
|
|
$results .= " - Skipped\n"; |
845
|
|
|
//get folder actual ID |
846
|
|
|
$data = DB::queryFirstRow( |
847
|
|
|
"SELECT id FROM ".prefix_table("nested_tree")." |
848
|
|
|
WHERE nlevel = %i AND title = %s AND parent_id = %i", |
849
|
|
|
intval($folderLevel + $startPathLevel), |
850
|
|
|
$fold, |
851
|
|
|
$parent_id |
852
|
|
|
); |
853
|
|
|
$id = $data['id']; |
854
|
|
|
} |
855
|
|
|
|
856
|
|
|
//store in array |
857
|
|
|
$foldersArray[$folder] = array( |
858
|
|
|
'folder' => $fold, |
859
|
|
|
'nlevel' => $folderLevel, |
860
|
|
|
'id' => $id |
861
|
|
|
); |
862
|
|
|
|
863
|
|
|
$_SESSION['nb_folders']++; |
864
|
|
|
$i++; |
865
|
|
|
} |
866
|
|
|
} |
867
|
|
|
|
868
|
|
|
$results .= "\n\nItems\n\n"; |
869
|
|
|
//if no new folders them inform |
870
|
|
|
if ($nbFoldersImported > 0) { |
871
|
|
|
fputs($cacheLogFile, date('H:i:s ')."Setting User Rights\n"); |
872
|
|
|
//Refresh the rights of actual user |
873
|
|
|
identifyUserRights( |
874
|
|
|
implode(';', $_SESSION['groupes_visibles']).';'.$newId, |
875
|
|
|
$_SESSION['groupes_interdits'], |
876
|
|
|
$_SESSION['is_admin'], |
877
|
|
|
$_SESSION['fonction_id'] |
878
|
|
|
); |
879
|
|
|
|
880
|
|
|
fputs($cacheLogFile, date('H:i:s ')."Rebuilding Tree\n"); |
881
|
|
|
//rebuild full tree |
882
|
|
|
$tree->rebuild(); |
883
|
|
|
} |
884
|
|
|
|
885
|
|
|
fputs($cacheLogFile, date('H:i:s ')."Importing Items\n"); |
886
|
|
|
|
887
|
|
|
// Now import ITEMS |
888
|
|
|
$nbItemsImported = 0; |
889
|
|
|
$count = 0; |
890
|
|
|
|
891
|
|
|
//Get some info about personal folder |
892
|
|
|
if ($post_destination == $_SESSION['user_id']) { |
893
|
|
|
$personalFolder = 1; |
894
|
|
|
} else { |
895
|
|
|
$personalFolder = 0; |
896
|
|
|
} |
897
|
|
|
|
898
|
|
|
//prepare file to be read |
899
|
|
|
fclose($cacheFile); |
900
|
|
|
$cacheFile = fopen($cacheFileName, "r"); |
901
|
|
|
|
902
|
|
|
while (!feof($cacheFile)) { |
903
|
|
|
//prepare an array with item to import |
904
|
|
|
$full_item = fgets($cacheFile, 8192); |
905
|
|
|
$full_item = str_replace(array("\r\n", "\n", "\r"), '', $full_item); |
906
|
|
|
$item = explode($itemsSeparator, $full_item); |
907
|
|
|
|
908
|
|
|
$count++; |
909
|
|
|
if (!($count % 10)) { |
910
|
|
|
fputs($cacheLogFile, date('H:i:s ')." Imported $count items (".number_format(($count / $numItems) * 100, 1).")\n"); |
911
|
|
|
} |
912
|
|
|
|
913
|
|
|
if (!empty($item[KP_TITLE])) { |
914
|
|
|
//$count++; |
915
|
|
|
//check if not exists |
916
|
|
|
$results .= str_replace($foldersSeparator, "\\", $item[KP_PATH]).'\\'.$item[KP_TITLE]; |
917
|
|
|
|
918
|
|
|
$pwd = $item[KP_PASSWORD]; |
919
|
|
|
|
920
|
|
|
//Get folder label |
921
|
|
|
if (count($foldersArray) == 0 || empty($item[KP_PATH])) { |
922
|
|
|
$folderId = $post_destination; |
923
|
|
|
} else { |
924
|
|
|
$folderId = $foldersArray[$item[KP_PATH]]['id']; |
925
|
|
|
} |
926
|
|
|
$data = DB::queryFirstRow( |
927
|
|
|
"SELECT title FROM ".prefix_table("nested_tree")." WHERE id = %i", |
928
|
|
|
intval($folderId) |
929
|
|
|
); |
930
|
|
|
|
931
|
|
|
// escape if folderId is empty |
932
|
|
|
if (!empty($folderId)) { |
933
|
|
|
$results .= " - Inserting\n"; |
934
|
|
|
|
935
|
|
|
// prepare PW |
936
|
|
|
if ($import_perso === true) { |
937
|
|
|
$encrypt = cryption( |
938
|
|
|
$pwd, |
939
|
|
|
$_SESSION['user_settings']['session_psk'], |
940
|
|
|
"encrypt" |
941
|
|
|
); |
942
|
|
|
} else { |
943
|
|
|
$encrypt = cryption( |
944
|
|
|
$pwd, |
945
|
|
|
"", |
946
|
|
|
"encrypt" |
947
|
|
|
); |
948
|
|
|
} |
949
|
|
|
|
950
|
|
|
//ADD item |
951
|
|
|
DB::insert( |
952
|
|
|
prefix_table("items"), |
953
|
|
|
array( |
954
|
|
|
'label' => substr(stripslashes($item[KP_TITLE]), 0, 500), |
955
|
|
|
'description' => stripslashes(str_replace($lineEndSeparator, '<br />', $item[KP_NOTES])), |
956
|
|
|
'pw' => $encrypt['string'], |
957
|
|
|
'pw_iv' => $encrypt['iv'], |
958
|
|
|
'url' => substr(stripslashes($item[KP_URL]), 0, 500), |
959
|
|
|
'id_tree' => $folderId, |
960
|
|
|
'login' => substr(stripslashes($item[KP_USERNAME]), 0, 500), |
961
|
|
|
'anyone_can_modify' => filter_input(INPUT_POST, 'import_kps_anyone_can_modify', FILTER_SANITIZE_STRING) === "true" ? 1 : 0 |
962
|
|
|
) |
963
|
|
|
); |
964
|
|
|
$newId = DB::insertId(); |
965
|
|
|
|
966
|
|
|
//if asked, anyone in role can modify |
967
|
|
|
if (null !== filter_input(INPUT_POST, 'import_kps_anyone_can_modify_in_role', FILTER_SANITIZE_STRING) && filter_input(INPUT_POST, 'import_kps_anyone_can_modify_in_role', FILTER_SANITIZE_STRING) === "true") { |
968
|
|
|
foreach ($_SESSION['arr_roles'] as $role) { |
969
|
|
|
DB::insert( |
970
|
|
|
prefix_table("restriction_to_roles"), |
971
|
|
|
array( |
972
|
|
|
'role_id' => $role['id'], |
973
|
|
|
'item_id' => $newId |
974
|
|
|
) |
975
|
|
|
); |
976
|
|
|
} |
977
|
|
|
} |
978
|
|
|
|
979
|
|
|
//Add log |
980
|
|
|
DB::insert( |
981
|
|
|
prefix_table("log_items"), |
982
|
|
|
array( |
983
|
|
|
'id_item' => $newId, |
984
|
|
|
'date' => time(), |
985
|
|
|
'id_user' => $_SESSION['user_id'], |
986
|
|
|
'action' => 'at_creation', |
987
|
|
|
'raison' => 'at_import' |
988
|
|
|
) |
989
|
|
|
); |
990
|
|
|
|
991
|
|
|
//Add entry to cache table |
992
|
|
|
DB::insert( |
993
|
|
|
prefix_table("cache"), |
994
|
|
|
array( |
995
|
|
|
'id' => $newId, |
996
|
|
|
'label' => substr(stripslashes($item[KP_TITLE]), 0, 500), |
997
|
|
|
'description' => stripslashes(str_replace($lineEndSeparator, '<br />', $item[KP_NOTES])), |
998
|
|
|
'url' => substr(stripslashes($item[KP_URL]), 0, 500), |
999
|
|
|
'tags' => "", |
1000
|
|
|
'id_tree' => $folderId, |
1001
|
|
|
'perso' => $personalFolder == 0 ? 0 : 1, |
1002
|
|
|
'login' => substr(stripslashes($item[KP_USERNAME]), 0, 500), |
1003
|
|
|
'restricted_to' => "0", |
1004
|
|
|
'folder' => $data['title'], |
1005
|
|
|
'author' => $_SESSION['user_id'], |
1006
|
|
|
'renewal_period' => "0", |
1007
|
|
|
'timestamp' => time() |
1008
|
|
|
) |
1009
|
|
|
); |
1010
|
|
|
|
1011
|
|
|
//increment number of imported items |
1012
|
|
|
$nbItemsImported++; |
1013
|
|
|
} else { |
1014
|
|
|
$results .= " - ".$item[KP_TITLE]." was not imported\n"; |
1015
|
|
|
} |
1016
|
|
|
fputs($cacheLogFile, date('H:i:s ')." ".$results."\n"); |
1017
|
|
|
} |
1018
|
|
|
} |
1019
|
|
|
|
1020
|
|
|
//SHow finished |
1021
|
|
|
$text .= "Folders imported: $nbFoldersImported<br />"; |
1022
|
|
|
$text .= "Items imported: $nbItemsImported<br />"; |
1023
|
|
|
$text .= '</div><br /><br /><b>'.$LANG['import_kp_finished'].'</b>'; |
1024
|
|
|
$text .= '<a href=\''.$SETTINGS['url_to_files_folder'].'/'.$logFileName.'\' target=\'_blank\'>'.$LANG['pdf_download'].'</a>'; |
1025
|
|
|
|
1026
|
|
|
fputs($cacheLogFile, date('H:i:s ')."Import finished\n"); |
1027
|
|
|
fputs($cacheLogFile, date('H:i:s ')."Statistics\n"); |
1028
|
|
|
fputs($cacheLogFile, date('H:i:s ')."Folders imported: $nbFoldersImported\n"); |
1029
|
|
|
fputs($cacheLogFile, date('H:i:s ')."Items imported: $nbItemsImported\n\n".$results); |
1030
|
|
|
|
1031
|
|
|
//Delete cache file |
1032
|
|
|
fclose($cacheFileF); |
1033
|
|
|
fclose($cacheFile); |
1034
|
|
|
fclose($cacheLogFile); |
1035
|
|
|
unlink($cacheFileName); |
1036
|
|
|
unlink($cacheFileNameFolder); |
1037
|
|
|
unlink($SETTINGS['path_to_files_folder']."/".$file); |
1038
|
|
|
|
1039
|
|
|
//Display all messages to user |
1040
|
|
|
echo '[{"error":"" , "message":"'.str_replace('"', ""e;", strip_tags($text, '<br /><a><div><b><br>')).'"}]'; |
1041
|
|
|
} else { |
1042
|
|
|
echo '[{"error":"yes" , "message":"Error - No item found!"}]'; |
1043
|
|
|
} |
1044
|
|
|
break; |
1045
|
|
|
} |
1046
|
|
|
|
1047
|
|
|
spl_autoload_register(function ($class) { |
1048
|
|
|
$prefix = 'League\\Csv\\'; |
1049
|
|
|
$base_dir = __DIR__.'/src/'; |
1050
|
|
|
$len = strlen($prefix); |
1051
|
|
|
if (strncmp($prefix, $class, $len) !== 0) { |
1052
|
|
|
// no, move to the next registered autoloader |
1053
|
|
|
return; |
1054
|
|
|
} |
1055
|
|
|
$relative_class = substr($class, $len); |
1056
|
|
|
$file = $base_dir.str_replace('\\', '/', $relative_class).'.php'; |
1057
|
|
|
if (file_exists($file)) { |
1058
|
|
|
require $file; |
1059
|
|
|
} |
1060
|
|
|
}); |
1061
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.