Passed
Branch development (e0e718)
by Nils
04:45
created

rest_get()   F

Complexity

Conditions 279
Paths > 20000

Size

Total Lines 2380
Code Lines 1463

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 279
eloc 1463
nc 46611
nop 0
dl 0
loc 2380
rs 2
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
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
                            ""
1000
                        );
1001
1002
                        // update LOG
1003
                        logEvents('user_mngt', 'at_user_added', 'api - '.$GLOBALS['apikey'], $new_user_id, "");
1004
1005
                        echo '{"status":"user added"}';
1006
                    } catch (PDOException $ex) {
1007
                        echo '<br />'.$ex->getMessage();
1008
                    }
1009
                } else {
1010
                    rest_error('USERALREADYEXISTS');
1011
                }
1012
            } elseif ($GLOBALS['request'][1] == "folder") {
1013
            /*
1014
            * ADDING A FOLDER
1015
            * <url to teampass>/api/index.php/add/folder/<title>;<complexity_level>;<parent_id>;<renewal_period>;<personal>?apikey=<valid api key>
1016
            * http://localhost/teampass/api/index.php/add/folder/Import from API;0;38;0;0?apikey=piesae7ahghae1iiP9ohPhaefaideeThohgh1te
1017
            */
1018
                if (!empty($GLOBALS['request'][2])) {
1019
                    // get sent parameters
1020
                    $params = explode(';', base64_decode($GLOBALS['request'][2]));
1021
1022
                    if (empty($params[0]) === false && (intval($params[1]) >= 0 && intval($params[1]) <= 1000)) {
1023
                        if (empty($params[3])) {
1024
                            $params[3] = 0;
1025
                        }
1026
                        if (empty($params[4])) {
1027
                            $params[4] = 0;
1028
                        }
1029
                        if (empty($params[2])) {
1030
                            rest_error('NO_DESTINATION_FOLDER');
1031
                        }
1032
                        if ($params[2] < 0) {
1033
                            rest_error('NO_DATA_EXIST');
1034
                        }
1035
1036
                        //Check if title doesn't contains html codes
1037
                        if (preg_match_all("|<[^>]+>(.*)</[^>]+>|U", $params[0], $out)) {
1038
                            rest_error('HTML_CODES_NOT_ALLOWED');
1039
                        }
1040
1041
                        // check if title is numeric
1042
                        if (is_numeric($params[0]) === true) {
1043
                            rest_error('TITLE_ONLY_WITH_NUMBERS');
1044
                        }
1045
1046
                        //Check if duplicate folders name are allowed
1047
                        $data = DB::queryfirstrow(
1048
                            "SELECT valeur
1049
                            FROM ".prefix_table("misc")."
1050
                            WHERE type = %s AND intitule = %s",
1051
                            "admin",
1052
                            "duplicate_folder"
1053
                        );
1054
                        // if valeur = 0 then duplicate folders not allowed
1055
                        if ($data['valeur'] === '0') {
1056
                            DB::query(
1057
                                "SELECT *
1058
                                FROM ".prefix_table("nested_tree")."
1059
                                WHERE title = %s",
1060
                                $params[0]
1061
                            );
1062
                            $counter = DB::count();
1063
                            if ($counter != 0) {
1064
                                rest_error('ALREADY_EXISTS');
1065
                            }
1066
                        }
1067
1068
                        //check if parent folder is personal
1069
                        $data = DB::queryfirstrow(
1070
                            "SELECT personal_folder
1071
                            FROM ".prefix_table("nested_tree")."
1072
                            WHERE id = %i",
1073
                            $params[2]
1074
                        );
1075
                        if ($data['personal_folder'] === "1") {
1076
                            $isPersonal = 1;
1077
                        } else {
1078
                            if ($params[4] === 1) {
1079
                                $isPersonal = 1;
1080
                            } else {
1081
                                $isPersonal = 0;
1082
                            }
1083
1084
                            // get complexity level for this folder
1085
                            $data = DB::queryfirstrow(
1086
                                "SELECT valeur
1087
                                FROM ".prefix_table("misc")."
1088
                                WHERE intitule = %i AND type = %s",
1089
                                $params[2],
1090
                                "complex"
1091
                            );
1092
                            if (intval($params[1]) < intval($data['valeur'])) {
1093
                                rest_error('COMPLEXICITY_LEVEL_NOT_REACHED');
1094
                            }
1095
                        }
1096
1097
                        try {
1098
                            //create folder
1099
                            DB::insert(
1100
                                prefix_table("nested_tree"),
1101
                                array(
1102
                                    'parent_id' => $params[2],
1103
                                    'title' => $params[0],
1104
                                    'personal_folder' => $isPersonal,
1105
                                    'renewal_period' => $params[3],
1106
                                    'bloquer_creation' => '0',
1107
                                    'bloquer_modification' => '0'
1108
                                )
1109
                            );
1110
                            $newId = DB::insertId();
1111
1112
                            //Add complexity
1113
                            DB::insert(
1114
                                prefix_table("misc"),
1115
                                array(
1116
                                    'type' => 'complex',
1117
                                    'intitule' => $newId,
1118
                                    'valeur' => $params[1]
1119
                                )
1120
                            );
1121
1122
                            // Run nested tree update
1123
                            require_once '../sources/SplClassLoader.php';
1124
                            $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
1125
                            $tree->register();
1126
                            $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
1127
                            $tree->rebuild();
1128
1129
                            // We need to allocate the same access rights as the parent
1130
                            // We will considere that if created as root then its rights must be set through the GUI
1131
                            $ret = DB::query(
1132
                                "SELECT role_id, type
1133
                                FROM ".prefix_table("roles_values")."
1134
                                WHERE folder_id = %i",
1135
                                $params[2]
1136
                            );
1137
                            foreach ($ret as $entry) {
1138
                                DB::insert(
1139
                                    prefix_table("roles_values"),
1140
                                    array(
1141
                                        'role_id' => $entry['role_id'],
1142
                                        'folder_id' => $newId,
1143
                                        'type' => $entry['type']
1144
                                    )
1145
                                );
1146
                            }
1147
1148
                            echo '{"status":"folder created" , "new_folder_id":"'.$newId.'"}';
1149
                        } catch (PDOException $ex) {
1150
                            echo '<br />'.$ex->getMessage();
1151
                        }
1152
                    } else {
1153
                        rest_error('NO_DATA_EXIST');
1154
                    }
1155
                } else {
1156
                    rest_error('SET_NO_DATA');
1157
                }
1158
            }
1159
        } elseif ($GLOBALS['request'][0] == "update") {
1160
            /*
1161
            * Section dedicated for UPDATING
1162
            */
1163
            if ($GLOBALS['request'][1] == "item") {
1164
                /*
1165
                * 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>
1166
                */
1167
                if ($GLOBALS['request'][2] !== "" && is_numeric($GLOBALS['request'][2])) {
1168
                    // get sent parameters
1169
                    $params = explode(';', base64_decode($GLOBALS['request'][3]));
1170
1171
                    if (!empty($params[0]) && !empty($params[1]) && !empty($params[3])) {
1172
                        // Check length
1173
                        if (strlen($params[1]) > 50) {
1174
                            rest_error('PASSWORDTOOLONG');
1175
                        }
1176
1177
                        // Check Folder ID
1178
                        DB::query(
1179
                            "SELECT *
1180
                            FROM ".prefix_table("nested_tree")."
1181
                            WHERE id = %i",
1182
                            $params[3]
1183
                        );
1184
                        $counter = DB::count();
1185
                        if ($counter == 0) {
1186
                            rest_error('NOSUCHFOLDER');
1187
                        }
1188
1189
                        // check if item exists
1190
                        DB::query(
1191
                            "SELECT *
1192
                            FROM ".prefix_table("items")."
1193
                            WHERE id = %i",
1194
                            $GLOBALS['request'][2]
1195
                        );
1196
                        $counter = DB::count();
1197
                        if ($counter > 0) {
1198
                            // encrypt pwd
1199
                            $encrypt = cryption(
1200
                                $params[1],
1201
                                "",
1202
                                "encrypt"
1203
                            );
1204
                            if (empty($encrypt['string'])) {
1205
                                rest_error('PASSWORDEMPTY');
1206
                            }
1207
1208
                            // ADD item
1209
                            try {
1210
                                DB::update(
1211
                                    prefix_table("items"),
1212
                                    array(
1213
                                        "label" => $params[0],
1214
                                        "description" => $params[2],
1215
                                        'pw' => $encrypt['string'],
1216
                                        'pw_iv' => '',
1217
                                        "email" => $params[5],
1218
                                        "url" => $params[6],
1219
                                        "id_tree" => intval($params[3]),
1220
                                        "login" => $params[4],
1221
                                        "anyone_can_modify" => intval($params[8])
1222
                                    ),
1223
                                    "id = %i",
1224
                                    $GLOBALS['request'][2]
1225
                                );
1226
1227
                                // log
1228
                                DB::insert(
1229
                                    prefix_table("log_items"),
1230
                                    array(
1231
                                        "id_item" => $GLOBALS['request'][2],
1232
                                        "date" => time(),
1233
                                        "id_user" => API_USER_ID,
1234
                                        "action" => "at_modification"
1235
                                    )
1236
                                );
1237
1238
                                // Add tags
1239
                                $tags = explode(' ', $params[7]);
1240
                                foreach ((array) $tags as $tag) {
1241
                                    if (!empty($tag)) {
1242
                                        // check if already exists
1243
                                        DB::query(
1244
                                            "SELECT *
1245
                                            FROM ".prefix_table("tags")."
1246
                                            WHERE tag = %s AND item_id = %i",
1247
                                            strtolower($tag),
1248
                                            $GLOBALS['request'][2]
1249
                                        );
1250
                                        $counter = DB::count();
1251
                                        if ($counter === 0) {
1252
                                            DB::insert(
1253
                                                prefix_table("tags"),
1254
                                                array(
1255
                                                    "item_id" => $GLOBALS['request'][2],
1256
                                                    "tag" => strtolower($tag)
1257
                                                )
1258
                                            );
1259
                                        }
1260
                                    }
1261
                                }
1262
1263
                                // Update CACHE table
1264
                                DB::update(
1265
                                    prefix_table("cache"),
1266
                                    array(
1267
                                        "label" => $params[0],
1268
                                        "description" => $params[2],
1269
                                        "tags" => $params[7],
1270
                                        "id_tree" => intval($params[3]),
1271
                                        "perso" => "0",
1272
                                        "restricted_to" => "",
1273
                                        "login" => $params[4],
1274
                                        "folder" => "",
1275
                                        "author" => API_USER_ID,
1276
                                        "renewal_period" => "0",
1277
                                        "timestamp" => time(),
1278
                                        "url" => $params[6],
1279
                                    ),
1280
                                    "id = %i",
1281
                                    $GLOBALS['request'][2]
1282
                                );
1283
1284
                                echo '{"status":"item updated"}';
1285
                            } catch (PDOException $ex) {
1286
                                echo '<br />'.$ex->getMessage();
1287
                            }
1288
                        } else {
1289
                            rest_error('NO_DATA_EXIST');
1290
                        }
1291
                    } else {
1292
                        rest_error('ITEMMISSINGDATA');
1293
                    }
1294
                } else {
1295
                    rest_error('NO_ITEM');
1296
                }
1297
            } elseif ($GLOBALS['request'][1] == "folder") {
1298
            /*
1299
            * UPDATING A FOLDER
1300
            * <url to teampass>/api/index.php/update/folder/<folder_id>/<title>;<complexity_level>;<renewal_period>?apikey=<valid api key>
1301
            */
1302
                if ($GLOBALS['request'][2] !== "" && is_numeric($GLOBALS['request'][2])) {
1303
                    // get sent parameters
1304
                    $params = explode(';', base64_decode($GLOBALS['request'][3]));
1305
1306
                    if (!empty($params[0])) {
1307
                        if ($params[1] < 0) {
1308
                            rest_error('NO_DATA_EXIST');
1309
                        }
1310
                        if (empty($params[2])) {
1311
                            $params[2] = 0;
1312
                        }
1313
1314
                        // check if folder exists and get folder data
1315
                        $data_folder = DB::queryfirstrow(
1316
                            "SELECT *
1317
                            FROM ".prefix_table("nested_tree")."
1318
                            WHERE id = %s",
1319
                            $GLOBALS['request'][2]
1320
                        );
1321
                        $counter = DB::count();
1322
                        if ($counter === 0) {
1323
                            rest_error('NO_DATA_EXIST');
1324
                        }
1325
1326
                        //Check if title doesn't contains html codes
1327
                        if (preg_match_all("|<[^>]+>(.*)</[^>]+>|U", $params[0], $out)) {
1328
                            rest_error('HTML_CODES_NOT_ALLOWED');
1329
                        }
1330
1331
                        // check if title is numeric
1332
                        if (is_numeric($params[0]) === true) {
1333
                            rest_error('TITLE_ONLY_WITH_NUMBERS');
1334
                        }
1335
1336
                        // get complexity level for this folder
1337
                        $data = DB::queryfirstrow(
1338
                            "SELECT valeur
1339
                            FROM ".prefix_table("misc")."
1340
                            WHERE intitule = %i AND type = %s",
1341
                            $data_folder['parent_id'],
1342
                            "complex"
1343
                        );
1344
                        if (intval($params[1]) < intval($data['valeur'])) {
1345
                            rest_error('COMPLEXICITY_LEVEL_NOT_REACHED');
1346
                        }
1347
1348
                        try {
1349
                            DB::update(
1350
                                prefix_table("nested_tree"),
1351
                                array(
1352
                                    'parent_id' => $data_folder['parent_id'],
1353
                                    'title' => $params[0],
1354
                                    'personal_folder' => 0,
1355
                                    'renewal_period' => $params[2],
1356
                                    'bloquer_creation' => '0',
1357
                                    'bloquer_modification' => '0'
1358
                                ),
1359
                                "id = %i",
1360
                                $GLOBALS['request'][2]
1361
                            );
1362
1363
                            //Add complexity
1364
                            DB::update(
1365
                                prefix_table("misc"),
1366
                                array(
1367
                                    'valeur' => $params[1]
1368
                                ),
1369
                                "intitule = %s AND type = %s",
1370
                                $GLOBALS['request'][2],
1371
                                "complex"
1372
                            );
1373
1374
                            // Run nested tree update
1375
                            require_once '../sources/SplClassLoader.php';
1376
                            $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
1377
                            $tree->register();
1378
                            $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
1379
                            $tree->rebuild();
1380
1381
                            echo '{"status":"folder updated"}';
1382
                        } catch (PDOException $ex) {
1383
                            echo '<br />'.$ex->getMessage();
1384
                        }
1385
                    } else {
1386
                        rest_error('ITEMMISSINGDATA');
1387
                    }
1388
                } else {
1389
                    rest_error('NO_ITEM');
1390
                }
1391
            } elseif ($GLOBALS['request'][1] == "user") {
1392
            /*
1393
             * Case where a user has to be updated
1394
             *
1395
             * 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>
1396
             * with:
1397
             * for READ_ONLY, IS_ADMIN, IS_MANAGER, PERSONAL_FOLDER, accepted value is 1 for TRUE and 0 for FALSE
1398
             * for ADMINISTRATEDBY and ROLE1, accepted value is the real label (not the IDs)
1399
             *
1400
             * Example: /api/index.php/update/user/U4;Nils;Laumaille;test;[email protected];Users;0;Managers,Users;0;1;1?apikey=sae6iekahxiseL3viShoo0chahc1ievei8aequi
1401
             *
1402
             */
1403
1404
                // get user definition
1405
                $array_user = explode(';', base64_decode($GLOBALS['request'][2]));
1406
                if (count($array_user) != 11) {
1407
                    rest_error('USERBADDEFINITION');
1408
                }
1409
1410
                $login = $array_user[0];
1411
                $name = $array_user[1];
1412
                $lastname = $array_user[2];
1413
                $password = $array_user[3];
1414
                $email = $array_user[4];
1415
                $adminby = urldecode($array_user[5]);
1416
                $isreadonly = urldecode($array_user[6]);
1417
                $roles = urldecode($array_user[7]);
1418
                $isadmin = $array_user[8];
1419
                $ismanager = $array_user[9];
1420
                $haspf = $array_user[10];
1421
1422
                // Empty user
1423
                if (mysqli_escape_string($link, htmlspecialchars_decode($login)) == "") {
1424
                    rest_error('USERLOGINEMPTY');
1425
                }
1426
                // Check if user already exists
1427
                $data = DB::query(
1428
                    "SELECT id, fonction_id, groupes_interdits, groupes_visibles, personal_folder
1429
                    FROM ".prefix_table("users")."
1430
                    WHERE login LIKE %ss",
1431
                    mysqli_escape_string($link, stripslashes($login))
1432
                );
1433
1434
                if (DB::count() === 1) {
1435
                    try {
1436
                        // find AdminRole code in DB
1437
                        $resRole = DB::queryFirstRow(
1438
                            "SELECT id
1439
                            FROM ".prefix_table("roles_title")."
1440
                            WHERE title LIKE %ss",
1441
                            mysqli_escape_string($link, stripslashes($adminby))
1442
                        );
1443
1444
1445
                        // get default language
1446
                        $lang = DB::queryFirstRow(
1447
                            "SELECT `valeur`
1448
                            FROM ".prefix_table("misc")."
1449
                            WHERE type = %s AND intitule = %s",
1450
                            "admin",
1451
                            "default_language"
1452
                        );
1453
1454
                        // prepare roles list
1455
                        $rolesList = "";
1456
                        foreach (explode(',', $roles) as $role) {
1457
                            $tmp = DB::queryFirstRow(
1458
                                "SELECT `id`
1459
                                FROM ".prefix_table("roles_title")."
1460
                                WHERE title = %s",
1461
                                $role
1462
                            );
1463
                            if (empty($rolesList)) {
1464
                                $rolesList = $tmp['id'];
1465
                            } else {
1466
                                $rolesList .= ";".$tmp['id'];
1467
                            }
1468
                        }
1469
1470
                        // Update user in DB
1471
                        DB::update(
1472
                            prefix_table("users"),
1473
                            array(
1474
                                'login' => $login,
1475
                                'name' => $name,
1476
                                'lastname' => $lastname,
1477
                                'pw' => bCrypt(stringUtf8Decode($password), COST),
1478
                                'email' => $email,
1479
                                'admin' => intval($isadmin),
1480
                                'gestionnaire' => intval($ismanager),
1481
                                'read_only' => intval($isreadonly),
1482
                                'personal_folder' => intval($haspf),
1483
                                'user_language' => $lang['valeur'],
1484
                                'fonction_id' => $rolesList,
1485
                                'groupes_interdits' => '0',
1486
                                'groupes_visibles' => '0',
1487
                                'isAdministratedByRole' => empty($resRole) ? '0' : $resRole['id']
1488
                            ),
1489
                            "id = %i",
1490
                            $data['id']
1491
                        );
1492
1493
                        // Create personnal folder
1494
                        if (intval($haspf) === 1) {
1495
                            DB::query(
1496
                                "SELECT id
1497
                                FROM ".prefix_table("nested_tree")."
1498
                                WHERE title = %s",
1499
                                $data['id']
1500
                            );
1501
                            if (DB::count() === 0) {
1502
                                DB::insert(
1503
                                    prefix_table("nested_tree"),
1504
                                    array(
1505
                                        'parent_id' => '0',
1506
                                        'title' => $data['id'],
1507
                                        'bloquer_creation' => '0',
1508
                                        'bloquer_modification' => '0',
1509
                                        'personal_folder' => '1'
1510
                                    )
1511
                                );
1512
                            }
1513
                        }
1514
1515
                        // load settings
1516
                        loadSettings();
1517
1518
                        // update LOG
1519
                        logEvents('user_mngt', 'at_user_updated', 'api - '.$GLOBALS['apikey'], $data['id'], "");
1520
1521
                        echo '{"status":"user added"}';
1522
                    } catch (PDOException $ex) {
1523
                        echo '<br />'.$ex->getMessage();
1524
                    }
1525
                } else {
1526
                    rest_error('USER_NOT_EXISTS');
1527
                }
1528
            }
1529
        } elseif ($GLOBALS['request'][0] == "auth") {
1530
            /*
1531
            ** FOR SECURITY PURPOSE, it is mandatory to use SSL to connect your teampass instance. The user password is not encrypted!
1532
            **
1533
            **
1534
            ** Expected call format: .../api/index.php/auth/<PROTOCOL>/<URL>/<login>/<password>?apikey=<VALID API KEY>
1535
            ** Example: https://127.0.0.1/teampass/api/index.php/auth/http/www.zadig-tge.adp.com/U1/test/76?apikey=chahthait5Aidood6johh6Avufieb6ohpaixain
1536
            ** RESTRICTIONS:
1537
            **              - <PROTOCOL>        ==> http|https|ftp|...
1538
            **              - <URL>             ==> encode URL without protocol (example: http://www.teampass.net becomes www.teampass.net)
1539
            **              - <login>           ==> user's login
1540
            **              - <password>        ==> currently clear password
1541
            **
1542
            ** RETURNED ANSWER:
1543
            **              - format sent back is JSON
1544
            **              - Example: {"<item_id>":{"label":"<pass#1>","login":"<login#1>","pw":"<pwd#1>"},"<item_id>":{"label":"<pass#2>","login":"<login#2>","pw":"<pwd#2>"}}
1545
            **
1546
            */
1547
            // get user credentials
1548
            if (isset($GLOBALS['request'][3]) && isset($GLOBALS['request'][4])) {
1549
                // get url
1550
                if (isset($GLOBALS['request'][1]) && isset($GLOBALS['request'][2])) {
1551
                    // is user granted?
1552
                    $userData = DB::queryFirstRow(
1553
                        "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id`
1554
                        FROM ".prefix_table("users")."
1555
                        WHERE login = %s",
1556
                        $GLOBALS['request'][3]
1557
                    );
1558
1559
                    // load passwordLib library
1560
                    require_once '../sources/SplClassLoader.php';
1561
                    $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
1562
                    $pwdlib->register();
1563
                    $pwdlib = new PasswordLib\PasswordLib();
1564
1565
                    if ($pwdlib->verifyPasswordHash($GLOBALS['request'][4], $userData['pw']) === true) {
1566
                        // define the restriction of "id_tree" of this user
1567
                        //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...
1568
                        $userDef = DB::queryOneColumn(
1569
                            'folder_id',
1570
                            "SELECT DISTINCT folder_id
1571
                            FROM ".prefix_table("roles_values")."
1572
                            WHERE type IN ('R', 'W', 'ND', 'NE', 'NDNE', 'NEND') ",
1573
                            empty($userData['groupes_interdits']) ? "" : "
1574
                            AND folder_id NOT IN (".str_replace(";", ",", $userData['groupes_interdits']).")",
1575
                            "AND role_id IN %ls
1576
                            GROUP BY folder_id",
1577
                            explode(";", $userData['groupes_interdits'])
1578
                        );
1579
                        // complete with "groupes_visibles"
1580
                        foreach (explode(";", $userData['groupes_visibles']) as $v) {
1581
                            array_push($userDef, $v);
1582
                        }
1583
1584
                        // find the item associated to the url
1585
                        $response = DB::query(
1586
                            "SELECT id, label, login, pw, pw_iv, id_tree, restricted_to
1587
                            FROM ".prefix_table("items")."
1588
                            WHERE url LIKE %s
1589
                            AND id_tree IN (".implode(",", $userDef).")
1590
                            ORDER BY id DESC",
1591
                            $GLOBALS['request'][1]."://".urldecode($GLOBALS['request'][2].'%')
1592
                        );
1593
                        $counter = DB::count();
1594
1595
                        if ($counter > 0) {
1596
                            $json = "";
1597
                            foreach ($response as $data) {
1598
                                // check if item visible
1599
                                if (empty($data['restricted_to']) ||
1600
                                    ($data['restricted_to'] != "" && in_array($userData['id'], explode(";", $data['restricted_to'])))
1601
                                ) {
1602
                                    // prepare export
1603
                                    $json[$data['id']]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
1604
                                    $json[$data['id']]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
1605
                                    $crypt_pw = cryption(
1606
                                        $data['pw'],
1607
                                        "",
1608
                                        "decrypt"
1609
                                    );
1610
                                    $json[$data['id']]['pw'] = $crypt_pw['string'];
1611
                                }
1612
                            }
1613
                            // prepare answer. If no access then inform
1614
                            if (empty($json)) {
0 ignored issues
show
introduced by
The condition empty($json) is always true.
Loading history...
1615
                                rest_error('AUTH_NO_DATA');
1616
                            } else {
1617
                                echo json_encode($json);
1618
                            }
1619
                        } else {
1620
                            rest_error('NO_DATA_EXIST');
1621
                        }
1622
                    } else {
1623
                        rest_error('AUTH_NOT_GRANTED');
1624
                    }
1625
                } else {
1626
                    rest_error('AUTH_NO_URL');
1627
                }
1628
            } else {
1629
                rest_error('AUTH_NO_IDENTIFIER');
1630
            }
1631
        } elseif ($GLOBALS['request'][0] === "auth_tpc") {
1632
            /*
1633
            ** TO BE USED ONLY BY TEAMPASS-CONNECT
1634
            **
1635
            */
1636
            // get user credentials
1637
            if (isset($GLOBALS['request'][1])) {
1638
                // Get passed variables
1639
                $passedData = explode(';', base64_decode($GLOBALS['request'][1]));
1640
                if (count($passedData) === 4) {
1641
                    $tpc_url = $passedData[0];
1642
                    $user_login = $passedData[1];
1643
                    $user_pwd = $passedData[2];
1644
                    $user_saltkey = $passedData[3];
1645
1646
                    // get url
1647
                    if (isset($tpc_url)) {
1648
                        // is user granted?
1649
                        $userData = DB::queryFirstRow(
1650
                            "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id`, `encrypted_psk`
1651
                            FROM ".prefix_table("users")."
1652
                            WHERE login = %s",
1653
                            $user_login
1654
                        );
1655
1656
                        // Check if user exists
1657
                        if (empty($userData['id']) === true) {
1658
                            rest_error('AUTH_NOT_GRANTED');
1659
                        }
1660
1661
                        // check if psk is correct.
1662
                        if (empty($user_saltkey) === false) {
1663
                            $user_saltkey = defuse_validate_personal_key(
1664
                                $user_saltkey,
1665
                                $userData['encrypted_psk']
1666
                            );
1667
                            if (strpos($user_saltkey, "Error ") !== false) {
1668
                                // error
1669
                                rest_error('AUTH_PSK_ERROR');
1670
                            }
1671
                        }
1672
1673
                        // load passwordLib library
1674
                        require_once '../sources/SplClassLoader.php';
1675
                        $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
1676
                        $pwdlib->register();
1677
                        $pwdlib = new PasswordLib\PasswordLib();
1678
1679
                        if ($pwdlib->verifyPasswordHash($user_pwd, $userData['pw']) === true) {
1680
                            // Manage the case TPC asks for user identification
1681
                            if ($tpc_url === 'identify_user') {
1682
                                echo json_encode(array('err' => '', 'status' => 'USER_GRANTED'));
1683
                                return false;
1684
                            }
1685
1686
                            // define the restriction of "id_tree" of this user
1687
                            //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...
1688
                            $userDef = DB::queryOneColumn(
1689
                                'folder_id',
1690
                                "SELECT DISTINCT folder_id
1691
                                FROM ".prefix_table("roles_values")."
1692
                                WHERE type IN ('R', 'W', 'ND', 'NE', 'NDNE', 'NEND') ",
1693
                                empty($userData['groupes_interdits']) ? "" : "AND folder_id NOT IN (".str_replace(";", ",", $userData['groupes_interdits']).")",
1694
                                "AND role_id IN %ls
1695
                                GROUP BY folder_id",
1696
                                explode(";", $userData['groupes_interdits'])
1697
                            );
1698
                            // complete with "groupes_visibles"
1699
                            foreach (explode(";", $userData['groupes_visibles']) as $v) {
1700
                                array_push($userDef, $v);
1701
                            }
1702
1703
                            // add PF
1704
                            $userpf = DB::queryFirstRow(
1705
                                "SELECT `id` FROM ".prefix_table("nested_tree")." WHERE title = %s",
1706
                                $userData['id']
1707
                            );
1708
                            array_push($userDef, $userpf['id']);
1709
1710
                            // Parse provided URL
1711
                            $url_scheme = parse_url($tpc_url, PHP_URL_SCHEME);
1712
                            $url_post = parse_url($tpc_url, PHP_URL_HOST);
1713
1714
                            // find the item associated to the url
1715
                            //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...
1716
                            $response = DB::query(
1717
                                "SELECT id, label, login, pw, pw_iv, id_tree, restricted_to, perso
1718
                                FROM ".prefix_table("items")."
1719
                                WHERE url LIKE %s
1720
                                AND id_tree IN (".implode(",", array_filter($userDef)).")
1721
                                AND inactif = %i
1722
                                ORDER BY id DESC",
1723
                                $url_scheme.'://'.$url_post.'%',
1724
                                0
1725
                            );
1726
                            $counter = DB::count();
1727
1728
                            if ($counter > 0) {
1729
                                $json = [];
1730
                                foreach ($response as $data) {
1731
                                    // check if item visible
1732
                                    if (empty($data['restricted_to']) ||
1733
                                        ($data['restricted_to'] != "" && in_array($userData['id'], explode(";", $data['restricted_to'])))
1734
                                    ) {
1735
                                        // prepare export
1736
                                        $json[$data['id']]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
1737
                                        $json[$data['id']]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
1738
                                        if ($data['perso'] === "0") {
1739
                                            $crypt_pw = cryption(
1740
                                                $data['pw'],
1741
                                                "",
1742
                                                "decrypt"
1743
                                            );
1744
                                        } elseif (empty($user_saltkey)) {
1745
                                            $crypt_pw['string'] = "no_psk";
1746
                                        } else {
1747
                                            $crypt_pw = cryption(
1748
                                                $data['pw'],
1749
                                                $user_saltkey,
1750
                                                "decrypt"
1751
                                            );
1752
                                        }
1753
                                        $json[$data['id']]['pw'] = mb_detect_encoding($crypt_pw['string'], 'UTF-8', true) ? $crypt_pw['string'] : "not_utf8";
1754
                                        $json[$data['id']]['perso'] = $data['perso'];
1755
                                        $json[$data['id']]['domain'] = $url_scheme.'://'.$url_post;
1756
                                        $json[$data['id']]['id'] = $data['id'];
1757
                                    }
1758
                                }
1759
                                // prepare answer. If no access then inform
1760
                                if (empty($json)) {
1761
                                    rest_error('AUTH_NO_DATA');
1762
                                } else {
1763
                                    echo json_encode($json);
1764
                                }
1765
                            } else {
1766
                                rest_error('NO_DATA_EXIST');
1767
                            }
1768
                        } else {
1769
                            rest_error('AUTH_NOT_GRANTED');
1770
                        }
1771
                    } else {
1772
                        rest_error('AUTH_NO_URL');
1773
                    }
1774
                } else {
1775
                  rest_error('AUTH_NO_IDENTIFIER');
1776
                }
1777
            } else {
1778
                rest_error('AUTH_NO_IDENTIFIER');
1779
            }
1780
        } else if ($GLOBALS['request'][0] === "tpc_find") {
1781
            // get user credentials
1782
            if (isset($GLOBALS['request'][1])) {
1783
                // Get passed variables
1784
                $passedData = explode(';', base64_decode($GLOBALS['request'][1]));
1785
                $tpc_phrase = $passedData[0];
1786
                $user_login = $passedData[1];
1787
                $user_pwd = $passedData[2];
1788
                $user_saltkey = $passedData[3];
1789
1790
                // get url
1791
                if (isset($tpc_phrase)) {
1792
                    // is user granted?
1793
                    //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...
1794
                    $userData = DB::queryFirstRow(
1795
                        "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id`, `encrypted_psk`
1796
                        FROM ".prefix_table("users")."
1797
                        WHERE login = %s",
1798
                        $user_login
1799
                    );
1800
1801
                    // check if psk is correct.
1802
                    if (empty($user_saltkey) === false) {
1803
                        $user_saltkey = defuse_validate_personal_key(
1804
                            $user_saltkey,
1805
                            $userData['encrypted_psk']
1806
                        );
1807
                        if (strpos($user_saltkey, "Error ") !== false) {
1808
                            // error
1809
                            rest_error('AUTH_PSK_ERROR');
1810
                        }
1811
                    }
1812
1813
                    // load passwordLib library
1814
                    require_once '../sources/SplClassLoader.php';
1815
                    $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
1816
                    $pwdlib->register();
1817
                    $pwdlib = new PasswordLib\PasswordLib();
1818
1819
                    if ($pwdlib->verifyPasswordHash($user_pwd, $userData['pw']) === true) {
1820
                        // define the restriction of "id_tree" of this user
1821
                        //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...
1822
                        $userDef = DB::queryOneColumn(
1823
                            'folder_id',
1824
                            "SELECT DISTINCT folder_id
1825
                            FROM ".prefix_table("roles_values")."
1826
                            WHERE type IN ('R', 'W', 'ND', 'NE', 'NDNE', 'NEND') ",
1827
                            empty($userData['groupes_interdits']) ? "" : "AND folder_id NOT IN (".str_replace(";", ",", $userData['groupes_interdits']).")",
1828
                            "AND role_id IN %ls
1829
                            GROUP BY folder_id",
1830
                            explode(";", $userData['groupes_interdits'])
1831
                        );
1832
                        // complete with "groupes_visibles"
1833
                        foreach (explode(";", $userData['groupes_visibles']) as $v) {
1834
                            array_push($userDef, $v);
1835
                        }
1836
1837
                        // add PF
1838
                        $userpf = DB::queryFirstRow(
1839
                            "SELECT `id` FROM ".prefix_table("nested_tree")." WHERE title = %s",
1840
                            $userData['id']
1841
                        );
1842
                        array_push($userDef, $userpf['id']);
1843
1844
                        // Clean phrase
1845
                        if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $tpc_phrase, $result)) {
1846
                            rest_error('ITEM_MALFORMED');
1847
                        } elseif (empty($tpc_phrase)) {
1848
                            rest_error('MALFORMED');
1849
                        }
1850
1851
                        // find the item associated to the url
1852
                        //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...
1853
                        $response = DB::query(
1854
                            "SELECT id, label, login, pw, pw_iv, id_tree, restricted_to, perso, url
1855
                            FROM ".prefix_table("items")."
1856
                            WHERE (url LIKE %s OR label LIKE %s)
1857
                            AND id_tree IN (".implode(",", array_filter($userDef)).")
1858
                            AND inactif = %i
1859
                            ORDER BY id DESC",
1860
                            $tpc_phrase.'%',
1861
                            $tpc_phrase.'%',
1862
                            0
1863
                        );
1864
                        $counter = DB::count();
1865
1866
                        if ($counter > 0) {
1867
                            $json = [];
1868
                            $i = 0;
1869
                            foreach ($response as $data) {
1870
                                // check if item visible
1871
                                if (empty($data['restricted_to']) ||
1872
                                    ($data['restricted_to'] != "" && in_array($userData['id'], explode(";", $data['restricted_to'])))
1873
                                ) {
1874
                                    // prepare export
1875
                                    $json[$i]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
1876
                                    $json[$i]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
1877
                                    if ($data['perso'] === "0") {
1878
                                        $crypt_pw = cryption(
1879
                                            $data['pw'],
1880
                                            "",
1881
                                            "decrypt"
1882
                                        );
1883
                                    } elseif (empty($user_saltkey)) {
1884
                                        $crypt_pw['string'] = "no_psk";
1885
                                    } else {
1886
                                        $crypt_pw = cryption(
1887
                                            $data['pw'],
1888
                                            $user_saltkey,
1889
                                            "decrypt"
1890
                                        );
1891
                                    }
1892
                                    $json[$i]['pw'] = mb_detect_encoding($crypt_pw['string'], 'UTF-8', true) ? $crypt_pw['string'] : "not_utf8";
1893
                                    $json[$i]['perso'] = $data['perso'];
1894
                                    $json[$i]['domain'] = $data['url'];
1895
                                    $json[$i]['id'] = $data['id'];
1896
1897
                                    $i++;
1898
                                }
1899
                            }
1900
                            // prepare answer. If no access then inform
1901
                            if (empty($json)) {
1902
                                rest_error('AUTH_NO_DATA');
1903
                            } else {
1904
                                echo json_encode($json);
1905
                            }
1906
                        } else {
1907
                            rest_error('NO_DATA_EXIST');
1908
                        }
1909
                    } else {
1910
                        rest_error('AUTH_NOT_GRANTED');
1911
                    }
1912
                } else {
1913
                    rest_error('AUTH_NO_URL');
1914
                }
1915
            } else {
1916
                rest_error('AUTH_NO_IDENTIFIER');
1917
            }
1918
        } elseif ($GLOBALS['request'][0] == "tpc_userfolders") {
1919
            /*
1920
            * READ USER FOLDERS
1921
            * Sends back a list of folders
1922
            */
1923
            // get user credentials
1924
            if (isset($GLOBALS['request'][1])) {
1925
                // Get passed variables
1926
                $passedData = explode(';', base64_decode($GLOBALS['request'][1]));
1927
                $user_login = $passedData[0];
1928
                $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...
1929
                $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...
1930
1931
                $json = [];
1932
                $inc = 0;
1933
                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...
1934
                    // forbid admin access
1935
                }
1936
                $response = DB::query(
1937
                    "SELECT id AS user_id, fonction_id
1938
                    FROM ".prefix_table("users")."
1939
                    WHERE login = %s",
1940
                    $user_login
1941
                );
1942
                if (count($response) === 0) {
1943
                    rest_error('USER_NOT_EXISTS ');
1944
                }
1945
                foreach ($response as $data) {
1946
                    $role_str = $data['fonction_id'];
1947
                    $user_id = $data['user_id'];
1948
                }
1949
1950
                // Build tree
1951
                require_once '../sources/SplClassLoader.php';
1952
                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
1953
                $tree->register();
1954
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
1955
                $tree->rebuild();
1956
1957
                // If personal exists then get list of PF
1958
                $persoFld = DB::queryfirstrow(
1959
                    "SELECT id, title, nlevel
1960
                    FROM ".prefix_table("nested_tree")."
1961
                    WHERE title = %s",
1962
                    $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 1945. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1963
                );
1964
                if (empty($persoFld['id']) === false) {
1965
                    // Store main PF
1966
                    $json[$inc]['id'] = $persoFld['id'];
1967
                    $json[$inc]['title'] = $user_login;
1968
                    $json[$inc]['level'] = $persoFld['nlevel'];
1969
                    $json[$inc]['access_type'] = "W";
1970
                    $inc++;
1971
1972
                    // get all descendants
1973
                    $ids = $tree->getDescendants($persoFld['id'], false, false);
1974
                    foreach ($ids as $ident) {
1975
                        // Do query to get folder info
1976
                        $fldInfo = DB::queryfirstrow(
1977
                            "SELECT title, nlevel
1978
                            FROM ".prefix_table("nested_tree")."
1979
                            WHERE id = %i",
1980
                            $ident->id
1981
                        );
1982
1983
                        // Store info
1984
                        $json[$inc]['id'] = $ident->id;
1985
                        $json[$inc]['title'] = $fldInfo['title'];
1986
                        $json[$inc]['level'] = $fldInfo['nlevel'];
1987
                        $json[$inc]['personal'] = "1";
1988
                        $json[$inc]['access_type'] = "W";
1989
                        $inc++;
1990
                    }
1991
                }
1992
1993
                $folder_arr = array();
1994
                $roles = explode(";", $role_str);
1995
                foreach ($roles as $role) {
1996
                    $response = DB::query(
1997
                        "SELECT folder_id, type
1998
                        FROM ".prefix_table("roles_values")."
1999
                        WHERE role_id = %i",
2000
                        $role
2001
                    );
2002
                    foreach ($response as $data) {
2003
                        $folder_id = $data['folder_id'];
2004
                        if (array_key_exists($folder_id, $folder_arr) === false) {
2005
                            array_push($folder_arr, $folder_id);
2006
2007
                            $response2 = DB::queryFirstRow(
2008
                                "SELECT title, nlevel
2009
                                FROM ".prefix_table("nested_tree")."
2010
                                WHERE id = %i",
2011
                                $folder_id
2012
                            );
2013
2014
                            if (empty($response2['title']) === false) {
2015
                                // get all descendants
2016
                                $ids = $tree->getDescendants($folder_id, true, false);
2017
                                foreach ($ids as $ident) {
2018
                                    if (array_key_exists($ident->id, $folder_arr) === false) {
2019
                                        array_push($folder_arr, $ident->id);
2020
                                        // Do query to get folder info
2021
                                        $fldInfo = DB::queryfirstrow(
2022
                                            "SELECT title, nlevel
2023
                                            FROM ".prefix_table("nested_tree")."
2024
                                            WHERE id = %i",
2025
                                            $ident->id
2026
                                        );
2027
2028
                                        // Store info
2029
                                        $json[$inc]['id'] = $ident->id;
2030
                                        $json[$inc]['title'] = $fldInfo['title'];
2031
                                        $json[$inc]['level'] = $fldInfo['nlevel'];
2032
                                        $json[$inc]['personal'] = "0";
2033
                                        $json[$inc]['access_type'] = "W";
2034
                                        $inc++;
2035
                                    }
2036
                                }
2037
                                /*$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...
2038
                                $json[$inc]['title'] = $response2['title'];
2039
                                $json[$inc]['level'] = $response2['nlevel'];
2040
                                $json[$inc]['access_type'] = $data['type'];
2041
                                $json[$inc]['personal'] = "0";
2042
                                $inc++;*/
2043
                            }
2044
                        }
2045
                    }
2046
                }
2047
                // prepare answer. If no access then inform
2048
                if (empty($json)) {
2049
                    rest_error('AUTH_NO_DATA');
2050
                } else {
2051
                    echo json_encode($json);
2052
                }
2053
            }
2054
        } elseif ($GLOBALS['request'][0] == "set") {
2055
            /*
2056
             * Expected call format: .../api/index.php/set/<login_to_save>/<password_to_save>/<url>/<user_login>/<user_password>/<label>/<protocol>?apikey=<VALID API KEY>
2057
             * Example: https://127.0.0.1/teampass/api/index.php/set/newLogin/newPassword/newUrl/myLogin/myPassword?apikey=gu6Eexaewaishooph6iethoh5woh0yoit6ohquo
2058
             *
2059
             * NEW ITEM WILL BE STORED IN SPECIFIC FOLDER
2060
             */
2061
            // get user credentials
2062
            if (isset($GLOBALS['request'][4]) && isset($GLOBALS['request'][5])) {
2063
                // get url
2064
                if (isset($GLOBALS['request'][1]) && isset($GLOBALS['request'][2]) && isset($GLOBALS['request'][3])) {
2065
                    // is user granted?
2066
                    $userData = DB::queryFirstRow(
2067
                        "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id`
2068
                        FROM ".prefix_table("users")."
2069
                        WHERE login = %s",
2070
                        $GLOBALS['request'][4]
2071
                    );
2072
                    if (DB::count() == 0) {
2073
                        rest_error('AUTH_NO_IDENTIFIER');
2074
                    }
2075
2076
                    // load passwordLib library
2077
                    require_once '../sources/SplClassLoader.php';
2078
                    $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
2079
                    $pwdlib->register();
2080
                    $pwdlib = new PasswordLib\PasswordLib();
2081
2082
                    // is user identified?
2083
                    if ($pwdlib->verifyPasswordHash($GLOBALS['request'][5], $userData['pw']) === true) {
2084
                        // does the personal folder of this user exists?
2085
                        DB::queryFirstRow(
2086
                            "SELECT `id`
2087
                            FROM ".prefix_table("nested_tree")."
2088
                            WHERE title = %s AND personal_folder = 1",
2089
                            $userData['id']
2090
                        );
2091
                        if (DB::count() > 0) {
2092
                            // check if "teampass-connect" folder exists
2093
                            // if not create it
2094
                            $folder = DB::queryFirstRow(
2095
                                "SELECT `id`
2096
                                FROM " . $pre."nested_tree
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $pre seems to be never defined.
Loading history...
2097
                                WHERE title = %s",
2098
                                "teampass-connect"
2099
                            );
2100
                            if (DB::count() == 0) {
2101
                                DB::insert(
2102
                                    prefix_table("nested_tree"),
2103
                                    array(
2104
                                        'parent_id' => '0',
2105
                                        'title' => "teampass-connect"
2106
                                    )
2107
                                );
2108
                                $tpc_folder_id = DB::insertId();
2109
2110
                                //Add complexity
2111
                                DB::insert(
2112
                                    prefix_table("misc"),
2113
                                    array(
2114
                                        'type' => 'complex',
2115
                                        'intitule' => $tpc_folder_id,
2116
                                        'valeur' => '0'
2117
                                    )
2118
                                );
2119
2120
                                // rebuild tree
2121
                                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
2122
                                $tree->register();
2123
                                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
2124
                                $tree->rebuild();
2125
                            } else {
2126
                                $tpc_folder_id = $folder['id'];
2127
                            }
2128
2129
                            // encrypt password
2130
                            $encrypt = cryption(
2131
                                $GLOBALS['request'][2],
2132
                                "",
2133
                                "encrypt"
2134
                            );
2135
2136
                            // is there a protocol?
2137
                            if (isset($GLOBALS['request'][7]) || empty($GLOBALS['request'][7])) {
2138
                                $protocol = "http://";
0 ignored issues
show
Unused Code introduced by
The assignment to $protocol is dead and can be removed.
Loading history...
2139
                            } else {
2140
                                $protocol = urldecode($GLOBALS['request'][7])."://";
2141
                            }
2142
2143
                            // add new item
2144
                            DB::insert(
2145
                                prefix_table("items"),
2146
                                array(
2147
                                    'label' => "Credentials for ".urldecode($GLOBALS['request'][3]),
2148
                                    'description' => "Imported with Teampass-Connect",
2149
                                    'pw' => $encrypt['string'],
2150
                                    'pw_iv' => "",
2151
                                    'email' => "",
2152
                                    'url' => urldecode($GLOBALS['request'][3]),
2153
                                    'id_tree' => $tpc_folder_id,
2154
                                    'login' => $GLOBALS['request'][1],
2155
                                    'inactif' => '0',
2156
                                    'restricted_to' => $userData['id'],
2157
                                    'perso' => '0',
2158
                                    'anyone_can_modify' => '0',
2159
                                    'complexity_level' => '0'
2160
                                )
2161
                            );
2162
                            $newID = DB::insertId();
2163
2164
                            // log
2165
                            logItems(
2166
                                $newID,
2167
                                "Credentials for ".urldecode($GLOBALS['request'][3].'%'),
2168
                                $userData['id'],
2169
                                'at_creation',
2170
                                $GLOBALS['request'][1]
2171
                            );
2172
2173
                            $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...
2174
                            // prepare answer. If no access then inform
2175
                            if (empty($json)) {
2176
                                rest_error('AUTH_NO_DATA');
2177
                            } else {
2178
                                echo json_encode($json);
2179
                            }
2180
                        } else {
2181
                            rest_error('NO_PF_EXIST_FOR_USER');
2182
                        }
2183
                    } else {
2184
                        rest_error('AUTH_NOT_GRANTED');
2185
                    }
2186
                } else {
2187
                    rest_error('SET_NO_DATA');
2188
                }
2189
            } else {
2190
                rest_error('AUTH_NO_IDENTIFIER');
2191
            }
2192
        } elseif ($GLOBALS['request'][0] == "set_tpc") {
2193
            /*
2194
             * TO BE USED ONLY BY TEAMPASS-CONNECT
2195
             */
2196
            // get user credentials
2197
            if (isset($GLOBALS['request'][1]) === true && isset($GLOBALS['request'][2]) === true && isset($GLOBALS['request'][3]) === true) {
2198
                // Get passed variables
2199
                $item_definition = json_decode(base64_decode($GLOBALS['request'][2]), true);
2200
                $passedData = explode(';', base64_decode($GLOBALS['request'][3]));
2201
                $user_login = $passedData[0];
2202
                $user_pwd = $passedData[1];
2203
                $user_saltkey = $passedData[2];
2204
2205
                // is user granted?
2206
                $userData = DB::queryFirstRow(
2207
                    "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id`
2208
                    FROM ".prefix_table("users")."
2209
                    WHERE login = %s",
2210
                    $user_login
2211
                );
2212
                if (DB::count() === 0) {
2213
                    rest_error('AUTH_NO_IDENTIFIER');
2214
                }
2215
2216
                // load passwordLib library
2217
                require_once '../sources/SplClassLoader.php';
2218
                $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
2219
                $pwdlib->register();
2220
                $pwdlib = new PasswordLib\PasswordLib();
2221
2222
                // is user identified?
2223
                if ($pwdlib->verifyPasswordHash($user_pwd, $userData['pw']) === true) {
2224
                    // It is a new ITEM
2225
                    if ($GLOBALS['request'][1] === "add") {
2226
                        // encrypt PW
2227
                        if ($item_definition['personal'] === '1') {
2228
                            $passwd = cryption(
2229
                                $item_definition['pwd'],
2230
                                $user_saltkey,
2231
                                "encrypt"
2232
                            );
2233
                        } else {
2234
                            $passwd = cryption(
2235
                                $item_definition['pwd'],
2236
                                "",
2237
                                "encrypt"
2238
                            );
2239
                        }
2240
2241
                        // add new item
2242
                        DB::insert(
2243
                            prefix_table("items"),
2244
                            array(
2245
                                'label' => $item_definition['label'],
2246
                                'description' => $item_definition['description'],
2247
                                'pw' => $passwd['string'],
2248
                                'pw_iv' => "",
2249
                                'email' => "",
2250
                                'url' => $item_definition['url'],
2251
                                'id_tree' => $item_definition['destination_folder'],
2252
                                'login' => $item_definition['login'],
2253
                                'inactif' => '0',
2254
                                'restricted_to' => $userData['id'],
2255
                                'perso' => '0',
2256
                                'anyone_can_modify' => '0',
2257
                                'complexity_level' => '0'
2258
                            )
2259
                        );
2260
                        $newID = DB::insertId();
2261
2262
                        // log
2263
                        logItems(
2264
                            $newID,
2265
                            $item_definition['label'],
2266
                            $userData['id'],
2267
                            'at_creation',
2268
                            $GLOBALS['request'][1]
2269
                        );
2270
2271
                        // rebuild tree
2272
                        $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
2273
                        $tree->register();
2274
                        $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
2275
                        $tree->rebuild();
2276
2277
                        echo json_encode(array('new_id' => $newID , 'err' => ''));
2278
                    } elseif ($GLOBALS['request'][1] === "edit") {
2279
                        // Is this folder a personal one?
2280
                        $fldData = DB::queryFirstRow(
2281
                            "SELECT `personal_folder`
2282
                            FROM ".prefix_table("nested_tree")."
2283
                            WHERE id = %i",
2284
                            $item_definition['item_id']
2285
                        );
2286
2287
                        // encrypt PW
2288
                        if ($fldData['personal_folder'] === '1') {
2289
                            $passwd = cryption(
2290
                                $item_definition['pwd'],
2291
                                $user_saltkey,
2292
                                "encrypt"
2293
                            );
2294
                        } else {
2295
                            $passwd = cryption(
2296
                                $item_definition['pwd'],
2297
                                "",
2298
                                "encrypt"
2299
                            );
2300
                        }
2301
2302
                        // UPDATE item
2303
                        DB::update(
2304
                            prefix_table("items"),
2305
                            array(
2306
                                'pw' => $passwd['string'],
2307
                                'pw_iv' => '',
2308
                                "url" => $item_definition['url'],
2309
                                "login" => $item_definition['login']
2310
                            ),
2311
                            "id = %i",
2312
                            $item_definition['item_id']
2313
                        );
2314
2315
                        // log
2316
                        DB::insert(
2317
                            prefix_table("log_items"),
2318
                            array(
2319
                                "id_item" => $item_definition['item_id'],
2320
                                "date" => time(),
2321
                                "id_user" => $userData['id'],
2322
                                "action" => "at_modification"
2323
                            )
2324
                        );
2325
2326
                        // Update CACHE table
2327
                        DB::update(
2328
                            prefix_table("cache"),
2329
                            array(
2330
                                "login" => $item_definition['login'],
2331
                                "author" => $userData['id'],
2332
                                "timestamp" => time(),
2333
                                "url" => $item_definition['url'],
2334
                            ),
2335
                            "id = %i",
2336
                            $item_definition['item_id']
2337
                        );
2338
2339
                        echo json_encode(array('new_id' => '' , 'err' => ''));
2340
                    }
2341
                } else {
2342
                    rest_error('AUTH_NOT_GRANTED');
2343
                }
2344
            } else {
2345
                rest_error('AUTH_NO_IDENTIFIER');
2346
            }
2347
        } elseif ($GLOBALS['request'][0] == "tpc_delete") {
2348
            /*
2349
             * TO BE USED ONLY BY TEAMPASS-CONNECT
2350
             */
2351
            // get user credentials
2352
            if (isset($GLOBALS['request'][1]) === true) {
2353
                // Get passed variables
2354
                $passedData = explode(';', base64_decode($GLOBALS['request'][1]));
2355
                $item_id = $passedData[0];
2356
                $user_login = $passedData[1];
2357
                $user_pwd = $passedData[2];
2358
                $user_saltkey = $passedData[3];
2359
2360
                // is user granted?
2361
                $userData = DB::queryFirstRow(
2362
                    "SELECT `id`, `pw`, `groupes_interdits`, `groupes_visibles`, `fonction_id`
2363
                    FROM ".prefix_table("users")."
2364
                    WHERE login = %s",
2365
                    $user_login
2366
                );
2367
                if (DB::count() == 0) {
2368
                    rest_error('AUTH_NO_IDENTIFIER');
2369
                }
2370
2371
                // load passwordLib library
2372
                require_once '../sources/SplClassLoader.php';
2373
                $pwdlib = new SplClassLoader('PasswordLib', '../includes/libraries');
2374
                $pwdlib->register();
2375
                $pwdlib = new PasswordLib\PasswordLib();
2376
2377
                // is user identified?
2378
                if ($pwdlib->verifyPasswordHash($user_pwd, $userData['pw']) === true) {
2379
                    DB::update(
2380
                        prefix_table("items"),
2381
                        array(
2382
                            'inactif' => '1',
2383
                        ),
2384
                        "id = %i",
2385
                        $item_id
2386
                    );
2387
                    //log
2388
                    DB::insert(
2389
                        prefix_table("log_items"),
2390
                        array(
2391
                            'id_item' => $item_id,
2392
                            'date' => time(),
2393
                            'id_user' => $userData['id'],
2394
                            'action' => 'at_delete'
2395
                        )
2396
                    );
2397
2398
                    //Update CACHE table
2399
                    updateCacheTable("delete_value", $item_id);
2400
2401
                    echo json_encode(array('code' => 'done'));
2402
                } else {
2403
                    rest_error('AUTH_NOT_GRANTED');
2404
                }
2405
            } else {
2406
                rest_error('AUTH_NO_IDENTIFIER');
2407
            }
2408
        } elseif ($GLOBALS['request'][0] === "delete") {
2409
        /*
2410
        * DELETE
2411
        *
2412
        * Expected call format: .../api/index.php/delete/folder/<folder_id1;folder_id2;folder_id3>?apikey=<VALID API KEY>
2413
        * Expected call format: .../api/index.php/delete/item>/<item_id1;item_id2;item_id3>?apikey=<VALID API KEY>
2414
        */
2415
            if ($GLOBALS['request'][1] === "folder") {
2416
                $array_category = explode(';', $GLOBALS['request'][2]);
2417
2418
                // get user info
2419
                if (isset($GLOBALS['request'][3]) && !empty($GLOBALS['request'][3])) {
2420
                    $userData = DB::queryFirstRow(
2421
                        "SELECT `id` FROM ".$pre."users WHERE login = %s",
2422
                        $GLOBALS['request'][3]
2423
                    );
2424
                    if (DB::count() == 0) {
2425
                        $user_id = API_USER_ID;
2426
                    } else {
2427
                        $user_id = $userData['id'];
2428
                    }
2429
                } else {
2430
                    $user_id = API_USER_ID;
2431
                }
2432
2433
                if (count($array_category) > 0 && count($array_category) < 5) {
2434
                    // load passwordLib library
2435
                    require_once '../sources/SplClassLoader.php';
2436
2437
                    // prepare tree
2438
                    $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
2439
                    $tree->register();
2440
                    $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

2440
                    $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...
2441
2442
                    // this will delete all sub folders and items associated
2443
                    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...
2444
                        // Does this folder exist?
2445
                        DB::queryFirstRow(
2446
                            "SELECT id
2447
                            FROM ".prefix_table("nested_tree")."
2448
                            WHERE id = %i",
2449
                            $array_category[$i]
2450
                        );
2451
                        if (DB::count() > 0) {
2452
                            // Get through each subfolder
2453
                            $folders = $tree->getDescendants($array_category[$i], true);
2454
                            if (count($folders) > 0) {
2455
                                foreach ($folders as $folder) {
2456
                                    if (($folder->parent_id > 0 || $folder->parent_id == 0) && $folder->personal_folder != 1) {
2457
                                        //Store the deleted folder (recycled bin)
2458
                                        DB::insert(
2459
                                            prefix_table("misc"),
2460
                                            array(
2461
                                                'type' => 'folder_deleted',
2462
                                                'intitule' => "f".$array_category[$i],
2463
                                                'valeur' => $folder->id.', '.$folder->parent_id.', '.
2464
                                                    $folder->title.', '.$folder->nleft.', '.$folder->nright.', '.$folder->nlevel.', 0, 0, 0, 0'
2465
                                            )
2466
                                        );
2467
                                        //delete folder
2468
                                        DB::delete(prefix_table("nested_tree"), "id = %i", $folder->id);
2469
2470
                                        //delete items & logs
2471
                                        $items = DB::query(
2472
                                            "SELECT id
2473
                                            FROM ".prefix_table("items")."
2474
                                            WHERE id_tree=%i",
2475
                                            $folder->id
2476
                                        );
2477
                                        foreach ($items as $item) {
2478
                                            DB::update(
2479
                                                prefix_table("items"),
2480
                                                array(
2481
                                                    'inactif' => '1',
2482
                                                ),
2483
                                                "id = %i",
2484
                                                $item['id']
2485
                                            );
2486
                                            //log
2487
                                            DB::insert(
2488
                                                prefix_table("log_items"),
2489
                                                array(
2490
                                                    'id_item' => $item['id'],
2491
                                                    'date' => time(),
2492
                                                    'id_user' => $user_id,
2493
                                                    'action' => 'at_delete'
2494
                                                )
2495
                                            );
2496
                                        }
2497
                                        //Update CACHE table
2498
                                        updateCacheTable("delete_value", $array_category[$i]);
2499
                                    }
2500
                                }
2501
                            }
2502
                        } 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...
2503
                            // Folder doesn't exist
2504
                        }
2505
                    }
2506
                } else {
2507
                    rest_error('NO_CATEGORY');
2508
                }
2509
2510
                $json['status'] = 'OK';
2511
            } elseif ($GLOBALS['request'][1] == "item") {
2512
                $array_items = explode(';', $GLOBALS['request'][2]);
2513
2514
                // get user info
2515
                if (isset($GLOBALS['request'][3]) && !empty($GLOBALS['request'][3])) {
2516
                    $userData = DB::queryFirstRow(
2517
                        "SELECT `id` FROM ".$pre."users WHERE login = %s",
2518
                        $GLOBALS['request'][3]
2519
                    );
2520
                    if (DB::count() == 0) {
2521
                        $user_id = API_USER_ID;
2522
                    } else {
2523
                        $user_id = $userData['id'];
2524
                    }
2525
                }
2526
2527
                for ($i = 0, $c = count($array_items); $i < $c; $i++) {
2528
                    DB::update(
2529
                        prefix_table("items"),
2530
                        array(
2531
                            'inactif' => '1',
2532
                        ),
2533
                        "id = %i",
2534
                        $array_items[$i]
2535
                    );
2536
                    //log
2537
                    DB::insert(
2538
                        prefix_table("log_items"),
2539
                        array(
2540
                            'id_item' => $array_items[$i],
2541
                            'date' => time(),
2542
                            'id_user' => $user_id,
2543
                            'action' => 'at_delete'
2544
                        )
2545
                    );
2546
2547
                    //Update CACHE table
2548
                    updateCacheTable("delete_value", $array_items[$i]);
2549
                }
2550
2551
                $json['status'] = 'OK';
2552
            }
2553
2554
            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...
2555
                echo json_encode($json);
2556
            } else {
2557
                rest_error('EMPTY');
2558
            }
2559
        } elseif ($GLOBALS['request'][0] == "new_password") {
2560
            if (!empty($GLOBALS['request'][1])) {
2561
                $params = explode(";", $GLOBALS['request'][1]);
2562
2563
                if (empty($params[0])) {
2564
                    $params[0] = 8;
2565
                }
2566
                if (empty($params[1])) {
2567
                    $params[1] = 0;
2568
                }
2569
                if (empty($params[2])) {
2570
                    $params[2] = 0;
2571
                }
2572
                if (empty($params[3])) {
2573
                    $params[3] = 0;
2574
                }
2575
                if (empty($params[4])) {
2576
                    $params[4] = 0;
2577
                }
2578
                if (empty($params[5])) {
2579
                    $params[5] = 0;
2580
                }
2581
                if (empty($params[6])) {
2582
                    $params[6] = 0;
2583
                }
2584
2585
                // Generate key
2586
                $pwd = GenerateCryptKey(
2587
                    $params[0],
2588
                    $params[1] === "1" ? true : false,
2589
                    $params[2] === "1" ? true : false,
2590
                    $params[3] === "1" ? true : false,
2591
                    $params[5] === "1" && $params[6] === "1" ? true : false
2592
                );
2593
2594
                // generate and send back (generate in base64 if symbols are asked)
2595
                if ($params[6] === "1") {
2596
                    echo '{"password" : "'.base64_encode($pwd).'"}';
2597
                } else {
2598
                    echo '{"password" : "'.$pwd.'"}';
2599
                }
2600
            } else {
2601
                rest_error('NO_PARAMETERS');
2602
            }
2603
        } elseif ($GLOBALS['request'][0] === "info") {
2604
            if ($GLOBALS['request'][1] === "complexicity_levels_list") {
2605
                require_once '../includes/language/english.php';
2606
                $json = array(
2607
                    0=> $LANG['complex_level0'],
2608
                    25=> $LANG['complex_level1'],
2609
                    50=> $LANG['complex_level2'],
2610
                    60=> $LANG['complex_level3'],
2611
                    70=> $LANG['complex_level4'],
2612
                    80=> $LANG['complex_level5'],
2613
                    90=> $LANG['complex_level6']
2614
                );
2615
2616
                echo json_encode($json);
2617
            } elseif ($GLOBALS['request'][1] === "folder") {
2618
                if (!empty($GLOBALS['request'][2]) && is_numeric($GLOBALS['request'][2])) {
2619
                    $data = DB::queryFirstRow(
2620
                        "SELECT * FROM ".$pre."nested_tree WHERE id = %i",
2621
                        $GLOBALS['request'][2]
2622
                    );
2623
                    if (DB::count() == 0) {
2624
                        rest_error('NOSUCHFOLDER');
2625
                    }
2626
2627
                    // form id_tree to full foldername
2628
                    require_once '../sources/SplClassLoader.php';
2629
                    //Load Tree
2630
                    $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
2631
                    $tree->register();
2632
                    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
2633
2634
                    $folder = "";
2635
                    $arbo = $tree->getPath($GLOBALS['request'][2], true);
2636
                    foreach ($arbo as $elem) {
2637
                        if (empty($folder)) {
2638
                            $folder = stripslashes($elem->title);
2639
                        } else {
2640
                            $folder .= " > ".stripslashes($elem->title);
2641
                        }
2642
                    }
2643
2644
                    // prepare info
2645
                    $json = array(
2646
                        "title" => $data['title'],
2647
                        "personal_folder" => $data['personal_folder'],
2648
                        "renewal_period" => $data['renewal_period'],
2649
                        "parent_id" => $data['parent_id'],
2650
                        "path" => $folder,
2651
                    );
2652
2653
                    echo json_encode($json);
2654
                } else {
2655
                    rest_error('NO_PARAMETERS');
2656
                }
2657
            } elseif ($GLOBALS['request'][1] === "version") {
2658
                echo '{"api-version":"'.$api_version.'"}';
2659
            } else {
2660
                rest_error('NO_PARAMETERS');
2661
            }
2662
        } else {
2663
            rest_error('METHOD');
2664
        }
2665
    }
2666
}
2667
2668
function rest_put()
2669
{
2670
    if (!@count($GLOBALS['request']) == 0) {
2671
        $request_uri = $GLOBALS['_SERVER']['REQUEST_URI'];
2672
        preg_match('/\/api(\/index.php|)\/(.*)\?apikey=(.*)/', $request_uri, $matches);
2673
        if (count($matches) == 0) {
2674
            rest_error('REQUEST_SENT_NOT_UNDERSTANDABLE');
2675
        }
2676
        $GLOBALS['request'] = explode('/', $matches[2]);
2677
    }
2678
    if (apikey_checker($GLOBALS['apikey'])) {
2679
        teampass_connect();
2680
    }
2681
}
2682
2683
/**
2684
 * @param string $type
2685
 */
2686
function rest_error($type, $detail = 'N/A')
2687
{
2688
    switch ($type) {
2689
        case 'APIKEY':
2690
            $message = array('err' => 'This api_key '.$GLOBALS['apikey'].' doesn\'t exist', 'code' => 'API_KEY_NOT_FOUND');
2691
            header('HTTP/1.1 405 Method Not Allowed');
2692
            break;
2693
        case 'NO_CATEGORY':
2694
            $message = array('err' => 'No folder specified');
2695
            break;
2696
        case 'NO_ITEM':
2697
            $message = array('err' => 'No item specified');
2698
            break;
2699
        case 'EMPTY':
2700
            $message = array('err' => 'No results');
2701
            break;
2702
        case 'IPWHITELIST':
2703
            $message = array('err' => 'Ip address not allowed.');
2704
            header('HTTP/1.1 405 Method Not Allowed');
2705
            break;
2706
        case 'MYSQLERR':
2707
            $message = array('err' => $detail);
2708
            header('HTTP/1.1 500 Internal Server Error');
2709
            break;
2710
        case 'METHOD':
2711
            $message = array('err' => 'Method not authorized', 'code' => 'METHOD_NOT_AUTHORIZED');
2712
            header('HTTP/1.1 405 Method Not Allowed');
2713
            break;
2714
        case 'ITEMBADDEFINITION':
2715
            $message = array('err' => 'Item definition not complete');
2716
            header('HTTP/1.1 405 Method Not Allowed');
2717
            break;
2718
        case 'ITEM_MALFORMED':
2719
            $message = array('err' => 'Item definition not numeric');
2720
            header('HTTP/1.1 405 Method Not Allowed');
2721
            break;
2722
        case 'USERBADDEFINITION':
2723
            $message = array('err' => 'User definition not complete');
2724
            header('HTTP/1.1 405 Method Not Allowed');
2725
            break;
2726
        case 'USERLOGINEMPTY':
2727
            $message = array('err' => 'Empty Login given');
2728
            header('HTTP/1.1 405 Method Not Allowed');
2729
            break;
2730
        case 'USERALREADYEXISTS':
2731
            $message = array('err' => 'User already exists');
2732
            header('HTTP/1.1 405 Method Not Allowed');
2733
            break;
2734
        case 'REQUEST_SENT_NOT_UNDERSTANDABLE':
2735
            $message = array('err' => 'URL format is not following requirements');
2736
            break;
2737
        case 'AUTH_NOT_GRANTED':
2738
            $message = array('err' => 'Bad credentials for user', 'code' => 'AUTH_NOT_GRANTED');
2739
            header('HTTP/1.1 404 Error');
2740
            break;
2741
        case 'AUTH_NO_URL':
2742
            $message = array('err' => 'URL needed to grant access');
2743
            break;
2744
        case 'AUTH_NO_IDENTIFIER':
2745
            $message = array('err' => 'Credentials needed to grant access', 'code' => 'AUTH_NO_IDENTIFIER');
2746
            break;
2747
        case 'AUTH_NO_DATA':
2748
            $message = array('err' => 'Data not allowed for the user', 'code' => 'AUTH_NO_DATA');
2749
            break;
2750
        case 'AUTH_PSK_ERROR':
2751
            $message = array('err' => 'Personal Saltkey is wrong', 'code' => 'AUTH_PSK_ERROR');
2752
            header('HTTP/1.1 404 Error');
2753
            break;
2754
        case 'NO_DATA_EXIST':
2755
            $message = array('err' => 'No data exists', 'code' => 'NO_DATA_EXIST');
2756
            break;
2757
        case 'NO_DESTINATION_FOLDER':
2758
            $message = array('err' => 'No destination folder provided');
2759
            break;
2760
        case 'PASSWORDTOOLONG':
2761
            $message = array('err' => 'Password is too long');
2762
            break;
2763
        case 'NOSUCHFOLDER':
2764
            $message = array('err' => 'Folder ID does not exist');
2765
            break;
2766
        case 'PASSWORDEMPTY':
2767
            $message = array('err' => 'Password is empty');
2768
            break;
2769
        case 'ITEMEXISTS':
2770
            $message = array('err' => 'Label already exists');
2771
            break;
2772
        case 'ITEMMISSINGDATA':
2773
            $message = array('err' => 'Label or Password or Folder ID is missing');
2774
            break;
2775
        case 'SET_NO_DATA':
2776
            $message = array('err' => 'No data to be stored');
2777
            break;
2778
        case 'NO_PF_EXIST_FOR_USER':
2779
            $message = array('err' => 'No Personal Folder exists for this user');
2780
            break;
2781
        case 'HTML_CODES_NOT_ALLOWED':
2782
            $message = array('err' => 'HTML tags not allowed');
2783
            break;
2784
        case 'TITLE_ONLY_WITH_NUMBERS':
2785
            $message = array('err' => 'Title only with numbers not allowed');
2786
            break;
2787
        case 'ALREADY_EXISTS':
2788
            $message = array('err' => 'Data already exists');
2789
            break;
2790
        case 'COMPLEXICITY_LEVEL_NOT_REACHED':
2791
            $message = array('err' => 'complexity level was not reached');
2792
            break;
2793
        case 'NO_PARAMETERS':
2794
            $message = array('err' => 'No parameters given');
2795
            break;
2796
        case 'USER_NOT_EXISTS':
2797
            $message = array('err' => 'User does not exist');
2798
            break;
2799
        case 'NO_PSALTK_PROVIDED':
2800
            $message = array('err' => 'No Personal saltkey provided');
2801
            break;
2802
        case 'EXPECTED_PARAMETER_NOT_PROVIDED':
2803
            $message = array('err' => 'Provided parameters are not correct');
2804
            break;
2805
        default:
2806
            $message = array('err' => 'Something happen ... but what ?');
2807
            header('HTTP/1.1 500 Internal Server Error');
2808
            break;
2809
    }
2810
2811
    echo json_encode($message);
2812
    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...
2813
}
2814
2815
function apikey_checker($apikey_used)
2816
{
2817
    teampass_connect();
2818
    $apikey_pool = teampass_get_keys();
2819
2820
    // if needed extract key from credentials
2821
    if (strlen($apikey_used) > 40) {
2822
        $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...
2823
        $apikey_used = substr($apikey_used, 0, 39);
2824
    }
2825
2826
    if (in_array($apikey_used, $apikey_pool)) {
2827
        return(1);
2828
    } else {
2829
        rest_error('APIKEY', $apikey_used);
2830
    }
2831
}
2832
2833
function teampass_pbkdf2_hash($var_p, $var_s, $var_c, $var_kl, $var_st = 0, $var_a = 'sha256')
2834
{
2835
    $var_kb = $var_st + $var_kl;
2836
    $var_dk = '';
2837
2838
    for ($block = 1; $block <= $var_kb; $block++) {
2839
        $var_ib = $var_h = hash_hmac($var_a, $var_s.pack('N', $block), $var_p, true);
2840
        for ($var_i = 1; $var_i < $var_c; $var_i++) {
2841
            $var_ib ^= ($var_h = hash_hmac($var_a, $var_h, $var_p, true));
2842
        }
2843
        $var_dk .= $var_ib;
2844
    }
2845
2846
    return substr($var_dk, $var_st, $var_kl);
2847
}
2848