Passed
Push — development ( ee13b6...7c2d55 )
by Nils
04:34
created

addToCacheTable()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 41
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 28
nc 3
nop 1
dl 0
loc 41
rs 8.8571
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 21 and the first side effect is on line 16.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 *
4
 * @file          (api)functions.php
5
 * @author        Nils Laumaillé
6
 * @version       2.1.0
7
 * @copyright     (c) 2009-2018 Nils Laumaillé
8
 * @licensing     GNU 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
{
23
    if (function_exists('apache_request_headers')) {
24
        $headers = apache_request_headers();
25
    } else {
26
        $headers = $_SERVER;
27
    }
28
    if (array_key_exists('X-Forwarded-For', $headers) && filter_var($headers['X-Forwarded-For'], FILTER_VALIDATE_IP)) {
29
        $the_ip = $headers['X-Forwarded-For'];
30
    } elseif (array_key_exists('HTTP_X_FORWARDED_FOR', $headers) && filter_var($headers['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP)) {
31
        $the_ip = $headers['HTTP_X_FORWARDED_FOR'];
32
    } else {
33
        $the_ip = filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP);
34
    }
35
    return $the_ip;
36
}
37
38
39
function teampass_api_enabled()
40
{
41
    teampass_connect();
42
    $response = DB::queryFirstRow(
43
        "SELECT `valeur` FROM ".prefix_table("misc")." WHERE type = %s AND intitule = %s",
44
        "admin",
45
        "api"
46
    );
47
    return $response['valeur'];
48
}
49
50
function teampass_whitelist()
51
{
52
    teampass_connect();
53
    $apiip_pool = teampass_get_ips();
54
    if (count($apiip_pool) > 0 && array_search(get_ip(), $apiip_pool) === false) {
55
        rest_error('IPWHITELIST');
56
    }
57
}
58
59
function teampass_connect()
60
{
61
    global $server, $user, $pass, $database, $link, $port, $encoding;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
62
    require_once("../includes/config/settings.php");
63
    require_once('../includes/libraries/Database/Meekrodb/db.class.php');
64
    $pass = defuse_return_decrypted($pass);
65
    DB::$host = $server;
66
    DB::$user = $user;
67
    DB::$password = $pass;
68
    DB::$dbName = $database;
69
    DB::$port = $port;
70
    DB::$encoding = $encoding;
71
    DB::$error_handler = true;
72
    $link = mysqli_connect($server, $user, $pass, $database, $port);
73
    $link->set_charset($encoding);
74
}
75
76
function teampass_get_ips()
77
{
78
    $array_of_results = array();
79
    teampass_connect();
80
    $response = DB::query("select value from ".prefix_table("api")." WHERE type = %s", "ip");
81
    foreach ($response as $data) {
82
        array_push($array_of_results, $data['value']);
83
    }
84
85
    return $array_of_results;
86
}
87
88
function teampass_get_keys()
89
{
90
    teampass_connect();
91
    $response = array_unique(array_merge(
92
        DB::queryOneColumn("value", "select * from ".prefix_table("api")." WHERE type = %s", "key"),
93
        DB::queryOneColumn("user_api_key", "select * from ".prefix_table("users")."")
94
    ));
95
96
    // remove none value
97
    if (($key = array_search('none', $response)) !== false) {
98
        unset($response[$key]);
99
    }
100
101
    return $response;
102
}
103
104
function rest_head()
105
{
106
    header('HTTP/1.1 402 Payment Required');
107
}
108
109
function addToCacheTable($item_id)
110
{
111
    teampass_connect();
112
    // get data
113
    $data = DB::queryfirstrow(
114
        "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
115
        FROM ".prefix_table("items")." AS i
116
        AND ".prefix_table("log_items")." AS l ON (l.id_item = i.id)
117
        WHERE i.id = %i
118
        AND l.action = %s",
119
        intval($item_id),
120
        at_creation
0 ignored issues
show
Bug introduced by
The constant at_creation was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
121
    );
122
123
    // Get all TAGS
124
    $tags = "";
125
    $data_tags = DB::query("SELECT tag FROM ".prefix_table("tags")." WHERE item_id=%i", $item_id);
126
    foreach ($data_tags as $itemTag) {
127
        if (!empty($itemTag['tag'])) {
128
            $tags .= $itemTag['tag']." ";
129
        }
130
    }
131
132
    // finaly update
133
    DB::insert(
134
        prefix_table("cache"),
135
        array(
136
            "id" => $data['id'],
137
            "label" => $data['label'],
138
            "description" => $data['description'],
139
            "tags" => $tags,
140
            "id_tree" => $data['id_tree'],
141
            "perso" => $data['perso'],
142
            "restricted_to" => $data['restricted_to'],
143
            "login" => $data['login'],
144
            "folder" => "",
145
            //"restricted_to" => "0",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
146
            "author" => API_USER_ID,
147
            "renewal_period" => 0,
148
            "timestamp" => time(),
149
            "url" => 0
150
        )
151
    );
152
}
153
154
155
/**
156
 * @param string $setting
157
 */
158
function getSettingValue($setting)
159
{
160
    // get default language
161
    $set = DB::queryFirstRow(
162
        "SELECT `valeur` FROM ".prefix_table("misc")." WHERE type = %s AND intitule = %s",
163
        "admin",
164
        $setting
165
    );
166
167
    return $set['valeur'];
168
}
169
170
function rest_delete()
171
{
172
    if (!@count($GLOBALS['request']) == 0) {
173
        $request_uri = $GLOBALS['_SERVER']['REQUEST_URI'];
174
        preg_match('/\/api(\/index.php|)\/(.*)\?apikey=(.*)/', $request_uri, $matches);
175
        if (count($matches) == 0) {
176
            rest_error('REQUEST_SENT_NOT_UNDERSTANDABLE');
177
        }
178
        $GLOBALS['request'] = explode('/', $matches[2]);
179
    }
180
    if (apikey_checker($GLOBALS['apikey'])) {
181
        include "../sources/main.functions.php";
182
        teampass_connect();
183
        $category_query = "";
184
185
        if ($GLOBALS['request'][0] == "write") {
186
            if ($GLOBALS['request'][1] == "category") {
187
                $array_category = explode(';', $GLOBALS['request'][2]);
188
189
                foreach ($array_category as $category) {
190
                    if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $category, $result)) {
191
                        rest_error('CATEGORY_MALFORMED');
192
                    }
193
                }
194
195
                if (count($array_category) > 1 && count($array_category) < 5) {
196
                    for ($i = count($array_category); $i > 0; $i--) {
197
                        $slot = $i - 1;
198
                        if (!$slot) {
199
                            $category_query .= "select id from ".prefix_table("nested_tree")." where title LIKE '".filter_var($array_category[$slot], FILTER_SANITIZE_STRING)."' AND parent_id = 0";
200
                        } else {
201
                            $category_query .= "select id from ".prefix_table("nested_tree")." where title LIKE '".filter_var($array_category[$slot], FILTER_SANITIZE_STRING)."' AND parent_id = (";
202
                        }
203
                    }
204
                    for ($i = 1; $i < count($array_category); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

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

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

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
205
                        $category_query .= ")";
206
                    }
207
                } elseif (count($array_category) == 1) {
208
                    $category_query = "select id from ".prefix_table("nested_tree")." where title LIKE '".filter_var($array_category[0], FILTER_SANITIZE_STRING)."' AND parent_id = 0";
209
                } else {
210
                    rest_error('NO_CATEGORY');
211
                }
212
213
                // Delete items which in category
214
                $response = DB::delete(prefix_table("items"), "id_tree = (".$category_query.")");
0 ignored issues
show
Unused Code introduced by
The assignment to $response is dead and can be removed.
Loading history...
215
                // Delete sub-categories which in category
216
                $response = DB::delete(prefix_table("nested_tree"), "parent_id = (".$category_query.")");
217
                // Delete category
218
                $response = DB::delete(prefix_table("nested_tree"), "id = (".$category_query.")");
219
220
                $json['type'] = 'category';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$json was never initialized. Although not strictly required by PHP, it is generally a good practice to add $json = array(); before regardless.
Loading history...
221
                $json['category'] = $GLOBALS['request'][2];
222
                if ($response) {
223
                    $json['status'] = 'OK';
224
                } else {
225
                    $json['status'] = 'KO';
226
                }
227
            } elseif ($GLOBALS['request'][1] == "item") {
228
                $array_category = explode(';', $GLOBALS['request'][2]);
229
                $item = $GLOBALS['request'][3];
230
231
                foreach ($array_category as $category) {
232
                    if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $category, $result)) {
233
                        rest_error('CATEGORY_MALFORMED');
234
                    }
235
                }
236
237
                if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $item, $result)) {
238
                    rest_error('ITEM_MALFORMED');
239
                } elseif (empty($item) || count($array_category) == 0) {
240
                    rest_error('MALFORMED');
241
                }
242
243
                if (count($array_category) > 1 && count($array_category) < 5) {
244
                    for ($i = count($array_category); $i > 0; $i--) {
245
                        $slot = $i - 1;
246
                        if (!$slot) {
247
                            $category_query .= "select id from ".prefix_table("nested_tree")." where title LIKE '".filter_var($array_category[$slot], FILTER_SANITIZE_STRING)."' AND parent_id = 0";
248
                        } else {
249
                            $category_query .= "select id from ".prefix_table("nested_tree")." where title LIKE '".filter_var($array_category[$slot], FILTER_SANITIZE_STRING)."' AND parent_id = (";
250
                        }
251
                    }
252
                    for ($i = 1; $i < count($array_category); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

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

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

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
253
                        $category_query .= ")";
254
                    }
255
                } elseif (count($array_category) == 1) {
256
                    $category_query = "select id from ".prefix_table("nested_tree")." where title LIKE '".filter_var($array_category[0], FILTER_SANITIZE_STRING)."' AND parent_id = 0";
257
                } else {
258
                    rest_error('NO_CATEGORY');
259
                }
260
261
                // Delete item
262
                $response = DB::delete(prefix_table("items"), "id_tree = (".$category_query.") and label LIKE '".filter_var($item, FILTER_SANITIZE_STRING)."'");
263
                $json['type'] = 'item';
264
                $json['item'] = $item;
265
                $json['category'] = $GLOBALS['request'][2];
266
                if ($response) {
267
                    $json['status'] = 'OK';
268
                } else {
269
                    $json['status'] = 'KO';
270
                }
271
            }
272
273
            if ($json) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $json does not seem to be defined for all execution paths leading up to this point.
Loading history...
274
                echo json_encode($json);
275
            } else {
276
                rest_error('EMPTY');
277
            }
278
        } else {
279
            rest_error('METHOD');
280
        }
281
    }
282
}
283
284
function rest_get()
285
{
286
    global $api_version;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
287
    global $SETTINGS;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
288
289
    if (!@count($GLOBALS['request']) == 0) {
290
        $request_uri = $GLOBALS['_SERVER']['REQUEST_URI'];
291
        preg_match('/\/api(\/index.php|)\/(.*)\?apikey=(.*)/', $request_uri, $matches);
292
        if (count($matches) == 0) {
293
            rest_error('REQUEST_SENT_NOT_UNDERSTANDABLE');
294
        }
295
        $GLOBALS['request'] = explode('/', $matches[2]);
296
    }
297
298
    if (apikey_checker($GLOBALS['apikey'])) {
299
300
        teampass_connect();
301
302
        // define the API user through the LABEL of apikey
303
        $api_info = DB::queryFirstRow(
304
            "SELECT label
305
            FROM ".prefix_table("api")."
306
            WHERE value = %s",
307
            $GLOBALS['apikey']
308
        );
309
310
        // Load config
311
        if (file_exists('../includes/config/tp.config.php')) {
312
            require_once '../includes/config/tp.config.php';
313
        } else {
314
            throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
315
        }
316
317
        if ($GLOBALS['request'][0] == "read") {
318
            if ($GLOBALS['request'][1] == "folder") {
319
                /*
320
                * READ FOLDERS
321
                */
322
323
                // load library
324
                require_once '../sources/SplClassLoader.php';
325
                //Load Tree
326
                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
327
                $tree->register();
328
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
329
330
                // get ids
331
                if (strpos($GLOBALS['request'][2], ";") > 0) {
332
                    $condition = "id_tree IN %ls";
333
                    $condition_value = explode(';', $GLOBALS['request'][2]);
334
                } else {
335
                    $condition = "id_tree = %s";
336
                    $condition_value = $GLOBALS['request'][2];
337
                }
338
339
                // get items in this folder
340
                $response = DB::query(
341
                    "SELECT id, label, login, pw, pw_iv, url, id_tree, description, email
342
                    FROM ".prefix_table("items")."
343
                    WHERE inactif='0' AND ".$condition,
344
                    $condition_value
345
                );
346
                $inc = 0;
347
                foreach ($response as $data) {
348
                    // build the path to the Item
349
                    $path = "";
350
                    $arbo = $tree->getPath($data['id_tree'], true);
351
                    foreach ($arbo as $elem) {
352
                        if (empty($path)) {
353
                            $path = stripslashes($elem->title);
354
                        } else {
355
                            $path .= " > ".stripslashes($elem->title);
356
                        }
357
                    }
358
359
                    // prepare output
360
                    $json[$inc]['id'] = $data['id'];
361
                    $json[$inc]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
362
                    $json[$inc]['description'] = mb_convert_encoding($data['description'], mb_detect_encoding($data['description']), 'UTF-8');
363
                    $json[$inc]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
364
                    $json[$inc]['email'] = mb_convert_encoding($data['email'], mb_detect_encoding($data['email']), 'UTF-8');
365
                    $json[$inc]['url'] = mb_convert_encoding($data['url'], mb_detect_encoding($data['url']), 'UTF-8');
366
                    $crypt_pw = cryption(
367
                        $data['pw'],
368
                        "",
369
                        "decrypt"
370
                    );
371
                    $json[$inc]['pw'] = $crypt_pw['string'];
372
                    $json[$inc]['folder_id'] = $data['id_tree'];
373
                    $json[$inc]['path'] = $path;
374
375
                    $inc++;
376
                }
377
            } elseif ($GLOBALS['request'][1] == "userpw") {
378
                /*
379
                * READ USER ITEMS
380
                */
381
382
                // load library
383
                require_once '../sources/SplClassLoader.php';
384
                //Load Tree
385
                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
386
                $tree->register();
387
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
388
389
                // about the user
390
                $username = $GLOBALS['request'][2];
391
                if (strcmp($username, "admin") == 0) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
392
                    // forbid admin access
393
                }
394
                $response = DB::query(
395
                    "SELECT fonction_id
396
                    FROM ".prefix_table("users")."
397
                    WHERE login = %s'",
398
                    $username
399
                );
400
                if (count($response) === 0) {
401
                    rest_error('USER_NOT_EXISTS');
402
                }
403
                foreach ($response as $data) {
404
                    $role_str = $data['fonction_id'];
405
                }
406
                $folder_arr = array();
407
                $roles = explode(";", $role_str);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $role_str seems to be defined by a foreach iteration on line 403. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
408
                foreach ($roles as $role) {
409
                    $response = DB::query(
410
                        "SELECT folder_id
411
                        FROM ".prefix_table("roles_values")."
412
                        WHERE role_id = %i",
413
                        $role
414
                    );
415
                    foreach ($response as $data) {
416
                        $folder_id = $data['folder_id'];
417
                        if (!array_key_exists($folder_id, $folder_arr)) {
418
                            array_push($folder_arr, $folder_id);
419
                        }
420
                    }
421
                }
422
                $folder_str = array_filter($folder_arr);
423
424
                // get ids
425
                if (is_array($folder_str)) {
0 ignored issues
show
introduced by
The condition is_array($folder_str) is always true.
Loading history...
426
                    $condition = "id_tree IN %ls";
427
                    $condition_value = $folder_str;
428
                } else {
429
                    $condition = "id_tree = %s";
430
                    $condition_value = $folder_str;
431
                }
432
433
                $data = "";
0 ignored issues
show
Unused Code introduced by
The assignment to $data is dead and can be removed.
Loading history...
434
                // get items in this module
435
                $response = DB::query(
436
                    "SELECT id,label,url,login,pw, pw_iv, url, id_tree, description, email
437
                    FROM ".prefix_table("items")."
438
                    WHERE inactif='0' AND ".$condition,
439
                    $condition_value
440
                );
441
                $inc = 0;
442
                foreach ($response as $data) {
443
                    // build the path to the Item
444
                    $path = "";
445
                    $arbo = $tree->getPath($data['id_tree'], true);
446
                    foreach ($arbo as $elem) {
447
                        if (empty($path)) {
448
                            $path = stripslashes($elem->title);
449
                        } else {
450
                            $path .= " > ".stripslashes($elem->title);
451
                        }
452
                    }
453
454
                    // prepare output
455
                    $json[$data['id']]['id'] = $data['id'];
456
                    $json[$data['id']]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
457
                    $json[$data['id']]['description'] = mb_convert_encoding($data['description'], mb_detect_encoding($data['description']), 'UTF-8');
458
                    $json[$data['id']]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
459
                    $json[$data['id']]['email'] = mb_convert_encoding($data['email'], mb_detect_encoding($data['email']), 'UTF-8');
460
                    $json[$data['id']]['url'] = mb_convert_encoding($data['url'], mb_detect_encoding($data['url']), 'UTF-8');
461
                    $crypt_pw = cryption($data['pw'], "", "decrypt");
462
                    $json[$data['id']]['pw'] = $crypt_pw['string'];
463
                    $json[$data['id']]['folder_id'] = $data['id_tree'];
464
                    $json[$data['id']]['path'] = $path;
465
466
                    $inc++;
467
                }
468
            } elseif ($GLOBALS['request'][1] == "userfolders") {
469
                /*
470
                * READ USER FOLDERS
471
                * Sends back a list of folders
472
                */
473
                $json = "";
474
                $username = $GLOBALS['request'][2];
475
                if (strcmp($username, "admin") == 0) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
476
                    // forbid admin access
477
                }
478
                $response = DB::query(
479
                    "SELECT fonction_id
480
                    FROM ".prefix_table("users")."
481
                    WHERE login = %s",
482
                    $username
483
                );
484
                if (count($response) === 0) {
485
                    rest_error('USER_NOT_EXISTS');
486
                }
487
                foreach ($response as $data) {
488
                    $role_str = $data['fonction_id'];
489
                }
490
491
                $folder_arr = array();
492
                $roles = explode(";", $role_str);
493
                $inc = 0;
494
                foreach ($roles as $role) {
495
                    $response = DB::query(
496
                        "SELECT folder_id, type
497
                        FROM ".prefix_table("roles_values")."
498
                        WHERE role_id = %i",
499
                        $role
500
                    );
501
                    foreach ($response as $data) {
502
                        $folder_id = $data['folder_id'];
503
                        if (!array_key_exists($folder_id, $folder_arr)) {
504
                            array_push($folder_arr, $folder_id);
505
506
                            $response2 = DB::queryFirstRow(
507
                                "SELECT title, nlevel
508
                                FROM ".prefix_table("nested_tree")."
509
                                WHERE id = %i",
510
                                $folder_id
511
                            );
512
513
                            if (!empty($response2['title'])) {
514
                                $json[$folder_id]['id'] = $folder_id;
515
                                $json[$folder_id]['title'] = $response2['title'];
516
                                $json[$folder_id]['level'] = $response2['nlevel'];
517
                                $json[$folder_id]['access_type'] = $data['type'];
518
                                $inc++;
519
                            }
520
                        }
521
                    }
522
                }
523
            } elseif ($GLOBALS['request'][1] == "items") {
524
                /*
525
                * READ ITEMS asked
526
                */
527
528
                // load library
529
                require_once '../sources/SplClassLoader.php';
530
                //Load Tree
531
                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
532
                $tree->register();
533
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
534
535
                // get parameters
536
                $array_items = explode(';', $GLOBALS['request'][2]);
537
538
                // check if not empty
539
                if (count($array_items) == 0) {
540
                    rest_error('NO_ITEM');
541
                }
542
543
                // only accepts numeric
544
                foreach ($array_items as $item) {
545
                    if (!is_numeric($item)) {
546
                        rest_error('ITEM_MALFORMED');
547
                    }
548
                }
549
550
                $response = DB::query(
551
                    "SELECT id,label,login,pw, pw_iv, url, id_tree, description, email
552
                    FROM ".prefix_table("items")."
553
                    WHERE inactif = %i AND id IN %ls",
554
                    "0",
555
                    $array_items
556
                );
557
                $inc = 0;
558
                foreach ($response as $data) {
559
                    // build the path to the Item
560
                    $path = "";
561
                    $arbo = $tree->getPath($data['id_tree'], true);
562
                    foreach ($arbo as $elem) {
563
                        if (empty($path)) {
564
                            $path = stripslashes($elem->title);
565
                        } else {
566
                            $path .= " > ".stripslashes($elem->title);
567
                        }
568
                    }
569
570
                    // prepare output
571
                    $json[$inc]['id'] = $data['id'];
572
                    $json[$inc]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
573
                    $json[$inc]['description'] = mb_convert_encoding($data['description'], mb_detect_encoding($data['description']), 'UTF-8');
574
                    $json[$inc]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
575
                    $json[$inc]['email'] = mb_convert_encoding($data['email'], mb_detect_encoding($data['email']), 'UTF-8');
576
                    $json[$inc]['url'] = mb_convert_encoding($data['url'], mb_detect_encoding($data['url']), 'UTF-8');
577
                    $crypt_pw = cryption($data['pw'], "", "decrypt");
578
                    $json[$inc]['pw'] = $crypt_pw['string'];
579
                    $json[$inc]['folder_id'] = $data['id_tree'];
580
                    $json[$inc]['path'] = $path;
581
582
                    $inc++;
583
                }
584
            } elseif ($GLOBALS['request'][1] == "folder_descendants") {
585
                /*
586
                * PRovide full list of folders
587
                * <url to teampass>/api/index.php/read/folder_descendants/<id OR title>/<folder_id or folder_title>?apikey=<valid api key>
588
                */
589
590
                // get parameters
591
                if (isset($GLOBALS['request'][2]) === true && isset($GLOBALS['request'][3]) === true) {
592
                    // load library
593
                    require_once '../sources/SplClassLoader.php';
594
                    //Load Tree
595
                    $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
596
                    $tree->register();
597
                    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
598
599
                    // get parameters
600
                    $parameter_by = $GLOBALS['request'][2];
601
                    $parameter_criteria = $GLOBALS['request'][3];
602
603
                    // Check data consistency
604
                    if (preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $parameter_by, $result) === false) {
605
                        rest_error('MALFORMED');
606
                    }
607
608
                    if (preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $parameter_criteria, $result) === false) {
609
                        rest_error('MALFORMED');
610
                    }
611
612
                    // Is BY criteria correct
613
                    if ($parameter_by !== "id" && $parameter_by !== "title") {
614
                        rest_error('EXPECTED_PARAMETER_NOT_PROVIDED');
615
                    }
616
617
                    // If criteria is by Title
618
                    // Then search its id first
619
                    if ($parameter_by === "title") {
620
                        $response = DB::queryFirstRow(
621
                            "SELECT id
622
                            FROM ".prefix_table("nested_tree")."
623
                            WHERE
624
                            title LIKE %s",
625
                            $parameter_criteria
626
                        );
627
                        $parameter_criteria = $response['id'];
628
                    }
629
630
                    // List folder descendants
631
                    $folders = $tree->getDescendants(intval($parameter_criteria), true, false, false);
632
                    if (count($folders) > 0) {
633
                        $inc = 0;
634
                        foreach ($folders as $folder) {
635
                            // Prepare answer
636
                            $json[$inc]['id'] = mb_convert_encoding($folder->id, mb_detect_encoding($folder->id), 'UTF-8');
637
                            $json[$inc]['parent_id'] = mb_convert_encoding($folder->parent_id, mb_detect_encoding($folder->parent_id), 'UTF-8');
638
                            $json[$inc]['title'] = mb_convert_encoding(htmlspecialchars_decode($folder->title, ENT_QUOTES), mb_detect_encoding($folder->title), 'UTF-8');
639
                            $json[$inc]['nleft'] = mb_convert_encoding($folder->nleft, mb_detect_encoding($folder->nleft), 'UTF-8');
640
                            $json[$inc]['nright'] = mb_convert_encoding($folder->nright, mb_detect_encoding($folder->nright), 'UTF-8');
641
                            $json[$inc]['nlevel'] = mb_convert_encoding($folder->nlevel, mb_detect_encoding($folder->nlevel), 'UTF-8');
642
                            $json[$inc]['personal'] = mb_convert_encoding($folder->personal_folder, mb_detect_encoding($folder->personal_folder), 'UTF-8');
643
644
                            $inc ++;
645
                        }
646
                    }
647
                }
648
            }
649
650
            if (isset($json) && $json) {
651
                echo json_encode($json);
652
            } else {
653
                rest_error('EMPTY');
654
            }
655
        } elseif ($GLOBALS['request'][0] == "find") {
656
            if ($GLOBALS['request'][1] == "item") {
657
                /*
658
                * FIND ITEMS in FOLDERS
659
                */
660
661
                // load library
662
                require_once '../sources/SplClassLoader.php';
663
                //Load Tree
664
                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
665
                $tree->register();
666
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
667
668
                // get parameters
669
                $array_category = explode(';', $GLOBALS['request'][2]);
670
                $item = $GLOBALS['request'][3];
671
                foreach ($array_category as $category) {
672
                    if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $category, $result)) {
673
                        rest_error('CATEGORY_MALFORMED');
674
                    }
675
                }
676
677
                if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $item, $result)) {
678
                    rest_error('ITEM_MALFORMED');
679
                } elseif (empty($item) || count($array_category) == 0) {
680
                    rest_error('MALFORMED');
681
                }
682
683
                if (count($array_category) === 0) {
684
                    rest_error('NO_CATEGORY');
685
                }
686
687
                DB::debugMode(false);
688
                $response = DB::query(
689
                    "SELECT id, label, login, pw, pw_iv, url, id_tree, description, email
690
                    FROM ".prefix_table("items")."
691
                    WHERE
692
                    inactif = %i
693
                    AND id_tree IN %ls
694
                    AND label LIKE %ss",
695
                    "0",
696
                    $array_category,
697
                    $item
698
                );
699
                $inc = 0;
700
                foreach ($response as $data) {
701
                    // build the path to the Item
702
                    $path = "";
703
                    $arbo = $tree->getPath($data['id_tree'], true);
704
                    foreach ($arbo as $elem) {
705
                        if (empty($path)) {
706
                            $path = stripslashes($elem->title);
707
                        } else {
708
                            $path .= " > ".stripslashes($elem->title);
709
                        }
710
                    }
711
712
                    // prepare output
713
                    $json[$inc]['id'] = mb_convert_encoding($data['id'], mb_detect_encoding($data['id']), 'UTF-8');
714
                    $json[$inc]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
715
                    $json[$inc]['description'] = mb_convert_encoding($data['description'], mb_detect_encoding($data['description']), 'UTF-8');
716
                    $json[$inc]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
717
                    $json[$inc]['email'] = mb_convert_encoding($data['email'], mb_detect_encoding($data['email']), 'UTF-8');
718
                    $json[$inc]['url'] = mb_convert_encoding($data['url'], mb_detect_encoding($data['url']), 'UTF-8');
719
                    $crypt_pw = cryption($data['pw'], "", "decrypt");
720
                    $json[$inc]['pw'] = $crypt_pw['string'];
721
                    $json[$inc]['folder_id'] = $data['id_tree'];
722
                    $json[$inc]['path'] = $path;
723
                    $json[$inc]['status'] = utf8_encode("OK");
724
725
                    $inc++;
726
                }
727
                if (isset($json) && $json) {
728
                    echo json_encode($json);
729
                } else {
730
                    rest_error('EMPTY');
731
                }
732
            }
733
        } elseif ($GLOBALS['request'][0] == "add") {
734
            if ($GLOBALS['request'][1] == "item") {
735
                // get sent parameters
736
                $params = explode(';', base64_decode($GLOBALS['request'][2]));
737
                if (count($params) != 9) {
738
                    rest_error('ITEMBADDEFINITION');
739
                }
740
741
                $item_label = $params[0];
742
                $item_pwd = $params[1];
743
                $item_desc = $params[2];
744
                $item_folder_id = $params[3];
745
                $item_login = $params[4];
746
                $item_email = $params[5];
747
                $item_url = $params[6];
748
                $item_tags = $params[7];
749
                $item_anyonecanmodify = $params[8];
750
751
                // do some checks
752
                if (!empty($item_label) && !empty($item_pwd) && !empty($item_folder_id)) {
753
                    // Check length
754
                    if (strlen($item_pwd) > 50) {
755
                        rest_error('PASSWORDTOOLONG');
756
                    }
757
758
                    // Check Folder ID
759
                    DB::query("SELECT * FROM ".prefix_table("nested_tree")." WHERE id = %i", $item_folder_id);
760
                    $counter = DB::count();
761
                    if ($counter == 0) {
762
                        rest_error('NOSUCHFOLDER');
763
                    }
764
765
                    // check if element doesn't already exist
766
                    $item_duplicate_allowed = getSettingValue("duplicate_item");
767
                    if ($item_duplicate_allowed !== "1") {
768
                        DB::query(
769
                            "SELECT *
770
                            FROM ".prefix_table("items")."
771
                            WHERE label = %s AND inactif = %i",
772
                            addslashes($item_label),
773
                            "0"
774
                        );
775
                        $counter = DB::count();
776
                        if ($counter != 0) {
777
                            $itemExists = 1;
778
                            // prevent the error if the label already exists
779
                            // so lets just add the time() as a random factor
780
                            $item_label .= " (".time().")";
781
                        } else {
782
                            $itemExists = 0;
783
                        }
784
                    } else {
785
                        $itemExists = 0;
786
                    }
787
                    if ($itemExists === 0) {
788
                        $encrypt = cryption(
789
                            $item_pwd,
790
                            "",
791
                            "encrypt"
792
                        );
793
                        if (empty($encrypt['string'])) {
794
                            rest_error('PASSWORDEMPTY');
795
                        }
796
797
                        // ADD item
798
                        try {
799
                            DB::insert(
800
                                prefix_table("items"),
801
                                array(
802
                                    "label" => $item_label,
803
                                    "description" => $item_desc,
804
                                    'pw' => $encrypt['string'],
805
                                    'pw_iv' => '',
806
                                    "email" => $item_email,
807
                                    "url" => $item_url,
808
                                    "id_tree" => intval($item_folder_id),
809
                                    "login" => $item_login,
810
                                    "inactif" => 0,
811
                                    "restricted_to" => "",
812
                                    "perso" => 0,
813
                                    "anyone_can_modify" => intval($item_anyonecanmodify)
814
                                )
815
                            );
816
                            $newID = DB::InsertId();
817
818
                            // log
819
                            DB::insert(
820
                                prefix_table("log_items"),
821
                                array(
822
                                    "id_item" => $newID,
823
                                    "date" => time(),
824
                                    "id_user" => API_USER_ID,
825
                                    "action" => "at_creation",
826
                                    "raison" => $api_info['label']
827
                                )
828
                            );
829
830
                            // Add tags
831
                            $tags = explode(' ', $item_tags);
832
                            foreach ((array) $tags as $tag) {
833
                                if (!empty($tag)) {
834
                                    DB::insert(
835
                                        prefix_table("tags"),
836
                                        array(
837
                                            "item_id" => $newID,
838
                                            "tag" => strtolower($tag)
839
                                        )
840
                                    );
841
                                }
842
                            }
843
844
                            // Update CACHE table
845
                            DB::insert(
846
                                prefix_table("cache"),
847
                                array(
848
                                    "id" => $newID,
849
                                    "label" => $item_label,
850
                                    "description" => $item_desc,
851
                                    "tags" => $item_tags,
852
                                    "id_tree" => $item_folder_id,
853
                                    "perso" => "0",
854
                                    "restricted_to" => "",
855
                                    "login" => $item_login,
856
                                    "folder" => "",
857
                                    "author" => API_USER_ID,
858
                                    "renewal_period" => "0",
859
                                    "timestamp" => time(),
860
                                    "url" => "0"
861
                                )
862
                            );
863
864
                            echo '{"status":"item added" , "new_item_id" : "'.$newID.'"}';
865
                        } catch (PDOException $ex) {
866
                            echo '<br />'.$ex->getMessage();
867
                        }
868
                    } else {
869
                        rest_error('ITEMEXISTS');
870
                    }
871
                } else {
872
                    rest_error('ITEMMISSINGDATA');
873
                }
874
            } elseif ($GLOBALS['request'][1] == "user") {
875
            /*
876
             * Case where a new user has to be added
877
             *
878
             * 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>
879
             * with:
880
             * for READ_ONLY, IS_ADMIN, IS_MANAGER, PERSONAL_FOLDER, accepted value is 1 for TRUE and 0 for FALSE
881
             * for ADMINISTRATEDBY and ROLE1, accepted value is the real label (not the IDs)
882
             *
883
             * Example: /api/index.php/add/user/U4;Nils;Laumaille;test;[email protected];Users;0;Managers,Users;0;1;1?apikey=sae6iekahxiseL3viShoo0chahc1ievei8aequi
884
             *
885
             */
886
887
                // get user definition
888
                $array_user = explode(';', base64_decode($GLOBALS['request'][2]));
889
                if (count($array_user) != 11) {
890
                    rest_error('USERBADDEFINITION');
891
                }
892
893
                $login = $array_user[0];
894
                $name = $array_user[1];
895
                $lastname = $array_user[2];
896
                $password = $array_user[3];
897
                $email = $array_user[4];
898
                $adminby = urldecode($array_user[5]);
899
                $isreadonly = urldecode($array_user[6]);
900
                $roles = urldecode($array_user[7]);
901
                $isadmin = $array_user[8];
902
                $ismanager = $array_user[9];
903
                $haspf = $array_user[10];
904
905
                // Empty user
906
                if (mysqli_escape_string($link, htmlspecialchars_decode($login)) == "") {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $link seems to be never defined.
Loading history...
907
                    rest_error('USERLOGINEMPTY');
908
                }
909
                // Check if user already exists
910
                $data = DB::query(
911
                    "SELECT id, fonction_id, groupes_interdits, groupes_visibles
912
                    FROM ".prefix_table("users")."
913
                    WHERE login LIKE %ss",
914
                    mysqli_escape_string($link, stripslashes($login))
915
                );
916
917
                if (DB::count() == 0) {
918
                    try {
919
                        // find AdminRole code in DB
920
                        $resRole = DB::queryFirstRow(
921
                            "SELECT id
922
                            FROM ".prefix_table("roles_title")."
923
                            WHERE title LIKE %ss",
924
                            mysqli_escape_string($link, stripslashes($adminby))
925
                        );
926
927
                        // get default language
928
                        $lang = DB::queryFirstRow(
929
                            "SELECT `valeur`
930
                            FROM ".prefix_table("misc")."
931
                            WHERE type = %s AND intitule = %s",
932
                            "admin",
933
                            "default_language"
934
                        );
935
936
                        // prepare roles list
937
                        $rolesList = "";
938
                        foreach (explode(',', $roles) as $role) {
939
                            $tmp = DB::queryFirstRow(
940
                                "SELECT `id`
941
                                FROM ".prefix_table("roles_title")."
942
                                WHERE title = %s",
943
                                $role
944
                            );
945
                            if (empty($rolesList)) {
946
                                $rolesList = $tmp['id'];
947
                            } else {
948
                                $rolesList .= ";".$tmp['id'];
949
                            }
950
                        }
951
952
                        // Add user in DB
953
                        DB::insert(
954
                            prefix_table("users"),
955
                            array(
956
                                'login' => $login,
957
                                'name' => $name,
958
                                'lastname' => $lastname,
959
                                'pw' => bCrypt(stringUtf8Decode($password), COST),
1 ignored issue
show
Bug introduced by
The constant COST was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
960
                                'email' => $email,
961
                                'admin' => intval($isadmin),
962
                                'gestionnaire' => intval($ismanager),
963
                                'read_only' => intval($isreadonly),
964
                                'personal_folder' => intval($haspf),
965
                                'user_language' => $lang['valeur'],
966
                                'fonction_id' => $rolesList,
967
                                'groupes_interdits' => '0',
968
                                'groupes_visibles' => '0',
969
                                'isAdministratedByRole' => empty($resRole) ? '0' : $resRole['id']
970
                            )
971
                        );
972
                        $new_user_id = DB::insertId();
973
                        // Create personnal folder
974
                        if (intval($haspf) === 1) {
975
                            DB::insert(
976
                                prefix_table("nested_tree"),
977
                                array(
978
                                    'parent_id' => '0',
979
                                    'title' => $new_user_id,
980
                                    'bloquer_creation' => '0',
981
                                    'bloquer_modification' => '0',
982
                                    'personal_folder' => '1'
983
                                )
984
                            );
985
                        }
986
987
                        // load settings
988
                        loadSettings();
989
990
                        // Send email to new user
991
                        @sendEmail(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for sendEmail(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

991
                        /** @scrutinizer ignore-unhandled */ @sendEmail(

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
992
                            $LANG['email_subject_new_user'],
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $LANG seems to be never defined.
Loading history...
993
                            str_replace(
994
                                array('#tp_login#', '#tp_pw#', '#tp_link#'),
995
                                array(" ".addslashes($login), addslashes($password), $SETTINGS['email_server_url']),
996
                                $LANG['email_new_user_mail']
997
                            ),
998
                            $email,
999
                            $LANG,
1000
                            $SETTINGS
1001
                        );
1002
1003
                        // update LOG
1004
                        logEvents('user_mngt', 'at_user_added', 'api - '.$GLOBALS['apikey'], $new_user_id, "");
1005
1006
                        echo '{"status":"user added"}';
1007
                    } catch (PDOException $ex) {
1008
                        echo '<br />'.$ex->getMessage();
1009
                    }
1010
                } else {
1011
                    rest_error('USERALREADYEXISTS');
1012
                }
1013
            } elseif ($GLOBALS['request'][1] == "folder") {
1014
            /*
1015
            * ADDING A FOLDER
1016
            * <url to teampass>/api/index.php/add/folder/<title>;<complexity_level>;<parent_id>;<renewal_period>;<personal>?apikey=<valid api key>
1017
            * http://localhost/teampass/api/index.php/add/folder/Import from API;0;38;0;0?apikey=piesae7ahghae1iiP9ohPhaefaideeThohgh1te
1018
            */
1019
                if (!empty($GLOBALS['request'][2])) {
1020
                    // get sent parameters
1021
                    $params = explode(';', base64_decode($GLOBALS['request'][2]));
1022
1023
                    if (empty($params[0]) === false && (intval($params[1]) >= 0 && intval($params[1]) <= 1000)) {
1024
                        if (empty($params[3])) {
1025
                            $params[3] = 0;
1026
                        }
1027
                        if (empty($params[4])) {
1028
                            $params[4] = 0;
1029
                        }
1030
                        if (empty($params[2])) {
1031
                            rest_error('NO_DESTINATION_FOLDER');
1032
                        }
1033
                        if ($params[2] < 0) {
1034
                            rest_error('NO_DATA_EXIST');
1035
                        }
1036
1037
                        //Check if title doesn't contains html codes
1038
                        if (preg_match_all("|<[^>]+>(.*)</[^>]+>|U", $params[0], $out)) {
1039
                            rest_error('HTML_CODES_NOT_ALLOWED');
1040
                        }
1041
1042
                        // check if title is numeric
1043
                        if (is_numeric($params[0]) === true) {
1044
                            rest_error('TITLE_ONLY_WITH_NUMBERS');
1045
                        }
1046
1047
                        //Check if duplicate folders name are allowed
1048
                        $data = DB::queryfirstrow(
1049
                            "SELECT valeur
1050
                            FROM ".prefix_table("misc")."
1051
                            WHERE type = %s AND intitule = %s",
1052
                            "admin",
1053
                            "duplicate_folder"
1054
                        );
1055
                        // if valeur = 0 then duplicate folders not allowed
1056
                        if ($data['valeur'] === '0') {
1057
                            DB::query(
1058
                                "SELECT *
1059
                                FROM ".prefix_table("nested_tree")."
1060
                                WHERE title = %s",
1061
                                $params[0]
1062
                            );
1063
                            $counter = DB::count();
1064
                            if ($counter != 0) {
1065
                                rest_error('ALREADY_EXISTS');
1066
                            }
1067
                        }
1068
1069
                        //check if parent folder is personal
1070
                        $data = DB::queryfirstrow(
1071
                            "SELECT personal_folder
1072
                            FROM ".prefix_table("nested_tree")."
1073
                            WHERE id = %i",
1074
                            $params[2]
1075
                        );
1076
                        if ($data['personal_folder'] === "1") {
1077
                            $isPersonal = 1;
1078
                        } else {
1079
                            if ($params[4] === 1) {
1080
                                $isPersonal = 1;
1081
                            } else {
1082
                                $isPersonal = 0;
1083
                            }
1084
1085
                            // get complexity level for this folder
1086
                            $data = DB::queryfirstrow(
1087
                                "SELECT valeur
1088
                                FROM ".prefix_table("misc")."
1089
                                WHERE intitule = %i AND type = %s",
1090
                                $params[2],
1091
                                "complex"
1092
                            );
1093
                            if (intval($params[1]) < intval($data['valeur'])) {
1094
                                rest_error('COMPLEXICITY_LEVEL_NOT_REACHED');
1095
                            }
1096
                        }
1097
1098
                        try {
1099
                            //create folder
1100
                            DB::insert(
1101
                                prefix_table("nested_tree"),
1102
                                array(
1103
                                    'parent_id' => $params[2],
1104
                                    'title' => $params[0],
1105
                                    'personal_folder' => $isPersonal,
1106
                                    'renewal_period' => $params[3],
1107
                                    'bloquer_creation' => '0',
1108
                                    'bloquer_modification' => '0'
1109
                                )
1110
                            );
1111
                            $newId = DB::insertId();
1112
1113
                            //Add complexity
1114
                            DB::insert(
1115
                                prefix_table("misc"),
1116
                                array(
1117
                                    'type' => 'complex',
1118
                                    'intitule' => $newId,
1119
                                    'valeur' => $params[1]
1120
                                )
1121
                            );
1122
1123
                            // Run nested tree update
1124
                            require_once '../sources/SplClassLoader.php';
1125
                            $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
1126
                            $tree->register();
1127
                            $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
1128
                            $tree->rebuild();
1129
1130
                            // We need to allocate the same access rights as the parent
1131
                            // We will considere that if created as root then its rights must be set through the GUI
1132
                            $ret = DB::query(
1133
                                "SELECT role_id, type
1134
                                FROM ".prefix_table("roles_values")."
1135
                                WHERE folder_id = %i",
1136
                                $params[2]
1137
                            );
1138
                            foreach ($ret as $entry) {
1139
                                DB::insert(
1140
                                    prefix_table("roles_values"),
1141
                                    array(
1142
                                        'role_id' => $entry['role_id'],
1143
                                        'folder_id' => $newId,
1144
                                        'type' => $entry['type']
1145
                                    )
1146
                                );
1147
                            }
1148
1149
                            echo '{"status":"folder created" , "new_folder_id":"'.$newId.'"}';
1150
                        } catch (PDOException $ex) {
1151
                            echo '<br />'.$ex->getMessage();
1152
                        }
1153
                    } else {
1154
                        rest_error('NO_DATA_EXIST');
1155
                    }
1156
                } else {
1157
                    rest_error('SET_NO_DATA');
1158
                }
1159
            }
1160
        } elseif ($GLOBALS['request'][0] == "update") {
1161
            /*
1162
            * Section dedicated for UPDATING
1163
            */
1164
            if ($GLOBALS['request'][1] == "item") {
1165
                /*
1166
                * 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>
1167
                */
1168
                if ($GLOBALS['request'][2] !== "" && is_numeric($GLOBALS['request'][2])) {
1169
                    // get sent parameters
1170
                    $params = explode(';', base64_decode($GLOBALS['request'][3]));
1171
1172
                    if (!empty($params[0]) && !empty($params[1]) && !empty($params[3])) {
1173
                        // Check length
1174
                        if (strlen($params[1]) > 50) {
1175
                            rest_error('PASSWORDTOOLONG');
1176
                        }
1177
1178
                        // Check Folder ID
1179
                        DB::query(
1180
                            "SELECT *
1181
                            FROM ".prefix_table("nested_tree")."
1182
                            WHERE id = %i",
1183
                            $params[3]
1184
                        );
1185
                        $counter = DB::count();
1186
                        if ($counter == 0) {
1187
                            rest_error('NOSUCHFOLDER');
1188
                        }
1189
1190
                        // check if item exists
1191
                        DB::query(
1192
                            "SELECT *
1193
                            FROM ".prefix_table("items")."
1194
                            WHERE id = %i",
1195
                            $GLOBALS['request'][2]
1196
                        );
1197
                        $counter = DB::count();
1198
                        if ($counter > 0) {
1199
                            // encrypt pwd
1200
                            $encrypt = cryption(
1201
                                $params[1],
1202
                                "",
1203
                                "encrypt"
1204
                            );
1205
                            if (empty($encrypt['string'])) {
1206
                                rest_error('PASSWORDEMPTY');
1207
                            }
1208
1209
                            // ADD item
1210
                            try {
1211
                                DB::update(
1212
                                    prefix_table("items"),
1213
                                    array(
1214
                                        "label" => $params[0],
1215
                                        "description" => $params[2],
1216
                                        'pw' => $encrypt['string'],
1217
                                        'pw_iv' => '',
1218
                                        "email" => $params[5],
1219
                                        "url" => $params[6],
1220
                                        "id_tree" => intval($params[3]),
1221
                                        "login" => $params[4],
1222
                                        "anyone_can_modify" => intval($params[8])
1223
                                    ),
1224
                                    "id = %i",
1225
                                    $GLOBALS['request'][2]
1226
                                );
1227
1228
                                // log
1229
                                DB::insert(
1230
                                    prefix_table("log_items"),
1231
                                    array(
1232
                                        "id_item" => $GLOBALS['request'][2],
1233
                                        "date" => time(),
1234
                                        "id_user" => API_USER_ID,
1235
                                        "action" => "at_modification"
1236
                                    )
1237
                                );
1238
1239
                                // Add tags
1240
                                $tags = explode(' ', $params[7]);
1241
                                foreach ((array) $tags as $tag) {
1242
                                    if (!empty($tag)) {
1243
                                        // check if already exists
1244
                                        DB::query(
1245
                                            "SELECT *
1246
                                            FROM ".prefix_table("tags")."
1247
                                            WHERE tag = %s AND item_id = %i",
1248
                                            strtolower($tag),
1249
                                            $GLOBALS['request'][2]
1250
                                        );
1251
                                        $counter = DB::count();
1252
                                        if ($counter === 0) {
1253
                                            DB::insert(
1254
                                                prefix_table("tags"),
1255
                                                array(
1256
                                                    "item_id" => $GLOBALS['request'][2],
1257
                                                    "tag" => strtolower($tag)
1258
                                                )
1259
                                            );
1260
                                        }
1261
                                    }
1262
                                }
1263
1264
                                // Update CACHE table
1265
                                DB::update(
1266
                                    prefix_table("cache"),
1267
                                    array(
1268
                                        "label" => $params[0],
1269
                                        "description" => $params[2],
1270
                                        "tags" => $params[7],
1271
                                        "id_tree" => intval($params[3]),
1272
                                        "perso" => "0",
1273
                                        "restricted_to" => "",
1274
                                        "login" => $params[4],
1275
                                        "folder" => "",
1276
                                        "author" => API_USER_ID,
1277
                                        "renewal_period" => "0",
1278
                                        "timestamp" => time(),
1279
                                        "url" => $params[6],
1280
                                    ),
1281
                                    "id = %i",
1282
                                    $GLOBALS['request'][2]
1283
                                );
1284
1285
                                echo '{"status":"item updated"}';
1286
                            } catch (PDOException $ex) {
1287
                                echo '<br />'.$ex->getMessage();
1288
                            }
1289
                        } else {
1290
                            rest_error('NO_DATA_EXIST');
1291
                        }
1292
                    } else {
1293
                        rest_error('ITEMMISSINGDATA');
1294
                    }
1295
                } else {
1296
                    rest_error('NO_ITEM');
1297
                }
1298
            } elseif ($GLOBALS['request'][1] == "folder") {
1299
            /*
1300
            * UPDATING A FOLDER
1301
            * <url to teampass>/api/index.php/update/folder/<folder_id>/<title>;<complexity_level>;<renewal_period>?apikey=<valid api key>
1302
            */
1303
                if ($GLOBALS['request'][2] !== "" && is_numeric($GLOBALS['request'][2])) {
1304
                    // get sent parameters
1305
                    $params = explode(';', base64_decode($GLOBALS['request'][3]));
1306
1307
                    if (!empty($params[0])) {
1308
                        if ($params[1] < 0) {
1309
                            rest_error('NO_DATA_EXIST');
1310
                        }
1311
                        if (empty($params[2])) {
1312
                            $params[2] = 0;
1313
                        }
1314
1315
                        // check if folder exists and get folder data
1316
                        $data_folder = DB::queryfirstrow(
1317
                            "SELECT *
1318
                            FROM ".prefix_table("nested_tree")."
1319
                            WHERE id = %s",
1320
                            $GLOBALS['request'][2]
1321
                        );
1322
                        $counter = DB::count();
1323
                        if ($counter === 0) {
1324
                            rest_error('NO_DATA_EXIST');
1325
                        }
1326
1327
                        //Check if title doesn't contains html codes
1328
                        if (preg_match_all("|<[^>]+>(.*)</[^>]+>|U", $params[0], $out)) {
1329
                            rest_error('HTML_CODES_NOT_ALLOWED');
1330
                        }
1331
1332
                        // check if title is numeric
1333
                        if (is_numeric($params[0]) === true) {
1334
                            rest_error('TITLE_ONLY_WITH_NUMBERS');
1335
                        }
1336
1337
                        // get complexity level for this folder
1338
                        $data = DB::queryfirstrow(
1339
                            "SELECT valeur
1340
                            FROM ".prefix_table("misc")."
1341
                            WHERE intitule = %i AND type = %s",
1342
                            $data_folder['parent_id'],
1343
                            "complex"
1344
                        );
1345
                        if (intval($params[1]) < intval($data['valeur'])) {
1346
                            rest_error('COMPLEXICITY_LEVEL_NOT_REACHED');
1347
                        }
1348
1349
                        try {
1350
                            DB::update(
1351
                                prefix_table("nested_tree"),
1352
                                array(
1353
                                    'parent_id' => $data_folder['parent_id'],
1354
                                    'title' => $params[0],
1355
                                    'personal_folder' => 0,
1356
                                    'renewal_period' => $params[2],
1357
                                    'bloquer_creation' => '0',
1358
                                    'bloquer_modification' => '0'
1359
                                ),
1360
                                "id = %i",
1361
                                $GLOBALS['request'][2]
1362
                            );
1363
1364
                            //Add complexity
1365
                            DB::update(
1366
                                prefix_table("misc"),
1367
                                array(
1368
                                    'valeur' => $params[1]
1369
                                ),
1370
                                "intitule = %s AND type = %s",
1371
                                $GLOBALS['request'][2],
1372
                                "complex"
1373
                            );
1374
1375
                            // Run nested tree update
1376
                            require_once '../sources/SplClassLoader.php';
1377
                            $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
1378
                            $tree->register();
1379
                            $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
1380
                            $tree->rebuild();
1381
1382
                            echo '{"status":"folder updated"}';
1383
                        } catch (PDOException $ex) {
1384
                            echo '<br />'.$ex->getMessage();
1385
                        }
1386
                    } else {
1387
                        rest_error('ITEMMISSINGDATA');
1388
                    }
1389
                } else {
1390
                    rest_error('NO_ITEM');
1391
                }
1392
            } elseif ($GLOBALS['request'][1] == "user") {
1393
            /*
1394
             * Case where a user has to be updated
1395
             *
1396
             * Expected call format: .../api/index.php/updated/user/<LOGIN>;<NAME>;<LASTNAME>;<PASSWORD>;<EMAIL>;<ADMINISTRATEDBY>;<READ_ONLY>;<ROLE1,ROLE2,...>;<IS_ADMIN>;<ISMANAGER>;<PERSONAL_FOLDER>?apikey=<VALID API KEY>
1397
             * with:
1398
             * for READ_ONLY, IS_ADMIN, IS_MANAGER, PERSONAL_FOLDER, accepted value is 1 for TRUE and 0 for FALSE
1399
             * for ADMINISTRATEDBY and ROLE1, accepted value is the real label (not the IDs)
1400
             *
1401
             * Example: /api/index.php/update/user/U4;Nils;Laumaille;test;[email protected];Users;0;Managers,Users;0;1;1?apikey=sae6iekahxiseL3viShoo0chahc1ievei8aequi
1402
             *
1403
             */
1404
1405
                // get user definition
1406
                $array_user = explode(';', base64_decode($GLOBALS['request'][2]));
1407
                if (count($array_user) != 11) {
1408
                    rest_error('USERBADDEFINITION');
1409
                }
1410
1411
                $login = $array_user[0];
1412
                $name = $array_user[1];
1413
                $lastname = $array_user[2];
1414
                $password = $array_user[3];
1415
                $email = $array_user[4];
1416
                $adminby = urldecode($array_user[5]);
1417
                $isreadonly = urldecode($array_user[6]);
1418
                $roles = urldecode($array_user[7]);
1419
                $isadmin = $array_user[8];
1420
                $ismanager = $array_user[9];
1421
                $haspf = $array_user[10];
1422
1423
                // Empty user
1424
                if (mysqli_escape_string($link, htmlspecialchars_decode($login)) == "") {
1425
                    rest_error('USERLOGINEMPTY');
1426
                }
1427
                // Check if user already exists
1428
                $data = DB::query(
1429
                    "SELECT id, fonction_id, groupes_interdits, groupes_visibles, personal_folder
1430
                    FROM ".prefix_table("users")."
1431
                    WHERE login LIKE %ss",
1432
                    mysqli_escape_string($link, stripslashes($login))
1433
                );
1434
1435
                if (DB::count() === 1) {
1436
                    try {
1437
                        // find AdminRole code in DB
1438
                        $resRole = DB::queryFirstRow(
1439
                            "SELECT id
1440
                            FROM ".prefix_table("roles_title")."
1441
                            WHERE title LIKE %ss",
1442
                            mysqli_escape_string($link, stripslashes($adminby))
1443
                        );
1444
1445
1446
                        // get default language
1447
                        $lang = DB::queryFirstRow(
1448
                            "SELECT `valeur`
1449
                            FROM ".prefix_table("misc")."
1450
                            WHERE type = %s AND intitule = %s",
1451
                            "admin",
1452
                            "default_language"
1453
                        );
1454
1455
                        // prepare roles list
1456
                        $rolesList = "";
1457
                        foreach (explode(',', $roles) as $role) {
1458
                            $tmp = DB::queryFirstRow(
1459
                                "SELECT `id`
1460
                                FROM ".prefix_table("roles_title")."
1461
                                WHERE title = %s",
1462
                                $role
1463
                            );
1464
                            if (empty($rolesList)) {
1465
                                $rolesList = $tmp['id'];
1466
                            } else {
1467
                                $rolesList .= ";".$tmp['id'];
1468
                            }
1469
                        }
1470
1471
                        // Update user in DB
1472
                        DB::update(
1473
                            prefix_table("users"),
1474
                            array(
1475
                                'login' => $login,
1476
                                'name' => $name,
1477
                                'lastname' => $lastname,
1478
                                'pw' => bCrypt(stringUtf8Decode($password), COST),
1479
                                'email' => $email,
1480
                                'admin' => intval($isadmin),
1481
                                'gestionnaire' => intval($ismanager),
1482
                                'read_only' => intval($isreadonly),
1483
                                'personal_folder' => intval($haspf),
1484
                                'user_language' => $lang['valeur'],
1485
                                'fonction_id' => $rolesList,
1486
                                'groupes_interdits' => '0',
1487
                                'groupes_visibles' => '0',
1488
                                'isAdministratedByRole' => empty($resRole) ? '0' : $resRole['id']
1489
                            ),
1490
                            "id = %i",
1491
                            $data['id']
1492
                        );
1493
1494
                        // Create personnal folder
1495
                        if (intval($haspf) === 1) {
1496
                            DB::query(
1497
                                "SELECT id
1498
                                FROM ".prefix_table("nested_tree")."
1499
                                WHERE title = %s",
1500
                                $data['id']
1501
                            );
1502
                            if (DB::count() === 0) {
1503
                                DB::insert(
1504
                                    prefix_table("nested_tree"),
1505
                                    array(
1506
                                        'parent_id' => '0',
1507
                                        'title' => $data['id'],
1508
                                        'bloquer_creation' => '0',
1509
                                        'bloquer_modification' => '0',
1510
                                        'personal_folder' => '1'
1511
                                    )
1512
                                );
1513
                            }
1514
                        }
1515
1516
                        // load settings
1517
                        loadSettings();
1518
1519
                        // update LOG
1520
                        logEvents('user_mngt', 'at_user_updated', 'api - '.$GLOBALS['apikey'], $data['id'], "");
1521
1522
                        echo '{"status":"user added"}';
1523
                    } catch (PDOException $ex) {
1524
                        echo '<br />'.$ex->getMessage();
1525
                    }
1526
                } else {
1527
                    rest_error('USER_NOT_EXISTS');
1528
                }
1529
            }
1530
        } elseif ($GLOBALS['request'][0] == "auth") {
1531
            /*
1532
            ** FOR SECURITY PURPOSE, it is mandatory to use SSL to connect your teampass instance. The user password is not encrypted!
1533
            **
1534
            **
1535
            ** Expected call format: .../api/index.php/auth/<PROTOCOL>/<URL>/<login>/<password>?apikey=<VALID API KEY>
1536
            ** Example: https://127.0.0.1/teampass/api/index.php/auth/http/www.zadig-tge.adp.com/U1/test/76?apikey=chahthait5Aidood6johh6Avufieb6ohpaixain
1537
            ** RESTRICTIONS:
1538
            **              - <PROTOCOL>        ==> http|https|ftp|...
1539
            **              - <URL>             ==> encode URL without protocol (example: http://www.teampass.net becomes www.teampass.net)
1540
            **              - <login>           ==> user's login
1541
            **              - <password>        ==> currently clear password
1542
            **
1543
            ** RETURNED ANSWER:
1544
            **              - format sent back is JSON
1545
            **              - Example: {"<item_id>":{"label":"<pass#1>","login":"<login#1>","pw":"<pwd#1>"},"<item_id>":{"label":"<pass#2>","login":"<login#2>","pw":"<pwd#2>"}}
1546
            **
1547
            */
1548
            // get user credentials
1549
            if (isset($GLOBALS['request'][3]) && isset($GLOBALS['request'][4])) {
1550
                // get url
1551
                if (isset($GLOBALS['request'][1]) && isset($GLOBALS['request'][2])) {
1552
                    // is user granted?
1553
                    $userData = DB::queryFirstRow(
1554
                        "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id`
1555
                        FROM ".prefix_table("users")."
1556
                        WHERE login = %s",
1557
                        $GLOBALS['request'][3]
1558
                    );
1559
1560
                    // load passwordLib library
1561
                    require_once '../sources/SplClassLoader.php';
1562
                    $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
1563
                    $pwdlib->register();
1564
                    $pwdlib = new PasswordLib\PasswordLib();
1565
1566
                    if ($pwdlib->verifyPasswordHash($GLOBALS['request'][4], $userData['pw']) === true) {
1567
                        // define the restriction of "id_tree" of this user
1568
                        //db::debugMode(true);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1569
                        $userDef = DB::queryOneColumn(
1570
                            'folder_id',
1571
                            "SELECT DISTINCT folder_id
1572
                            FROM ".prefix_table("roles_values")."
1573
                            WHERE type IN ('R', 'W', 'ND', 'NE', 'NDNE', 'NEND') ",
1574
                            empty($userData['groupes_interdits']) ? "" : "
1575
                            AND folder_id NOT IN (".str_replace(";", ",", $userData['groupes_interdits']).")",
1576
                            "AND role_id IN %ls
1577
                            GROUP BY folder_id",
1578
                            explode(";", $userData['groupes_interdits'])
1579
                        );
1580
                        // complete with "groupes_visibles"
1581
                        foreach (explode(";", $userData['groupes_visibles']) as $v) {
1582
                            array_push($userDef, $v);
1583
                        }
1584
1585
                        // find the item associated to the url
1586
                        $response = DB::query(
1587
                            "SELECT id, label, login, pw, pw_iv, id_tree, restricted_to
1588
                            FROM ".prefix_table("items")."
1589
                            WHERE url LIKE %s
1590
                            AND id_tree IN (".implode(",", $userDef).")
1591
                            ORDER BY id DESC",
1592
                            $GLOBALS['request'][1]."://".urldecode($GLOBALS['request'][2].'%')
1593
                        );
1594
                        $counter = DB::count();
1595
1596
                        if ($counter > 0) {
1597
                            $json = "";
1598
                            foreach ($response as $data) {
1599
                                // check if item visible
1600
                                if (empty($data['restricted_to']) ||
1601
                                    ($data['restricted_to'] != "" && in_array($userData['id'], explode(";", $data['restricted_to'])))
1602
                                ) {
1603
                                    // prepare export
1604
                                    $json[$data['id']]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
1605
                                    $json[$data['id']]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
1606
                                    $crypt_pw = cryption(
1607
                                        $data['pw'],
1608
                                        "",
1609
                                        "decrypt"
1610
                                    );
1611
                                    $json[$data['id']]['pw'] = $crypt_pw['string'];
1612
                                }
1613
                            }
1614
                            // prepare answer. If no access then inform
1615
                            if (empty($json)) {
0 ignored issues
show
introduced by
The condition empty($json) is always true.
Loading history...
1616
                                rest_error('AUTH_NO_DATA');
1617
                            } else {
1618
                                echo json_encode($json);
1619
                            }
1620
                        } else {
1621
                            rest_error('NO_DATA_EXIST');
1622
                        }
1623
                    } else {
1624
                        rest_error('AUTH_NOT_GRANTED');
1625
                    }
1626
                } else {
1627
                    rest_error('AUTH_NO_URL');
1628
                }
1629
            } else {
1630
                rest_error('AUTH_NO_IDENTIFIER');
1631
            }
1632
        } elseif ($GLOBALS['request'][0] === "auth_tpc") {
1633
            /*
1634
            ** TO BE USED ONLY BY TEAMPASS-CONNECT
1635
            **
1636
            */
1637
            // get user credentials
1638
            if (isset($GLOBALS['request'][1])) {
1639
                // Get passed variables
1640
                $passedData = explode(';', base64_decode($GLOBALS['request'][1]));
1641
                if (count($passedData) === 4) {
1642
                    $tpc_url = $passedData[0];
1643
                    $user_login = $passedData[1];
1644
                    $user_pwd = $passedData[2];
1645
                    $user_saltkey = $passedData[3];
1646
1647
                    // get url
1648
                    if (isset($tpc_url)) {
1649
                        // is user granted?
1650
                        $userData = DB::queryFirstRow(
1651
                            "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id`, `encrypted_psk`
1652
                            FROM ".prefix_table("users")."
1653
                            WHERE login = %s",
1654
                            $user_login
1655
                        );
1656
1657
                        // Check if user exists
1658
                        if (empty($userData['id']) === true) {
1659
                            rest_error('AUTH_NOT_GRANTED');
1660
                        }
1661
1662
                        // check if psk is correct.
1663
                        if (empty($user_saltkey) === false) {
1664
                            $user_saltkey = defuse_validate_personal_key(
1665
                                $user_saltkey,
1666
                                $userData['encrypted_psk']
1667
                            );
1668
                            if (strpos($user_saltkey, "Error ") !== false) {
1669
                                // error
1670
                                rest_error('AUTH_PSK_ERROR');
1671
                            }
1672
                        }
1673
1674
                        // load passwordLib library
1675
                        require_once '../sources/SplClassLoader.php';
1676
                        $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
1677
                        $pwdlib->register();
1678
                        $pwdlib = new PasswordLib\PasswordLib();
1679
1680
                        if ($pwdlib->verifyPasswordHash($user_pwd, $userData['pw']) === true) {
1681
                            // Manage the case TPC asks for user identification
1682
                            if ($tpc_url === 'identify_user') {
1683
                                echo json_encode(array('err' => '', 'status' => 'USER_GRANTED'));
1684
                                return false;
1685
                            }
1686
1687
                            // define the restriction of "id_tree" of this user
1688
                            //db::debugMode(true);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1689
                            $userDef = DB::queryOneColumn(
1690
                                'folder_id',
1691
                                "SELECT DISTINCT folder_id
1692
                                FROM ".prefix_table("roles_values")."
1693
                                WHERE type IN ('R', 'W', 'ND', 'NE', 'NDNE', 'NEND') ",
1694
                                empty($userData['groupes_interdits']) ? "" : "AND folder_id NOT IN (".str_replace(";", ",", $userData['groupes_interdits']).")",
1695
                                "AND role_id IN %ls
1696
                                GROUP BY folder_id",
1697
                                explode(";", $userData['groupes_interdits'])
1698
                            );
1699
                            // complete with "groupes_visibles"
1700
                            foreach (explode(";", $userData['groupes_visibles']) as $v) {
1701
                                array_push($userDef, $v);
1702
                            }
1703
1704
                            // add PF
1705
                            $userpf = DB::queryFirstRow(
1706
                                "SELECT `id` FROM ".prefix_table("nested_tree")." WHERE title = %s",
1707
                                $userData['id']
1708
                            );
1709
                            array_push($userDef, $userpf['id']);
1710
1711
                            // Parse provided URL
1712
                            $url_scheme = parse_url($tpc_url, PHP_URL_SCHEME);
1713
                            $url_post = parse_url($tpc_url, PHP_URL_HOST);
1714
1715
                            // find the item associated to the url
1716
                            //db::debugmode(true);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1717
                            $response = DB::query(
1718
                                "SELECT id, label, login, pw, pw_iv, id_tree, restricted_to, perso
1719
                                FROM ".prefix_table("items")."
1720
                                WHERE url LIKE %s
1721
                                AND id_tree IN (".implode(",", array_filter($userDef)).")
1722
                                AND inactif = %i
1723
                                ORDER BY id DESC",
1724
                                $url_scheme.'://'.$url_post.'%',
1725
                                0
1726
                            );
1727
                            $counter = DB::count();
1728
1729
                            if ($counter > 0) {
1730
                                $json = [];
1731
                                foreach ($response as $data) {
1732
                                    // check if item visible
1733
                                    if (empty($data['restricted_to']) ||
1734
                                        ($data['restricted_to'] != "" && in_array($userData['id'], explode(";", $data['restricted_to'])))
1735
                                    ) {
1736
                                        // prepare export
1737
                                        $json[$data['id']]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
1738
                                        $json[$data['id']]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
1739
                                        if ($data['perso'] === "0") {
1740
                                            $crypt_pw = cryption(
1741
                                                $data['pw'],
1742
                                                "",
1743
                                                "decrypt"
1744
                                            );
1745
                                        } elseif (empty($user_saltkey)) {
1746
                                            $crypt_pw['string'] = "no_psk";
1747
                                        } else {
1748
                                            $crypt_pw = cryption(
1749
                                                $data['pw'],
1750
                                                $user_saltkey,
1751
                                                "decrypt"
1752
                                            );
1753
                                        }
1754
                                        $json[$data['id']]['pw'] = mb_detect_encoding($crypt_pw['string'], 'UTF-8', true) ? $crypt_pw['string'] : "not_utf8";
1755
                                        $json[$data['id']]['perso'] = $data['perso'];
1756
                                        $json[$data['id']]['domain'] = $url_scheme.'://'.$url_post;
1757
                                        $json[$data['id']]['id'] = $data['id'];
1758
                                    }
1759
                                }
1760
                                // prepare answer. If no access then inform
1761
                                if (empty($json)) {
1762
                                    rest_error('AUTH_NO_DATA');
1763
                                } else {
1764
                                    echo json_encode($json);
1765
                                }
1766
                            } else {
1767
                                rest_error('NO_DATA_EXIST');
1768
                            }
1769
                        } else {
1770
                            rest_error('AUTH_NOT_GRANTED');
1771
                        }
1772
                    } else {
1773
                        rest_error('AUTH_NO_URL');
1774
                    }
1775
                } else {
1776
                  rest_error('AUTH_NO_IDENTIFIER');
1777
                }
1778
            } else {
1779
                rest_error('AUTH_NO_IDENTIFIER');
1780
            }
1781
        } else if ($GLOBALS['request'][0] === "tpc_find") {
1782
            // get user credentials
1783
            if (isset($GLOBALS['request'][1])) {
1784
                // Get passed variables
1785
                $passedData = explode(';', base64_decode($GLOBALS['request'][1]));
1786
                $tpc_phrase = $passedData[0];
1787
                $user_login = $passedData[1];
1788
                $user_pwd = $passedData[2];
1789
                $user_saltkey = $passedData[3];
1790
1791
                // get url
1792
                if (isset($tpc_phrase)) {
1793
                    // is user granted?
1794
                    //db::debugMode(true);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1795
                    $userData = DB::queryFirstRow(
1796
                        "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id`, `encrypted_psk`
1797
                        FROM ".prefix_table("users")."
1798
                        WHERE login = %s",
1799
                        $user_login
1800
                    );
1801
1802
                    // check if psk is correct.
1803
                    if (empty($user_saltkey) === false) {
1804
                        $user_saltkey = defuse_validate_personal_key(
1805
                            $user_saltkey,
1806
                            $userData['encrypted_psk']
1807
                        );
1808
                        if (strpos($user_saltkey, "Error ") !== false) {
1809
                            // error
1810
                            rest_error('AUTH_PSK_ERROR');
1811
                        }
1812
                    }
1813
1814
                    // load passwordLib library
1815
                    require_once '../sources/SplClassLoader.php';
1816
                    $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
1817
                    $pwdlib->register();
1818
                    $pwdlib = new PasswordLib\PasswordLib();
1819
1820
                    if ($pwdlib->verifyPasswordHash($user_pwd, $userData['pw']) === true) {
1821
                        // define the restriction of "id_tree" of this user
1822
                        //db::debugMode(true);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1823
                        $userDef = DB::queryOneColumn(
1824
                            'folder_id',
1825
                            "SELECT DISTINCT folder_id
1826
                            FROM ".prefix_table("roles_values")."
1827
                            WHERE type IN ('R', 'W', 'ND', 'NE', 'NDNE', 'NEND') ",
1828
                            empty($userData['groupes_interdits']) ? "" : "AND folder_id NOT IN (".str_replace(";", ",", $userData['groupes_interdits']).")",
1829
                            "AND role_id IN %ls
1830
                            GROUP BY folder_id",
1831
                            explode(";", $userData['groupes_interdits'])
1832
                        );
1833
                        // complete with "groupes_visibles"
1834
                        foreach (explode(";", $userData['groupes_visibles']) as $v) {
1835
                            array_push($userDef, $v);
1836
                        }
1837
1838
                        // add PF
1839
                        $userpf = DB::queryFirstRow(
1840
                            "SELECT `id` FROM ".prefix_table("nested_tree")." WHERE title = %s",
1841
                            $userData['id']
1842
                        );
1843
                        array_push($userDef, $userpf['id']);
1844
1845
                        // Clean phrase
1846
                        if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $tpc_phrase, $result)) {
1847
                            rest_error('ITEM_MALFORMED');
1848
                        } elseif (empty($tpc_phrase)) {
1849
                            rest_error('MALFORMED');
1850
                        }
1851
1852
                        // find the item associated to the url
1853
                        //db::debugmode(true);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1854
                        $response = DB::query(
1855
                            "SELECT id, label, login, pw, pw_iv, id_tree, restricted_to, perso, url
1856
                            FROM ".prefix_table("items")."
1857
                            WHERE (url LIKE %s OR label LIKE %s)
1858
                            AND id_tree IN (".implode(",", array_filter($userDef)).")
1859
                            AND inactif = %i
1860
                            ORDER BY id DESC",
1861
                            $tpc_phrase.'%',
1862
                            $tpc_phrase.'%',
1863
                            0
1864
                        );
1865
                        $counter = DB::count();
1866
1867
                        if ($counter > 0) {
1868
                            $json = [];
1869
                            $i = 0;
1870
                            foreach ($response as $data) {
1871
                                // check if item visible
1872
                                if (empty($data['restricted_to']) ||
1873
                                    ($data['restricted_to'] != "" && in_array($userData['id'], explode(";", $data['restricted_to'])))
1874
                                ) {
1875
                                    // prepare export
1876
                                    $json[$i]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
1877
                                    $json[$i]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
1878
                                    if ($data['perso'] === "0") {
1879
                                        $crypt_pw = cryption(
1880
                                            $data['pw'],
1881
                                            "",
1882
                                            "decrypt"
1883
                                        );
1884
                                    } elseif (empty($user_saltkey)) {
1885
                                        $crypt_pw['string'] = "no_psk";
1886
                                    } else {
1887
                                        $crypt_pw = cryption(
1888
                                            $data['pw'],
1889
                                            $user_saltkey,
1890
                                            "decrypt"
1891
                                        );
1892
                                    }
1893
                                    $json[$i]['pw'] = mb_detect_encoding($crypt_pw['string'], 'UTF-8', true) ? $crypt_pw['string'] : "not_utf8";
1894
                                    $json[$i]['perso'] = $data['perso'];
1895
                                    $json[$i]['domain'] = $data['url'];
1896
                                    $json[$i]['id'] = $data['id'];
1897
1898
                                    $i++;
1899
                                }
1900
                            }
1901
                            // prepare answer. If no access then inform
1902
                            if (empty($json)) {
1903
                                rest_error('AUTH_NO_DATA');
1904
                            } else {
1905
                                echo json_encode($json);
1906
                            }
1907
                        } else {
1908
                            rest_error('NO_DATA_EXIST');
1909
                        }
1910
                    } else {
1911
                        rest_error('AUTH_NOT_GRANTED');
1912
                    }
1913
                } else {
1914
                    rest_error('AUTH_NO_URL');
1915
                }
1916
            } else {
1917
                rest_error('AUTH_NO_IDENTIFIER');
1918
            }
1919
        } elseif ($GLOBALS['request'][0] == "tpc_userfolders") {
1920
            /*
1921
            * READ USER FOLDERS
1922
            * Sends back a list of folders
1923
            */
1924
            // get user credentials
1925
            if (isset($GLOBALS['request'][1])) {
1926
                // Get passed variables
1927
                $passedData = explode(';', base64_decode($GLOBALS['request'][1]));
1928
                $user_login = $passedData[0];
1929
                $user_pwd = $passedData[1];
0 ignored issues
show
Unused Code introduced by
The assignment to $user_pwd is dead and can be removed.
Loading history...
1930
                $user_saltkey = $passedData[2];
0 ignored issues
show
Unused Code introduced by
The assignment to $user_saltkey is dead and can be removed.
Loading history...
1931
1932
                $json = [];
1933
                $inc = 0;
1934
                if (strcmp($user_login, "admin") == 0) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
1935
                    // forbid admin access
1936
                }
1937
                $response = DB::query(
1938
                    "SELECT id AS user_id, fonction_id
1939
                    FROM ".prefix_table("users")."
1940
                    WHERE login = %s",
1941
                    $user_login
1942
                );
1943
                if (count($response) === 0) {
1944
                    rest_error('USER_NOT_EXISTS ');
1945
                }
1946
                foreach ($response as $data) {
1947
                    $role_str = $data['fonction_id'];
1948
                    $user_id = $data['user_id'];
1949
                }
1950
1951
                // Build tree
1952
                require_once '../sources/SplClassLoader.php';
1953
                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
1954
                $tree->register();
1955
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
1956
                $tree->rebuild();
1957
1958
                // If personal exists then get list of PF
1959
                $persoFld = DB::queryfirstrow(
1960
                    "SELECT id, title, nlevel
1961
                    FROM ".prefix_table("nested_tree")."
1962
                    WHERE title = %s",
1963
                    $user_id
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user_id seems to be defined by a foreach iteration on line 1946. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1964
                );
1965
                if (empty($persoFld['id']) === false) {
1966
                    // Store main PF
1967
                    $json[$inc]['id'] = $persoFld['id'];
1968
                    $json[$inc]['title'] = $user_login;
1969
                    $json[$inc]['level'] = $persoFld['nlevel'];
1970
                    $json[$inc]['access_type'] = "W";
1971
                    $inc++;
1972
1973
                    // get all descendants
1974
                    $ids = $tree->getDescendants($persoFld['id'], false, false);
1975
                    foreach ($ids as $ident) {
1976
                        // Do query to get folder info
1977
                        $fldInfo = DB::queryfirstrow(
1978
                            "SELECT title, nlevel
1979
                            FROM ".prefix_table("nested_tree")."
1980
                            WHERE id = %i",
1981
                            $ident->id
1982
                        );
1983
1984
                        // Store info
1985
                        $json[$inc]['id'] = $ident->id;
1986
                        $json[$inc]['title'] = $fldInfo['title'];
1987
                        $json[$inc]['level'] = $fldInfo['nlevel'];
1988
                        $json[$inc]['personal'] = "1";
1989
                        $json[$inc]['access_type'] = "W";
1990
                        $inc++;
1991
                    }
1992
                }
1993
1994
                $folder_arr = array();
1995
                $roles = explode(";", $role_str);
1996
                foreach ($roles as $role) {
1997
                    $response = DB::query(
1998
                        "SELECT folder_id, type
1999
                        FROM ".prefix_table("roles_values")."
2000
                        WHERE role_id = %i",
2001
                        $role
2002
                    );
2003
                    foreach ($response as $data) {
2004
                        $folder_id = $data['folder_id'];
2005
                        if (array_key_exists($folder_id, $folder_arr) === false) {
2006
                            array_push($folder_arr, $folder_id);
2007
2008
                            $response2 = DB::queryFirstRow(
2009
                                "SELECT title, nlevel
2010
                                FROM ".prefix_table("nested_tree")."
2011
                                WHERE id = %i",
2012
                                $folder_id
2013
                            );
2014
2015
                            if (empty($response2['title']) === false) {
2016
                                // get all descendants
2017
                                $ids = $tree->getDescendants($folder_id, true, false);
2018
                                foreach ($ids as $ident) {
2019
                                    if (array_key_exists($ident->id, $folder_arr) === false) {
2020
                                        array_push($folder_arr, $ident->id);
2021
                                        // Do query to get folder info
2022
                                        $fldInfo = DB::queryfirstrow(
2023
                                            "SELECT title, nlevel
2024
                                            FROM ".prefix_table("nested_tree")."
2025
                                            WHERE id = %i",
2026
                                            $ident->id
2027
                                        );
2028
2029
                                        // Store info
2030
                                        $json[$inc]['id'] = $ident->id;
2031
                                        $json[$inc]['title'] = $fldInfo['title'];
2032
                                        $json[$inc]['level'] = $fldInfo['nlevel'];
2033
                                        $json[$inc]['personal'] = "0";
2034
                                        $json[$inc]['access_type'] = "W";
2035
                                        $inc++;
2036
                                    }
2037
                                }
2038
                                /*$json[$inc]['id'] = $folder_id;
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
2039
                                $json[$inc]['title'] = $response2['title'];
2040
                                $json[$inc]['level'] = $response2['nlevel'];
2041
                                $json[$inc]['access_type'] = $data['type'];
2042
                                $json[$inc]['personal'] = "0";
2043
                                $inc++;*/
2044
                            }
2045
                        }
2046
                    }
2047
                }
2048
                // prepare answer. If no access then inform
2049
                if (empty($json)) {
2050
                    rest_error('AUTH_NO_DATA');
2051
                } else {
2052
                    echo json_encode($json);
2053
                }
2054
            }
2055
        } elseif ($GLOBALS['request'][0] == "set") {
2056
            /*
2057
             * Expected call format: .../api/index.php/set/<login_to_save>/<password_to_save>/<url>/<user_login>/<user_password>/<label>/<protocol>?apikey=<VALID API KEY>
2058
             * Example: https://127.0.0.1/teampass/api/index.php/set/newLogin/newPassword/newUrl/myLogin/myPassword?apikey=gu6Eexaewaishooph6iethoh5woh0yoit6ohquo
2059
             *
2060
             * NEW ITEM WILL BE STORED IN SPECIFIC FOLDER
2061
             */
2062
            // get user credentials
2063
            if (isset($GLOBALS['request'][4]) && isset($GLOBALS['request'][5])) {
2064
                // get url
2065
                if (isset($GLOBALS['request'][1]) && isset($GLOBALS['request'][2]) && isset($GLOBALS['request'][3])) {
2066
                    // is user granted?
2067
                    $userData = DB::queryFirstRow(
2068
                        "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id`
2069
                        FROM ".prefix_table("users")."
2070
                        WHERE login = %s",
2071
                        $GLOBALS['request'][4]
2072
                    );
2073
                    if (DB::count() == 0) {
2074
                        rest_error('AUTH_NO_IDENTIFIER');
2075
                    }
2076
2077
                    // load passwordLib library
2078
                    require_once '../sources/SplClassLoader.php';
2079
                    $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
2080
                    $pwdlib->register();
2081
                    $pwdlib = new PasswordLib\PasswordLib();
2082
2083
                    // is user identified?
2084
                    if ($pwdlib->verifyPasswordHash($GLOBALS['request'][5], $userData['pw']) === true) {
2085
                        // does the personal folder of this user exists?
2086
                        DB::queryFirstRow(
2087
                            "SELECT `id`
2088
                            FROM ".prefix_table("nested_tree")."
2089
                            WHERE title = %s AND personal_folder = 1",
2090
                            $userData['id']
2091
                        );
2092
                        if (DB::count() > 0) {
2093
                            // check if "teampass-connect" folder exists
2094
                            // if not create it
2095
                            $folder = DB::queryFirstRow(
2096
                                "SELECT `id`
2097
                                FROM " . $pre."nested_tree
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $pre seems to be never defined.
Loading history...
2098
                                WHERE title = %s",
2099
                                "teampass-connect"
2100
                            );
2101
                            if (DB::count() == 0) {
2102
                                DB::insert(
2103
                                    prefix_table("nested_tree"),
2104
                                    array(
2105
                                        'parent_id' => '0',
2106
                                        'title' => "teampass-connect"
2107
                                    )
2108
                                );
2109
                                $tpc_folder_id = DB::insertId();
2110
2111
                                //Add complexity
2112
                                DB::insert(
2113
                                    prefix_table("misc"),
2114
                                    array(
2115
                                        'type' => 'complex',
2116
                                        'intitule' => $tpc_folder_id,
2117
                                        'valeur' => '0'
2118
                                    )
2119
                                );
2120
2121
                                // rebuild tree
2122
                                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
2123
                                $tree->register();
2124
                                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
2125
                                $tree->rebuild();
2126
                            } else {
2127
                                $tpc_folder_id = $folder['id'];
2128
                            }
2129
2130
                            // encrypt password
2131
                            $encrypt = cryption(
2132
                                $GLOBALS['request'][2],
2133
                                "",
2134
                                "encrypt"
2135
                            );
2136
2137
                            // is there a protocol?
2138
                            if (isset($GLOBALS['request'][7]) || empty($GLOBALS['request'][7])) {
2139
                                $protocol = "http://";
0 ignored issues
show
Unused Code introduced by
The assignment to $protocol is dead and can be removed.
Loading history...
2140
                            } else {
2141
                                $protocol = urldecode($GLOBALS['request'][7])."://";
2142
                            }
2143
2144
                            // add new item
2145
                            DB::insert(
2146
                                prefix_table("items"),
2147
                                array(
2148
                                    'label' => "Credentials for ".urldecode($GLOBALS['request'][3]),
2149
                                    'description' => "Imported with Teampass-Connect",
2150
                                    'pw' => $encrypt['string'],
2151
                                    'pw_iv' => "",
2152
                                    'email' => "",
2153
                                    'url' => urldecode($GLOBALS['request'][3]),
2154
                                    'id_tree' => $tpc_folder_id,
2155
                                    'login' => $GLOBALS['request'][1],
2156
                                    'inactif' => '0',
2157
                                    'restricted_to' => $userData['id'],
2158
                                    'perso' => '0',
2159
                                    'anyone_can_modify' => '0',
2160
                                    'complexity_level' => '0'
2161
                                )
2162
                            );
2163
                            $newID = DB::insertId();
2164
2165
                            // log
2166
                            logItems(
2167
                                $newID,
2168
                                "Credentials for ".urldecode($GLOBALS['request'][3].'%'),
2169
                                $userData['id'],
2170
                                'at_creation',
2171
                                $GLOBALS['request'][1]
2172
                            );
2173
2174
                            $json['status'] = "ok";
0 ignored issues
show
Comprehensibility Best Practice introduced by
$json was never initialized. Although not strictly required by PHP, it is generally a good practice to add $json = array(); before regardless.
Loading history...
2175
                            // prepare answer. If no access then inform
2176
                            if (empty($json)) {
2177
                                rest_error('AUTH_NO_DATA');
2178
                            } else {
2179
                                echo json_encode($json);
2180
                            }
2181
                        } else {
2182
                            rest_error('NO_PF_EXIST_FOR_USER');
2183
                        }
2184
                    } else {
2185
                        rest_error('AUTH_NOT_GRANTED');
2186
                    }
2187
                } else {
2188
                    rest_error('SET_NO_DATA');
2189
                }
2190
            } else {
2191
                rest_error('AUTH_NO_IDENTIFIER');
2192
            }
2193
        } elseif ($GLOBALS['request'][0] == "set_tpc") {
2194
            /*
2195
             * TO BE USED ONLY BY TEAMPASS-CONNECT
2196
             */
2197
            // get user credentials
2198
            if (isset($GLOBALS['request'][1]) === true && isset($GLOBALS['request'][2]) === true && isset($GLOBALS['request'][3]) === true) {
2199
                // Get passed variables
2200
                $item_definition = json_decode(base64_decode($GLOBALS['request'][2]), true);
2201
                $passedData = explode(';', base64_decode($GLOBALS['request'][3]));
2202
                $user_login = $passedData[0];
2203
                $user_pwd = $passedData[1];
2204
                $user_saltkey = $passedData[2];
2205
2206
                // is user granted?
2207
                $userData = DB::queryFirstRow(
2208
                    "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id`
2209
                    FROM ".prefix_table("users")."
2210
                    WHERE login = %s",
2211
                    $user_login
2212
                );
2213
                if (DB::count() === 0) {
2214
                    rest_error('AUTH_NO_IDENTIFIER');
2215
                }
2216
2217
                // load passwordLib library
2218
                require_once '../sources/SplClassLoader.php';
2219
                $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
2220
                $pwdlib->register();
2221
                $pwdlib = new PasswordLib\PasswordLib();
2222
2223
                // is user identified?
2224
                if ($pwdlib->verifyPasswordHash($user_pwd, $userData['pw']) === true) {
2225
                    // It is a new ITEM
2226
                    if ($GLOBALS['request'][1] === "add") {
2227
                        // encrypt PW
2228
                        if ($item_definition['personal'] === '1') {
2229
                            $passwd = cryption(
2230
                                $item_definition['pwd'],
2231
                                $user_saltkey,
2232
                                "encrypt"
2233
                            );
2234
                        } else {
2235
                            $passwd = cryption(
2236
                                $item_definition['pwd'],
2237
                                "",
2238
                                "encrypt"
2239
                            );
2240
                        }
2241
2242
                        // add new item
2243
                        DB::insert(
2244
                            prefix_table("items"),
2245
                            array(
2246
                                'label' => $item_definition['label'],
2247
                                'description' => $item_definition['description'],
2248
                                'pw' => $passwd['string'],
2249
                                'pw_iv' => "",
2250
                                'email' => "",
2251
                                'url' => $item_definition['url'],
2252
                                'id_tree' => $item_definition['destination_folder'],
2253
                                'login' => $item_definition['login'],
2254
                                'inactif' => '0',
2255
                                'restricted_to' => $userData['id'],
2256
                                'perso' => '0',
2257
                                'anyone_can_modify' => '0',
2258
                                'complexity_level' => '0'
2259
                            )
2260
                        );
2261
                        $newID = DB::insertId();
2262
2263
                        // log
2264
                        logItems(
2265
                            $newID,
2266
                            $item_definition['label'],
2267
                            $userData['id'],
2268
                            'at_creation',
2269
                            $GLOBALS['request'][1]
2270
                        );
2271
2272
                        // rebuild tree
2273
                        $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
2274
                        $tree->register();
2275
                        $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
2276
                        $tree->rebuild();
2277
2278
                        echo json_encode(array('new_id' => $newID , 'err' => ''));
2279
                    } elseif ($GLOBALS['request'][1] === "edit") {
2280
                        // Is this folder a personal one?
2281
                        $fldData = DB::queryFirstRow(
2282
                            "SELECT `personal_folder`
2283
                            FROM ".prefix_table("nested_tree")."
2284
                            WHERE id = %i",
2285
                            $item_definition['item_id']
2286
                        );
2287
2288
                        // encrypt PW
2289
                        if ($fldData['personal_folder'] === '1') {
2290
                            $passwd = cryption(
2291
                                $item_definition['pwd'],
2292
                                $user_saltkey,
2293
                                "encrypt"
2294
                            );
2295
                        } else {
2296
                            $passwd = cryption(
2297
                                $item_definition['pwd'],
2298
                                "",
2299
                                "encrypt"
2300
                            );
2301
                        }
2302
2303
                        // UPDATE item
2304
                        DB::update(
2305
                            prefix_table("items"),
2306
                            array(
2307
                                'pw' => $passwd['string'],
2308
                                'pw_iv' => '',
2309
                                "url" => $item_definition['url'],
2310
                                "login" => $item_definition['login']
2311
                            ),
2312
                            "id = %i",
2313
                            $item_definition['item_id']
2314
                        );
2315
2316
                        // log
2317
                        DB::insert(
2318
                            prefix_table("log_items"),
2319
                            array(
2320
                                "id_item" => $item_definition['item_id'],
2321
                                "date" => time(),
2322
                                "id_user" => $userData['id'],
2323
                                "action" => "at_modification"
2324
                            )
2325
                        );
2326
2327
                        // Update CACHE table
2328
                        DB::update(
2329
                            prefix_table("cache"),
2330
                            array(
2331
                                "login" => $item_definition['login'],
2332
                                "author" => $userData['id'],
2333
                                "timestamp" => time(),
2334
                                "url" => $item_definition['url'],
2335
                            ),
2336
                            "id = %i",
2337
                            $item_definition['item_id']
2338
                        );
2339
2340
                        echo json_encode(array('new_id' => '' , 'err' => ''));
2341
                    }
2342
                } else {
2343
                    rest_error('AUTH_NOT_GRANTED');
2344
                }
2345
            } else {
2346
                rest_error('AUTH_NO_IDENTIFIER');
2347
            }
2348
        } elseif ($GLOBALS['request'][0] == "tpc_delete") {
2349
            /*
2350
             * TO BE USED ONLY BY TEAMPASS-CONNECT
2351
             */
2352
            // get user credentials
2353
            if (isset($GLOBALS['request'][1]) === true) {
2354
                // Get passed variables
2355
                $passedData = explode(';', base64_decode($GLOBALS['request'][1]));
2356
                $item_id = $passedData[0];
2357
                $user_login = $passedData[1];
2358
                $user_pwd = $passedData[2];
2359
                $user_saltkey = $passedData[3];
2360
2361
                // is user granted?
2362
                $userData = DB::queryFirstRow(
2363
                    "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id`
2364
                    FROM ".prefix_table("users")."
2365
                    WHERE login = %s",
2366
                    $user_login
2367
                );
2368
                if (DB::count() == 0) {
2369
                    rest_error('AUTH_NO_IDENTIFIER');
2370
                }
2371
2372
                // load passwordLib library
2373
                require_once '../sources/SplClassLoader.php';
2374
                $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
2375
                $pwdlib->register();
2376
                $pwdlib = new PasswordLib\PasswordLib();
2377
2378
                // is user identified?
2379
                if ($pwdlib->verifyPasswordHash($user_pwd, $userData['pw']) === true) {
2380
                    DB::update(
2381
                        prefix_table("items"),
2382
                        array(
2383
                            'inactif' => '1',
2384
                        ),
2385
                        "id = %i",
2386
                        $item_id
2387
                    );
2388
                    //log
2389
                    DB::insert(
2390
                        prefix_table("log_items"),
2391
                        array(
2392
                            'id_item' => $item_id,
2393
                            'date' => time(),
2394
                            'id_user' => $userData['id'],
2395
                            'action' => 'at_delete'
2396
                        )
2397
                    );
2398
2399
                    //Update CACHE table
2400
                    updateCacheTable("delete_value", $item_id);
2401
2402
                    echo json_encode(array('code' => 'done'));
2403
                } else {
2404
                    rest_error('AUTH_NOT_GRANTED');
2405
                }
2406
            } else {
2407
                rest_error('AUTH_NO_IDENTIFIER');
2408
            }
2409
        } elseif ($GLOBALS['request'][0] === "delete") {
2410
        /*
2411
        * DELETE
2412
        *
2413
        * Expected call format: .../api/index.php/delete/folder/<folder_id1;folder_id2;folder_id3>?apikey=<VALID API KEY>
2414
        * Expected call format: .../api/index.php/delete/item>/<item_id1;item_id2;item_id3>?apikey=<VALID API KEY>
2415
        */
2416
            if ($GLOBALS['request'][1] === "folder") {
2417
                $array_category = explode(';', $GLOBALS['request'][2]);
2418
2419
                // get user info
2420
                if (isset($GLOBALS['request'][3]) && !empty($GLOBALS['request'][3])) {
2421
                    $userData = DB::queryFirstRow(
2422
                        "SELECT `id` FROM ".$pre."users WHERE login = %s",
2423
                        $GLOBALS['request'][3]
2424
                    );
2425
                    if (DB::count() == 0) {
2426
                        $user_id = API_USER_ID;
2427
                    } else {
2428
                        $user_id = $userData['id'];
2429
                    }
2430
                } else {
2431
                    $user_id = API_USER_ID;
2432
                }
2433
2434
                if (count($array_category) > 0 && count($array_category) < 5) {
2435
                    // load passwordLib library
2436
                    require_once '../sources/SplClassLoader.php';
2437
2438
                    // prepare tree
2439
                    $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
2440
                    $tree->register();
2441
                    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title', 'personal_folder');
0 ignored issues
show
Unused Code introduced by
The call to Tree\NestedTree\NestedTree::__construct() has too many arguments starting with 'personal_folder'. ( Ignorable by Annotation )

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

2441
                    $tree = /** @scrutinizer ignore-call */ new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title', 'personal_folder');

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
2442
2443
                    // this will delete all sub folders and items associated
2444
                    for ($i = 0; $i < count($array_category); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

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

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

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
2445
                        // Does this folder exist?
2446
                        DB::queryFirstRow(
2447
                            "SELECT id
2448
                            FROM ".prefix_table("nested_tree")."
2449
                            WHERE id = %i",
2450
                            $array_category[$i]
2451
                        );
2452
                        if (DB::count() > 0) {
2453
                            // Get through each subfolder
2454
                            $folders = $tree->getDescendants($array_category[$i], true);
2455
                            if (count($folders) > 0) {
2456
                                foreach ($folders as $folder) {
2457
                                    if (($folder->parent_id > 0 || $folder->parent_id == 0) && $folder->personal_folder != 1) {
2458
                                        //Store the deleted folder (recycled bin)
2459
                                        DB::insert(
2460
                                            prefix_table("misc"),
2461
                                            array(
2462
                                                'type' => 'folder_deleted',
2463
                                                'intitule' => "f".$array_category[$i],
2464
                                                'valeur' => $folder->id.', '.$folder->parent_id.', '.
2465
                                                    $folder->title.', '.$folder->nleft.', '.$folder->nright.', '.$folder->nlevel.', 0, 0, 0, 0'
2466
                                            )
2467
                                        );
2468
                                        //delete folder
2469
                                        DB::delete(prefix_table("nested_tree"), "id = %i", $folder->id);
2470
2471
                                        //delete items & logs
2472
                                        $items = DB::query(
2473
                                            "SELECT id
2474
                                            FROM ".prefix_table("items")."
2475
                                            WHERE id_tree=%i",
2476
                                            $folder->id
2477
                                        );
2478
                                        foreach ($items as $item) {
2479
                                            DB::update(
2480
                                                prefix_table("items"),
2481
                                                array(
2482
                                                    'inactif' => '1',
2483
                                                ),
2484
                                                "id = %i",
2485
                                                $item['id']
2486
                                            );
2487
                                            //log
2488
                                            DB::insert(
2489
                                                prefix_table("log_items"),
2490
                                                array(
2491
                                                    'id_item' => $item['id'],
2492
                                                    'date' => time(),
2493
                                                    'id_user' => $user_id,
2494
                                                    'action' => 'at_delete'
2495
                                                )
2496
                                            );
2497
                                        }
2498
                                        //Update CACHE table
2499
                                        updateCacheTable("delete_value", $array_category[$i]);
2500
                                    }
2501
                                }
2502
                            }
2503
                        } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
2504
                            // Folder doesn't exist
2505
                        }
2506
                    }
2507
                } else {
2508
                    rest_error('NO_CATEGORY');
2509
                }
2510
2511
                $json['status'] = 'OK';
2512
            } elseif ($GLOBALS['request'][1] == "item") {
2513
                $array_items = explode(';', $GLOBALS['request'][2]);
2514
2515
                // get user info
2516
                if (isset($GLOBALS['request'][3]) && !empty($GLOBALS['request'][3])) {
2517
                    $userData = DB::queryFirstRow(
2518
                        "SELECT `id` FROM ".$pre."users WHERE login = %s",
2519
                        $GLOBALS['request'][3]
2520
                    );
2521
                    if (DB::count() == 0) {
2522
                        $user_id = API_USER_ID;
2523
                    } else {
2524
                        $user_id = $userData['id'];
2525
                    }
2526
                }
2527
2528
                for ($i = 0, $c = count($array_items); $i < $c; $i++) {
2529
                    DB::update(
2530
                        prefix_table("items"),
2531
                        array(
2532
                            'inactif' => '1',
2533
                        ),
2534
                        "id = %i",
2535
                        $array_items[$i]
2536
                    );
2537
                    //log
2538
                    DB::insert(
2539
                        prefix_table("log_items"),
2540
                        array(
2541
                            'id_item' => $array_items[$i],
2542
                            'date' => time(),
2543
                            'id_user' => $user_id,
2544
                            'action' => 'at_delete'
2545
                        )
2546
                    );
2547
2548
                    //Update CACHE table
2549
                    updateCacheTable("delete_value", $array_items[$i]);
2550
                }
2551
2552
                $json['status'] = 'OK';
2553
            }
2554
2555
            if ($json) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $json does not seem to be defined for all execution paths leading up to this point.
Loading history...
2556
                echo json_encode($json);
2557
            } else {
2558
                rest_error('EMPTY');
2559
            }
2560
        } elseif ($GLOBALS['request'][0] == "new_password") {
2561
            if (!empty($GLOBALS['request'][1])) {
2562
                $params = explode(";", $GLOBALS['request'][1]);
2563
2564
                if (empty($params[0])) {
2565
                    $params[0] = 8;
2566
                }
2567
                if (empty($params[1])) {
2568
                    $params[1] = 0;
2569
                }
2570
                if (empty($params[2])) {
2571
                    $params[2] = 0;
2572
                }
2573
                if (empty($params[3])) {
2574
                    $params[3] = 0;
2575
                }
2576
                if (empty($params[4])) {
2577
                    $params[4] = 0;
2578
                }
2579
                if (empty($params[5])) {
2580
                    $params[5] = 0;
2581
                }
2582
                if (empty($params[6])) {
2583
                    $params[6] = 0;
2584
                }
2585
2586
                // Generate key
2587
                $pwd = GenerateCryptKey(
2588
                    $params[0],
2589
                    $params[1] === "1" ? true : false,
2590
                    $params[2] === "1" ? true : false,
2591
                    $params[3] === "1" ? true : false,
2592
                    $params[5] === "1" && $params[6] === "1" ? true : false
2593
                );
2594
2595
                // generate and send back (generate in base64 if symbols are asked)
2596
                if ($params[6] === "1") {
2597
                    echo '{"password" : "'.base64_encode($pwd).'"}';
2598
                } else {
2599
                    echo '{"password" : "'.$pwd.'"}';
2600
                }
2601
            } else {
2602
                rest_error('NO_PARAMETERS');
2603
            }
2604
        } elseif ($GLOBALS['request'][0] === "info") {
2605
            if ($GLOBALS['request'][1] === "complexicity_levels_list") {
2606
                require_once '../includes/language/english.php';
2607
                $json = array(
2608
                    0=> $LANG['complex_level0'],
2609
                    25=> $LANG['complex_level1'],
2610
                    50=> $LANG['complex_level2'],
2611
                    60=> $LANG['complex_level3'],
2612
                    70=> $LANG['complex_level4'],
2613
                    80=> $LANG['complex_level5'],
2614
                    90=> $LANG['complex_level6']
2615
                );
2616
2617
                echo json_encode($json);
2618
            } elseif ($GLOBALS['request'][1] === "folder") {
2619
                if (!empty($GLOBALS['request'][2]) && is_numeric($GLOBALS['request'][2])) {
2620
                    $data = DB::queryFirstRow(
2621
                        "SELECT * FROM ".$pre."nested_tree WHERE id = %i",
2622
                        $GLOBALS['request'][2]
2623
                    );
2624
                    if (DB::count() == 0) {
2625
                        rest_error('NOSUCHFOLDER');
2626
                    }
2627
2628
                    // form id_tree to full foldername
2629
                    require_once '../sources/SplClassLoader.php';
2630
                    //Load Tree
2631
                    $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
2632
                    $tree->register();
2633
                    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
2634
2635
                    $folder = "";
2636
                    $arbo = $tree->getPath($GLOBALS['request'][2], true);
2637
                    foreach ($arbo as $elem) {
2638
                        if (empty($folder)) {
2639
                            $folder = stripslashes($elem->title);
2640
                        } else {
2641
                            $folder .= " > ".stripslashes($elem->title);
2642
                        }
2643
                    }
2644
2645
                    // prepare info
2646
                    $json = array(
2647
                        "title" => $data['title'],
2648
                        "personal_folder" => $data['personal_folder'],
2649
                        "renewal_period" => $data['renewal_period'],
2650
                        "parent_id" => $data['parent_id'],
2651
                        "path" => $folder,
2652
                    );
2653
2654
                    echo json_encode($json);
2655
                } else {
2656
                    rest_error('NO_PARAMETERS');
2657
                }
2658
            } elseif ($GLOBALS['request'][1] === "version") {
2659
                echo '{"api-version":"'.$api_version.'"}';
2660
            } else {
2661
                rest_error('NO_PARAMETERS');
2662
            }
2663
        } else {
2664
            rest_error('METHOD');
2665
        }
2666
    }
2667
}
2668
2669
function rest_put()
2670
{
2671
    if (!@count($GLOBALS['request']) == 0) {
2672
        $request_uri = $GLOBALS['_SERVER']['REQUEST_URI'];
2673
        preg_match('/\/api(\/index.php|)\/(.*)\?apikey=(.*)/', $request_uri, $matches);
2674
        if (count($matches) == 0) {
2675
            rest_error('REQUEST_SENT_NOT_UNDERSTANDABLE');
2676
        }
2677
        $GLOBALS['request'] = explode('/', $matches[2]);
2678
    }
2679
    if (apikey_checker($GLOBALS['apikey'])) {
2680
        teampass_connect();
2681
    }
2682
}
2683
2684
/**
2685
 * @param string $type
2686
 */
2687
function rest_error($type, $detail = 'N/A')
2688
{
2689
    switch ($type) {
2690
        case 'APIKEY':
2691
            $message = array('err' => 'This api_key '.$GLOBALS['apikey'].' doesn\'t exist', 'code' => 'API_KEY_NOT_FOUND');
2692
            header('HTTP/1.1 405 Method Not Allowed');
2693
            break;
2694
        case 'NO_CATEGORY':
2695
            $message = array('err' => 'No folder specified');
2696
            break;
2697
        case 'NO_ITEM':
2698
            $message = array('err' => 'No item specified');
2699
            break;
2700
        case 'EMPTY':
2701
            $message = array('err' => 'No results');
2702
            break;
2703
        case 'IPWHITELIST':
2704
            $message = array('err' => 'Ip address not allowed.');
2705
            header('HTTP/1.1 405 Method Not Allowed');
2706
            break;
2707
        case 'MYSQLERR':
2708
            $message = array('err' => $detail);
2709
            header('HTTP/1.1 500 Internal Server Error');
2710
            break;
2711
        case 'METHOD':
2712
            $message = array('err' => 'Method not authorized', 'code' => 'METHOD_NOT_AUTHORIZED');
2713
            header('HTTP/1.1 405 Method Not Allowed');
2714
            break;
2715
        case 'ITEMBADDEFINITION':
2716
            $message = array('err' => 'Item definition not complete');
2717
            header('HTTP/1.1 405 Method Not Allowed');
2718
            break;
2719
        case 'ITEM_MALFORMED':
2720
            $message = array('err' => 'Item definition not numeric');
2721
            header('HTTP/1.1 405 Method Not Allowed');
2722
            break;
2723
        case 'USERBADDEFINITION':
2724
            $message = array('err' => 'User definition not complete');
2725
            header('HTTP/1.1 405 Method Not Allowed');
2726
            break;
2727
        case 'USERLOGINEMPTY':
2728
            $message = array('err' => 'Empty Login given');
2729
            header('HTTP/1.1 405 Method Not Allowed');
2730
            break;
2731
        case 'USERALREADYEXISTS':
2732
            $message = array('err' => 'User already exists');
2733
            header('HTTP/1.1 405 Method Not Allowed');
2734
            break;
2735
        case 'REQUEST_SENT_NOT_UNDERSTANDABLE':
2736
            $message = array('err' => 'URL format is not following requirements');
2737
            break;
2738
        case 'AUTH_NOT_GRANTED':
2739
            $message = array('err' => 'Bad credentials for user', 'code' => 'AUTH_NOT_GRANTED');
2740
            header('HTTP/1.1 404 Error');
2741
            break;
2742
        case 'AUTH_NO_URL':
2743
            $message = array('err' => 'URL needed to grant access');
2744
            break;
2745
        case 'AUTH_NO_IDENTIFIER':
2746
            $message = array('err' => 'Credentials needed to grant access', 'code' => 'AUTH_NO_IDENTIFIER');
2747
            break;
2748
        case 'AUTH_NO_DATA':
2749
            $message = array('err' => 'Data not allowed for the user', 'code' => 'AUTH_NO_DATA');
2750
            break;
2751
        case 'AUTH_PSK_ERROR':
2752
            $message = array('err' => 'Personal Saltkey is wrong', 'code' => 'AUTH_PSK_ERROR');
2753
            header('HTTP/1.1 404 Error');
2754
            break;
2755
        case 'NO_DATA_EXIST':
2756
            $message = array('err' => 'No data exists', 'code' => 'NO_DATA_EXIST');
2757
            break;
2758
        case 'NO_DESTINATION_FOLDER':
2759
            $message = array('err' => 'No destination folder provided');
2760
            break;
2761
        case 'PASSWORDTOOLONG':
2762
            $message = array('err' => 'Password is too long');
2763
            break;
2764
        case 'NOSUCHFOLDER':
2765
            $message = array('err' => 'Folder ID does not exist');
2766
            break;
2767
        case 'PASSWORDEMPTY':
2768
            $message = array('err' => 'Password is empty');
2769
            break;
2770
        case 'ITEMEXISTS':
2771
            $message = array('err' => 'Label already exists');
2772
            break;
2773
        case 'ITEMMISSINGDATA':
2774
            $message = array('err' => 'Label or Password or Folder ID is missing');
2775
            break;
2776
        case 'SET_NO_DATA':
2777
            $message = array('err' => 'No data to be stored');
2778
            break;
2779
        case 'NO_PF_EXIST_FOR_USER':
2780
            $message = array('err' => 'No Personal Folder exists for this user');
2781
            break;
2782
        case 'HTML_CODES_NOT_ALLOWED':
2783
            $message = array('err' => 'HTML tags not allowed');
2784
            break;
2785
        case 'TITLE_ONLY_WITH_NUMBERS':
2786
            $message = array('err' => 'Title only with numbers not allowed');
2787
            break;
2788
        case 'ALREADY_EXISTS':
2789
            $message = array('err' => 'Data already exists');
2790
            break;
2791
        case 'COMPLEXICITY_LEVEL_NOT_REACHED':
2792
            $message = array('err' => 'complexity level was not reached');
2793
            break;
2794
        case 'NO_PARAMETERS':
2795
            $message = array('err' => 'No parameters given');
2796
            break;
2797
        case 'USER_NOT_EXISTS':
2798
            $message = array('err' => 'User does not exist');
2799
            break;
2800
        case 'NO_PSALTK_PROVIDED':
2801
            $message = array('err' => 'No Personal saltkey provided');
2802
            break;
2803
        case 'EXPECTED_PARAMETER_NOT_PROVIDED':
2804
            $message = array('err' => 'Provided parameters are not correct');
2805
            break;
2806
        default:
2807
            $message = array('err' => 'Something happen ... but what ?');
2808
            header('HTTP/1.1 500 Internal Server Error');
2809
            break;
2810
    }
2811
2812
    echo json_encode($message);
2813
    exit(0);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
2814
}
2815
2816
function apikey_checker($apikey_used)
2817
{
2818
    teampass_connect();
2819
    $apikey_pool = teampass_get_keys();
2820
2821
    // if needed extract key from credentials
2822
    if (strlen($apikey_used) > 40) {
2823
        $userCredentials = base64_decode(substr($apikey_used, 40));
0 ignored issues
show
Unused Code introduced by
The assignment to $userCredentials is dead and can be removed.
Loading history...
2824
        $apikey_used = substr($apikey_used, 0, 39);
2825
    }
2826
2827
    if (in_array($apikey_used, $apikey_pool)) {
2828
        return(1);
2829
    } else {
2830
        rest_error('APIKEY', $apikey_used);
2831
    }
2832
}
2833
2834
function teampass_pbkdf2_hash($var_p, $var_s, $var_c, $var_kl, $var_st = 0, $var_a = 'sha256')
2835
{
2836
    $var_kb = $var_st + $var_kl;
2837
    $var_dk = '';
2838
2839
    for ($block = 1; $block <= $var_kb; $block++) {
2840
        $var_ib = $var_h = hash_hmac($var_a, $var_s.pack('N', $block), $var_p, true);
2841
        for ($var_i = 1; $var_i < $var_c; $var_i++) {
2842
            $var_ib ^= ($var_h = hash_hmac($var_a, $var_h, $var_p, true));
2843
        }
2844
        $var_dk .= $var_ib;
2845
    }
2846
2847
    return substr($var_dk, $var_st, $var_kl);
2848
}
2849