Passed
Push — development ( 72acab...588a17 )
by Nils
04:47
created

Urlsafe_b64decode()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

Loading history...
2
/**
3
 *
4
 * @file          (api)functions.php
5
 * @author        Nils Laumaillé
6
 * @version       2.1.0
7
 * @copyright     (c) 2009-2018 Nils Laumaillé
8
 * @licensing     GNU GPL-3.0
9
 * @link          http://www.teampass.net
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 */
15
16
$api_version = "2.1";
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'
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
/**
171
 * Permits to get rid of special characters that can break the url
172
 *
173
 * @param  string $string adapted base64 encoded string
174
 * @return string
175
 */
176
function Urlsafe_b64decode($string)
177
{
178
    $data = str_replace(
179
        array('-', '_'),
180
        array('+', '/'),
181
        $string
182
    );
183
    $mod4 = strlen($data) % 4;
184
    if ($mod4) {
185
        $data .= substr('====', $mod4);
186
    }
187
    return base64_decode($data);
188
}
189
190
function rest_delete()
191
{
192
    if (!@count($GLOBALS['request']) == 0) {
193
        $request_uri = $GLOBALS['_SERVER']['REQUEST_URI'];
194
        preg_match('/\/api(\/index.php|)\/(.*)\?apikey=(.*)/', $request_uri, $matches);
195
        if (count($matches) == 0) {
196
            rest_error('REQUEST_SENT_NOT_UNDERSTANDABLE');
197
        }
198
        $GLOBALS['request'] = explode('/', $matches[2]);
199
    }
200
    if (apikey_checker($GLOBALS['apikey'])) {
201
        include "../sources/main.functions.php";
202
        teampass_connect();
203
        $category_query = "";
204
205
        if ($GLOBALS['request'][0] == "write") {
206
            if ($GLOBALS['request'][1] == "category") {
207
                $array_category = explode(';', $GLOBALS['request'][2]);
208
209
                foreach ($array_category as $category) {
210
                    if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $category, $result)) {
211
                        rest_error('CATEGORY_MALFORMED');
212
                    }
213
                }
214
215
                if (count($array_category) > 1 && count($array_category) < 5) {
216
                    for ($i = count($array_category); $i > 0; $i--) {
217
                        $slot = $i - 1;
218
                        if (!$slot) {
219
                            $category_query .= "select id from ".prefix_table("nested_tree")." where title LIKE '".filter_var($array_category[$slot], FILTER_SANITIZE_STRING)."' AND parent_id = 0";
220
                        } else {
221
                            $category_query .= "select id from ".prefix_table("nested_tree")." where title LIKE '".filter_var($array_category[$slot], FILTER_SANITIZE_STRING)."' AND parent_id = (";
222
                        }
223
                    }
224
                    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...
225
                        $category_query .= ")";
226
                    }
227
                } elseif (count($array_category) == 1) {
228
                    $category_query = "select id from ".prefix_table("nested_tree")." where title LIKE '".filter_var($array_category[0], FILTER_SANITIZE_STRING)."' AND parent_id = 0";
229
                } else {
230
                    rest_error('NO_CATEGORY');
231
                }
232
233
                // Delete items which in category
234
                $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...
235
                // Delete sub-categories which in category
236
                $response = DB::delete(prefix_table("nested_tree"), "parent_id = (".$category_query.")");
237
                // Delete category
238
                $response = DB::delete(prefix_table("nested_tree"), "id = (".$category_query.")");
239
240
                $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...
241
                $json['category'] = $GLOBALS['request'][2];
242
                if ($response) {
243
                    $json['status'] = 'OK';
244
                } else {
245
                    $json['status'] = 'KO';
246
                }
247
            } elseif ($GLOBALS['request'][1] == "item") {
248
                $array_category = explode(';', $GLOBALS['request'][2]);
249
                $item = $GLOBALS['request'][3];
250
251
                foreach ($array_category as $category) {
252
                    if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $category, $result)) {
253
                        rest_error('CATEGORY_MALFORMED');
254
                    }
255
                }
256
257
                if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $item, $result)) {
258
                    rest_error('ITEM_MALFORMED');
259
                } elseif (empty($item) || count($array_category) == 0) {
260
                    rest_error('MALFORMED');
261
                }
262
263
                if (count($array_category) > 1 && count($array_category) < 5) {
264
                    for ($i = count($array_category); $i > 0; $i--) {
265
                        $slot = $i - 1;
266
                        if (!$slot) {
267
                            $category_query .= "select id from ".prefix_table("nested_tree")." where title LIKE '".filter_var($array_category[$slot], FILTER_SANITIZE_STRING)."' AND parent_id = 0";
268
                        } else {
269
                            $category_query .= "select id from ".prefix_table("nested_tree")." where title LIKE '".filter_var($array_category[$slot], FILTER_SANITIZE_STRING)."' AND parent_id = (";
270
                        }
271
                    }
272
                    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...
273
                        $category_query .= ")";
274
                    }
275
                } elseif (count($array_category) == 1) {
276
                    $category_query = "select id from ".prefix_table("nested_tree")." where title LIKE '".filter_var($array_category[0], FILTER_SANITIZE_STRING)."' AND parent_id = 0";
277
                } else {
278
                    rest_error('NO_CATEGORY');
279
                }
280
281
                // Delete item
282
                $response = DB::delete(prefix_table("items"), "id_tree = (".$category_query.") and label LIKE '".filter_var($item, FILTER_SANITIZE_STRING)."'");
283
                $json['type'] = 'item';
284
                $json['item'] = $item;
285
                $json['category'] = $GLOBALS['request'][2];
286
                if ($response) {
287
                    $json['status'] = 'OK';
288
                } else {
289
                    $json['status'] = 'KO';
290
                }
291
            }
292
293
            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...
294
                echo json_encode($json);
295
            } else {
296
                rest_error('EMPTY');
297
            }
298
        } else {
299
            rest_error('METHOD');
300
        }
301
    }
302
}
303
304
function rest_get()
305
{
306
    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...
307
    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...
308
    global $link;
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...
309
310
    if (!@count($GLOBALS['request']) == 0) {
311
        $request_uri = $GLOBALS['_SERVER']['REQUEST_URI'];
312
        preg_match('/\/api(\/index.php|)\/(.*)\?apikey=(.*)/', $request_uri, $matches);
313
        if (count($matches) == 0) {
314
            rest_error('REQUEST_SENT_NOT_UNDERSTANDABLE');
315
        }
316
        $GLOBALS['request'] = explode('/', $matches[2]);
317
    }
318
319
    if (apikey_checker($GLOBALS['apikey'])) {
320
321
        teampass_connect();
322
323
        // define the API user through the LABEL of apikey
324
        $api_info = DB::queryFirstRow(
325
            "SELECT label
326
            FROM ".prefix_table("api")."
327
            WHERE value = %s",
328
            $GLOBALS['apikey']
329
        );
330
331
        // Load config
332
        if (file_exists('../includes/config/tp.config.php')) {
333
            require_once '../includes/config/tp.config.php';
334
        } else {
335
            throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
336
        }
337
338
        if ($GLOBALS['request'][0] == "read") {
339
            if ($GLOBALS['request'][1] == "folder") {
340
                /*
341
                * READ FOLDERS
342
                */
343
344
                // load library
345
                require_once '../sources/SplClassLoader.php';
346
                //Load Tree
347
                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
348
                $tree->register();
349
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
350
351
                // get ids
352
                if (strpos($GLOBALS['request'][2], ";") > 0) {
353
                    $condition = "id_tree IN %ls";
354
                    $condition_value = explode(';', $GLOBALS['request'][2]);
355
                } else {
356
                    $condition = "id_tree = %s";
357
                    $condition_value = $GLOBALS['request'][2];
358
                }
359
360
                // get items in this folder
361
                $response = DB::query(
362
                    "SELECT id, label, login, pw, pw_iv, url, id_tree, description, email
363
                    FROM ".prefix_table("items")."
364
                    WHERE inactif='0' AND ".$condition,
365
                    $condition_value
366
                );
367
                $inc = 0;
368
                foreach ($response as $data) {
369
                    // build the path to the Item
370
                    $path = "";
371
                    $arbo = $tree->getPath($data['id_tree'], true);
372
                    foreach ($arbo as $elem) {
373
                        if (empty($path)) {
374
                            $path = stripslashes($elem->title);
375
                        } else {
376
                            $path .= " > ".stripslashes($elem->title);
377
                        }
378
                    }
379
380
                    // prepare output
381
                    $json[$inc]['id'] = $data['id'];
382
                    $json[$inc]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
383
                    $json[$inc]['description'] = mb_convert_encoding($data['description'], mb_detect_encoding($data['description']), 'UTF-8');
384
                    $json[$inc]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
385
                    $json[$inc]['email'] = mb_convert_encoding($data['email'], mb_detect_encoding($data['email']), 'UTF-8');
386
                    $json[$inc]['url'] = mb_convert_encoding($data['url'], mb_detect_encoding($data['url']), 'UTF-8');
387
                    $crypt_pw = cryption(
388
                        $data['pw'],
389
                        "",
390
                        "decrypt"
391
                    );
392
                    $json[$inc]['pw'] = $crypt_pw['string'];
393
                    $json[$inc]['folder_id'] = $data['id_tree'];
394
                    $json[$inc]['path'] = $path;
395
396
                    $inc++;
397
                }
398
            } elseif ($GLOBALS['request'][1] == "userpw") {
399
                /*
400
                * READ USER ITEMS
401
                */
402
403
                // load library
404
                require_once '../sources/SplClassLoader.php';
405
                //Load Tree
406
                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
407
                $tree->register();
408
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
409
410
                // about the user
411
                $username = $GLOBALS['request'][2];
412
                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...
413
                    // forbid admin access
414
                }
415
                $response = DB::query(
416
                    "SELECT fonction_id
417
                    FROM ".prefix_table("users")."
418
                    WHERE login = %s'",
419
                    $username
420
                );
421
                if (count($response) === 0) {
422
                    rest_error('USER_NOT_EXISTS');
423
                }
424
                foreach ($response as $data) {
425
                    $role_str = $data['fonction_id'];
426
                }
427
                $folder_arr = array();
428
                $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 424. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
429
                foreach ($roles as $role) {
430
                    $response = DB::query(
431
                        "SELECT folder_id
432
                        FROM ".prefix_table("roles_values")."
433
                        WHERE role_id = %i",
434
                        $role
435
                    );
436
                    foreach ($response as $data) {
437
                        $folder_id = $data['folder_id'];
438
                        if (!array_key_exists($folder_id, $folder_arr)) {
439
                            array_push($folder_arr, $folder_id);
440
                        }
441
                    }
442
                }
443
                $folder_str = array_filter($folder_arr);
444
445
                // get ids
446
                if (is_array($folder_str)) {
0 ignored issues
show
introduced by
The condition is_array($folder_str) is always true.
Loading history...
447
                    $condition = "id_tree IN %ls";
448
                    $condition_value = $folder_str;
449
                } else {
450
                    $condition = "id_tree = %s";
451
                    $condition_value = $folder_str;
452
                }
453
454
                $data = "";
0 ignored issues
show
Unused Code introduced by
The assignment to $data is dead and can be removed.
Loading history...
455
                // get items in this module
456
                $response = DB::query(
457
                    "SELECT id,label,url,login,pw, pw_iv, url, id_tree, description, email
458
                    FROM ".prefix_table("items")."
459
                    WHERE inactif='0' AND ".$condition,
460
                    $condition_value
461
                );
462
                $inc = 0;
463
                foreach ($response as $data) {
464
                    // build the path to the Item
465
                    $path = "";
466
                    $arbo = $tree->getPath($data['id_tree'], true);
467
                    foreach ($arbo as $elem) {
468
                        if (empty($path)) {
469
                            $path = stripslashes($elem->title);
470
                        } else {
471
                            $path .= " > ".stripslashes($elem->title);
472
                        }
473
                    }
474
475
                    // prepare output
476
                    $json[$data['id']]['id'] = $data['id'];
477
                    $json[$data['id']]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
478
                    $json[$data['id']]['description'] = mb_convert_encoding($data['description'], mb_detect_encoding($data['description']), 'UTF-8');
479
                    $json[$data['id']]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
480
                    $json[$data['id']]['email'] = mb_convert_encoding($data['email'], mb_detect_encoding($data['email']), 'UTF-8');
481
                    $json[$data['id']]['url'] = mb_convert_encoding($data['url'], mb_detect_encoding($data['url']), 'UTF-8');
482
                    $crypt_pw = cryption($data['pw'], "", "decrypt");
483
                    $json[$data['id']]['pw'] = $crypt_pw['string'];
484
                    $json[$data['id']]['folder_id'] = $data['id_tree'];
485
                    $json[$data['id']]['path'] = $path;
486
487
                    $inc++;
488
                }
489
            } elseif ($GLOBALS['request'][1] == "userfolders") {
490
                /*
491
                * READ USER FOLDERS
492
                * Sends back a list of folders
493
                */
494
                $json = "";
495
                $username = $GLOBALS['request'][2];
496
                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...
497
                    // forbid admin access
498
                }
499
                $response = DB::query(
500
                    "SELECT fonction_id
501
                    FROM ".prefix_table("users")."
502
                    WHERE login = %s",
503
                    $username
504
                );
505
                if (count($response) === 0) {
506
                    rest_error('USER_NOT_EXISTS');
507
                }
508
                foreach ($response as $data) {
509
                    $role_str = $data['fonction_id'];
510
                }
511
512
                $folder_arr = array();
513
                $roles = explode(";", $role_str);
514
                $inc = 0;
515
                foreach ($roles as $role) {
516
                    $response = DB::query(
517
                        "SELECT folder_id, type
518
                        FROM ".prefix_table("roles_values")."
519
                        WHERE role_id = %i",
520
                        $role
521
                    );
522
                    foreach ($response as $data) {
523
                        $folder_id = $data['folder_id'];
524
                        if (!array_key_exists($folder_id, $folder_arr)) {
525
                            array_push($folder_arr, $folder_id);
526
527
                            $response2 = DB::queryFirstRow(
528
                                "SELECT title, nlevel
529
                                FROM ".prefix_table("nested_tree")."
530
                                WHERE id = %i",
531
                                $folder_id
532
                            );
533
534
                            if (!empty($response2['title'])) {
535
                                $json[$folder_id]['id'] = $folder_id;
536
                                $json[$folder_id]['title'] = $response2['title'];
537
                                $json[$folder_id]['level'] = $response2['nlevel'];
538
                                $json[$folder_id]['access_type'] = $data['type'];
539
                                $inc++;
540
                            }
541
                        }
542
                    }
543
                }
544
            } elseif ($GLOBALS['request'][1] == "items") {
545
                /*
546
                * READ ITEMS asked
547
                */
548
549
                // load library
550
                require_once '../sources/SplClassLoader.php';
551
                //Load Tree
552
                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
553
                $tree->register();
554
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
555
556
                // get parameters
557
                $array_items = explode(';', $GLOBALS['request'][2]);
558
559
                // check if not empty
560
                if (count($array_items) == 0) {
561
                    rest_error('NO_ITEM');
562
                }
563
564
                // only accepts numeric
565
                foreach ($array_items as $item) {
566
                    if (!is_numeric($item)) {
567
                        rest_error('ITEM_MALFORMED');
568
                    }
569
                }
570
571
                $response = DB::query(
572
                    "SELECT id,label,login,pw, pw_iv, url, id_tree, description, email
573
                    FROM ".prefix_table("items")."
574
                    WHERE inactif = %i AND id IN %ls",
575
                    "0",
576
                    $array_items
577
                );
578
                $inc = 0;
579
                foreach ($response as $data) {
580
                    // build the path to the Item
581
                    $path = "";
582
                    $arbo = $tree->getPath($data['id_tree'], true);
583
                    foreach ($arbo as $elem) {
584
                        if (empty($path)) {
585
                            $path = stripslashes($elem->title);
586
                        } else {
587
                            $path .= " > ".stripslashes($elem->title);
588
                        }
589
                    }
590
591
                    // prepare output
592
                    $json[$inc]['id'] = $data['id'];
593
                    $json[$inc]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
594
                    $json[$inc]['description'] = mb_convert_encoding($data['description'], mb_detect_encoding($data['description']), 'UTF-8');
595
                    $json[$inc]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
596
                    $json[$inc]['email'] = mb_convert_encoding($data['email'], mb_detect_encoding($data['email']), 'UTF-8');
597
                    $json[$inc]['url'] = mb_convert_encoding($data['url'], mb_detect_encoding($data['url']), 'UTF-8');
598
                    $crypt_pw = cryption($data['pw'], "", "decrypt");
599
                    $json[$inc]['pw'] = $crypt_pw['string'];
600
                    $json[$inc]['folder_id'] = $data['id_tree'];
601
                    $json[$inc]['path'] = $path;
602
603
                    $inc++;
604
                }
605
            } elseif ($GLOBALS['request'][1] == "folder_descendants") {
606
                /*
607
                * PRovide full list of folders
608
                * <url to teampass>/api/index.php/read/folder_descendants/<id OR title>/<folder_id or folder_title>?apikey=<valid api key>
609
                */
610
611
                // get parameters
612
                if (isset($GLOBALS['request'][2]) === true && isset($GLOBALS['request'][3]) === true) {
613
                    // load library
614
                    require_once '../sources/SplClassLoader.php';
615
                    //Load Tree
616
                    $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
617
                    $tree->register();
618
                    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
619
620
                    // get parameters
621
                    $parameter_by = $GLOBALS['request'][2];
622
                    $parameter_criteria = $GLOBALS['request'][3];
623
624
                    // Check data consistency
625
                    if (preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $parameter_by, $result) === false) {
626
                        rest_error('MALFORMED');
627
                    }
628
629
                    if (preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $parameter_criteria, $result) === false) {
630
                        rest_error('MALFORMED');
631
                    }
632
633
                    // Is BY criteria correct
634
                    if ($parameter_by !== "id" && $parameter_by !== "title") {
635
                        rest_error('EXPECTED_PARAMETER_NOT_PROVIDED');
636
                    }
637
638
                    // If criteria is by Title
639
                    // Then search its id first
640
                    if ($parameter_by === "title") {
641
                        $response = DB::queryFirstRow(
642
                            "SELECT id
643
                            FROM ".prefix_table("nested_tree")."
644
                            WHERE
645
                            title LIKE %s",
646
                            $parameter_criteria
647
                        );
648
                        $parameter_criteria = $response['id'];
649
                    }
650
651
                    // List folder descendants
652
                    $folders = $tree->getDescendants(intval($parameter_criteria), true, false, false);
653
                    if (count($folders) > 0) {
654
                        $inc = 0;
655
                        foreach ($folders as $folder) {
656
                            // Prepare answer
657
                            $json[$inc]['id'] = mb_convert_encoding($folder->id, mb_detect_encoding($folder->id), 'UTF-8');
658
                            $json[$inc]['parent_id'] = mb_convert_encoding($folder->parent_id, mb_detect_encoding($folder->parent_id), 'UTF-8');
659
                            $json[$inc]['title'] = mb_convert_encoding(htmlspecialchars_decode($folder->title, ENT_QUOTES), mb_detect_encoding($folder->title), 'UTF-8');
660
                            $json[$inc]['nleft'] = mb_convert_encoding($folder->nleft, mb_detect_encoding($folder->nleft), 'UTF-8');
661
                            $json[$inc]['nright'] = mb_convert_encoding($folder->nright, mb_detect_encoding($folder->nright), 'UTF-8');
662
                            $json[$inc]['nlevel'] = mb_convert_encoding($folder->nlevel, mb_detect_encoding($folder->nlevel), 'UTF-8');
663
                            $json[$inc]['personal'] = mb_convert_encoding($folder->personal_folder, mb_detect_encoding($folder->personal_folder), 'UTF-8');
664
665
                            $inc ++;
666
                        }
667
                    }
668
                }
669
            }
670
671
            if (isset($json) && $json) {
672
                echo json_encode($json);
673
            } else {
674
                rest_error('EMPTY');
675
            }
676
        } elseif ($GLOBALS['request'][0] == "find") {
677
            if ($GLOBALS['request'][1] == "item") {
678
                /*
679
                * FIND ITEMS in FOLDERS
680
                */
681
682
                // load library
683
                require_once '../sources/SplClassLoader.php';
684
                //Load Tree
685
                $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
686
                $tree->register();
687
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
688
689
                // get parameters
690
                $array_category = explode(';', $GLOBALS['request'][2]);
691
                $item = $GLOBALS['request'][3];
692
                foreach ($array_category as $category) {
693
                    if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $category, $result)) {
694
                        rest_error('CATEGORY_MALFORMED');
695
                    }
696
                }
697
698
                if (!preg_match_all("/^([\w\:\'\-\sàáâãäåçèéêëìíîïðòóôõöùúûüýÿ]+)$/i", $item, $result)) {
699
                    rest_error('ITEM_MALFORMED');
700
                } elseif (empty($item) || count($array_category) == 0) {
701
                    rest_error('MALFORMED');
702
                }
703
704
                if (count($array_category) === 0) {
705
                    rest_error('NO_CATEGORY');
706
                }
707
708
                DB::debugMode(false);
709
                $response = DB::query(
710
                    "SELECT id, label, login, pw, pw_iv, url, id_tree, description, email
711
                    FROM ".prefix_table("items")."
712
                    WHERE
713
                    inactif = %i
714
                    AND id_tree IN %ls
715
                    AND label LIKE %ss",
716
                    "0",
717
                    $array_category,
718
                    $item
719
                );
720
                $inc = 0;
721
                foreach ($response as $data) {
722
                    // build the path to the Item
723
                    $path = "";
724
                    $arbo = $tree->getPath($data['id_tree'], true);
725
                    foreach ($arbo as $elem) {
726
                        if (empty($path)) {
727
                            $path = stripslashes($elem->title);
728
                        } else {
729
                            $path .= " > ".stripslashes($elem->title);
730
                        }
731
                    }
732
733
                    // prepare output
734
                    $json[$inc]['id'] = mb_convert_encoding($data['id'], mb_detect_encoding($data['id']), 'UTF-8');
735
                    $json[$inc]['label'] = mb_convert_encoding($data['label'], mb_detect_encoding($data['label']), 'UTF-8');
736
                    $json[$inc]['description'] = mb_convert_encoding($data['description'], mb_detect_encoding($data['description']), 'UTF-8');
737
                    $json[$inc]['login'] = mb_convert_encoding($data['login'], mb_detect_encoding($data['login']), 'UTF-8');
738
                    $json[$inc]['email'] = mb_convert_encoding($data['email'], mb_detect_encoding($data['email']), 'UTF-8');
739
                    $json[$inc]['url'] = mb_convert_encoding($data['url'], mb_detect_encoding($data['url']), 'UTF-8');
740
                    $crypt_pw = cryption($data['pw'], "", "decrypt");
741
                    $json[$inc]['pw'] = $crypt_pw['string'];
742
                    $json[$inc]['folder_id'] = $data['id_tree'];
743
                    $json[$inc]['path'] = $path;
744
                    $json[$inc]['status'] = utf8_encode("OK");
745
746
                    $inc++;
747
                }
748
                if (isset($json) && $json) {
749
                    echo json_encode($json);
750
                } else {
751
                    rest_error('EMPTY');
752
                }
753
            }
754
        } elseif ($GLOBALS['request'][0] == "add") {
755
            if ($GLOBALS['request'][1] == "item") {
756
                // get sent parameters
757
                $params = explode(';', Urlsafe_b64decode($GLOBALS['request'][2]));
758
                if (count($params) != 9) {
759
                    rest_error('ITEMBADDEFINITION');
760
                }
761
762
                $item_label = $params[0];
763
                $item_pwd = $params[1];
764
                $item_desc = $params[2];
765
                $item_folder_id = $params[3];
766
                $item_login = $params[4];
767
                $item_email = $params[5];
768
                $item_url = $params[6];
769
                $item_tags = $params[7];
770
                $item_anyonecanmodify = $params[8];
771
772
                // do some checks
773
                if (!empty($item_label) && !empty($item_pwd) && !empty($item_folder_id)) {
774
                    // Check length
775
                    if (strlen($item_pwd) > 50) {
776
                        rest_error('PASSWORDTOOLONG');
777
                    }
778
779
                    // Check Folder ID
780
                    DB::query("SELECT * FROM ".prefix_table("nested_tree")." WHERE id = %i", $item_folder_id);
781
                    $counter = DB::count();
782
                    if ($counter == 0) {
783
                        rest_error('NOSUCHFOLDER');
784
                    }
785
786
                    // check if element doesn't already exist
787
                    $item_duplicate_allowed = getSettingValue("duplicate_item");
788
                    if ($item_duplicate_allowed !== "1") {
789
                        DB::query(
790
                            "SELECT *
791
                            FROM ".prefix_table("items")."
792
                            WHERE label = %s AND inactif = %i",
793
                            addslashes($item_label),
794
                            "0"
795
                        );
796
                        $counter = DB::count();
797
                        if ($counter != 0) {
798
                            $itemExists = 1;
799
                            // prevent the error if the label already exists
800
                            // so lets just add the time() as a random factor
801
                            $item_label .= " (".time().")";
802
                        } else {
803
                            $itemExists = 0;
804
                        }
805
                    } else {
806
                        $itemExists = 0;
807
                    }
808
                    if ($itemExists === 0) {
809
                        $encrypt = cryption(
810
                            $item_pwd,
811
                            "",
812
                            "encrypt"
813
                        );
814
                        if (empty($encrypt['string'])) {
815
                            rest_error('PASSWORDEMPTY');
816
                        }
817
818
                        // ADD item
819
                        try {
820
                            DB::insert(
821
                                prefix_table("items"),
822
                                array(
823
                                    "label" => $item_label,
824
                                    "description" => $item_desc,
825
                                    'pw' => $encrypt['string'],
826
                                    'pw_iv' => '',
827
                                    "email" => $item_email,
828
                                    "url" => $item_url,
829
                                    "id_tree" => intval($item_folder_id),
830
                                    "login" => $item_login,
831
                                    "inactif" => 0,
832
                                    "restricted_to" => "",
833
                                    "perso" => 0,
834
                                    "anyone_can_modify" => intval($item_anyonecanmodify)
835
                                )
836
                            );
837
                            $newID = DB::InsertId();
838
839
                            // log
840
                            DB::insert(
841
                                prefix_table("log_items"),
842
                                array(
843
                                    "id_item" => $newID,
844
                                    "date" => time(),
845
                                    "id_user" => API_USER_ID,
846
                                    "action" => "at_creation",
847
                                    "raison" => $api_info['label']
848
                                )
849
                            );
850
851
                            // Add tags
852
                            $tags = explode(' ', $item_tags);
853
                            foreach ((array) $tags as $tag) {
854
                                if (!empty($tag)) {
855
                                    DB::insert(
856
                                        prefix_table("tags"),
857
                                        array(
858
                                            "item_id" => $newID,
859
                                            "tag" => strtolower($tag)
860
                                        )
861
                                    );
862
                                }
863
                            }
864
865
                            // Update CACHE table
866
                            DB::insert(
867
                                prefix_table("cache"),
868
                                array(
869
                                    "id" => $newID,
870
                                    "label" => $item_label,
871
                                    "description" => $item_desc,
872
                                    "tags" => $item_tags,
873
                                    "id_tree" => $item_folder_id,
874
                                    "perso" => "0",
875
                                    "restricted_to" => "",
876
                                    "login" => $item_login,
877
                                    "folder" => "",
878
                                    "author" => API_USER_ID,
879
                                    "renewal_period" => "0",
880
                                    "timestamp" => time(),
881
                                    "url" => "0"
882
                                )
883
                            );
884
885
                            echo '{"status":"item added" , "new_item_id" : "'.$newID.'"}';
886
                        } catch (PDOException $ex) {
887
                            echo '<br />'.$ex->getMessage();
888
                        }
889
                    } else {
890
                        rest_error('ITEMEXISTS');
891
                    }
892
                } else {
893
                    rest_error('ITEMMISSINGDATA');
894
                }
895
            } elseif ($GLOBALS['request'][1] == "user") {
896
            /*
897
             * Case where a new user has to be added
898
             *
899
             * 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>
900
             * with:
901
             * for READ_ONLY, IS_ADMIN, IS_MANAGER, PERSONAL_FOLDER, accepted value is 1 for TRUE and 0 for FALSE
902
             * for ADMINISTRATEDBY and ROLE1, accepted value is the real label (not the IDs)
903
             *
904
             * Example: /api/index.php/add/user/U4;Nils;Laumaille;test;[email protected];Users;0;Managers,Users;0;1;1?apikey=sae6iekahxiseL3viShoo0chahc1ievei8aequi
905
             *
906
             */
907
908
                // get user definition
909
                $array_user = explode(';', Urlsafe_b64decode($GLOBALS['request'][2]));
910
                if (count($array_user) != 11) {
911
                    rest_error('USERBADDEFINITION');
912
                }
913
914
                $login = $array_user[0];
915
                $name = $array_user[1];
916
                $lastname = $array_user[2];
917
                $password = $array_user[3];
918
                $email = $array_user[4];
919
                $adminby = urldecode($array_user[5]);
920
                $isreadonly = urldecode($array_user[6]);
921
                $roles = urldecode($array_user[7]);
922
                $isadmin = $array_user[8];
923
                $ismanager = $array_user[9];
924
                $haspf = $array_user[10];
925
926
                // Empty user
927
                if (mysqli_escape_string($link, htmlspecialchars_decode($login)) == "") {
928
                    rest_error('USERLOGINEMPTY');
929
                }
930
                // Check if user already exists
931
                $data = DB::query(
932
                    "SELECT id, fonction_id, groupes_interdits, groupes_visibles
933
                    FROM ".prefix_table("users")."
934
                    WHERE login LIKE %ss",
935
                    mysqli_escape_string($link, stripslashes($login))
936
                );
937
938
                if (DB::count() == 0) {
939
                    try {
940
                        // find AdminRole code in DB
941
                        $resRole = DB::queryFirstRow(
942
                            "SELECT id
943
                            FROM ".prefix_table("roles_title")."
944
                            WHERE title LIKE %ss",
945
                            mysqli_escape_string($link, stripslashes($adminby))
946
                        );
947
948
                        // get default language
949
                        $lang = DB::queryFirstRow(
950
                            "SELECT `valeur`
951
                            FROM ".prefix_table("misc")."
952
                            WHERE type = %s AND intitule = %s",
953
                            "admin",
954
                            "default_language"
955
                        );
956
957
                        // prepare roles list
958
                        $rolesList = "";
959
                        foreach (explode(',', $roles) as $role) {
960
                            $tmp = DB::queryFirstRow(
961
                                "SELECT `id`
962
                                FROM ".prefix_table("roles_title")."
963
                                WHERE title = %s",
964
                                $role
965
                            );
966
                            if (empty($rolesList)) {
967
                                $rolesList = $tmp['id'];
968
                            } else {
969
                                $rolesList .= ";".$tmp['id'];
970
                            }
971
                        }
972
973
                        // Add user in DB
974
                        DB::insert(
975
                            prefix_table("users"),
976
                            array(
977
                                'login' => $login,
978
                                'name' => $name,
979
                                'lastname' => $lastname,
980
                                'pw' => bCrypt(stringUtf8Decode($password), COST),
981
                                'email' => $email,
982
                                'admin' => intval($isadmin),
983
                                'gestionnaire' => intval($ismanager),
984
                                'read_only' => intval($isreadonly),
985
                                'personal_folder' => intval($haspf),
986
                                'user_language' => $lang['valeur'],
987
                                'fonction_id' => $rolesList,
988
                                'groupes_interdits' => '0',
989
                                'groupes_visibles' => '0',
990
                                'isAdministratedByRole' => empty($resRole) ? '0' : $resRole['id']
991
                            )
992
                        );
993
                        $new_user_id = DB::insertId();
994
                        // Create personnal folder
995
                        if (intval($haspf) === 1) {
996
                            DB::insert(
997
                                prefix_table("nested_tree"),
998
                                array(
999
                                    'parent_id' => '0',
1000
                                    'title' => $new_user_id,
1001
                                    'bloquer_creation' => '0',
1002
                                    'bloquer_modification' => '0',
1003
                                    'personal_folder' => '1'
1004
                                )
1005
                            );
1006
                        }
1007
1008
                        // load settings
1009
                        loadSettings();
1010
1011
                        // Send email to new user
1012
                        @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

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

2462
                    $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...
2463
2464
                    // this will delete all sub folders and items associated
2465
                    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...
2466
                        // Does this folder exist?
2467
                        DB::queryFirstRow(
2468
                            "SELECT id
2469
                            FROM ".prefix_table("nested_tree")."
2470
                            WHERE id = %i",
2471
                            $array_category[$i]
2472
                        );
2473
                        if (DB::count() > 0) {
2474
                            // Get through each subfolder
2475
                            $folders = $tree->getDescendants($array_category[$i], true);
0 ignored issues
show
Bug introduced by
$array_category[$i] of type string is incompatible with the type integer expected by parameter $folder_id of Tree\NestedTree\NestedTree::getDescendants(). ( Ignorable by Annotation )

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

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