Completed
Push — development ( 813154...a4b5b1 )
by Nils
07:28
created

api/functions.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 *
4
 * @file          (api)functions.php
5
 * @author        Nils Laumaillé
6
 * @version       2.0
7
 * @copyright     (c) 2009-2017 Nils Laumaillé
8
 * @licensing     GNU AFFERO GPL 3.0
9
 * @link          http://www.teampass.net
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 */
15
16
$api_version = "2.0";
17
$_SESSION['CPM'] = 1;
18
require_once "../includes/config/include.php";
19
require_once "../sources/main.functions.php";
20
21
function get_ip() {
22
    if (function_exists('apache_request_headers')) {
23
        $headers = apache_request_headers();
24
    } else {
25
        $headers = $_SERVER;
26
    }
27
    if (array_key_exists('X-Forwarded-For', $headers) && filter_var($headers['X-Forwarded-For'], FILTER_VALIDATE_IP)) {
28
        $the_ip = $headers['X-Forwarded-For'];
29
    } elseif (array_key_exists('HTTP_X_FORWARDED_FOR', $headers) && filter_var($headers['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP)) {
30
        $the_ip = $headers['HTTP_X_FORWARDED_FOR'];
31
    } else {
32
        $the_ip = filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP);
33
    }
34
    return $the_ip;
35
}
36
37
38
function teampass_api_enabled() {
39
    teampass_connect();
40
    $response = DB::queryFirstRow(
41
        "SELECT `valeur` FROM ".prefix_table("misc")." WHERE type = %s AND intitule = %s",
42
        "admin",
43
        "api"
44
    );
45
    return $response['valeur'];
46
}
47
48
function teampass_whitelist() {
49
    teampass_connect();
50
    $apiip_pool = teampass_get_ips();
51
    if (count($apiip_pool) > 0 && array_search(get_ip(), $apiip_pool) === false) {
52
        rest_error('IPWHITELIST');
53
    }
54
}
55
56
function teampass_connect()
57
{
58
    global $server, $user, $pass, $database, $link, $port, $encoding;
59
    require_once("../includes/config/settings.php");
60
    require_once('../includes/libraries/Database/Meekrodb/db.class.php');
61
    DB::$host = $server;
62
    DB::$user = $user;
63
    DB::$password = $pass;
64
    DB::$dbName = $database;
65
    DB::$port = $port;
66
    DB::$encoding = $encoding;
67
    DB::$error_handler = 'db_error_handler';
68
    $link = mysqli_connect($server, $user, $pass, $database, $port);
69
    $link->set_charset($encoding);
70
}
71
72
function teampass_get_ips() {
73
    global $server, $user, $pass, $database, $link;
74
    $array_of_results = array();
75
    teampass_connect();
76
    $response = DB::query("select value from ".prefix_table("api")." WHERE type = %s", "ip");
77
    foreach ($response as $data)
78
    {
79
        array_push($array_of_results, $data['value']);
80
    }
81
82
    return $array_of_results;
83
}
84
85
function teampass_get_keys() {
86
    global $server, $user, $pass, $database, $link;
87
    teampass_connect();
88
    $response = DB::queryOneColumn("value", "select * from ".prefix_table("api")." WHERE type = %s", "key");
89
90
    return $response;
91
}
92
93
function rest_head() {
94
    header('HTTP/1.1 402 Payment Required');
95
}
96
97
function addToCacheTable($id)
98
{
99
    global $server, $user, $pass, $database, $link;
100
    teampass_connect();
101
    // get data
102
    $data = DB::queryfirstrow(
103
        "SELECT i.label AS label, i.description AS description, i.id_tree AS id_tree, i.perso AS perso, i.restricted_to AS restricted_to, i.login AS login, i.id AS id
104
        FROM ".prefix_table("items")." AS i
105
        AND ".prefix_table("log_items")." AS l ON (l.id_item = i.id)
106
        WHERE i.id = %i
107
        AND l.action = %s",
108
        intval($id),
109
        at_creation
110
    );
111
112
    // Get all TAGS
113
    $tags = "";
114
    $data_tags = DB::query("SELECT tag FROM ".prefix_table("tags")." WHERE item_id=%i", $id);
115
    foreach ($data_tags as $itemTag) {
116
        if (!empty($itemTag['tag'])) {
117
            $tags .= $itemTag['tag']." ";
118
        }
119
    }
120
121
    // finaly update
122
    DB::insert(
123
        prefix_table("cache"),
124
        array(
125
            "id" => $data['id'],
126
            "label" => $data['label'],
127
            "description" => $data['description'],
128
            "tags" => $tags,
129
            "id_tree" => $data['id_tree'],
130
            "perso" => $data['perso'],
131
            "restricted_to" => $data['restricted_to'],
132
            "login" => $data['login'],
133
            "folder" => "",
134
            //"restricted_to" => "0",
135
            "author" => API_USER_ID,
136
            "renewal_period" => 0,
137
            "timestamp" => time(),
138
            "url" => 0
139
        )
140
    );
141
}
142
143
144
/**
145
 * @param string $setting
146
 */
147
function getSettingValue($setting) {
148
149
    // get default language
150
    $set = DB::queryFirstRow(
151
        "SELECT `valeur` FROM ".prefix_table("misc")." WHERE type = %s AND intitule = %s",
152
        "admin",
153
        $setting
154
    );
155
156
    return $set['valeur'];
157
}
158
159
function rest_delete() {
160 View Code Duplication
    if (!@count($GLOBALS['request']) == 0) {
161
        $request_uri = $GLOBALS['_SERVER']['REQUEST_URI'];
162
        preg_match('/\/api(\/index.php|)\/(.*)\?apikey=(.*)/', $request_uri, $matches);
163
        if (count($matches) == 0) {
164
            rest_error('REQUEST_SENT_NOT_UNDERSTANDABLE');
165
        }
166
        $GLOBALS['request'] = explode('/', $matches[2]);
167
    }
168
    if (apikey_checker($GLOBALS['apikey'])) {
169
        global $server, $user, $pass, $database, $pre, $link;
170
        include "../sources/main.functions.php";
171
        teampass_connect();
172
        $category_query = "";
173
174
        if ($GLOBALS['request'][0] == "write") {
175
            if ($GLOBALS['request'][1] == "category") {
176
                $array_category = explode(';', $GLOBALS['request'][2]);
177
178
                foreach ($array_category as $category) {
179
                    if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $category, $result)) {
180
                        rest_error('CATEGORY_MALFORMED');
181
                    }
182
                }
183
184 View Code Duplication
                if (count($array_category) > 1 && count($array_category) < 5) {
185
                    for ($i = count($array_category); $i > 0; $i--) {
186
                        $slot = $i - 1;
187
                        if (!$slot) {
188
                            $category_query .= "select id from ".prefix_table("nested_tree")." where title LIKE '".$array_category[$slot]."' AND parent_id = 0";
189
                        } else {
190
                            $category_query .= "select id from ".prefix_table("nested_tree")." where title LIKE '".$array_category[$slot]."' AND parent_id = (";
191
                        }
192
                    }
193
                    for ($i = 1; $i < count($array_category); $i++) { $category_query .= ")"; }
194
                } elseif (count($array_category) == 1) {
195
                    $category_query = "select id from ".prefix_table("nested_tree")." where title LIKE '".$array_category[0]."' AND parent_id = 0";
196
                } else {
197
                    rest_error('NO_CATEGORY');
198
                }
199
200
                // Delete items which in category
201
                $response = DB::delete(prefix_table("items"), "id_tree = (".$category_query.")");
202
                // Delete sub-categories which in category
203
                $response = DB::delete(prefix_table("nested_tree"), "parent_id = (".$category_query.")");
204
                // Delete category
205
                $response = DB::delete(prefix_table("nested_tree"), "id = (".$category_query.")");
206
207
                $json['type'] = 'category';
208
                $json['category'] = $GLOBALS['request'][2];
209
                if ($response) {
210
                    $json['status'] = 'OK';
211
                } else {
212
                    $json['status'] = 'KO';
213
                }
214
215
            } elseif ($GLOBALS['request'][1] == "item") {
216
                $array_category = explode(';', $GLOBALS['request'][2]);
217
                $item = $GLOBALS['request'][3];
218
219
                foreach ($array_category as $category) {
220
                    if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $category, $result)) {
221
                        rest_error('CATEGORY_MALFORMED');
222
                    }
223
                }
224
225 View Code Duplication
                if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $item, $result)) {
226
                    rest_error('ITEM_MALFORMED');
227
                } elseif (empty($item) || count($array_category) == 0) {
228
                    rest_error('MALFORMED');
229
                }
230
231 View Code Duplication
                if (count($array_category) > 1 && count($array_category) < 5) {
232
                    for ($i = count($array_category); $i > 0; $i--) {
233
                        $slot = $i - 1;
234
                        if (!$slot) {
235
                            $category_query .= "select id from ".prefix_table("nested_tree")." where title LIKE '".$array_category[$slot]."' AND parent_id = 0";
236
                        } else {
237
                            $category_query .= "select id from ".prefix_table("nested_tree")." where title LIKE '".$array_category[$slot]."' AND parent_id = (";
238
                        }
239
                    }
240
                    for ($i = 1; $i < count($array_category); $i++) { $category_query .= ")"; }
241
                } elseif (count($array_category) == 1) {
242
                    $category_query = "select id from ".prefix_table("nested_tree")." where title LIKE '".$array_category[0]."' AND parent_id = 0";
243
                } else {
244
                    rest_error('NO_CATEGORY');
245
                }
246
247
                // Delete item
248
                $response = DB::delete(prefix_table("items"), "id_tree = (".$category_query.") and label LIKE '".$item."'");
249
                $json['type'] = 'item';
250
                $json['item'] = $item;
251
                $json['category'] = $GLOBALS['request'][2];
252
                if ($response) {
253
                    $json['status'] = 'OK';
254
                } else {
255
                    $json['status'] = 'KO';
256
                }
257
            }
258
259
            if ($json) {
260
                echo json_encode($json);
261
            } else {
262
                rest_error('EMPTY');
263
            }
264
        } else {
265
            rest_error('METHOD');
266
        }
267
    }
268
}
269
270
function rest_get() {
271
    global $api_version;
272
273 View Code Duplication
    if (!@count($GLOBALS['request']) == 0) {
274
        $request_uri = $GLOBALS['_SERVER']['REQUEST_URI'];
275
        preg_match('/\/api(\/index.php|)\/(.*)\?apikey=(.*)/', $request_uri, $matches);
276
        if (count($matches) == 0) {
277
            rest_error('REQUEST_SENT_NOT_UNDERSTANDABLE');
278
        }
279
        $GLOBALS['request'] = explode('/', $matches[2]);
280
    }
281
282
    if (apikey_checker($GLOBALS['apikey'])) {
283
        global $server, $user, $pass, $database, $pre, $link;
284
        teampass_connect();
285
        $category_query = "";
286
287
        // define the API user through the LABEL of apikey
288
        $api_info = DB::queryFirstRow(
289
            "SELECT label
290
            FROM ".prefix_table("api")."
291
            WHERE value = %s",
292
            $GLOBALS['apikey']
293
        );
294
295
        if ($GLOBALS['request'][0] == "read") {
296
            if ($GLOBALS['request'][1] == "folder") {
297
                /*
298
                * READ FOLDERS
299
                */
300
301
                // load library
302
                require_once '../sources/SplClassLoader.php';
303
                //Load Tree
304
                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
305
                $tree->register();
306
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
307
308
                // get ids
309
                if (strpos($GLOBALS['request'][2], ";") > 0) {
310
                    $condition = "id_tree IN %ls";
311
                    $condition_value = explode(';', $GLOBALS['request'][2]);
312
                } else {
313
                    $condition = "id_tree = %s";
314
                    $condition_value = $GLOBALS['request'][2];
315
                }
316
317
                // get items in this folder
318
                $response = DB::query(
319
                    "SELECT id, label, login, pw, pw_iv, url, id_tree, description, email
320
                    FROM ".prefix_table("items")."
321
                    WHERE inactif='0' AND ".$condition, $condition_value
322
                );
323
                $x = 0;
324 View Code Duplication
                foreach ($response as $data)
325
                {
326
                    // build the path to the Item
327
                    $path = "";
328
                    $arbo = $tree->getPath($data['id_tree'], true);
329
                    foreach ($arbo as $elem) {
330
                        if (empty($path)) {
331
                            $path = stripslashes($elem->title);
332
                        } else {
333
                            $path .= " > ".stripslashes($elem->title);
334
                        }
335
                    }
336
337
                    // prepare output
338
                    $json[$x]['id'] = $data['id'];
339
                    $json[$x]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
340
                    $json[$x]['description'] = mb_convert_encoding($data['description'], mb_detect_encoding($data['description']), 'UTF-8');
341
                    $json[$x]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
342
                    $json[$x]['email'] = mb_convert_encoding($data['email'], mb_detect_encoding($data['email']), 'UTF-8');
343
                    $json[$x]['url'] = mb_convert_encoding($data['url'], mb_detect_encoding($data['url']), 'UTF-8');
344
                    $crypt_pw = cryption(
345
                        $data['pw'],
346
                        "",
347
                        "decrypt"
348
                    );
349
                    $json[$x]['pw'] = $crypt_pw['string'];
350
                    $json[$x]['folder_id'] = $data['id_tree'];
351
                    $json[$x]['path'] = $path;
352
353
                    $x++;
354
                }
355
            } else if ($GLOBALS['request'][1] == "userpw") {
356
                /*
357
                * READ USER ITEMS
358
                */
359
360
                // load library
361
                require_once '../sources/SplClassLoader.php';
362
                //Load Tree
363
                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
364
                $tree->register();
365
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
366
367
                // about the user
368
                $username = $GLOBALS['request'][2];
369
                if (strcmp($username, "admin") == 0) {
370
                    // forbid admin access
371
                }
372
                $response = DB::query("SELECT fonction_id FROM ".prefix_table("users")." WHERE login='".$username."'");
373
                if (count($response) === 0) {
374
                    rest_error('USER_NOT_EXISTS');
375
                }
376
                foreach ($response as $data)
377
                {
378
                    $role_str = $data['fonction_id'];
379
                }
380
                $folder_arr = array();
381
                $roles = explode(";", $role_str);
382
                foreach ($roles as $role)
383
                {
384
                    $response = DB::query("SELECT folder_id FROM ".prefix_table("roles_values")." WHERE role_id='".$role."'");
385
                    foreach ($response as $data)
386
                    {
387
                        $folder_id = $data['folder_id'];
388
                        if (!array_key_exists($folder_id, $folder_arr)) {
389
                            array_push($folder_arr, $folder_id);
390
                        }
391
                    }
392
                }
393
                $folder_str = array_filter($folder_arr);
394
395
                // get ids
396
                if (is_array($folder_str)) {
397
                    $condition = "id_tree IN %ls";
398
                    $condition_value = $folder_str;
399
                } else {
400
                    $condition = "id_tree = %s";
401
                    $condition_value = $folder_str;
402
                }
403
404
                $data = "";
405
                // get items in this module
406
                $response = DB::query(
407
                    "SELECT id,label,url,login,pw, pw_iv, url, id_tree, description, email
408
                    FROM ".prefix_table("items")."
409
                    WHERE inactif='0' AND ".$condition, $condition_value
410
                );
411
                $x = 0;
412
                foreach ($response as $data)
413
                {
414
                    // build the path to the Item
415
                    $path = "";
416
                    $arbo = $tree->getPath($data['id_tree'], true);
417
                    foreach ($arbo as $elem) {
418
                        if (empty($path)) {
419
                            $path = stripslashes($elem->title);
420
                        } else {
421
                            $path .= " > ".stripslashes($elem->title);
422
                        }
423
                    }
424
425
                    // prepare output
426
                    $json[$data['id']]['id'] = $data['id'];
427
                    $json[$data['id']]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
428
                    $json[$data['id']]['description'] = mb_convert_encoding($data['description'], mb_detect_encoding($data['description']), 'UTF-8');
429
                    $json[$data['id']]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
430
                    $json[$data['id']]['email'] = mb_convert_encoding($data['email'], mb_detect_encoding($data['email']), 'UTF-8');
431
                    $json[$data['id']]['url'] = mb_convert_encoding($data['url'], mb_detect_encoding($data['url']), 'UTF-8');
432
                    $crypt_pw = cryption($data['pw'], "", "decrypt");
433
                    $json[$data['id']]['pw'] = $crypt_pw['string'];
434
                    $json[$data['id']]['folder_id'] = $data['id_tree'];
435
                    $json[$data['id']]['path'] = $path;
436
437
                    $x++;
438
                }
439
            } else if ($GLOBALS['request'][1] == "userfolders") {
440
                /*
441
                * READ USER FOLDERS
442
                * Sends back a list of folders
443
                */
444
                $json = "";
445
                $username = $GLOBALS['request'][2];
446
                if (strcmp($username, "admin") == 0) {
447
                    // forbid admin access
448
                }
449
                $response = DB::query("SELECT fonction_id FROM ".prefix_table("users")." WHERE login='".$username."'");
450
                if (count($response) === 0) {
451
                    rest_error('USER_NOT_EXISTS');
452
                }
453
                foreach ($response as $data)
454
                {
455
                    $role_str = $data['fonction_id'];
456
                }
457
458
                $folder_arr = array();
459
                $roles = explode(";", $role_str);
460
                $x = 0;
461
                foreach ($roles as $role)
462
                {
463
                    $response = DB::query("SELECT folder_id, type FROM ".prefix_table("roles_values")." WHERE role_id='".$role."'");
464
                    foreach ($response as $data)
465
                    {
466
                        $folder_id = $data['folder_id'];
467
                        if (!array_key_exists($folder_id, $folder_arr)) {
468
                            array_push($folder_arr, $folder_id);
469
470
                            $response2 = DB::queryFirstRow("SELECT title, nlevel FROM ".prefix_table("nested_tree")." WHERE id='".$folder_id."'");
471
472
                            if (!empty($response2['title'])) {
473
                                $json[$folder_id]['id'] = $folder_id;
474
                                $json[$folder_id]['title'] = $response2['title'];
475
                                $json[$folder_id]['level'] = $response2['nlevel'];
476
                                $json[$folder_id]['access_type'] = $data['type'];
477
                                $x++;
478
                            }
479
                        }
480
                    }
481
                }
482
            } elseif ($GLOBALS['request'][1] == "items") {
483
                /*
484
                * READ ITEMS asked
485
                */
486
487
                // load library
488
                require_once '../sources/SplClassLoader.php';
489
                //Load Tree
490
                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
491
                $tree->register();
492
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
493
494
                // get parameters
495
                $array_items = explode(';', $GLOBALS['request'][2]);
496
497
                // check if not empty
498
                if (count($array_items) == 0) {
499
                    rest_error('NO_ITEM');
500
                }
501
502
                // only accepts numeric
503
                foreach ($array_items as $item) {
504
                    if (!is_numeric($item)) {
505
                        rest_error('ITEM_MALFORMED');
506
                    }
507
                }
508
509
                $response = DB::query(
510
                    "SELECT id,label,login,pw, pw_iv, url, id_tree, description, email
511
                    FROM ".prefix_table("items")."
512
                    WHERE inactif = %i AND id IN %ls", "0", $array_items
513
                );
514
                $x = 0;
515 View Code Duplication
                foreach ($response as $data)
516
                {
517
                    // build the path to the Item
518
                    $path = "";
519
                    $arbo = $tree->getPath($data['id_tree'], true);
520
                    foreach ($arbo as $elem) {
521
                        if (empty($path)) {
522
                            $path = stripslashes($elem->title);
523
                        } else {
524
                            $path .= " > ".stripslashes($elem->title);
525
                        }
526
                    }
527
528
                    // prepare output
529
                    $json[$x]['id'] = $data['id'];
530
                    $json[$x]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
531
                    $json[$x]['description'] = mb_convert_encoding($data['description'], mb_detect_encoding($data['description']), 'UTF-8');
532
                    $json[$x]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
533
                    $json[$x]['email'] = mb_convert_encoding($data['email'], mb_detect_encoding($data['email']), 'UTF-8');
534
                    $json[$x]['url'] = mb_convert_encoding($data['url'], mb_detect_encoding($data['url']), 'UTF-8');
535
                    $crypt_pw = cryption($data['pw'], "", "decrypt");
536
                    $json[$x]['pw'] = $crypt_pw['string'];
537
                    $json[$x]['folder_id'] = $data['id_tree'];
538
                    $json[$x]['path'] = $path;
539
540
                    $x++;
541
                }
542
            }
543
544
            if (isset($json) && $json) {
545
                echo json_encode($json);
546
            } else {
547
                rest_error('EMPTY');
548
            }
549
        } elseif ($GLOBALS['request'][0] == "find") {
550
            if ($GLOBALS['request'][1] == "item") {
551
                /*
552
                * FIND ITEMS in FOLDERS
553
                */
554
555
                // load library
556
                require_once '../sources/SplClassLoader.php';
557
                //Load Tree
558
                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
559
                $tree->register();
560
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
561
562
                // get parameters
563
                $array_category = explode(';', $GLOBALS['request'][2]);
564
                $item = $GLOBALS['request'][3];
565
                foreach ($array_category as $category) {
566
                    if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $category, $result)) {
567
                        rest_error('CATEGORY_MALFORMED');
568
                    }
569
                }
570
571 View Code Duplication
                if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $item, $result)) {
572
                    rest_error('ITEM_MALFORMED');
573
                } elseif (empty($item) || count($array_category) == 0) {
574
                    rest_error('MALFORMED');
575
                }
576
577
                if (count($array_category) === 0) {
578
                    rest_error('NO_CATEGORY');
579
                }
580
581
                DB::debugMode(false);
582
                $response = DB::query(
583
                    "SELECT id, label, login, pw, pw_iv, url, id_tree, description, email
584
                    FROM ".prefix_table("items")."
585
                    WHERE
586
                    inactif = %i
587
                    AND id_tree IN %ls
588
                    AND label LIKE %ss",
589
                    "0",
590
                    $array_category,
591
                    $item
592
                );
593
                $x = 0;
594
                foreach ($response as $data) {
595
                    // build the path to the Item
596
                    $path = "";
597
                    $arbo = $tree->getPath($data['id_tree'], true);
598
                    foreach ($arbo as $elem) {
599
                        if (empty($path)) {
600
                            $path = stripslashes($elem->title);
601
                        } else {
602
                            $path .= " > ".stripslashes($elem->title);
603
                        }
604
                    }
605
606
                    // prepare output
607
                    $json[$x]['id'] = mb_convert_encoding($data['id'], mb_detect_encoding($data['id']), 'UTF-8');
608
                    $json[$x]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
609
                    $json[$x]['description'] = mb_convert_encoding($data['description'], mb_detect_encoding($data['description']), 'UTF-8');
610
                    $json[$x]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
611
                    $json[$x]['email'] = mb_convert_encoding($data['email'], mb_detect_encoding($data['email']), 'UTF-8');
612
                    $json[$x]['url'] = mb_convert_encoding($data['url'], mb_detect_encoding($data['url']), 'UTF-8');
613
                    $crypt_pw = cryption($data['pw'], "", "decrypt");
614
                    $json[$x]['pw'] = $crypt_pw['string'];
615
                    $json[$x]['folder_id'] = $data['id_tree'];
616
                    $json[$x]['path'] = $path;
617
                    $json[$x]['status'] = utf8_encode("OK");
618
619
                    $x++;
620
                }
621
                if (isset($json) && $json) {
622
                    echo json_encode($json);
623
                } else {
624
                    rest_error('EMPTY');
625
                }
626
            }
627
        } elseif ($GLOBALS['request'][0] == "add") {
628
            if ($GLOBALS['request'][1] == "item") {
629
                // get sent parameters
630
                $params = explode(';', base64_decode($GLOBALS['request'][2]));
631
                if (count($params) != 9) {
632
                    rest_error('ITEMBADDEFINITION');
633
                }
634
635
                $item_label = $params[0];
636
                $item_pwd = $params[1];
637
                $item_desc = $params[2];
638
                $item_folder_id = $params[3];
639
                $item_login = $params[4];
640
                $item_email = $params[5];
641
                $item_url = $params[6];
642
                $item_tags = $params[7];
643
                $item_anyonecanmodify = $params[8];
644
645
                // do some checks
646
                if (!empty($item_label) && !empty($item_pwd) && !empty($item_folder_id)) {
647
                    // Check length
648
                    if (strlen($item_pwd) > 50) {
649
                        rest_error('PASSWORDTOOLONG');
650
                    }
651
652
                    // Check Folder ID
653
                    DB::query("SELECT * FROM ".prefix_table("nested_tree")." WHERE id = %i", $item_folder_id);
654
                    $counter = DB::count();
655
                    if ($counter == 0) {
656
                        rest_error('NOSUCHFOLDER');
657
                    }
658
659
                    // check if element doesn't already exist
660
                    $item_duplicate_allowed = getSettingValue("duplicate_item");
661
                    if ($item_duplicate_allowed !== "1") {
662
                        DB::query("SELECT * FROM ".prefix_table("items")." WHERE label = %s AND inactif = %i", addslashes($item_label), "0");
663
                        $counter = DB::count();
664
                        if ($counter != 0) {
665
                            $itemExists = 1;
666
                            // prevent the error if the label already exists
667
                            // so lets just add the time() as a random factor
668
                            $item_label .= " (".time().")";
669
                        } else {
670
                            $itemExists = 0;
671
                        }
672
                    } else {
673
                        $itemExists = 0;
674
                    }
675
                    if ($itemExists === 0) {
676
                        $encrypt = cryption(
677
                            $item_pwd,
678
                            "",
679
                            "encrypt"
680
                        );
681
                        if (empty($encrypt['string'])) {
682
                            rest_error('PASSWORDEMPTY');
683
                        }
684
685
                        // ADD item
686
                        try {
687
                            DB::insert(
688
                                prefix_table("items"),
689
                                array(
690
                                    "label" => $item_label,
691
                                    "description" => $item_desc,
692
                                    'pw' => $encrypt['string'],
693
                                    'pw_iv' => '',
694
                                    "email" => $item_email,
695
                                    "url" => $item_url,
696
                                    "id_tree" => intval($item_folder_id),
697
                                    "login" => $item_login,
698
                                    "inactif" => 0,
699
                                    "restricted_to" => "",
700
                                    "perso" => 0,
701
                                    "anyone_can_modify" => intval($item_anyonecanmodify)
702
                                )
703
                            );
704
                            $newID = DB::InsertId();
705
706
                            // log
707
                            DB::insert(
708
                                prefix_table("log_items"),
709
                                array(
710
                                    "id_item" => $newID,
711
                                    "date" => time(),
712
                                    "id_user" => API_USER_ID,
713
                                    "action" => "at_creation",
714
                                    "raison" => $api_info['label']
715
                                )
716
                            );
717
718
                            // Add tags
719
                            $tags = explode(' ', $item_tags);
720 View Code Duplication
                            foreach ((array) $tags as $tag) {
721
                                if (!empty($tag)) {
722
                                    DB::insert(
723
                                        prefix_table("tags"),
724
                                        array(
725
                                            "item_id" => $newID,
726
                                            "tag" => strtolower($tag)
727
                                        )
728
                                    );
729
                                }
730
                            }
731
732
                            // Update CACHE table
733
                            DB::insert(
734
                                prefix_table("cache"),
735
                                array(
736
                                    "id" => $newID,
737
                                    "label" => $item_label,
738
                                    "description" => $item_desc,
739
                                    "tags" => $item_tags,
740
                                    "id_tree" => $item_folder_id,
741
                                    "perso" => "0",
742
                                    "restricted_to" => "",
743
                                    "login" => $item_login,
744
                                    "folder" => "",
745
                                    "author" => API_USER_ID,
746
                                    "renewal_period" => "0",
747
                                    "timestamp" => time(),
748
                                    "url" => "0"
749
                                )
750
                            );
751
752
                            echo '{"status":"item added" , "new_item_id" : "'.$newID.'"}';
753
                        } catch (PDOException $ex) {
754
                            echo '<br />'.$ex->getMessage();
755
                        }
756
                    } else {
757
                        rest_error('ITEMEXISTS');
758
                    }
759
                } else {
760
                    rest_error('ITEMMISSINGDATA');
761
                }
762
            }
763
            /*
764
             * Case where a new user has to be added
765
             *
766
             * Expected call format: .../api/index.php/add/user/<LOGIN>;<NAME>;<LASTNAME>;<PASSWORD>;<EMAIL>;<ADMINISTRATEDBY>;<READ_ONLY>;<ROLE1,ROLE2,...>;<IS_ADMIN>;<ISMANAGER>;<PERSONAL_FOLDER>?apikey=<VALID API KEY>
767
             * with:
768
             * for READ_ONLY, IS_ADMIN, IS_MANAGER, PERSONAL_FOLDER, accepted value is 1 for TRUE and 0 for FALSE
769
             * for ADMINISTRATEDBY and ROLE1, accepted value is the real label (not the IDs)
770
             *
771
             * Example: /api/index.php/add/user/U4;Nils;Laumaille;test;[email protected];Users;0;Managers,Users;0;1;1?apikey=sae6iekahxiseL3viShoo0chahc1ievei8aequi
772
             *
773
             */
774
            elseif ($GLOBALS['request'][1] == "user") {
775
776
                // get user definition
777
                $array_user = explode(';', base64_decode($GLOBALS['request'][2]));
778
                if (count($array_user) != 11) {
779
                    rest_error('USERBADDEFINITION');
780
                }
781
782
                $login = $array_user[0];
783
                $name = $array_user[1];
784
                $lastname = $array_user[2];
785
                $password = $array_user[3];
786
                $email = $array_user[4];
787
                $adminby = urldecode($array_user[5]);
788
                $isreadonly = urldecode($array_user[6]);
789
                $roles = urldecode($array_user[7]);
790
                $isadmin = $array_user[8];
791
                $ismanager = $array_user[9];
792
                $haspf = $array_user[10];
793
794
                // Empty user
795
                if (mysqli_escape_string($link, htmlspecialchars_decode($login)) == "") {
796
                    rest_error('USERLOGINEMPTY');
797
                }
798
                // Check if user already exists
799
                $data = DB::query(
800
                    "SELECT id, fonction_id, groupes_interdits, groupes_visibles FROM ".prefix_table("users")."
801
            WHERE login LIKE %ss",
802
                    mysqli_escape_string($link, stripslashes($login))
803
                );
804
805
                if (DB::count() == 0) {
806
                    try {
807
                        // find AdminRole code in DB
808
                        $resRole = DB::queryFirstRow(
809
                            "SELECT id
810
                            FROM ".prefix_table("roles_title")."
811
                            WHERE title LIKE %ss",
812
                            mysqli_escape_string($link, stripslashes($adminby))
813
                        );
814
815
                        // get default language
816
                        $lang = DB::queryFirstRow(
817
                            "SELECT `valeur` FROM ".prefix_table("misc")." WHERE type = %s AND intitule = %s",
818
                            "admin",
819
                            "default_language"
820
                        );
821
822
                        // prepare roles list
823
                        $rolesList = "";
824
                        foreach (explode(',', $roles) as $role) {//echo $role."-";
825
                            $tmp = DB::queryFirstRow(
826
                                "SELECT `id` FROM ".prefix_table("roles_title")." WHERE title = %s",
827
                                $role
828
                            );
829
                            if (empty($rolesList)) {
830
                                $rolesList = $tmp['id'];
831
                            } else {
832
                                $rolesList .= ";".$tmp['id'];
833
                            }
834
                        }
835
836
                        // Add user in DB
837
                        DB::insert(
838
                            prefix_table("users"),
839
                            array(
840
                                'login' => $login,
841
                                'name' => $name,
842
                                'lastname' => $lastname,
843
                                'pw' => bCrypt(stringUtf8Decode($password), COST),
844
                                'email' => $email,
845
                                'admin' => intval($isadmin),
846
                                'gestionnaire' => intval($ismanager),
847
                                'read_only' => intval($isreadonly),
848
                                'personal_folder' => intval($haspf),
849
                                'user_language' => $lang['valeur'],
850
                                'fonction_id' => $rolesList,
851
                                'groupes_interdits' => '0',
852
                                'groupes_visibles' => '0',
853
                                'isAdministratedByRole' => empty($resRole) ? '0' : $resRole['id']
854
                            )
855
                        );
856
                        $new_user_id = DB::insertId();
857
                        // Create personnal folder
858
                        if (intval($haspf) == 1) {
859
                            DB::insert(
860
                                prefix_table("nested_tree"),
861
                                array(
862
                                    'parent_id' => '0',
863
                                    'title' => $new_user_id,
864
                                    'bloquer_creation' => '0',
865
                                    'bloquer_modification' => '0',
866
                                    'personal_folder' => '1'
867
                                )
868
                            );
869
                        }
870
871
                        // load settings
872
                        loadSettings();
873
874
                        // Send email to new user
875
                        @sendEmail(
876
                            $LANG['email_subject_new_user'],
877
                            str_replace(
878
                                array('#tp_login#', '#tp_pw#', '#tp_link#'),
879
                                array(" ".addslashes($login), addslashes($password), $_SESSION['settings']['email_server_url']), $LANG['email_new_user_mail']),
880
                            $email,
881
                            ""
882
                        );
883
884
                        // update LOG
885
                        logEvents('user_mngt', 'at_user_added', 'api - '.$GLOBALS['apikey'], $new_user_id, "");
886
887
                        echo '{"status":"user added"}';
888
                    } catch (PDOException $ex) {
889
                        echo '<br />'.$ex->getMessage();
890
                    }
891
                } else {
892
                    rest_error('USERALREADYEXISTS');
893
                }
894
            }
895
            /*
896
            * ADDING A FOLDER
897
            * <url to teampass>/api/index.php/add/folder/<title>;<complexity_level>;<parent_id>;<renewal_period>;<personal>?apikey=<valid api key>
898
            */
899
            elseif ($GLOBALS['request'][1] == "folder") {
900
                if (!empty($GLOBALS['request'][2])) {
901
                    // get sent parameters
902
                    $params = explode(';', base64_decode($GLOBALS['request'][2]));
903
904
                    if (!empty($params[0]) && !empty($params[1])) {
905
                        if (empty($params[3])) {
906
                            $params[3] = 0;
907
                        }
908
                        if (empty($params[4])) {
909
                            $params[4] = 0;
910
                        }
911
                        if ($params[2] < 0) {
912
                            rest_error('NO_DATA_EXIST');
913
                        }
914
915
                        //Check if title doesn't contains html codes
916
                        if (preg_match_all("|<[^>]+>(.*)</[^>]+>|U", $params[0], $out)) {
917
                            rest_error('HTML_CODES_NOT_ALLOWED');
918
                        }
919
920
                        // check if title is numeric
921
                        if (is_numeric($params[0]) === true) {
922
                            rest_error('TITLE_ONLY_WITH_NUMBERS');
923
                        }
924
925
                        //Check if duplicate folders name are allowed
926
                        $data = DB::queryfirstrow(
927
                            "SELECT valeur
928
                            FROM ".prefix_table("misc")."
929
                            WHERE type = %s AND intitule = %s",
930
                            "admin",
931
                            "duplicate_folder"
932
                        );
933
                        // if valeur = 0 then duplicate folders not allowed
934
                        if ($data === 0) {
935
                            DB::query("SELECT * FROM ".prefix_table("nested_tree")." WHERE title = %s", $params[0]);
936
                            $counter = DB::count();
937
                            if ($counter != 0) {
938
                                rest_error('ALREADY_EXISTS');
939
                            }
940
                        }
941
942
                        //check if parent folder is personal
943
                        $data = DB::queryfirstrow(
944
                            "SELECT personal_folder
945
                            FROM ".prefix_table("nested_tree")."
946
                            WHERE id = %i",
947
                            $params[2]
948
                        );
949
                        if ($data['personal_folder'] === "1") {
950
                            $isPersonal = 1;
951
                        } else {
952
                            if ($params[4] === 1) {
953
                                $isPersonal = 1;
954
                            } else {
955
                                $isPersonal = 0;
956
                            }
957
958
                            // get complexity level for this folder
959
                            $data = DB::queryfirstrow(
960
                                "SELECT valeur
961
                                FROM ".prefix_table("misc")."
962
                                WHERE intitule = %i AND type = %s",
963
                                $params[2],
964
                                "complex"
965
                            );
966
                            if (intval($params[1]) < intval($data['valeur'])) {
967
                                rest_error('COMPLEXICITY_LEVEL_NOT_REACHED');
968
                            }
969
                        }
970
971
                        try {
972
                            //create folder
973
                            DB::insert(
974
                                prefix_table("nested_tree"),
975
                                array(
976
                                    'parent_id' => $params[2],
977
                                    'title' => $params[0],
978
                                    'personal_folder' => $isPersonal,
979
                                    'renewal_period' => $params[3],
980
                                    'bloquer_creation' => '0',
981
                                    'bloquer_modification' => '0'
982
                                )
983
                            );
984
                            $newId = DB::insertId();
985
986
                            //Add complexity
987
                            DB::insert(
988
                                prefix_table("misc"),
989
                                array(
990
                                    'type' => 'complex',
991
                                    'intitule' => $newId,
992
                                    'valeur' => $params[1]
993
                                )
994
                            );
995
996
                            echo '{"status":"folder created" , "new_folder_id":"'.$newId.'"}';
997
                        } catch (PDOException $ex) {
998
                            echo '<br />'.$ex->getMessage();
999
                        }
1000
                    } else {
1001
                        rest_error('NO_DATA_EXIST');
1002
                    }
1003
                } else {
1004
                    rest_error('SET_NO_DATA');
1005
                }
1006
            }
1007
        } elseif ($GLOBALS['request'][0] == "update") {
1008
            /*
1009
            * Section dedicated for UPDATING
1010
            */
1011
            if ($GLOBALS['request'][1] == "item") {
1012
                /*
1013
                * Expected call format: .../api/index.php/update/item/<item_id>/<label>;<password>;<description>;<folder_id>;<login>;<email>;<url>;<tags>;<any one can modify>?apikey=<VALID API KEY>
1014
                */
1015
                if ($GLOBALS['request'][2] !== "" && is_numeric($GLOBALS['request'][2])) {
1016
                    // get sent parameters
1017
                    $params = explode(';', base64_decode($GLOBALS['request'][3]));
1018
1019
                    if (!empty($params[0]) && !empty($params[1]) && !empty($params[3])) {
1020
                        // Check length
1021
                        if (strlen($params[1]) > 50) {
1022
                            rest_error('PASSWORDTOOLONG');
1023
                        }
1024
1025
                        // Check Folder ID
1026
                        DB::query("SELECT * FROM ".prefix_table("nested_tree")." WHERE id = %i", $params[3]);
1027
                        $counter = DB::count();
1028
                        if ($counter == 0) {
1029
                            rest_error('NOSUCHFOLDER');
1030
                        }
1031
1032
                        // check if item exists
1033
                        DB::query(
1034
                            "SELECT * FROM ".prefix_table("items")." WHERE id = %i",
1035
                            $GLOBALS['request'][2]
1036
                        );
1037
                        $counter = DB::count();
1038
                        if ($counter > 0) {
1039
                            // encrypt pwd
1040
                            $encrypt = cryption(
1041
                                $params[1],
1042
                                "",
1043
                                "encrypt"
1044
                            );
1045
                            if (empty($encrypt['string'])) {
1046
                                rest_error('PASSWORDEMPTY');
1047
                            }
1048
1049
                            // ADD item
1050
                            try {
1051
                                DB::update(
1052
                                    prefix_table("items"),
1053
                                    array(
1054
                                        "label" => $params[0],
1055
                                        "description" => $params[2],
1056
                                        'pw' => $encrypt['string'],
1057
                                        'pw_iv' => '',
1058
                                        "email" => $params[5],
1059
                                        "url" => $params[6],
1060
                                        "id_tree" => intval($params[3]),
1061
                                        "login" => $params[4],
1062
                                        "anyone_can_modify" => intval($params[8])
1063
                                    ),
1064
                                    "id = %i",
1065
                                    $GLOBALS['request'][2]
1066
                                );
1067
1068
                                // log
1069
                                DB::insert(
1070
                                    prefix_table("log_items"),
1071
                                    array(
1072
                                        "id_item" => $GLOBALS['request'][2],
1073
                                        "date" => time(),
1074
                                        "id_user" => API_USER_ID,
1075
                                        "action" => "at_modification"
1076
                                    )
1077
                                );
1078
1079
                                // Add tags
1080
                                $tags = explode(' ', $params[7]);
1081
                                foreach ((array) $tags as $tag) {
1082
                                    if (!empty($tag)) {
1083
                                        // check if already exists
1084
                                        DB::query(
1085
                                            "SELECT * FROM ".prefix_table("tags")." WHERE tag = %s AND item_id = %i",
1086
                                            strtolower($tag),
1087
                                            $GLOBALS['request'][2]
1088
                                        );
1089
                                        $counter = DB::count();
1090
                                        if ($counter === 0) {
1091
                                            DB::insert(
1092
                                                prefix_table("tags"),
1093
                                                array(
1094
                                                    "item_id" => $GLOBALS['request'][2],
1095
                                                    "tag" => strtolower($tag)
1096
                                                )
1097
                                            );
1098
                                        }
1099
                                    }
1100
                                }
1101
1102
                                // Update CACHE table
1103
                                DB::update(
1104
                                    prefix_table("cache"),
1105
                                    array(
1106
                                        "label" => $params[0],
1107
                                        "description" => $params[2],
1108
                                        "tags" => $params[7],
1109
                                        "id_tree" => intval($params[3]),
1110
                                        "perso" => "0",
1111
                                        "restricted_to" => "",
1112
                                        "login" => $params[4],
1113
                                        "folder" => "",
1114
                                        "author" => API_USER_ID,
1115
                                        "renewal_period" => "0",
1116
                                        "timestamp" => time(),
1117
                                        "url" => $params[6],
1118
                                    ),
1119
                                    "id = %i",
1120
                                    $GLOBALS['request'][2]
1121
                                );
1122
1123
                                echo '{"status":"item updated"}';
1124
                            } catch (PDOException $ex) {
1125
                                echo '<br />'.$ex->getMessage();
1126
                            }
1127
                        } else {
1128
                            rest_error('NO_DATA_EXIST');
1129
                        }
1130
                    } else {
1131
                        rest_error('ITEMMISSINGDATA');
1132
                    }
1133
                } else {
1134
                    rest_error('NO_ITEM');
1135
                }
1136
            }
1137
            /*
1138
            * UPDATING A FOLDER
1139
            * <url to teampass>/api/index.php/update/folder/<folder_id>/<title>;<complexity_level>;<renewal_period>?apikey=<valid api key>
1140
            */
1141
            else if ($GLOBALS['request'][1] == "folder") {
1142
                if ($GLOBALS['request'][2] !== "" && is_numeric($GLOBALS['request'][2])) {
1143
                    // get sent parameters
1144
                    $params = explode(';', base64_decode($GLOBALS['request'][3]));
1145
1146
                    if (!empty($params[0])) {
1147
                        if ($params[1] < 0) {
1148
                            rest_error('NO_DATA_EXIST');
1149
                        }
1150
                        if (empty($params[2])) {
1151
                            $params[2] = 0;
1152
                        }
1153
1154
                        // check if folder exists and get folder data
1155
                        $data_folder = DB::queryfirstrow("SELECT * FROM ".prefix_table("nested_tree")." WHERE id = %s", $GLOBALS['request'][2]);
1156
                        $counter = DB::count();
1157
                        if ($counter === 0) {
1158
                            rest_error('NO_DATA_EXIST');
1159
                        }
1160
1161
                        //Check if title doesn't contains html codes
1162
                        if (preg_match_all("|<[^>]+>(.*)</[^>]+>|U", $params[0], $out)) {
1163
                            rest_error('HTML_CODES_NOT_ALLOWED');
1164
                        }
1165
1166
                        // check if title is numeric
1167
                        if (is_numeric($params[0]) === true) {
1168
                            rest_error('TITLE_ONLY_WITH_NUMBERS');
1169
                        }
1170
1171
                        // get complexity level for this folder
1172
                        $data = DB::queryfirstrow(
1173
                            "SELECT valeur
1174
                            FROM ".prefix_table("misc")."
1175
                            WHERE intitule = %i AND type = %s",
1176
                            $data_folder['parent_id'],
1177
                            "complex"
1178
                        );
1179
                        if (intval($params[1]) < intval($data['valeur'])) {
1180
                            rest_error('COMPLEXICITY_LEVEL_NOT_REACHED');
1181
                        }
1182
1183
                        try {
1184
                            DB::update(
1185
                                prefix_table("nested_tree"),
1186
                                array(
1187
                                    'parent_id' => $data_folder['parent_id'],
1188
                                    'title' => $params[0],
1189
                                    'personal_folder' => 0,
1190
                                    'renewal_period' => $params[2],
1191
                                    'bloquer_creation' => '0',
1192
                                    'bloquer_modification' => '0'
1193
                                ),
1194
                                "id = %i",
1195
                                $GLOBALS['request'][2]
1196
                            );
1197
1198
                            //Add complexity
1199
                            DB::update(
1200
                                prefix_table("misc"),
1201
                                array(
1202
                                    'valeur' => $params[1]
1203
                                ),
1204
                                "intitule = %s AND type = %s",
1205
                                $GLOBALS['request'][2],
1206
                                "complex"
1207
                            );
1208
1209
                            echo '{"status":"folder updated"}';
1210
                        } catch (PDOException $ex) {
1211
                            echo '<br />'.$ex->getMessage();
1212
                        }
1213
                    } else {
1214
                        rest_error('ITEMMISSINGDATA');
1215
                    }
1216
                } else {
1217
                    rest_error('NO_ITEM');
1218
                }
1219
            }
1220
        } elseif ($GLOBALS['request'][0] == "auth") {
1221
            /*
1222
            ** FOR SECURITY PURPOSE, it is mandatory to use SSL to connect your teampass instance. The user password is not encrypted!
1223
            **
1224
            **
1225
            ** Expected call format: .../api/index.php/auth/<PROTOCOL>/<URL>/<login>/<password>?apikey=<VALID API KEY>
1226
            ** Example: https://127.0.0.1/teampass/api/index.php/auth/http/www.zadig-tge.adp.com/U1/test/76?apikey=chahthait5Aidood6johh6Avufieb6ohpaixain
1227
            ** RESTRICTIONS:
1228
            **              - <PROTOCOL>        ==> http|https|ftp|...
1229
            **              - <URL>             ==> encode URL without protocol (example: http://www.teampass.net becomes www.teampass.net)
1230
            **              - <login>           ==> user's login
1231
            **              - <password>        ==> currently clear password
1232
            **
1233
            ** RETURNED ANSWER:
1234
            **              - format sent back is JSON
1235
            **              - Example: {"<item_id>":{"label":"<pass#1>","login":"<login#1>","pw":"<pwd#1>"},"<item_id>":{"label":"<pass#2>","login":"<login#2>","pw":"<pwd#2>"}}
1236
            **
1237
            */
1238
            // get user credentials
1239
            if (isset($GLOBALS['request'][3]) && isset($GLOBALS['request'][4])) {
1240
                // get url
1241
                if (isset($GLOBALS['request'][1]) && isset($GLOBALS['request'][2])) {
1242
                    // is user granted?
1243
                    $userData = DB::queryFirstRow(
1244
                        "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id` FROM ".$pre."users WHERE login = %s",
1245
                        $GLOBALS['request'][3]
1246
                    );
1247
1248
                    // load passwordLib library
1249
                    $_SESSION['settings']['cpassman_dir'] = "..";
1250
                    require_once '../sources/SplClassLoader.php';
1251
                    $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
1252
                    $pwdlib->register();
1253
                    $pwdlib = new PasswordLib\PasswordLib();
1254
1255
                    if ($pwdlib->verifyPasswordHash($GLOBALS['request'][4], $userData['pw']) === true) {
1256
                        // define the restriction of "id_tree" of this user
1257
                        //db::debugMode(true);
1258
                        $userDef = DB::queryOneColumn('folder_id',
1259
                            "SELECT DISTINCT folder_id
1260
                            FROM ".prefix_table("roles_values")."
1261
                            WHERE type IN ('R', 'W', 'ND', 'NE', 'NDNE', 'NEND') ", empty($userData['groupes_interdits']) ? "" : "
1262
                            AND folder_id NOT IN (".str_replace(";", ",", $userData['groupes_interdits']).")", "
1263
                            AND role_id IN %ls
1264
                            GROUP BY folder_id",
1265
                            explode(";", $userData['groupes_interdits'])
1266
                        );
1267
                        // complete with "groupes_visibles"
1268
                        foreach (explode(";", $userData['groupes_visibles']) as $v) {
1269
                            array_push($userDef, $v);
1270
                        }
1271
1272
                        // find the item associated to the url
1273
                        $response = DB::query(
1274
                            "SELECT id, label, login, pw, pw_iv, id_tree, restricted_to
1275
                            FROM ".prefix_table("items")."
1276
                            WHERE url LIKE %s
1277
                            AND id_tree IN (".implode(",", $userDef).")
1278
                            ORDER BY id DESC",
1279
                            $GLOBALS['request'][1]."://".urldecode($GLOBALS['request'][2].'%')
1280
                        );
1281
                        $counter = DB::count();
1282
1283
                        if ($counter > 0) {
1284
                            $json = "";
1285
                            foreach ($response as $data) {
1286
                                // check if item visible
1287
                                if (
1288
                                    empty($data['restricted_to']) ||
1289
                                    ($data['restricted_to'] != "" && in_array($userData['id'], explode(";", $data['restricted_to'])))
1290
                                ) {
1291
                                    // prepare export
1292
                                    $json[$data['id']]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
1293
                                    $json[$data['id']]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
1294
                                    $crypt_pw = cryption(
1295
                                        $data['pw'],
1296
                                        "",
1297
                                        "decrypt"
1298
                                    );
1299
                                    $json[$data['id']]['pw'] = $crypt_pw['string'];
1300
                                }
1301
                            }
1302
                            // prepare answer. If no access then inform
1303
                            if (empty($json)) {
1304
                                rest_error('AUTH_NO_DATA');
1305
                            } else {
1306
                                echo json_encode($json);
1307
                            }
1308
                        } else {
1309
                            rest_error('NO_DATA_EXIST');
1310
                        }
1311
                    } else {
1312
                        rest_error('AUTH_NOT_GRANTED');
1313
                    }
1314
                } else {
1315
                    rest_error('AUTH_NO_URL');
1316
                }
1317
            } else {
1318
                rest_error('AUTH_NO_IDENTIFIER');
1319
            }
1320
        } elseif ($GLOBALS['request'][0] == "auth_tpc") {
1321
            /*
1322
            ** TO BE USED ONLY BY TEAMPASS-CONNECT
1323
            **
1324
            */
1325
            // get user credentials
1326
            if (isset($GLOBALS['request'][2]) && isset($GLOBALS['request'][3]) && isset($GLOBALS['request'][4])) {
1327
                // get url
1328
                if (isset($GLOBALS['request'][1])) {
1329
                    // decode base64 criterium
1330
                    $tpc_url = base64_decode($GLOBALS['request'][1]);
1331
                    $user_pwd = base64_decode($GLOBALS['request'][3]);
1332
                    $user_saltkey = base64_decode($GLOBALS['request'][4]);
1333
1334
                    // is user granted?
1335
                    //db::debugMode(true);
1336
                    $userData = DB::queryFirstRow(
1337
                        "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id`, `encrypted_psk` FROM ".$pre."users WHERE login = %s",
1338
                        $GLOBALS['request'][2]
1339
                    );
1340
1341
                    // check if psk is correct.
1342
                    $user_saltkey = defuse_validate_personal_key(
1343
                        $user_saltkey,
1344
                        $userData['encrypted_psk']
1345
                    );
1346
                    if (strpos($user_saltkey, "Error ") !== false) {
1347
                        // error
1348
                        rest_error('AUTH_NO_DATA');
1349
                    }
1350
1351
                    // load passwordLib library
1352
                    $_SESSION['settings']['cpassman_dir'] = "..";
1353
                    require_once '../sources/SplClassLoader.php';
1354
                    $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
1355
                    $pwdlib->register();
1356
                    $pwdlib = new PasswordLib\PasswordLib();
1357
1358
                    if ($pwdlib->verifyPasswordHash($user_pwd, $userData['pw']) === true) {
1359
                        // define the restriction of "id_tree" of this user
1360
                        //db::debugMode(true);
1361
                        $userDef = DB::queryOneColumn('folder_id',
1362
                            "SELECT DISTINCT folder_id
1363
                            FROM ".prefix_table("roles_values")."
1364
                            WHERE type IN ('R', 'W', 'ND', 'NE', 'NDNE', 'NEND') ", empty($userData['groupes_interdits']) ? "" : "
1365
                            AND folder_id NOT IN (".str_replace(";", ",", $userData['groupes_interdits']).")", "
1366
                            AND role_id IN %ls
1367
                            GROUP BY folder_id",
1368
                            explode(";", $userData['groupes_interdits'])
1369
                        );
1370
                        // complete with "groupes_visibles"
1371
                        foreach (explode(";", $userData['groupes_visibles']) as $v) {
1372
                            array_push($userDef, $v);
1373
                        }
1374
1375
                        // add PF
1376
                        $userpf = DB::queryFirstRow(
1377
                            "SELECT `id` FROM ".$pre."nested_tree WHERE title = %s",
1378
                            $userData['id']
1379
                        );
1380
                        array_push($userDef, $userpf['id']);
1381
1382
                        // find the item associated to the url
1383
                        $response = DB::query(
1384
                            "SELECT id, label, login, pw, pw_iv, id_tree, restricted_to, perso
1385
                            FROM ".prefix_table("items")."
1386
                            WHERE url LIKE %s
1387
                            AND id_tree IN (".implode(",", array_filter($userDef)).")
1388
                            AND inactif = %i
1389
                            ORDER BY id DESC",
1390
                            $tpc_url.'%',
1391
                            0
1392
                        );
1393
                        $counter = DB::count();
1394
1395
                        if ($counter > 0) {
1396
                            $json = "";
1397
                            foreach ($response as $data) {
1398
                                // check if item visible
1399
                                if (
1400
                                    empty($data['restricted_to']) ||
1401
                                    ($data['restricted_to'] != "" && in_array($userData['id'], explode(";", $data['restricted_to'])))
1402
                                ) {
1403
                                    // prepare export
1404
                                    $json[$data['id']]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
1405
                                    $json[$data['id']]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
1406
                                    if ($data['perso'] === "0") {
1407
                                        $crypt_pw = cryption(
1408
                                            $data['pw'],
1409
                                            "",
1410
                                            "decrypt"
1411
                                        );
1412
                                    } else if (empty($user_saltkey)) {
1413
                                        $crypt_pw['string'] = "no_psk";
1414
                                    } else {
1415
                                        $crypt_pw = cryption(
1416
                                            $data['pw'],
1417
                                            $user_saltkey,
1418
                                            "decrypt"
1419
                                        );
1420
                                    }
1421
                                    $json[$data['id']]['pw'] = mb_detect_encoding($crypt_pw['string'], 'UTF-8', true) ? $crypt_pw['string'] : "not_utf8";
1422
                                    $json[$data['id']]['perso'] = $data['perso'];
1423
                                }
1424
                            }
1425
                            // prepare answer. If no access then inform
1426
                            if (empty($json)) {
1427
                                rest_error('AUTH_NO_DATA');
1428
                            } else {
1429
                                echo json_encode($json);
1430
                            }
1431
                        } else {
1432
                            rest_error('NO_DATA_EXIST');
1433
                        }
1434
                    } else {
1435
                        rest_error('AUTH_NOT_GRANTED');
1436
                    }
1437
                } else {
1438
                    rest_error('AUTH_NO_URL');
1439
                }
1440
            } else {
1441
                rest_error('AUTH_NO_IDENTIFIER');
1442
            }
1443
        } elseif ($GLOBALS['request'][0] == "set") {
1444
            /*
1445
             * Expected call format: .../api/index.php/set/<login_to_save>/<password_to_save>/<url>/<user_login>/<user_password>/<label>/<protocol>?apikey=<VALID API KEY>
1446
             * Example: https://127.0.0.1/teampass/api/index.php/set/newLogin/newPassword/newUrl/myLogin/myPassword?apikey=gu6Eexaewaishooph6iethoh5woh0yoit6ohquo
1447
             *
1448
             * NEW ITEM WILL BE STORED IN SPECIFIC FOLDER
1449
             */
1450
            // get user credentials
1451
            if (isset($GLOBALS['request'][4]) && isset($GLOBALS['request'][5])) {
1452
                // get url
1453
                if (isset($GLOBALS['request'][1]) && isset($GLOBALS['request'][2]) && isset($GLOBALS['request'][3])) {
1454
                    // is user granted?
1455
                    $userData = DB::queryFirstRow(
1456
                        "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id` FROM ".$pre."users WHERE login = %s",
1457
                        $GLOBALS['request'][4]
1458
                    );
1459
                    if (DB::count() == 0) {
1460
                        rest_error('AUTH_NO_IDENTIFIER');
1461
                    }
1462
1463
                    // load passwordLib library
1464
                    $_SESSION['settings']['cpassman_dir'] = "..";
1465
                    require_once '../sources/SplClassLoader.php';
1466
                    $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
1467
                    $pwdlib->register();
1468
                    $pwdlib = new PasswordLib\PasswordLib();
1469
1470
                    // is user identified?
1471
                    if ($pwdlib->verifyPasswordHash($GLOBALS['request'][5], $userData['pw']) === true) {
1472
                        // does the personal folder of this user exists?
1473
                        DB::queryFirstRow(
1474
                            "SELECT `id`
1475
                            FROM " . $pre."nested_tree
1476
                            WHERE title = %s AND personal_folder = 1",
1477
                            $userData['id']
1478
                        );
1479
                        if (DB::count() > 0) {
1480
                            // check if "teampass-connect" folder exists
1481
                            // if not create it
1482
                            $folder = DB::queryFirstRow(
1483
                                "SELECT `id`
1484
                                FROM " . $pre."nested_tree
1485
                                WHERE title = %s",
1486
                                "teampass-connect"
1487
                            );
1488 View Code Duplication
                            if (DB::count() == 0) {
1489
                                DB::insert(
1490
                                    prefix_table("nested_tree"),
1491
                                    array(
1492
                                        'parent_id' => '0',
1493
                                        'title' => "teampass-connect"
1494
                                    )
1495
                                );
1496
                                $tpc_folder_id = DB::insertId();
1497
1498
                                //Add complexity
1499
                                DB::insert(
1500
                                    prefix_table("misc"),
1501
                                    array(
1502
                                        'type' => 'complex',
1503
                                        'intitule' => $tpc_folder_id,
1504
                                        'valeur' => '0'
1505
                                    )
1506
                                );
1507
1508
                                // rebuild tree
1509
                                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
1510
                                $tree->register();
1511
                                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
1512
                                $tree->rebuild();
1513
                            } else {
1514
                                $tpc_folder_id = $folder['id'];
1515
                            }
1516
1517
                            // encrypt password
1518
                            $encrypt = cryption(
1519
                                $GLOBALS['request'][2],
1520
                                "",
1521
                                "encrypt"
1522
                            );
1523
1524
                            // is there a protocol?
1525
                            if (isset($GLOBALS['request'][7]) || empty($GLOBALS['request'][7])) {
1526
                                $protocol = "http://";
1527
                            } else {
1528
                                $protocol = urldecode($GLOBALS['request'][7])."://";
1529
                            }
1530
1531
                            // add new item
1532
                            DB::insert(
1533
                                prefix_table("items"),
1534
                                array(
1535
                                    'label' => "Credentials for ".urldecode($GLOBALS['request'][3]),
1536
                                    'description' => "Imported with Teampass-Connect",
1537
                                    'pw' => $encrypt['string'],
1538
                                    'pw_iv' => "",
1539
                                    'email' => "",
1540
                                    'url' => urldecode($GLOBALS['request'][3]),
1541
                                    'id_tree' => $tpc_folder_id,
1542
                                    'login' => $GLOBALS['request'][1],
1543
                                    'inactif' => '0',
1544
                                    'restricted_to' => $userData['id'],
1545
                                    'perso' => '0',
1546
                                    'anyone_can_modify' => '0',
1547
                                    'complexity_level' => '0'
1548
                                )
1549
                            );
1550
                            $newID = DB::insertId();
1551
1552
                            // log
1553
                            logItems(
1554
                                $newID,
1555
                                "Credentials for ".urldecode($GLOBALS['request'][3].'%'),
1556
                                $userData['id'],
1557
                                'at_creation',
1558
                                $GLOBALS['request'][1]
1559
                            );
1560
1561
                            $json['status'] = "ok";
1562
                            // prepare answer. If no access then inform
1563
                            if (empty($json)) {
1564
                                rest_error('AUTH_NO_DATA');
1565
                            } else {
1566
                                echo json_encode($json);
1567
                            }
1568
                        } else {
1569
                            rest_error('NO_PF_EXIST_FOR_USER');
1570
                        }
1571
                    } else {
1572
                        rest_error('AUTH_NOT_GRANTED');
1573
                    }
1574
                } else {
1575
                    rest_error('SET_NO_DATA');
1576
                }
1577
            } else {
1578
                rest_error('AUTH_NO_IDENTIFIER');
1579
            }
1580
        } elseif ($GLOBALS['request'][0] == "set_tpc") {
1581
            /*
1582
             * TO BE USED ONLY BY TEAMPASS-CONNECT
1583
             */
1584
            // get user credentials
1585
            if (isset($GLOBALS['request'][2]) && isset($GLOBALS['request'][3])) {
1586
                // get url
1587
                if (isset($GLOBALS['request'][1])) {
1588
                    // is user granted?
1589
                    $userData = DB::queryFirstRow(
1590
                        "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id`, `encrypted_psk` FROM ".$pre."users WHERE login = %s",
1591
                        $GLOBALS['request'][2]
1592
                    );
1593
                    if (DB::count() == 0) {
1594
                        rest_error('AUTH_NO_IDENTIFIER');
1595
                    }
1596
1597
                    // load passwordLib library
1598
                    $_SESSION['settings']['cpassman_dir'] = "..";
1599
                    require_once '../sources/SplClassLoader.php';
1600
                    $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
1601
                    $pwdlib->register();
1602
                    $pwdlib = new PasswordLib\PasswordLib();
1603
1604
                    // prepare TPC parameters
1605
                    $tpc_param = explode(';@;', base64_decode($GLOBALS['request'][1]));
1606
                    $tpc_param[5] = base64_decode($tpc_param[5]);
1607
1608
                    // is user identified?
1609
                    if ($pwdlib->verifyPasswordHash(base64_decode($GLOBALS['request'][3]), $userData['pw']) === true) {
1610
                        //
1611
                        if ($tpc_param[4] !== "0") {
1612
                            // it is not a personal folder
1613
                            $salt = "";
1614
                            $tpc_folder_id = $tpc_param[4];
1615
                            $perso = '0';
1616
                            $restricted_to = $userData['id'];
1617
1618
                        } else if ($tpc_param[4] === "0" && $tpc_param[5] !== "") {
1619
                            // it is a personal folder
1620
                            $salt = $tpc_param[5];
1621
1622
                            // check if psk is correct.
1623
                            $salt = defuse_validate_personal_key(
1624
                                $salt,
1625
                                $userData['encrypted_psk']
1626
                            );
1627
                            if (strpos($user_key_encoded, "Error ") !== false) {
1628
                                // error
1629
                                rest_error('AUTH_NO_DATA');
1630
                            }
1631
1632
1633
                            $perso = '1';
1634
                            $restricted_to = "";
1635
1636
                            // does the personal folder of this user exists?
1637
                            $user_folder = DB::queryFirstRow(
1638
                                "SELECT `id`
1639
                                FROM " . $pre."nested_tree
1640
                                WHERE title = %s AND personal_folder = 1",
1641
                                $userData['id']
1642
                            );
1643
                            if (DB::count() === 0) {
1644
                                // check if "teampass-connect" folder exists
1645
                                // if not create it
1646
                                $folder = DB::queryFirstRow(
1647
                                    "SELECT `id`
1648
                                    FROM " . $pre."nested_tree
1649
                                    WHERE title = %s",
1650
                                    "teampass-connect"
1651
                                );
1652 View Code Duplication
                                if (DB::count() == 0) {
1653
                                    DB::insert(
1654
                                        prefix_table("nested_tree"),
1655
                                        array(
1656
                                            'parent_id' => '0',
1657
                                            'title' => "teampass-connect"
1658
                                        )
1659
                                    );
1660
                                    $tpc_folder_id = DB::insertId();
1661
1662
                                    //Add complexity
1663
                                    DB::insert(
1664
                                        prefix_table("misc"),
1665
                                        array(
1666
                                            'type' => 'complex',
1667
                                            'intitule' => $tpc_folder_id,
1668
                                            'valeur' => '0'
1669
                                        )
1670
                                    );
1671
1672
                                    // rebuild tree
1673
                                    $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
1674
                                    $tree->register();
1675
                                    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
1676
                                    $tree->rebuild();
1677
                                } else {
1678
                                    $tpc_folder_id = $folder['id'];
1679
                                }
1680
                            } else {
1681
                                $tpc_folder_id = $user_folder['id'];
1682
                            }
1683
                        } else {
1684
                            // there is an error in PSALT
1685
                            rest_error('NO_PSALTK_PROVIDED');
1686
                        }
1687
1688
                        // now we continue
1689
                        // encrypt password
1690
                        $encrypt = cryption(
1691
                            urldecode($tpc_param[1]),
1692
                            $salt,
1693
                            "encrypt"
1694
                        );
1695
1696
                        // is there a label?
1697
                        if (empty($tpc_param[3])) {
1698
                            $label = "Credentials for ".urldecode($tpc_param[2]);
1699
                        } else {
1700
                            $label = urldecode($tpc_param[3]);
1701
                        }
1702
1703
                        // add new item
1704
                        DB::insert(
1705
                            prefix_table("items"),
1706
                            array(
1707
                                'label' => $label,
1708
                                'description' => "Imported with Teampass-Connect",
1709
                                'pw' => $encrypt['string'],
1710
                                'pw_iv' => "",
1711
                                'email' => "",
1712
                                'url' => urldecode($tpc_param[2]),
1713
                                'id_tree' => $tpc_folder_id,
1714
                                'login' => urldecode($tpc_param[0]),
1715
                                'inactif' => '0',
1716
                                'restricted_to' => $restricted_to,
1717
                                'perso' => $perso,
1718
                                'anyone_can_modify' => '0',
1719
                                'complexity_level' => '0'
1720
                            )
1721
                        );
1722
                        $newID = DB::insertId();
1723
1724
                        // log
1725
                        logItems(
1726
                            $newID,
1727
                            $label,
1728
                            $userData['id'],
1729
                            'at_creation',
1730
                            ''
1731
                        );
1732
1733
                        $json['status'] = "ok";
1734
                        $json['new_item_id'] = $newID;
1735
                        // prepare answer. If no access then inform
1736
                        if (empty($json)) {
1737
                            rest_error('AUTH_NO_DATA');
1738
                        } else {
1739
                            echo json_encode($json);
1740
                        }
1741
                    } else {
1742
                        rest_error('AUTH_NOT_GRANTED');
1743
                    }
1744
                } else {
1745
                    rest_error('SET_NO_DATA');
1746
                }
1747
            } else {
1748
                rest_error('AUTH_NO_IDENTIFIER');
1749
            }
1750
        }
1751
        /*
1752
        * DELETE
1753
        *
1754
        * Expected call format: .../api/index.php/delete/folder/<folder_id1;folder_id2;folder_id3>?apikey=<VALID API KEY>
1755
        * Expected call format: .../api/index.php/delete/item>/<item_id1;item_id2;item_id3>?apikey=<VALID API KEY>
1756
        */
1757
        elseif ($GLOBALS['request'][0] == "delete") {
1758
            $_SESSION['settings']['cpassman_dir'] = "..";
1759
            if ($GLOBALS['request'][1] == "folder") {
1760
                $array_category = explode(';', $GLOBALS['request'][2]);
1761
1762
                // get user info
1763 View Code Duplication
                if (isset($GLOBALS['request'][3]) && !empty($GLOBALS['request'][3])) {
1764
                    $userData = DB::queryFirstRow(
1765
                        "SELECT `id` FROM ".$pre."users WHERE login = %s",
1766
                        $GLOBALS['request'][3]
1767
                    );
1768
                    if (DB::count() == 0) {
1769
                        $user_id = API_USER_ID;
1770
                    } else {
1771
                        $user_id = $userData['id'];
1772
                    }
1773
                } else {
1774
                    $user_id = API_USER_ID;
1775
                }
1776
1777
                if (count($array_category) > 0 && count($array_category) < 5) {
1778
                    // load passwordLib library
1779
                    require_once '../sources/SplClassLoader.php';
1780
1781
                    // prepare tree
1782
                    $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
1783
                    $tree->register();
1784
                    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title', 'personal_folder');
1785
1786
                    // this will delete all sub folders and items associated
1787
                    for ($i = 0; $i < count($array_category); $i++) {echo "\n".$array_category[$i]."\n";
1788
                        // Get through each subfolder
1789
                        $folders = $tree->getDescendants($array_category[$i], true);
1790
                        print_r($folders);
1791
                        if (count($folders) > 0) {
1792
                            foreach ($folders as $folder) {
1793
                                if (($folder->parent_id > 0 || $folder->parent_id == 0) && $folder->personal_folder != 1) {
1794
                                    //Store the deleted folder (recycled bin)
1795
                                    DB::insert(
1796
                                        prefix_table("misc"),
1797
                                        array(
1798
                                            'type' => 'folder_deleted',
1799
                                            'intitule' => "f".$array_category[$i],
1800
                                            'valeur' => $folder->id.', '.$folder->parent_id.', '.
1801
                                                $folder->title.', '.$folder->nleft.', '.$folder->nright.', '.$folder->nlevel.', 0, 0, 0, 0'
1802
                                        )
1803
                                    );
1804
                                    //delete folder
1805
                                    DB::delete(prefix_table("nested_tree"), "id = %i", $folder->id);
1806
1807
                                    //delete items & logs
1808
                                    $items = DB::query(
1809
                                        "SELECT id
1810
                                        FROM ".prefix_table("items")."
1811
                                        WHERE id_tree=%i",
1812
                                        $folder->id
1813
                                    );
1814
                                    foreach ($items as $item) {
1815
                                        DB::update(
1816
                                            prefix_table("items"),
1817
                                            array(
1818
                                                'inactif' => '1',
1819
                                            ),
1820
                                            "id = %i",
1821
                                            $item['id']
1822
                                        );
1823
                                        //log
1824
                                        DB::insert(
1825
                                            prefix_table("log_items"),
1826
                                            array(
1827
                                                'id_item' => $item['id'],
1828
                                                'date' => time(),
1829
                                                'id_user' => $user_id,
1830
                                                'action' => 'at_delete'
1831
                                            )
1832
                                        );
1833
                                    }
1834
                                    //Update CACHE table
1835
                                    updateCacheTable("delete_value", $array_category[$i]);
1836
                                }
1837
                            }
1838
                        }
1839
                    }
1840
                } else {
1841
                    rest_error('NO_CATEGORY');
1842
                }
1843
1844
                $json['status'] = 'OK';
1845
1846
            } elseif ($GLOBALS['request'][1] == "item") {
1847
                $array_items = explode(';', $GLOBALS['request'][2]);
1848
1849
                // get user info
1850 View Code Duplication
                if (isset($GLOBALS['request'][3]) && !empty($GLOBALS['request'][3])) {
1851
                    $userData = DB::queryFirstRow(
1852
                        "SELECT `id` FROM ".$pre."users WHERE login = %s",
1853
                        $GLOBALS['request'][3]
1854
                    );
1855
                    if (DB::count() == 0) {
1856
                        $user_id = API_USER_ID;
1857
                    } else {
1858
                        $user_id = $userData['id'];
1859
                    }
1860
                }
1861
1862
                for ($i = 0; $i < count($array_items); $i++) {
1863
                    DB::update(
1864
                        prefix_table("items"),
1865
                        array(
1866
                            'inactif' => '1',
1867
                        ),
1868
                        "id = %i",
1869
                        $array_items[$i]
1870
                    );
1871
                    //log
1872
                    DB::insert(
1873
                        prefix_table("log_items"),
1874
                        array(
1875
                            'id_item' => $array_items[$i],
1876
                            'date' => time(),
1877
                            'id_user' => $user_id,
1878
                            'action' => 'at_delete'
1879
                        )
1880
                    );
1881
1882
                    //Update CACHE table
1883
                    updateCacheTable("delete_value", $array_items[$i]);
1884
                }
1885
1886
                $json['status'] = 'OK';
1887
            }
1888
1889
            if ($json) {
1890
                echo json_encode($json);
1891
            } else {
1892
                rest_error('EMPTY');
1893
            }
1894
        } else if ($GLOBALS['request'][0] == "new_password") {
1895
            if (!empty($GLOBALS['request'][1])) {
1896
                $params = explode(";", $GLOBALS['request'][1]);
1897
1898
                if (empty($params[0])) {
1899
                    $params[0] = 8;
1900
                }
1901
                if (empty($params[1])) {
1902
                    $params[1] = 0;
1903
                }
1904
                if (empty($params[2])) {
1905
                    $params[2] = 0;
1906
                }
1907
                if (empty($params[3])) {
1908
                    $params[3] = 0;
1909
                }
1910
                if (empty($params[4])) {
1911
                    $params[4] = 0;
1912
                }
1913
                if (empty($params[5])) {
1914
                    $params[5] = 0;
1915
                }
1916
                if (empty($params[6])) {
1917
                    $params[6] = 0;
1918
                }
1919
1920
                // load library
1921
                require_once '../sources/SplClassLoader.php';
1922
                $pwgen = new SplClassLoader('Encryption\PwGen', '../includes/libraries');
1923
                $pwgen->register();
1924
                $pwgen = new Encryption\PwGen\pwgen();
1925
1926
                // init
1927
                $pwgen->setLength($params[0]);
1928
                if ($params[1] === "1") {
1929
                    $pwgen->setSecure(true);
1930
                }
1931
                if ($params[2] === "1") {
1932
                    $pwgen->setNumerals(true);
1933
                }
1934
                if ($params[3] === "1") {
1935
                    $pwgen->setCapitalize(true);
1936
                }
1937
                if ($params[4] === "1") {
1938
                    $pwgen->setAmbiguous(true);
1939
                }
1940
                if ($params[5] === "1" && $params[6] === "1") {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $params[6] (integer) and '1' (string) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
1941
                    $pwgen->setSymbols(true);
1942
                }
1943
1944
                // generate and send back (generate in base64 if symbols are asked)
1945
                if ($params[6] === "1") {
1946
                    echo '{"password" : "'.base64_encode($pwgen->generate()).'"}';
1947
                } else {
1948
                    echo '{"password" : "'.($pwgen->generate()).'"}';
1949
                }
1950
            } else {
1951
                rest_error('NO_PARAMETERS');
1952
            }
1953
        } else if ($GLOBALS['request'][0] === "info") {
1954
            if ($GLOBALS['request'][1] === "complexicity_levels_list") {
1955
1956
                require_once '../includes/language/english.php';
1957
                $json = array(
1958
                    0=> $LANG['complex_level0'],
1959
                    25=> $LANG['complex_level1'],
1960
                    50=> $LANG['complex_level2'],
1961
                    60=> $LANG['complex_level3'],
1962
                    70=> $LANG['complex_level4'],
1963
                    80=> $LANG['complex_level5'],
1964
                    90=> $LANG['complex_level6']
1965
                );
1966
1967
                echo json_encode($json);
1968
            } else if ($GLOBALS['request'][1] === "folder") {
1969
                if (!empty($GLOBALS['request'][2]) && is_numeric($GLOBALS['request'][2])) {
1970
                    $data = DB::queryFirstRow(
1971
                        "SELECT * FROM ".$pre."nested_tree WHERE id = %i",
1972
                        $GLOBALS['request'][2]
1973
                    );
1974
                    if (DB::count() == 0) {
1975
                        rest_error('NOSUCHFOLDER');
1976
                    }
1977
1978
                    // form id_tree to full foldername
1979
                    require_once '../sources/SplClassLoader.php';
1980
                    //Load Tree
1981
                    $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
1982
                    $tree->register();
1983
                    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
1984
1985
                    $folder = "";
1986
                    $arbo = $tree->getPath($GLOBALS['request'][2], true);
1987
                    foreach ($arbo as $elem) {
1988
                        if (empty($folder)) {
1989
                            $folder = stripslashes($elem->title);
1990
                        } else {
1991
                            $folder .= " > ".stripslashes($elem->title);
1992
                        }
1993
                    }
1994
1995
                    // prepare info
1996
                    $json = array(
1997
                        "title" => $data['title'],
1998
                        "personal_folder" => $data['personal_folder'],
1999
                        "renewal_period" => $data['renewal_period'],
2000
                        "parent_id" => $data['parent_id'],
2001
                        "path" => $folder,
2002
                    );
2003
2004
                    echo json_encode($json);
2005
                } else {
2006
                    rest_error('NO_PARAMETERS');
2007
                }
2008
            } else if ($GLOBALS['request'][1] === "version") {
2009
                echo '{"api-version":"'.$api_version.'"}';
2010
            } else {
2011
                rest_error('NO_PARAMETERS');
2012
            }
2013
        } else {
2014
            rest_error('METHOD');
2015
        }
2016
    }
2017
}
2018
2019
function rest_put() {
2020 View Code Duplication
    if (!@count($GLOBALS['request']) == 0) {
2021
        $request_uri = $GLOBALS['_SERVER']['REQUEST_URI'];
2022
        preg_match('/\/api(\/index.php|)\/(.*)\?apikey=(.*)/', $request_uri, $matches);
2023
        if (count($matches) == 0) {
2024
            rest_error('REQUEST_SENT_NOT_UNDERSTANDABLE');
2025
        }
2026
        $GLOBALS['request'] = explode('/', $matches[2]);
2027
    }
2028
    if (apikey_checker($GLOBALS['apikey'])) {
2029
        global $server, $user, $pass, $database, $pre, $link;
2030
        teampass_connect();
2031
2032
    }
2033
}
2034
2035
/**
2036
 * @param string $type
2037
 */
2038
function rest_error($type, $detail = 'N/A') {
2039
    switch ($type) {
2040
        case 'APIKEY':
2041
            $message = Array('err' => 'This api_key '.$GLOBALS['apikey'].' doesn\'t exist');
2042
            header('HTTP/1.1 405 Method Not Allowed');
2043
            break;
2044
        case 'NO_CATEGORY':
2045
            $message = Array('err' => 'No folder specified');
2046
            break;
2047
        case 'NO_ITEM':
2048
            $message = Array('err' => 'No item specified');
2049
            break;
2050
        case 'EMPTY':
2051
            $message = Array('err' => 'No results');
2052
            break;
2053
        case 'IPWHITELIST':
2054
            $message = Array('err' => 'Ip address not allowed.');
2055
            header('HTTP/1.1 405 Method Not Allowed');
2056
            break;
2057
        case 'MYSQLERR':
2058
            $message = Array('err' => $detail);
2059
            header('HTTP/1.1 500 Internal Server Error');
2060
            break;
2061
        case 'METHOD':
2062
            $message = Array('err' => 'Method not authorized');
2063
            header('HTTP/1.1 405 Method Not Allowed');
2064
            break;
2065
        case 'ITEMBADDEFINITION':
2066
            $message = Array('err' => 'Item definition not complete');
2067
            header('HTTP/1.1 405 Method Not Allowed');
2068
            break;
2069
        case 'ITEM_MALFORMED':
2070
            $message = Array('err' => 'Item definition not numeric');
2071
            header('HTTP/1.1 405 Method Not Allowed');
2072
            break;
2073
        case 'USERBADDEFINITION':
2074
            $message = Array('err' => 'User definition not complete');
2075
            header('HTTP/1.1 405 Method Not Allowed');
2076
            break;
2077
        case 'USERLOGINEMPTY':
2078
            $message = Array('err' => 'Empty Login given');
2079
            header('HTTP/1.1 405 Method Not Allowed');
2080
            break;
2081
        case 'USERALREADYEXISTS':
2082
            $message = Array('err' => 'User already exists');
2083
            header('HTTP/1.1 405 Method Not Allowed');
2084
            break;
2085
        case 'REQUEST_SENT_NOT_UNDERSTANDABLE':
2086
            $message = Array('err' => 'URL format is not following requirements');
2087
            break;
2088
        case 'AUTH_NOT_GRANTED':
2089
            $message = Array('err' => 'Bad credentials for user');
2090
            break;
2091
        case 'AUTH_NO_URL':
2092
            $message = Array('err' => 'URL needed to grant access');
2093
            break;
2094
        case 'AUTH_NO_IDENTIFIER':
2095
            $message = Array('err' => 'Credentials needed to grant access');
2096
            break;
2097
        case 'AUTH_NO_DATA':
2098
            $message = Array('err' => 'Data not allowed for the user');
2099
            break;
2100
        case 'NO_DATA_EXIST':
2101
            $message = Array('err' => 'No data exists');
2102
            break;
2103
        case 'PASSWORDTOOLONG':
2104
            $message = Array('err' => 'Password is too long');
2105
            break;
2106
        case 'NOSUCHFOLDER':
2107
            $message = Array('err' => 'Folder ID does not exist');
2108
            break;
2109
        case 'PASSWORDEMPTY':
2110
            $message = Array('err' => 'Password is empty');
2111
            break;
2112
        case 'ITEMEXISTS':
2113
            $message = Array('err' => 'Label already exists');
2114
            break;
2115
        case 'ITEMMISSINGDATA':
2116
            $message = Array('err' => 'Label or Password or Folder ID is missing');
2117
            break;
2118
        case 'SET_NO_DATA':
2119
            $message = Array('err' => 'No data to be stored');
2120
            break;
2121
        case 'NO_PF_EXIST_FOR_USER':
2122
            $message = Array('err' => 'No Personal Folder exists for this user');
2123
            break;
2124
        case 'HTML_CODES_NOT_ALLOWED':
2125
            $message = Array('err' => 'HTML tags not allowed');
2126
            break;
2127
        case 'TITLE_ONLY_WITH_NUMBERS':
2128
            $message = Array('err' => 'Title only with numbers not allowed');
2129
            break;
2130
        case 'ALREADY_EXISTS':
2131
            $message = Array('err' => 'Data already exists');
2132
            break;
2133
        case 'COMPLEXICITY_LEVEL_NOT_REACHED':
2134
            $message = Array('err' => 'complexity level was not reached');
2135
            break;
2136
        case 'NO_PARAMETERS':
2137
            $message = Array('err' => 'No parameters given');
2138
            break;
2139
        case 'USER_NOT_EXISTS':
2140
            $message = Array('err' => 'User does not exist');
2141
            break;
2142
        case 'NO_PSALTK_PROVIDED':
2143
            $message = Array('err' => 'No Personal saltkey provided');
2144
            break;
2145
        default:
2146
            $message = Array('err' => 'Something happen ... but what ?');
2147
            header('HTTP/1.1 500 Internal Server Error');
2148
            break;
2149
    }
2150
2151
    echo json_encode($message);
2152
    exit(0);
2153
}
2154
2155
function apikey_checker($apikey_used) {
2156
    teampass_connect();
2157
    $apikey_pool = teampass_get_keys();
2158
    if (in_array($apikey_used, $apikey_pool)) {
2159
        return(1);
2160
    } else {
2161
        rest_error('APIKEY', $apikey_used);
2162
    }
2163
}
2164
2165 View Code Duplication
function teampass_pbkdf2_hash($p, $s, $c, $kl, $st = 0, $a = 'sha256')
2166
{
2167
    $kb = $st + $kl;
2168
    $dk = '';
2169
2170
    for ($block = 1; $block <= $kb; $block++) {
2171
        $ib = $h = hash_hmac($a, $s.pack('N', $block), $p, true);
2172
        for ($i = 1; $i < $c; $i++) {
2173
            $ib ^= ($h = hash_hmac($a, $h, $p, true));
2174
        }
2175
        $dk .= $ib;
2176
    }
2177
2178
    return substr($dk, $st, $kl);
2179
}
2180