Completed
Push — development ( 2dd399...b69053 )
by Nils
14:05 queued 07:08
created

main.functions.php ➔ accessToItemIsGranted()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 1
dl 0
loc 17
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 *
4
 * @file          main.functions.php
5
 * @author        Nils Laumaillé
6
 * @version       2.1.27
7
 * @copyright     (c) 2009-2017 Nils Laumaillé
8
 * @licensing     GNU AFFERO GPL 3.0
9
 * @link
10
 */
11
12
//define pbkdf2 iteration count
13
define('ITCOUNT', '2072');
14
15
if (!isset($_SESSION['CPM']) || $_SESSION['CPM'] != 1) {
16
    die('Hacking attempt...');
17
}
18
19
// Load config
20 View Code Duplication
if (file_exists('../includes/config/tp.config.php')) {
21
    require_once '../includes/config/tp.config.php';
22
} elseif (file_exists('./includes/config/tp.config.php')) {
23
    require_once './includes/config/tp.config.php';
24
} elseif (file_exists('../../includes/config/tp.config.php')) {
25
    require_once '../../includes/config/tp.config.php';
26
} else {
27
    throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
28
}
29
30
// load phpCrypt
31
if (!isset($SETTINGS['cpassman_dir']) || empty($SETTINGS['cpassman_dir'])) {
32
    require_once '../includes/libraries/phpcrypt/phpCrypt.php';
33
    require_once '../includes/config/settings.php';
34
} else {
35
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/phpcrypt/phpCrypt.php';
36
    require_once $SETTINGS['cpassman_dir'].'/includes/config/settings.php';
37
}
38
39
// Prepare PHPCrypt class calls
40
use PHP_Crypt\PHP_Crypt as PHP_Crypt;
41
42
// Prepare Encryption class calls
43
use \Defuse\Crypto\Crypto;
44
use \Defuse\Crypto\Exception as Ex;
45
46
//Generate N# of random bits for use as salt
47
/**
48
 * @param integer $size
49
 */
50
function getBits($size)
51
{
52
    $str = '';
53
    $var_x = $size + 10;
54
    for ($var_i = 0; $var_i < $var_x; $var_i++) {
55
        $str .= base_convert(mt_rand(1, 36), 10, 36);
56
    }
57
    return substr($str, 0, $size);
58
}
59
60
//generate pbkdf2 compliant hash
61 View Code Duplication
function strHashPbkdf2($var_p, $var_s, $var_c, $var_kl, $var_a = 'sha256', $var_st = 0)
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
62
{
63
    $var_kb = $var_st + $var_kl; // Key blocks to compute
64
    $var_dk = ''; // Derived key
65
66
    for ($block = 1; $block <= $var_kb; $block++) { // Create key
67
        $var_ib = $var_h = hash_hmac($var_a, $var_s.pack('N', $block), $var_p, true); // Initial hash for this block
68
        for ($var_i = 1; $var_i < $var_c; $var_i++) { // Perform block iterations
69
            $var_ib ^= ($var_h = hash_hmac($var_a, $var_h, $var_p, true)); // XOR each iterate
70
        }
71
        $var_dk .= $var_ib; // Append iterated block
72
    }
73
    return substr($var_dk, $var_st, $var_kl); // Return derived key of correct length
74
}
75
76
/**
77
 * stringUtf8Decode()
78
 *
79
 * utf8_decode
80
 */
81
function stringUtf8Decode($string)
82
{
83
    return str_replace(" ", "+", utf8_decode($string));
84
}
85
86
/**
87
 * encryptOld()
88
 *
89
 * crypt a string
90
 * @param string $text
91
 */
92
function encryptOld($text, $personalSalt = "")
93
{
94
    if (empty($personalSalt) === false) {
95
        return trim(
96
            base64_encode(
97
                mcrypt_encrypt(
98
                    MCRYPT_RIJNDAEL_256,
99
                    $personalSalt,
100
                    $text,
101
                    MCRYPT_MODE_ECB,
102
                    mcrypt_create_iv(
103
                        mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
104
                        MCRYPT_RAND
105
                    )
106
                )
107
            )
108
        );
109
    }
110
111
    // If $personalSalt is not empty
112
    return trim(
113
        base64_encode(
114
            mcrypt_encrypt(
115
                MCRYPT_RIJNDAEL_256,
116
                SALT,
117
                $text,
118
                MCRYPT_MODE_ECB,
119
                mcrypt_create_iv(
120
                    mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
121
                    MCRYPT_RAND
122
                )
123
            )
124
        )
125
    );
126
}
127
128
/**
129
 * decryptOld()
130
 *
131
 * decrypt a crypted string
132
 */
133
function decryptOld($text, $personalSalt = "")
134
{
135
    if (!empty($personalSalt)) {
136
        return trim(
137
            mcrypt_decrypt(
138
                MCRYPT_RIJNDAEL_256,
139
                $personalSalt,
140
                base64_decode($text),
141
                MCRYPT_MODE_ECB,
142
                mcrypt_create_iv(
143
                    mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
144
                    MCRYPT_RAND
145
                )
146
            )
147
        );
148
    }
149
150
    // No personal SK
151
    return trim(
152
        mcrypt_decrypt(
153
            MCRYPT_RIJNDAEL_256,
154
            SALT,
155
            base64_decode($text),
156
            MCRYPT_MODE_ECB,
157
            mcrypt_create_iv(
158
                mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
159
                MCRYPT_RAND
160
            )
161
        )
162
    );
163
}
164
165
/**
166
 * encrypt()
167
 *
168
 * crypt a string
169
 * @param string $decrypted
170
 */
171
function encrypt($decrypted, $personalSalt = "")
172
{
173
    global $SETTINGS;
174
175 View Code Duplication
    if (!isset($SETTINGS['cpassman_dir']) || empty($SETTINGS['cpassman_dir'])) {
176
        require_once '../includes/libraries/Encryption/PBKDF2/PasswordHash.php';
177
    } else {
178
        require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/PBKDF2/PasswordHash.php';
179
    }
180
181
    if (!empty($personalSalt)) {
182
        $staticSalt = $personalSalt;
183
    } else {
184
        $staticSalt = SALT;
185
    }
186
187
    //set our salt to a variable
188
    // Get 64 random bits for the salt for pbkdf2
189
    $pbkdf2Salt = getBits(64);
190
    // generate a pbkdf2 key to use for the encryption.
191
    $key = substr(pbkdf2('sha256', $staticSalt, $pbkdf2Salt, ITCOUNT, 16 + 32, true), 32, 16);
192
    // Build $init_vect and $ivBase64.  We use a block size of 256 bits (AES compliant)
193
    // and CTR mode.  (Note: ECB mode is inadequate as IV is not used.)
194
    $init_vect = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, 'ctr'), MCRYPT_RAND);
195
196
    //base64 trim
197
    if (strlen($ivBase64 = rtrim(base64_encode($init_vect), '=')) != 43) {
198
        return false;
199
    }
200
    // Encrypt $decrypted
201
    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $decrypted, 'ctr', $init_vect);
202
    // MAC the encrypted text
203
    $mac = hash_hmac('sha256', $encrypted, $staticSalt);
204
    // We're done!
205
    return base64_encode($ivBase64.$encrypted.$mac.$pbkdf2Salt);
206
}
207
208
/**
209
 * decrypt()
210
 *
211
 * decrypt a crypted string
212
 */
213
function decrypt($encrypted, $personalSalt = "")
214
{
215
    global $SETTINGS;
216
217 View Code Duplication
    if (!isset($SETTINGS['cpassman_dir']) || empty($SETTINGS['cpassman_dir'])) {
218
        require_once '../includes/libraries/Encryption/PBKDF2/PasswordHash.php';
219
    } else {
220
        require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/PBKDF2/PasswordHash.php';
221
    }
222
223
    if (!empty($personalSalt)) {
224
        $staticSalt = $personalSalt;
225
    } else {
226
        $staticSalt = SALT;
227
    }
228
    //base64 decode the entire payload
229
    $encrypted = base64_decode($encrypted);
230
    // get the salt
231
    $pbkdf2Salt = substr($encrypted, -64);
232
    //remove the salt from the string
233
    $encrypted = substr($encrypted, 0, -64);
234
    $key = substr(pbkdf2('sha256', $staticSalt, $pbkdf2Salt, ITCOUNT, 16 + 32, true), 32, 16);
235
    // Retrieve $init_vect which is the first 22 characters plus ==, base64_decoded.
236
    $init_vect = base64_decode(substr($encrypted, 0, 43).'==');
237
    // Remove $init_vect from $encrypted.
238
    $encrypted = substr($encrypted, 43);
239
    // Retrieve $mac which is the last 64 characters of $encrypted.
240
    $mac = substr($encrypted, -64);
241
    // Remove the last 64 chars from encrypted (remove MAC)
242
    $encrypted = substr($encrypted, 0, -64);
243
    //verify the sha256hmac from the encrypted data before even trying to decrypt it
244
    if (hash_hmac('sha256', $encrypted, $staticSalt) != $mac) {
245
        return false;
246
    }
247
    // Decrypt the data.
248
    $decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, 'ctr', $init_vect), "\0\4");
249
    // Yay!
250
    return $decrypted;
251
}
252
253
254
/**
255
 * genHash()
256
 *
257
 * Generate a hash for user login
258
 * @param string $password
259
 */
260 View Code Duplication
function bCrypt($password, $cost)
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Best Practice introduced by
The function bCrypt() has been defined more than once; this definition is ignored, only the first definition in install/install.queries.php (L57-69) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
261
{
262
    $salt = sprintf('$2y$%02d$', $cost);
263
    if (function_exists('openssl_random_pseudo_bytes')) {
264
        $salt .= bin2hex(openssl_random_pseudo_bytes(11));
265
    } else {
266
        $chars = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
267
        for ($i = 0; $i < 22; $i++) {
268
            $salt .= $chars[mt_rand(0, 63)];
269
        }
270
    }
271
    return crypt($password, $salt);
272
}
273
274
function cryption_before_defuse($message, $saltkey, $init_vect, $type = null, $scope = "public")
275
{
276
    if (DEFUSE_ENCRYPTION === true) {
277
        if ($scope === "perso") {
278
            return defuse_crypto(
279
                $message,
280
                $saltkey,
281
                $type
282
            );
283
        } else {
284
            return defuse_crypto(
285
                $message,
286
                file_get_contents(SECUREPATH."/teampass-seckey.txt"),
287
                $type
288
            );
289
        }
290
    } else {
291
        return cryption_phpCrypt($message, $saltkey, $init_vect, $type);
292
    }
293
}
294
295
/*
296
 * cryption() - Encrypt and decrypt string based upon phpCrypt library
297
 *
298
 * Using AES_128 and mode CBC
299
 *
300
 * $key and $init_vect have to be given in hex format
301
 */
302
function cryption_phpCrypt($string, $key, $init_vect, $type)
303
{
304
    // manage key origin
305
    if (null != SALT && $key != SALT) {
306
        // check key (AES-128 requires a 16 bytes length key)
307
        if (strlen($key) < 16) {
308
            for ($inc = strlen($key) + 1; $inc <= 16; $inc++) {
309
                $key .= chr(0);
310
            }
311
        } elseif (strlen($key) > 16) {
312
            $key = substr($key, 16);
313
        }
314
    }
315
316
    // load crypt
317
    $crypt = new PHP_Crypt($key, PHP_Crypt::CIPHER_AES_128, PHP_Crypt::MODE_CBC);
318
319
    if ($type == "encrypt") {
320
        // generate IV and encrypt
321
        $init_vect = $crypt->createIV();
322
        $encrypt = $crypt->encrypt($string);
323
        // return
324
        return array(
325
            "string" => bin2hex($encrypt),
326
            "iv" => bin2hex($init_vect),
327
            "error" => empty($encrypt) ? "ERR_ENCRYPTION_NOT_CORRECT" : ""
328
        );
329
    } elseif ($type == "decrypt") {
330
        // case if IV is empty
331
        if (empty($init_vect)) {
332
                    return array(
333
                'string' => "",
334
                'error' => "ERR_ENCRYPTION_NOT_CORRECT"
335
            );
336
        }
337
338
        // convert
339
        try {
340
            $string = testHex2Bin(trim($string));
341
            $init_vect = testHex2Bin($init_vect);
342
        } catch (Exception $e) {
343
            return array(
344
                'string' => "",
345
                'error' => "ERR_ENCRYPTION_NOT_CORRECT"
346
            );
347
        }
348
349
        // load IV
350
        $crypt->IV($init_vect);
351
        // decrypt
352
        $decrypt = $crypt->decrypt($string);
353
        // return
354
        return array(
355
            'string' => str_replace(chr(0), "", $decrypt),
356
            'error' => ""
357
        );
358
    }
359
}
360
361
function testHex2Bin($val)
362
{
363
    if (!@hex2bin($val)) {
364
        throw new Exception("ERROR");
365
    }
366
    return hex2bin($val);
367
}
368
369
/**
370
 * @param string $ascii_key
371
 * @param string $type
372
 */
373
function cryption($message, $ascii_key, $type) //defuse_crypto
374
{
375
    global $SETTINGS;
376
377
    // load PhpEncryption library
378 View Code Duplication
    if (!isset($SETTINGS['cpassman_dir']) || empty($SETTINGS['cpassman_dir'])) {
379
        $path = '../includes/libraries/Encryption/Encryption/';
380
    } else {
381
        $path = $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/Encryption/';
382
    }
383
384
    require_once $path.'Crypto.php';
385
    require_once $path.'Encoding.php';
386
    require_once $path.'DerivedKeys.php';
387
    require_once $path.'Key.php';
388
    require_once $path.'KeyOrPassword.php';
389
    require_once $path.'File.php';
390
    require_once $path.'RuntimeTests.php';
391
    require_once $path.'KeyProtectedByPassword.php';
392
    require_once $path.'Core.php';
393
394
    // init
395
    $err = '';
396
    if (empty($ascii_key)) {
397
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
398
    }
399
400
    // convert KEY
401
    $key = \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key);
402
403
    try {
404
        if ($type === "encrypt") {
405
            $text = \Defuse\Crypto\Crypto::encrypt($message, $key);
406
        } elseif ($type === "decrypt") {
407
            $text = \Defuse\Crypto\Crypto::decrypt($message, $key);
408
        }
409
    } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
410
        $err = "an attack! either the wrong key was loaded, or the ciphertext has changed since it was created either corrupted in the database or intentionally modified by someone trying to carry out an attack.";
411
    } catch (Defuse\Crypto\Exception\BadFormatException $ex) {
412
        $err = $ex;
413
    } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
414
        $err = $ex;
415
    } catch (Defuse\Crypto\Exception\CryptoException $ex) {
416
        $err = $ex;
417
    } catch (Defuse\Crypto\Exception\IOException $ex) {
418
        $err = $ex;
419
    }
420
421
    return array(
422
        'string' => isset($text) ? $text : "",
423
        'error' => $err
424
    );
425
}
426
427
function defuse_generate_key()
428
{
429
    require_once '../includes/libraries/Encryption/Encryption/Crypto.php';
430
    require_once '../includes/libraries/Encryption/Encryption/Encoding.php';
431
    require_once '../includes/libraries/Encryption/Encryption/DerivedKeys.php';
432
    require_once '../includes/libraries/Encryption/Encryption/Key.php';
433
    require_once '../includes/libraries/Encryption/Encryption/KeyOrPassword.php';
434
    require_once '../includes/libraries/Encryption/Encryption/File.php';
435
    require_once '../includes/libraries/Encryption/Encryption/RuntimeTests.php';
436
    require_once '../includes/libraries/Encryption/Encryption/KeyProtectedByPassword.php';
437
    require_once '../includes/libraries/Encryption/Encryption/Core.php';
438
439
    $key = \Defuse\Crypto\Key::createNewRandomKey();
440
    $key = $key->saveToAsciiSafeString();
441
    return $key;
442
}
443
444
function defuse_generate_personal_key($psk)
445
{
446
    require_once '../includes/libraries/Encryption/Encryption/Crypto.php';
447
    require_once '../includes/libraries/Encryption/Encryption/Encoding.php';
448
    require_once '../includes/libraries/Encryption/Encryption/DerivedKeys.php';
449
    require_once '../includes/libraries/Encryption/Encryption/Key.php';
450
    require_once '../includes/libraries/Encryption/Encryption/KeyOrPassword.php';
451
    require_once '../includes/libraries/Encryption/Encryption/File.php';
452
    require_once '../includes/libraries/Encryption/Encryption/RuntimeTests.php';
453
    require_once '../includes/libraries/Encryption/Encryption/KeyProtectedByPassword.php';
454
    require_once '../includes/libraries/Encryption/Encryption/Core.php';
455
456
    $protected_key = \Defuse\Crypto\KeyProtectedByPassword::createRandomPasswordProtectedKey($psk);
457
    $protected_key_encoded = $protected_key->saveToAsciiSafeString();
458
459
    return $protected_key_encoded; // save this in user table
460
}
461
462
/**
463
 * @param string $psk
464
 */
465
function defuse_validate_personal_key($psk, $protected_key_encoded)
466
{
467
    require_once '../includes/libraries/Encryption/Encryption/Crypto.php';
468
    require_once '../includes/libraries/Encryption/Encryption/Encoding.php';
469
    require_once '../includes/libraries/Encryption/Encryption/DerivedKeys.php';
470
    require_once '../includes/libraries/Encryption/Encryption/Key.php';
471
    require_once '../includes/libraries/Encryption/Encryption/KeyOrPassword.php';
472
    require_once '../includes/libraries/Encryption/Encryption/File.php';
473
    require_once '../includes/libraries/Encryption/Encryption/RuntimeTests.php';
474
    require_once '../includes/libraries/Encryption/Encryption/KeyProtectedByPassword.php';
475
    require_once '../includes/libraries/Encryption/Encryption/Core.php';
476
477
    try {
478
        $protected_key = \Defuse\Crypto\KeyProtectedByPassword::loadFromAsciiSafeString($protected_key_encoded);
479
        $user_key = $protected_key->unlockKey($psk);
480
        $user_key_encoded = $user_key->saveToAsciiSafeString();
481
    } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
482
        return "Error - Major issue as the encryption is broken.";
483
    } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
484
        return "Error - The saltkey is not the correct one.";
485
    }
486
487
    return $user_key_encoded; // store it in session once user has entered his psk
488
}
489
490
/**
491
 * Decrypt a defuse string if encrypted
492
 * @param  [type] $value Encrypted string
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
493
 * @return [type]        Decrypted string
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
494
 */
495
function defuse_return_decrypted($value)
496
{
497
    if (substr($value, 0, 3) === "def") {
498
        $value = cryption($value, "", "decrypt")['string'];
499
    }
500
    return $value;
501
}
502
503
/**
504
 * trimElement()
505
 *
506
 * trim a string depending on a specific string
507
 * @param string $element
508
 * @return string
509
 */
510
function trimElement($chaine, $element)
511
{
512
    if (!empty($chaine)) {
513
        $chaine = trim($chaine);
514
        if (substr($chaine, 0, 1) == $element) {
515
            $chaine = substr($chaine, 1);
516
        }
517
        if (substr($chaine, strlen($chaine) - 1, 1) == $element) {
518
            $chaine = substr($chaine, 0, strlen($chaine) - 1);
519
        }
520
    }
521
    return $chaine;
522
}
523
524
/**
525
 * cleanString()
526
 *
527
 * permits to suppress all "special" characters from string
528
 */
529
function cleanString($string, $special = false)
530
{
531
    // Create temporary table for special characters escape
532
    $tabSpecialChar = array();
533
    for ($i = 0; $i <= 31; $i++) {
534
        $tabSpecialChar[] = chr($i);
535
    }
536
    array_push($tabSpecialChar, "<br />");
537
    if ($special == "1") {
538
        $tabSpecialChar = array_merge($tabSpecialChar, array("</li>", "<ul>", "<ol>"));
539
    }
540
541
    return str_replace($tabSpecialChar, "\n", $string);
542
}
543
544
function db_error_handler($params)
545
{
546
    echo "Error: ".$params['error']."<br>\n";
547
    echo "Query: ".$params['query']."<br>\n";
548
    throw new Exception("Error - Query", 1);
549
}
550
551
/**
552
 * [identifyUserRights description]
553
 * @param  string $groupesVisiblesUser  [description]
554
 * @param  string $groupesInterditsUser [description]
555
 * @param  string $isAdmin              [description]
556
 * @param  string $idFonctions          [description]
557
 * @return string                       [description]
558
 */
559
function identifyUserRights($groupesVisiblesUser, $groupesInterditsUser, $isAdmin, $idFonctions)
560
{
561
    global $server, $user, $pass, $database, $port, $encoding;
562
    global $SETTINGS;
563
564
    //load ClassLoader
565
    require_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php';
566
567
    //Connect to DB
568
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
569
    $pass = defuse_return_decrypted($pass);
570
    DB::$host = $server;
571
    DB::$user = $user;
572
    DB::$password = $pass;
573
    DB::$dbName = $database;
574
    DB::$port = $port;
575
    DB::$encoding = $encoding;
576
    DB::$error_handler = true;
577
    $link = mysqli_connect($server, $user, $pass, $database, $port);
578
    $link->set_charset($encoding);
579
580
    //Build tree
581
    $tree = new SplClassLoader('Tree\NestedTree', $SETTINGS['cpassman_dir'].'/includes/libraries');
582
    $tree->register();
583
    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
584
585
    // Check if user is ADMINISTRATOR
586
    if ($isAdmin == 1) {
587
        $groupesVisibles = array();
588
        $_SESSION['personal_folders'] = array();
589
        $_SESSION['groupes_visibles'] = array();
590
        $_SESSION['groupes_interdits'] = array();
591
        $_SESSION['personal_visible_groups'] = array();
592
        $_SESSION['read_only_folders'] = array();
593
        $_SESSION['list_restricted_folders_for_items'] = array();
594
        $_SESSION['list_folders_editable_by_role'] = array();
595
        $_SESSION['list_folders_limited'] = array();
596
        $_SESSION['groupes_visibles_list'] = "";
597
        $_SESSION['list_folders_limited'] = "";
598
        $rows = DB::query("SELECT id FROM ".prefix_table("nested_tree")." WHERE personal_folder = %i", 0);
599
        foreach ($rows as $record) {
600
            array_push($groupesVisibles, $record['id']);
601
        }
602
        $_SESSION['groupes_visibles'] = $groupesVisibles;
603
        $_SESSION['all_non_personal_folders'] = $groupesVisibles;
604
        // Exclude all PF
605
        $_SESSION['forbiden_pfs'] = array();
606
        $where = new WhereClause('and'); // create a WHERE statement of pieces joined by ANDs
607
        $where->add('personal_folder=%i', 1);
608
        if (isset($SETTINGS['enable_pf_feature']) && $SETTINGS['enable_pf_feature'] == 1) {
609
            $where->add('title=%s', $_SESSION['user_id']);
610
            $where->negateLast();
611
        }
612
        // Get ID of personal folder
613
        $persfld = DB::queryfirstrow(
614
            "SELECT id FROM ".prefix_table("nested_tree")." WHERE title = %s",
615
            $_SESSION['user_id']
616
        );
617
        if (!empty($persfld['id'])) {
618
            if (!in_array($persfld['id'], $_SESSION['groupes_visibles'])) {
619
                array_push($_SESSION['groupes_visibles'], $persfld['id']);
620
                array_push($_SESSION['personal_visible_groups'], $persfld['id']);
621
                // get all descendants
622
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
623
                $tree->rebuild();
624
                $tst = $tree->getDescendants($persfld['id']);
625
                foreach ($tst as $t) {
626
                    array_push($_SESSION['groupes_visibles'], $t->id);
627
                    array_push($_SESSION['personal_visible_groups'], $t->id);
628
                }
629
            }
630
        }
631
632
        // get complete list of ROLES
633
        $tmp = explode(";", $idFonctions);
634
        $rows = DB::query(
635
            "SELECT * FROM ".prefix_table("roles_title")."
636
            ORDER BY title ASC"
637
        );
638
        foreach ($rows as $record) {
639
            if (!empty($record['id']) && !in_array($record['id'], $tmp)) {
640
                array_push($tmp, $record['id']);
641
            }
642
        }
643
        $_SESSION['fonction_id'] = implode(";", $tmp);
644
645
        $_SESSION['groupes_visibles_list'] = implode(',', $_SESSION['groupes_visibles']);
646
        $_SESSION['is_admin'] = $isAdmin;
647
        // Check if admin has created Folders and Roles
648
        DB::query("SELECT * FROM ".prefix_table("nested_tree")."");
649
        $_SESSION['nb_folders'] = DB::count();
650
        DB::query("SELECT * FROM ".prefix_table("roles_title"));
651
        $_SESSION['nb_roles'] = DB::count();
652
    } else {
653
        // init
654
        $_SESSION['groupes_visibles'] = array();
655
        $_SESSION['personal_folders'] = array();
656
        $_SESSION['groupes_interdits'] = array();
657
        $_SESSION['personal_visible_groups'] = array();
658
        $_SESSION['read_only_folders'] = array();
659
        $_SESSION['fonction_id'] = $idFonctions;
660
        $groupesInterdits = array();
661
        if (!is_array($groupesInterditsUser)) {
662
            $groupesInterditsUser = explode(';', trimElement($groupesInterditsUser, ";"));
663
        }
664
        if (!empty($groupesInterditsUser) && count($groupesInterditsUser) > 0) {
665
            $groupesInterdits = $groupesInterditsUser;
666
        }
667
        $_SESSION['is_admin'] = $isAdmin;
668
        $fonctionsAssociees = explode(';', trimElement($idFonctions, ";"));
669
670
        $listAllowedFolders = $listFoldersLimited = $listFoldersEditableByRole = $listRestrictedFoldersForItems = $listReadOnlyFolders = array();
671
672
        // rechercher tous les groupes visibles en fonction des roles de l'utilisateur
673
        foreach ($fonctionsAssociees as $roleId) {
674
            if (!empty($roleId)) {
675
                // Get allowed folders for each Role
676
                $rows = DB::query("SELECT folder_id FROM ".prefix_table("roles_values")." WHERE role_id=%i", $roleId);
677
678
                if (DB::count() > 0) {
679
                    $tmp = DB::queryfirstrow("SELECT allow_pw_change FROM ".prefix_table("roles_title")." WHERE id = %i", $roleId);
680
                    foreach ($rows as $record) {
681
                        if (isset($record['folder_id']) && !in_array($record['folder_id'], $listAllowedFolders)) {
682
                            array_push($listAllowedFolders, $record['folder_id']);
683
                        }
684
                        // Check if this group is allowed to modify any pw in allowed folders
685
                        if ($tmp['allow_pw_change'] == 1 && !in_array($record['folder_id'], $listFoldersEditableByRole)) {
686
                            array_push($listFoldersEditableByRole, $record['folder_id']);
687
                        }
688
                    }
689
                    // Check for the users roles if some specific rights exist on items
690
                    $rows = DB::query(
691
                        "SELECT i.id_tree, r.item_id
692
                        FROM ".prefix_table("items")." as i
693
                        INNER JOIN ".prefix_table("restriction_to_roles")." as r ON (r.item_id=i.id)
694
                        WHERE r.role_id=%i
695
                        ORDER BY i.id_tree ASC",
696
                        $roleId
697
                    );
698
                    $inc = 0;
699
                    foreach ($rows as $record) {
700
                        if (isset($record['id_tree'])) {
701
                            $listFoldersLimited[$record['id_tree']][$inc] = $record['item_id'];
702
                            $inc++;
703
                        }
704
                    }
705
                }
706
            }
707
        }
708
709
        // Does this user is allowed to see other items
710
        $inc = 0;
711
        $rows = DB::query(
712
            "SELECT id, id_tree FROM ".prefix_table("items")."
713
            WHERE restricted_to LIKE %ss AND inactif=%s",
714
            $_SESSION['user_id'].';',
715
            '0'
716
        );
717
        foreach ($rows as $record) {
718
            $listRestrictedFoldersForItems[$record['id_tree']][$inc] = $record['id'];
719
            $inc++;
720
        }
721
        // => Build final lists
722
        // Clean arrays
723
        $listAllowedFolders = array_unique($listAllowedFolders);
724
        $groupesVisiblesUser = explode(';', trimElement($groupesVisiblesUser, ";"));
725
        // Add user allowed folders
726
        $allowedFoldersTmp = array_unique(
727
            array_merge($listAllowedFolders, $groupesVisiblesUser)
728
        );
729
        // Exclude from allowed folders all the specific user forbidden folders
730
        $allowedFolders = array();
731
        foreach ($allowedFoldersTmp as $ident) {
732
            if (!in_array($ident, $groupesInterditsUser) && !empty($ident)) {
733
                array_push($allowedFolders, $ident);
734
            }
735
        }
736
737
        // Clean array
738
        $listAllowedFolders = array_filter(array_unique($allowedFolders));
739
740
        // Exclude all PF
741
        $_SESSION['forbiden_pfs'] = array();
742
743
        $where = new WhereClause('and');
744
        $where->add('personal_folder=%i', 1);
745
        if (isset($SETTINGS['enable_pf_feature']) &&
746
            $SETTINGS['enable_pf_feature'] == 1 &&
747
            isset($_SESSION['personal_folder']) &&
748
            $_SESSION['personal_folder'] == 1
749
        ) {
750
            $where->add('title=%s', $_SESSION['user_id']);
751
            $where->negateLast();
752
        }
753
754
        $persoFlds = DB::query("SELECT id FROM ".prefix_table("nested_tree")." WHERE %l", $where);
755
        foreach ($persoFlds as $persoFldId) {
756
            array_push($_SESSION['forbiden_pfs'], $persoFldId['id']);
757
        }
758
        // Get IDs of personal folders
759
        if (isset($SETTINGS['enable_pf_feature']) &&
760
            $SETTINGS['enable_pf_feature'] == 1 &&
761
            isset($_SESSION['personal_folder']) &&
762
            $_SESSION['personal_folder'] == 1
763
        ) {
764
            $persoFld = DB::queryfirstrow("SELECT id FROM ".prefix_table("nested_tree")." WHERE title = %s", $_SESSION['user_id']);
765
            if (!empty($persoFld['id'])) {
766
                if (!in_array($persoFld['id'], $listAllowedFolders)) {
767
                    array_push($_SESSION['personal_folders'], $persoFld['id']);
768
                    // get all descendants
769
                    $ids = $tree->getDescendants($persoFld['id'], true, false);
770
                    foreach ($ids as $ident) {
771
                        array_push($listAllowedFolders, $ident->id);
772
                        array_push($_SESSION['personal_visible_groups'], $ident->id);
773
                        array_push($_SESSION['personal_folders'], $ident->id);
774
                    }
775
                }
776
            }
777
            // get list of readonly folders when pf is disabled.
778
            // rule - if one folder is set as W or N in one of the Role, then User has access as W
779
            foreach ($listAllowedFolders as $folderId) {
780
                if (!in_array($folderId, array_unique(array_merge($listReadOnlyFolders, $_SESSION['personal_folders'])))) {   //
781
                    DB::query(
782
                        "SELECT *
783
                        FROM ".prefix_table("roles_values")."
784
                        WHERE folder_id = %i AND role_id IN %li AND type IN %ls",
785
                        $folderId,
786
                        $fonctionsAssociees,
787
                        array("W", "ND", "NE", "NDNE")
788
                    );
789
                    if (DB::count() == 0 && in_array($folderId, $groupesVisiblesUser) === false) {
790
                        array_push($listReadOnlyFolders, $folderId);
791
                    }
792
                }
793
            }
794
        } else {
795
            // get list of readonly folders when pf is disabled.
796
            // rule - if one folder is set as W in one of the Role, then User has access as W
797
            foreach ($listAllowedFolders as $folderId) {
798
                if (!in_array($folderId, $listReadOnlyFolders)) {
799
                    DB::query(
800
                        "SELECT *
801
                        FROM ".prefix_table("roles_values")."
802
                        WHERE folder_id = %i AND role_id IN %li AND type IN %ls",
803
                        $folderId,
804
                        $fonctionsAssociees,
805
                        array("W", "ND", "NE", "NDNE")
806
                    );
807
                    if (DB::count() == 0 && !in_array($folderId, $groupesVisiblesUser)) {
808
                        array_push($listReadOnlyFolders, $folderId);
809
                    }
810
                }
811
            }
812
        }
813
814
        // check if change proposals on User's items
815
        if (isset($SETTINGS['enable_suggestion']) && $SETTINGS['enable_suggestion'] == 1) {
816
            DB::query(
817
                "SELECT *
818
                FROM ".prefix_table("items_change")." AS c
819
                LEFT JOIN ".prefix_table("log_items")." AS i ON (c.item_id = i.id_item)
820
                WHERE i.action = %s AND i.id_user = %i",
821
                "at_creation",
822
                $_SESSION['user_id']
823
            );
824
            $_SESSION['nb_item_change_proposals'] = DB::count();
825
        } else {
826
            $_SESSION['nb_item_change_proposals'] = 0;
827
        }
828
829
        $_SESSION['all_non_personal_folders'] = $listAllowedFolders;
830
        $_SESSION['groupes_visibles'] = $listAllowedFolders;
831
        $_SESSION['groupes_visibles_list'] = implode(',', $listAllowedFolders);
832
        $_SESSION['personal_visible_groups_list'] = implode(',', $_SESSION['personal_visible_groups']);
833
        $_SESSION['read_only_folders'] = $listReadOnlyFolders;
834
        $_SESSION['no_access_folders'] = $groupesInterdits;
835
836
        $_SESSION['list_folders_limited'] = $listFoldersLimited;
837
        $_SESSION['list_folders_editable_by_role'] = $listFoldersEditableByRole;
838
        $_SESSION['list_restricted_folders_for_items'] = $listRestrictedFoldersForItems;
839
        // Folders and Roles numbers
840
        DB::queryfirstrow("SELECT id FROM ".prefix_table("nested_tree")."");
841
        $_SESSION['nb_folders'] = DB::count();
842
        DB::queryfirstrow("SELECT id FROM ".prefix_table("roles_title"));
843
        $_SESSION['nb_roles'] = DB::count();
844
    }
845
846
    // update user's timestamp
847
    DB::update(
848
        prefix_table('users'),
849
        array(
850
            'timestamp' => time()
851
        ),
852
        "id=%i",
853
        $_SESSION['user_id']
854
    );
855
}
856
857
/**
858
 * updateCacheTable()
859
 *
860
 * Update the CACHE table
861
 * @param string $action
862
 */
863
function updateCacheTable($action, $ident = "")
864
{
865
    global $server, $user, $pass, $database, $port, $encoding;
866
    global $SETTINGS;
867
868
    require_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php';
869
870
    //Connect to DB
871
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
872
    $pass = defuse_return_decrypted($pass);
873
    DB::$host = $server;
874
    DB::$user = $user;
875
    DB::$password = $pass;
876
    DB::$dbName = $database;
877
    DB::$port = $port;
878
    DB::$encoding = $encoding;
879
    DB::$error_handler = true;
880
    $link = mysqli_connect($server, $user, $pass, $database, $port);
881
    $link->set_charset($encoding);
882
883
    //Load Tree
884
    $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
885
    $tree->register();
886
    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
887
888
    // Rebuild full cache table
889
    if ($action === "reload") {
890
        // truncate table
891
        DB::query("TRUNCATE TABLE ".prefix_table("cache"));
892
893
        // reload date
894
        $rows = DB::query(
895
            "SELECT *
896
            FROM ".prefix_table('items')." as i
897
            INNER JOIN ".prefix_table('log_items')." as l ON (l.id_item = i.id)
898
            AND l.action = %s
899
            AND i.inactif = %i",
900
            'at_creation',
901
            0
902
        );
903
        foreach ($rows as $record) {
904
            // Get all TAGS
905
            $tags = "";
906
            $itemTags = DB::query("SELECT tag FROM ".prefix_table('tags')." WHERE item_id=%i", $record['id']);
907 View Code Duplication
            foreach ($itemTags as $itemTag) {
908
                if (!empty($itemTag['tag'])) {
909
                    $tags .= $itemTag['tag']." ";
910
                }
911
            }
912
            // Get renewal period
913
            $resNT = DB::queryfirstrow("SELECT renewal_period FROM ".prefix_table('nested_tree')." WHERE id=%i", $record['id_tree']);
914
915
            // form id_tree to full foldername
916
            $folder = "";
917
            $arbo = $tree->getPath($record['id_tree'], true);
918 View Code Duplication
            foreach ($arbo as $elem) {
919
                if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
920
                    $elem->title = $_SESSION['login'];
921
                }
922
                if (empty($folder)) {
923
                    $folder = stripslashes($elem->title);
924
                } else {
925
                    $folder .= " » ".stripslashes($elem->title);
926
                }
927
            }
928
            // store data
929
            DB::insert(
930
                prefix_table('cache'),
931
                array(
932
                    'id' => $record['id'],
933
                    'label' => $record['label'],
934
                    'description' => isset($record['description']) ? $record['description'] : "",
935
                    'url' => (isset($record['url']) && !empty($record['url'])) ? $record['url'] : "0",
936
                    'tags' => $tags,
937
                    'id_tree' => $record['id_tree'],
938
                    'perso' => $record['perso'],
939
                    'restricted_to' => (isset($record['restricted_to']) && !empty($record['restricted_to'])) ? $record['restricted_to'] : "0",
940
                    'login' => isset($record['login']) ? $record['login'] : "",
941
                    'folder' => $folder,
942
                    'author' => $record['id_user'],
943
                    'renewal_period' => isset($resNT['renewal_period']) ? $resNT['renewal_period'] : "0",
944
                    'timestamp' => $record['date']
945
                    )
946
            );
947
        }
948
        // UPDATE an item
949
    } elseif ($action === "update_value") {
950
        // get new value from db
951
        $data = DB::queryfirstrow(
952
            "SELECT label, description, id_tree, perso, restricted_to, login, url
953
            FROM ".prefix_table('items')."
954
            WHERE id=%i",
955
            $ident
956
        );
957
        // Get all TAGS
958
        $tags = "";
959
        $itemTags = DB::query("SELECT tag FROM ".prefix_table('tags')." WHERE item_id=%i", $ident);
960 View Code Duplication
        foreach ($itemTags as $itemTag) {
961
            if (!empty($itemTag['tag'])) {
962
                $tags .= $itemTag['tag']." ";
963
            }
964
        }
965
        // form id_tree to full foldername
966
        $folder = "";
967
        $arbo = $tree->getPath($data['id_tree'], true);
968 View Code Duplication
        foreach ($arbo as $elem) {
969
            if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
970
                $elem->title = $_SESSION['login'];
971
            }
972
            if (empty($folder)) {
973
                $folder = stripslashes($elem->title);
974
            } else {
975
                $folder .= " » ".stripslashes($elem->title);
976
            }
977
        }
978
        // finaly update
979
        DB::update(
980
            prefix_table('cache'),
981
            array(
982
                'label' => $data['label'],
983
                'description' => $data['description'],
984
                'tags' => $tags,
985
                'url' => (isset($data['url']) && !empty($data['url'])) ? $data['url'] : "0",
986
                'id_tree' => $data['id_tree'],
987
                'perso' => $data['perso'],
988
                'restricted_to' => (isset($data['restricted_to']) && !empty($data['restricted_to'])) ? $data['restricted_to'] : "0",
989
                'login' => isset($data['login']) ? $data['login'] : "",
990
                'folder' => $folder,
991
                'author' => $_SESSION['user_id'],
992
                ),
993
            "id = %i",
994
            $ident
995
        );
996
        // ADD an item
997
    } elseif ($action === "add_value") {
998
        // get new value from db
999
        $data = DB::queryFirstRow(
1000
            "SELECT i.label, i.description, i.id_tree as id_tree, i.perso, i.restricted_to, i.id, i.login, i.url, l.date
1001
            FROM ".prefix_table('items')." as i
1002
            INNER JOIN ".prefix_table('log_items')." as l ON (l.id_item = i.id)
1003
            WHERE i.id = %i
1004
            AND l.action = %s",
1005
            $ident,
1006
            'at_creation'
1007
        );
1008
        // Get all TAGS
1009
        $tags = "";
1010
        $itemTags = DB::query("SELECT tag FROM ".prefix_table('tags')." WHERE item_id = %i", $ident);
1011 View Code Duplication
        foreach ($itemTags as $itemTag) {
1012
            if (!empty($itemTag['tag'])) {
1013
                $tags .= $itemTag['tag']." ";
1014
            }
1015
        }
1016
        // form id_tree to full foldername
1017
        $folder = "";
1018
        $arbo = $tree->getPath($data['id_tree'], true);
1019 View Code Duplication
        foreach ($arbo as $elem) {
1020
            if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
1021
                $elem->title = $_SESSION['login'];
1022
            }
1023
            if (empty($folder)) {
1024
                $folder = stripslashes($elem->title);
1025
            } else {
1026
                $folder .= " » ".stripslashes($elem->title);
1027
            }
1028
        }
1029
        // finaly update
1030
        DB::insert(
1031
            prefix_table('cache'),
1032
            array(
1033
                'id' => $data['id'],
1034
                'label' => $data['label'],
1035
                'description' => $data['description'],
1036
                'tags' => (isset($tags) && !empty($tags)) ? $tags : "None",
1037
                'url' => (isset($data['url']) && !empty($data['url'])) ? $data['url'] : "0",
1038
                'id_tree' => $data['id_tree'],
1039
                'perso' => (isset($data['perso']) && !empty($data['perso']) && $data['perso'] !== "None") ? $data['perso'] : "0",
1040
                'restricted_to' => (isset($data['restricted_to']) && !empty($data['restricted_to'])) ? $data['restricted_to'] : "None",
1041
                'login' => isset($data['login']) ? $data['login'] : "",
1042
                'folder' => $folder,
1043
                'author' => $_SESSION['user_id'],
1044
                'timestamp' => $data['date']
1045
            )
1046
        );
1047
1048
        // DELETE an item
1049
    } elseif ($action === "delete_value") {
1050
        DB::delete(prefix_table('cache'), "id = %i", $ident);
1051
    }
1052
}
1053
1054
/*
1055
*
1056
*/
1057
function getStatisticsData()
1058
{
1059
    global $SETTINGS;
1060
1061
    DB::query(
1062
        "SELECT id FROM ".prefix_table("nested_tree")." WHERE personal_folder = %i",
1063
        0
1064
    );
1065
    $counter_folders = DB::count();
1066
1067
    DB::query(
1068
        "SELECT id FROM ".prefix_table("nested_tree")." WHERE personal_folder = %i",
1069
        1
1070
    );
1071
    $counter_folders_perso = DB::count();
1072
1073
    DB::query(
1074
        "SELECT id FROM ".prefix_table("items")." WHERE perso = %i",
1075
        0
1076
    );
1077
    $counter_items = DB::count();
1078
1079
    DB::query(
1080
        "SELECT id FROM ".prefix_table("items")." WHERE perso = %i",
1081
        1
1082
    );
1083
    $counter_items_perso = DB::count();
1084
1085
    DB::query(
1086
        "SELECT id FROM ".prefix_table("users").""
1087
    );
1088
    $counter_users = DB::count();
1089
1090
    DB::query(
1091
        "SELECT id FROM ".prefix_table("users")." WHERE admin = %i",
1092
        1
1093
    );
1094
    $admins = DB::count();
1095
1096
    DB::query(
1097
        "SELECT id FROM ".prefix_table("users")." WHERE gestionnaire = %i",
1098
        1
1099
    );
1100
    $managers = DB::count();
1101
1102
    DB::query(
1103
        "SELECT id FROM ".prefix_table("users")." WHERE read_only = %i",
1104
        1
1105
    );
1106
    $readOnly = DB::count();
1107
1108
    // list the languages
1109
    $usedLang = [];
1110
    $tp_languages = DB::query(
1111
        "SELECT name FROM ".prefix_table("languages")
1112
    );
1113
    foreach ($tp_languages as $tp_language) {
1114
        DB::query(
1115
            "SELECT * FROM ".prefix_table("users")." WHERE user_language = %s",
1116
            $tp_language['name']
1117
        );
1118
        $usedLang[$tp_language['name']] = round((DB::count() * 100 / $counter_users), 0);
1119
    }
1120
1121
    // get list of ips
1122
    $usedIp = [];
1123
    $tp_ips = DB::query(
1124
        "SELECT user_ip FROM ".prefix_table("users")
1125
    );
1126
    foreach ($tp_ips as $ip) {
1127
        if (array_key_exists($ip['user_ip'], $usedIp)) {
1128
            $usedIp[$ip['user_ip']] = $usedIp[$ip['user_ip']] + 1;
1129
        } elseif (!empty($ip['user_ip']) && $ip['user_ip'] !== "none") {
1130
            $usedIp[$ip['user_ip']] = 1;
1131
        }
1132
    }
1133
1134
    return array(
1135
        "error" => "",
1136
        "stat_phpversion" => phpversion(),
1137
        "stat_folders" => $counter_folders,
1138
        "stat_folders_shared" => intval($counter_folders) - intval($counter_folders_perso),
1139
        "stat_items" => $counter_items,
1140
        "stat_items_shared" => intval($counter_items) - intval($counter_items_perso),
1141
        "stat_users" => $counter_users,
1142
        "stat_admins" => $admins,
1143
        "stat_managers" => $managers,
1144
        "stat_ro" => $readOnly,
1145
        "stat_kb" => $SETTINGS['enable_kb'],
1146
        "stat_pf" => $SETTINGS['enable_pf_feature'],
1147
        "stat_fav" => $SETTINGS['enable_favourites'],
1148
        "stat_teampassversion" => $SETTINGS['cpassman_version'],
1149
        "stat_ldap" => $SETTINGS['ldap_mode'],
1150
        "stat_agses" => $SETTINGS['agses_authentication_enabled'],
1151
        "stat_duo" => $SETTINGS['duo'],
1152
        "stat_suggestion" => $SETTINGS['enable_suggestion'],
1153
        "stat_api" => $SETTINGS['api'],
1154
        "stat_customfields" => $SETTINGS['item_extra_fields'],
1155
        "stat_syslog" => $SETTINGS['syslog_enable'],
1156
        "stat_2fa" => $SETTINGS['google_authentication'],
1157
        "stat_stricthttps" => $SETTINGS['enable_sts'],
1158
        "stat_mysqlversion" => DB::serverVersion(),
1159
        "stat_languages" => $usedLang,
1160
        "stat_country" => $usedIp
1161
    );
1162
}
1163
1164
/**
1165
 * sendEmail()
1166
 *
1167
 * @return
1168
 */
1169
function sendEmail($subject, $textMail, $email, $textMailAlt = "")
1170
{
1171
    global $LANG;
1172
    global $SETTINGS;
1173
1174
    // CAse where email not defined
1175
    if ($email === "none") {
1176
        return '"error":"" , "message":"'.$LANG['forgot_my_pw_email_sent'].'"';
1177
    }
1178
1179
    include $SETTINGS['cpassman_dir'].'/includes/config/settings.php';
1180
    //load library
1181
    $user_language = isset($_SESSION['user_language']) ? $_SESSION['user_language'] : "english";
1182
    require_once $SETTINGS['cpassman_dir'].'/includes/language/'.$user_language.'.php';
1183
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Email/Phpmailer/PHPMailerAutoload.php';
1184
1185
    // load PHPMailer
1186
    $mail = new PHPMailer();
1187
1188
    // send to user
1189
    $mail->setLanguage("en", "../includes/libraries/Email/Phpmailer/language/");
1190
    $mail->SMTPDebug = 0; //value 1 can be used to debug
1191
    $mail->Port = $SETTINGS['email_port']; //COULD BE USED
1192
    $mail->CharSet = "utf-8";
1193
    if ($SETTINGS['email_security'] === "tls" || $SETTINGS['email_security'] === "ssl") {
1194
        $mail->SMTPSecure = $SETTINGS['email_security'];
1195
    }
1196
    $mail->isSmtp(); // send via SMTP
1197
    $mail->Host = $SETTINGS['email_smtp_server']; // SMTP servers
1198
    $mail->SMTPAuth = $SETTINGS['email_smtp_auth'] == '1' ? true : false; // turn on SMTP authentication
1199
    $mail->Username = $SETTINGS['email_auth_username']; // SMTP username
1200
    $mail->Password = $SETTINGS['email_auth_pwd']; // SMTP password
1201
    $mail->From = $SETTINGS['email_from'];
1202
    $mail->FromName = $SETTINGS['email_from_name'];
1203
    $mail->addAddress($email); //Destinataire
1204
    $mail->WordWrap = 80; // set word wrap
1205
    $mail->isHtml(true); // send as HTML
1206
    $mail->Subject = $subject;
1207
    $mail->Body = $textMail;
1208
    $mail->AltBody = $textMailAlt;
1209
    // send email
1210
    if (!$mail->send()) {
1211
        return '"error":"error_mail_not_send" , "message":"'.str_replace(array("\n", "\t", "\r"), '', $mail->ErrorInfo).'"';
1212
    } else {
1213
        return '"error":"" , "message":"'.$LANG['forgot_my_pw_email_sent'].'"';
1214
    }
1215
}
1216
1217
/**
1218
 * generateKey()
1219
 *
1220
 * @return
1221
 */
1222
function generateKey()
1223
{
1224
    return substr(md5(rand().rand()), 0, 15);
1225
}
1226
1227
/**
1228
 * dateToStamp()
1229
 *
1230
 * @return
1231
 */
1232
function dateToStamp($date)
1233
{
1234
    global $SETTINGS;
1235
1236
    $date = date_parse_from_format($SETTINGS['date_format'], $date);
1237
    if ($date['warning_count'] == 0 && $date['error_count'] == 0) {
1238
        return mktime(23, 59, 59, $date['month'], $date['day'], $date['year']);
1239
    } else {
1240
        return false;
1241
    }
1242
}
1243
1244
function isDate($date)
1245
{
1246
    return (strtotime($date) !== false);
1247
}
1248
1249
/**
1250
 * isUTF8()
1251
 *
1252
 * @return integer is the string in UTF8 format.
1253
 */
1254
1255
function isUTF8($string)
1256
{
1257
    if (is_array($string) === true) {
1258
        $string = $string['string'];
1259
    }
1260
    return preg_match(
1261
        '%^(?:
1262
        [\x09\x0A\x0D\x20-\x7E] # ASCII
1263
        | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
1264
        | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
1265
        | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
1266
        | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
1267
        | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
1268
        | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
1269
        | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
1270
        )*$%xs',
1271
        $string
1272
    );
1273
}
1274
1275
/*
1276
* FUNCTION
1277
* permits to prepare data to be exchanged
1278
*/
1279
/**
1280
 * @param string $type
1281
 */
1282
function prepareExchangedData($data, $type)
1283
{
1284
    global $SETTINGS;
1285
1286
    //load ClassLoader
1287
    require_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php';
1288
    //Load AES
1289
    $aes = new SplClassLoader('Encryption\Crypt', '../includes/libraries');
1290
    $aes->register();
1291
1292
    if ($type == "encode") {
1293
        if (isset($SETTINGS['encryptClientServer'])
1294
            && $SETTINGS['encryptClientServer'] === "0"
1295
        ) {
1296
            return json_encode(
1297
                $data,
1298
                JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
1299
            );
1300 View Code Duplication
        } else {
1301
            return Encryption\Crypt\aesctr::encrypt(
1302
                json_encode(
1303
                    $data,
1304
                    JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
1305
                ),
1306
                $_SESSION['key'],
1307
                256
1308
            );
1309
        }
1310
    } elseif ($type == "decode") {
1311
        if (isset($SETTINGS['encryptClientServer'])
1312
            && $SETTINGS['encryptClientServer'] === "0"
1313
        ) {
1314
            return json_decode(
1315
                $data,
1316
                true
1317
            );
1318
        } else {
1319
            return json_decode(
1320
                Encryption\Crypt\aesctr::decrypt(
1321
                    $data,
1322
                    $_SESSION['key'],
1323
                    256
1324
                ),
1325
                true
1326
            );
1327
        }
1328
    }
1329
}
1330
1331
function make_thumb($src, $dest, $desired_width)
1332
{
1333
    /* read the source image */
1334
    $source_image = imagecreatefrompng($src);
1335
    $width = imagesx($source_image);
1336
    $height = imagesy($source_image);
1337
1338
    /* find the "desired height" of this thumbnail, relative to the desired width  */
1339
    $desired_height = floor($height * ($desired_width / $width));
1340
1341
    /* create a new, "virtual" image */
1342
    $virtual_image = imagecreatetruecolor($desired_width, $desired_height);
1343
1344
    /* copy source image at a resized size */
1345
    imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $desired_width, $desired_height, $width, $height);
1346
1347
    /* create the physical thumbnail image to its destination */
1348
    imagejpeg($virtual_image, $dest);
1349
}
1350
1351
/*
1352
** check table prefix in SQL query
1353
*/
1354
/**
1355
 * @param string $table
1356
 */
1357
function prefix_table($table)
1358
{
1359
    global $pre;
1360
    $safeTable = htmlspecialchars($pre.$table);
1361
    if (!empty($safeTable)) {
1362
        // sanitize string
1363
        return $safeTable;
1364
    } else {
1365
        // stop error no table
1366
        return "table_not_exists";
1367
    }
1368
}
1369
1370
/*
1371
 * Creates a KEY using PasswordLib
1372
 */
1373
function GenerateCryptKey($size = "", $secure = false, $numerals = false, $capitalize = false, $ambiguous = false, $symbols = false)
1374
{
1375
    // load library
1376
    $pwgen = new SplClassLoader('Encryption\PwGen', '../includes/libraries');
1377
    $pwgen->register();
1378
    $pwgen = new Encryption\PwGen\pwgen();
1379
1380
    // init
1381
    if (!empty($size)) {
1382
        $pwgen->setLength($size);
1383
    }
1384
    if (!empty($secure)) {
1385
        $pwgen->setSecure($secure);
1386
    }
1387
    if (!empty($numerals)) {
1388
        $pwgen->setNumerals($numerals);
1389
    }
1390
    if (!empty($capitalize)) {
1391
        $pwgen->setCapitalize($capitalize);
1392
    }
1393
    if (!empty($ambiguous)) {
1394
        $pwgen->setAmbiguous($ambiguous);
1395
    }
1396
    if (!empty($symbols)) {
1397
        $pwgen->setSymbols($symbols);
1398
    }
1399
1400
    // generate and send back
1401
    return $pwgen->generate();
1402
}
1403
1404
/*
1405
* Send sysLOG message
1406
* @param string $message
1407
* @param string $host
1408
*/
1409
function send_syslog($message, $host, $port, $component = "teampass")
1410
{
1411
    $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
1412
    $syslog_message = "<123>".date('M d H:i:s ').$component.": ".$message;
1413
    socket_sendto($sock, $syslog_message, strlen($syslog_message), 0, $host, $port);
1414
    socket_close($sock);
1415
}
1416
1417
1418
1419
/**
1420
 * logEvents()
1421
 *
1422
 * permits to log events into DB
1423
 * @param string $type
1424
 * @param string $label
1425
 * @param string $field_1
1426
 */
1427
function logEvents($type, $label, $who, $login = "", $field_1 = null)
1428
{
1429
    global $server, $user, $pass, $database, $port, $encoding;
1430
    global $SETTINGS;
1431
1432
    if (empty($who)) {
1433
        $who = get_client_ip_server();
1434
    }
1435
1436
    // include librairies & connect to DB
1437
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1438
    $pass = defuse_return_decrypted($pass);
1439
    DB::$host = $server;
1440
    DB::$user = $user;
1441
    DB::$password = $pass;
1442
    DB::$dbName = $database;
1443
    DB::$port = $port;
1444
    DB::$encoding = $encoding;
1445
    DB::$error_handler = true;
1446
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1447
    $link->set_charset($encoding);
1448
1449
    DB::insert(
1450
        prefix_table("log_system"),
1451
        array(
1452
            'type' => $type,
1453
            'date' => time(),
1454
            'label' => $label,
1455
            'qui' => $who,
1456
            'field_1' => $field_1 === null ? "" : $field_1
1457
        )
1458
    );
1459
    if (isset($SETTINGS['syslog_enable']) && $SETTINGS['syslog_enable'] == 1) {
1460
        if ($type == "user_mngt") {
1461
            send_syslog(
1462
                "The User ".$login." performed the action of ".$label." to the user ".$field_1." - ".$type,
1463
                $SETTINGS['syslog_host'],
1464
                $SETTINGS['syslog_port'],
1465
                "teampass"
1466
            );
1467
        } else {
1468
            send_syslog(
1469
                "The User ".$login." performed the action of ".$label." - ".$type,
1470
                $SETTINGS['syslog_host'],
1471
                $SETTINGS['syslog_port'],
1472
                "teampass"
1473
            );
1474
        }
1475
    }
1476
}
1477
1478
/**
1479
 * @param string $item
1480
 * @param string $action
1481
 */
1482
function logItems($ident, $item, $id_user, $action, $login = "", $raison = null, $raison_iv = null, $encryption_type = "")
1483
{
1484
    global $server, $user, $pass, $database, $port, $encoding;
1485
    global $SETTINGS;
1486
1487
    // include librairies & connect to DB
1488
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1489
    $pass = defuse_return_decrypted($pass);
1490
    DB::$host = $server;
1491
    DB::$user = $user;
1492
    DB::$password = $pass;
1493
    DB::$dbName = $database;
1494
    DB::$port = $port;
1495
    DB::$encoding = $encoding;
1496
    DB::$error_handler = true;
1497
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1498
    $link->set_charset($encoding);
1499
    DB::insert(
1500
        prefix_table("log_items"),
1501
        array(
1502
            'id_item' => $ident,
1503
            'date' => time(),
1504
            'id_user' => $id_user,
1505
            'action' => $action,
1506
            'raison' => $raison,
1507
            'raison_iv' => $raison_iv,
1508
            'encryption_type' => $encryption_type
1509
        )
1510
    );
1511
    if (isset($SETTINGS['syslog_enable']) && $SETTINGS['syslog_enable'] == 1) {
1512
        send_syslog(
1513
            "The Item ".$item." was ".$action." by ".$login." ".$raison,
1514
            $SETTINGS['syslog_host'],
1515
            $SETTINGS['syslog_port'],
1516
            "teampass"
1517
        );
1518
    }
1519
}
1520
1521
/*
1522
* Function to get the client ip address
1523
 */
1524
function get_client_ip_server()
1525
{
1526
    if (getenv('HTTP_CLIENT_IP')) {
1527
            $ipaddress = getenv('HTTP_CLIENT_IP');
1528
    } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
1529
            $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
1530
    } elseif (getenv('HTTP_X_FORWARDED')) {
1531
            $ipaddress = getenv('HTTP_X_FORWARDED');
1532
    } elseif (getenv('HTTP_FORWARDED_FOR')) {
1533
            $ipaddress = getenv('HTTP_FORWARDED_FOR');
1534
    } elseif (getenv('HTTP_FORWARDED')) {
1535
            $ipaddress = getenv('HTTP_FORWARDED');
1536
    } elseif (getenv('REMOTE_ADDR')) {
1537
            $ipaddress = getenv('REMOTE_ADDR');
1538
    } else {
1539
            $ipaddress = 'UNKNOWN';
1540
    }
1541
1542
    return $ipaddress;
1543
}
1544
1545
/**
1546
 * Escape all HTML, JavaScript, and CSS
1547
 *
1548
 * @param string $input The input string
1549
 * @param string $encoding Which character encoding are we using?
1550
 * @return string
1551
 */
1552
function noHTML($input, $encoding = 'UTF-8')
1553
{
1554
    return htmlspecialchars($input, ENT_QUOTES | ENT_XHTML, $encoding, false);
1555
}
1556
1557
/**
1558
 * handleConfigFile()
1559
 *
1560
 * permits to handle the Teampass config file
1561
 * $action accepts "rebuild" and "update"
1562
 */
1563
function handleConfigFile($action, $field = null, $value = null)
1564
{
1565
    global $server, $user, $pass, $database, $port, $encoding;
1566
    global $SETTINGS;
1567
1568
    $tp_config_file = "../includes/config/tp.config.php";
1569
1570
    // Load AntiXSS
1571
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
1572
    $antiXss = new protect\AntiXSS\AntiXSS();
1573
1574
    // include librairies & connect to DB
1575
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1576
    $pass = defuse_return_decrypted($pass);
1577
    DB::$host = $server;
1578
    DB::$user = $user;
1579
    DB::$password = $pass;
1580
    DB::$dbName = $database;
1581
    DB::$port = $port;
1582
    DB::$encoding = $encoding;
1583
    DB::$error_handler = true;
1584
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1585
    $link->set_charset($encoding);
1586
1587
    if (!file_exists($tp_config_file) || $action == "rebuild") {
1588
        // perform a copy
1589
        if (file_exists($tp_config_file)) {
1590
            if (!copy($tp_config_file, $tp_config_file.'.'.date("Y_m_d_His", time()))) {
1591
                return "ERROR: Could not copy file '".$tp_config_file."'";
1592
            }
1593
        }
1594
1595
        // regenerate
1596
        $data = array();
1597
        $data[0] = "<?php\n";
1598
        $data[1] = "global \$SETTINGS;\n";
1599
        $data[2] = "\$SETTINGS = array (\n";
1600
        $rows = DB::query(
1601
            "SELECT * FROM ".prefix_table("misc")." WHERE type=%s",
1602
            "admin"
1603
        );
1604
        foreach ($rows as $record) {
1605
            array_push($data, "    '".$record['intitule']."' => '".$record['valeur']."',\n");
1606
        }
1607
        array_push($data, ");");
1608
        $data = array_unique($data);
1609
    } elseif ($action == "update" && !empty($field)) {
1610
        $data = file($tp_config_file);
1611
        $inc = 0;
1612
        $bFound = false;
1613
        foreach ($data as $line) {
1614
            if (stristr($line, ");")) {
1615
                break;
1616
            }
1617
1618
            //
1619
            if (stristr($line, "'".$field."' => '")) {
1620
                $data[$inc] = "    '".$field."' => '".$antiXss->xss_clean($value)."',\n";
1621
                $bFound = true;
1622
                break;
1623
            }
1624
            $inc++;
1625
        }
1626
        if ($bFound === false) {
1627
            $data[($inc - 1)] = "    '".$field."' => '".$antiXss->xss_clean($value)."',\n";
1628
        }
1629
    }
1630
1631
    // update file
1632
    file_put_contents($tp_config_file, implode('', isset($data) ? $data : array()));
1633
1634
    return true;
1635
}
1636
1637
/*
1638
** Permits to replace &#92; to permit correct display
1639
*/
1640
/**
1641
 * @param string $input
1642
 */
1643
function handleBackslash($input)
1644
{
1645
    return str_replace("&amp;#92;", "&#92;", $input);
1646
}
1647
1648
/*
1649
** Permits to loas settings
1650
*/
1651
function loadSettings()
1652
{
1653
    global $SETTINGS;
1654
1655
    /* LOAD CPASSMAN SETTINGS */
1656
    if (!isset($SETTINGS['loaded']) || $SETTINGS['loaded'] != 1) {
1657
        $SETTINGS['duplicate_folder'] = 0; //by default, this is set to 0;
1658
        $SETTINGS['duplicate_item'] = 0; //by default, this is set to 0;
1659
        $SETTINGS['number_of_used_pw'] = 5; //by default, this value is set to 5;
1660
        $settings = array();
1661
1662
        $rows = DB::query(
1663
            "SELECT * FROM ".prefix_table("misc")." WHERE type=%s_type OR type=%s_type2",
1664
            array(
1665
                'type' => "admin",
1666
                'type2' => "settings"
1667
            )
1668
        );
1669
        foreach ($rows as $record) {
1670
            if ($record['type'] == 'admin') {
1671
                $SETTINGS[$record['intitule']] = $record['valeur'];
1672
            } else {
1673
                $settings[$record['intitule']] = $record['valeur'];
1674
            }
1675
        }
1676
        $SETTINGS['loaded'] = 1;
1677
        $SETTINGS['default_session_expiration_time'] = 5;
1678
    }
1679
}
1680
1681
/*
1682
** check if folder has custom fields.
1683
** Ensure that target one also has same custom fields
1684
*/
1685
function checkCFconsistency($source_id, $target_id)
1686
{
1687
    $source_cf = array();
1688
    $rows = DB::QUERY(
1689
        "SELECT id_category
1690
        FROM ".prefix_table("categories_folders")."
1691
        WHERE id_folder = %i",
1692
        $source_id
1693
    );
1694
    foreach ($rows as $record) {
1695
        array_push($source_cf, $record['id_category']);
1696
    }
1697
1698
    $target_cf = array();
1699
    $rows = DB::QUERY(
1700
        "SELECT id_category
1701
        FROM ".prefix_table("categories_folders")."
1702
        WHERE id_folder = %i",
1703
        $target_id
1704
    );
1705
    foreach ($rows as $record) {
1706
        array_push($target_cf, $record['id_category']);
1707
    }
1708
1709
    $cf_diff = array_diff($source_cf, $target_cf);
1710
    if (count($cf_diff) > 0) {
1711
        return false;
1712
    }
1713
1714
    return true;
1715
}
1716
1717
/*
1718
*
1719
*/
1720
function encrypt_or_decrypt_file($filename_to_rework, $filename_status)
1721
{
1722
    global $server, $user, $pass, $database, $port, $encoding;
1723
    global $SETTINGS;
1724
1725
    // Include librairies & connect to DB
1726
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1727
    $pass = defuse_return_decrypted($pass);
1728
    DB::$host = $server;
1729
    DB::$user = $user;
1730
    DB::$password = $pass;
1731
    DB::$dbName = $database;
1732
    DB::$port = $port;
1733
    DB::$encoding = $encoding;
1734
    DB::$error_handler = true;
1735
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1736
    $link->set_charset($encoding);
1737
1738
    // Get file info in DB
1739
    $fileInfo = DB::queryfirstrow(
1740
        "SELECT id FROM ".prefix_table("files")." WHERE file = %s",
1741
        filter_var($filename_to_rework, FILTER_SANITIZE_STRING)
1742
    );
1743
    if (empty($fileInfo['id']) === false) {
1744
        // Load PhpEncryption library
1745
        $path_to_encryption = '/includes/libraries/Encryption/Encryption/';
1746
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Crypto.php';
1747
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Encoding.php';
1748
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'DerivedKeys.php';
1749
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Key.php';
1750
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyOrPassword.php';
1751
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'File.php';
1752
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'RuntimeTests.php';
1753
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyProtectedByPassword.php';
1754
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Core.php';
1755
1756
        // Get KEY
1757
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1758
1759
        if (isset($SETTINGS['enable_attachment_encryption'])
1760
            && $SETTINGS['enable_attachment_encryption'] === "1" &&
1761
            isset($filename_status)
1762
            && ($filename_status === "clear"
1763
                || $filename_status === "0")
1764
        ) {
1765
            // File needs to be encrypted
1766 View Code Duplication
            if (file_exists($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework)) {
1767
                // Make a copy of file
1768
                if (!copy(
1769
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1770
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1771
                )) {
1772
                    exit;
1773
                } else {
1774
                    // Do a bck
1775
                    copy(
1776
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1777
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1778
                    );
1779
                }
1780
1781
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework);
1782
1783
                // Now encrypt the file with saltkey
1784
                $err = '';
1785
                try {
1786
                    \Defuse\Crypto\File::encryptFile(
1787
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1788
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1789
                        \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1790
                    );
1791
                } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1792
                    $err = "An attack! Either the wrong key was loaded, or the ciphertext has changed since it was created either corrupted in the database or intentionally modified by someone trying to carry out an attack.";
1793
                } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1794
                    $err = $ex;
1795
                } catch (Defuse\Crypto\Exception\IOException $ex) {
1796
                    $err = $ex;
1797
                }
1798
                if (empty($err) === false) {
1799
                    echo $err;
1800
                }
1801
1802
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1803
1804
                // update table
1805
                DB::update(
1806
                    prefix_table('files'),
1807
                    array(
1808
                        'status' => 'encrypted'
1809
                        ),
1810
                    "id = %i",
1811
                    $fileInfo['id']
1812
                );
1813
            }
1814
        } elseif (isset($SETTINGS['enable_attachment_encryption'])
1815
            && $SETTINGS['enable_attachment_encryption'] === "0"
1816
            && isset($filename_status)
1817
            && $filename_status === "encrypted"
1818
        ) {
1819
            // file needs to be decrypted
1820 View Code Duplication
            if (file_exists($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework)) {
1821
                // make a copy of file
1822
                if (!copy(
1823
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1824
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1825
                )) {
1826
                    exit;
1827
                } else {
1828
                    // do a bck
1829
                    copy(
1830
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1831
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1832
                    );
1833
                }
1834
1835
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework);
1836
1837
                // Now encrypt the file with saltkey
1838
                $err = '';
1839
                try {
1840
                    \Defuse\Crypto\File::decryptFile(
1841
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1842
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1843
                        \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1844
                    );
1845
                } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1846
                    $err = "An attack! Either the wrong key was loaded, or the ciphertext has changed since it was created either corrupted in the database or intentionally modified by someone trying to carry out an attack.";
1847
                } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1848
                    $err = $ex;
1849
                } catch (Defuse\Crypto\Exception\IOException $ex) {
1850
                    $err = $ex;
1851
                }
1852
                if (empty($err) === false) {
1853
                    echo $err;
1854
                }
1855
1856
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1857
1858
                // update table
1859
                DB::update(
1860
                    prefix_table('files'),
1861
                    array(
1862
                        'status' => 'clear'
1863
                        ),
1864
                    "id = %i",
1865
                    $fileInfo['id']
1866
                );
1867
            }
1868
        }
1869
    }
1870
1871
    // Exit
1872
    return false;
1873
}
1874
1875
/**
1876
 * Will encrypte/decrypt a fil eusing Defuse
1877
 * @param  string $type        can be either encrypt or decrypt
1878
 * @param  string $source_file path to source file
1879
 * @param  string $target_file path to target file
1880
 * @return string              'true' is success or error message
1881
 */
1882
function prepareFileWithDefuse($type, $source_file, $target_file, $password = '')
1883
{
1884
    global $SETTINGS;
1885
1886
    // Load AntiXSS
1887
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
1888
    $antiXss = new protect\AntiXSS\AntiXSS();
1889
1890
    // Protect against bad inputs
1891
    if (is_array($source_file) ||is_array($target_file)) {
1892
        return 'error_cannot_be_array';
1893
    }
1894
1895
    // Sanitize
1896
    $source_file = $antiXss->xss_clean($source_file);
1897
    $target_file = $antiXss->xss_clean($target_file);
1898
1899
    // load PhpEncryption library
1900
    $path_to_encryption = '/includes/libraries/Encryption/Encryption/';
1901
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Crypto.php';
1902
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Encoding.php';
1903
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'DerivedKeys.php';
1904
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Key.php';
1905
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyOrPassword.php';
1906
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'File.php';
1907
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'RuntimeTests.php';
1908
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyProtectedByPassword.php';
1909
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Core.php';
1910
1911
    if (empty($password) === true) {
1912
    /*
1913
    File encryption/decryption is done with the SALTKEY
1914
     */
1915
1916
        // get KEY
1917
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1918
1919
        // Now perform action on the file
1920
        $err = '';
1921 View Code Duplication
        if ($type === 'decrypt') {
1922
            try {
1923
                \Defuse\Crypto\File::decryptFile(
1924
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1896 can also be of type array; however, Defuse\Crypto\File::decryptFile() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1925
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1897 can also be of type array; however, Defuse\Crypto\File::decryptFile() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1926
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1927
                );
1928
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1929
                $err = "decryption_not_possible";
1930
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1931
                $err = $ex;
1932
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1933
                $err = $ex;
1934
            }
1935
        } elseif ($type === 'encrypt') {
1936
            try {
1937
                \Defuse\Crypto\File::encryptFile(
1938
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1896 can also be of type array; however, Defuse\Crypto\File::encryptFile() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1939
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1897 can also be of type array; however, Defuse\Crypto\File::encryptFile() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1940
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1941
                );
1942
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1943
                $err = "encryption_not_possible";
1944
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1945
                $err = $ex;
1946
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1947
                $err = $ex;
1948
            }
1949
        }
1950
    } else {
1951
    /*
1952
    File encryption/decryption is done with special password and not the SALTKEY
1953
     */
1954
1955
        $err = '';
1956 View Code Duplication
        if ($type === 'decrypt') {
1957
            try {
1958
                \Defuse\Crypto\File::decryptFileWithPassword(
1959
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1896 can also be of type array; however, Defuse\Crypto\File::decryptFileWithPassword() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1960
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1897 can also be of type array; however, Defuse\Crypto\File::decryptFileWithPassword() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1961
                    $password
1962
                );
1963
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1964
                $err = "wrong_key";
1965
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1966
                $err = $ex;
1967
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1968
                $err = $ex;
1969
            }
1970
        } elseif ($type === 'encrypt') {
1971
            try {
1972
                \Defuse\Crypto\File::encryptFileWithPassword(
1973
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1896 can also be of type array; however, Defuse\Crypto\File::encryptFileWithPassword() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1974
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1897 can also be of type array; however, Defuse\Crypto\File::encryptFileWithPassword() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1975
                    $password
1976
                );
1977
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1978
                $err = "wrong_key";
1979
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1980
                $err = $ex;
1981
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1982
                $err = $ex;
1983
            }
1984
        }
1985
    }
1986
1987
    // return error
1988
    if (empty($err) === false) {
1989
        return $err;
1990
    } else {
1991
        return true;
1992
    }
1993
}
1994
1995
/*
1996
* NOT TO BE USED
1997
*/
1998
function debugTeampass($text)
1999
{
2000
    $debugFile = fopen('D:/wamp64/www/TeamPass/debug.txt', 'r+');
2001
    fputs($debugFile, $text);
2002
    fclose($debugFile);
2003
}
2004
2005
2006
/**
2007
 * DELETE the file with expected command depending on server type
2008
 * @param  string $file Path to file
2009
 * @return              Nothing
2010
 */
2011
function fileDelete($file)
2012
{
2013
    global $SETTINGS;
2014
2015
    // Load AntiXSS
2016
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
2017
    $antiXss = new protect\AntiXSS\AntiXSS();
2018
2019
    $file = $antiXss->xss_clean($file);
2020
    if (is_file($file)) {
2021
        unlink($file);
2022
    }
2023
}
2024
2025
/*
2026
* Permits to extract the file extension
2027
*/
2028
function getFileExtension($file)
2029
{
2030
    if (strpos($file, '.') === false) {
2031
        return $file;
2032
    }
2033
2034
    return substr($file, strrpos($file, '.') + 1);
2035
}
2036
2037
/**
2038
 * array_map
2039
 * @param  [type] $func [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
2040
 * @param  [type] $arr  [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
2041
 * @return [type]       [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
2042
 */
2043
function array_map_r($func, $arr)
2044
{
2045
    $newArr = array();
2046
2047
    foreach ($arr as $key => $value) {
2048
        $newArr[ $key ] = (is_array($value) ? array_map_r($func, $value) : ( is_array($func) ? call_user_func_array($func, $value) : $func( $value )));
2049
    }
2050
2051
    return $newArr;
2052
}
2053
2054
/**
2055
 * Permits to clean and sanitize text to be displayed
2056
 * @param  string $text text to clean
0 ignored issues
show
Bug introduced by
There is no parameter named $text. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2057
 * @param  string $type what clean to perform
2058
 * @return string       text cleaned up
2059
 */
2060
function cleanText($string, $type = "")
2061
{
2062
    global $SETTINGS;
2063
2064
    // Load AntiXSS
2065
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
2066
    $antiXss = new protect\AntiXSS\AntiXSS();
2067
2068
    if ($type === "css") {
2069
        // Escape text and quotes in UTF8 format
2070
        return htmlentities($string, ENT_QUOTES | ENT_HTML5, 'UTF-8');
2071
    } elseif ($type === "html" || empty($type)) {
2072
        // Html cleaner
2073
        return $antiXss->xss_clean($string);
2074
    }
2075
}
2076
2077
/**
2078
 * Performs chmod operation on subfolders
2079
 * @param  string  $dir             Parent folder
2080
 * @param  integer $dirPermissions  New permission on folders
2081
 * @param  integer $filePermissions New permission on files
2082
 * @return boolean                  Success/Failure
2083
 */
2084 View Code Duplication
function chmodRecursive($dir, $dirPermissions, $filePermissions)
0 ignored issues
show
Best Practice introduced by
The function chmodRecursive() has been defined more than once; this definition is ignored, only the first definition in install/install.queries.php (L20-49) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2085
{
2086
    $pointer_dir = opendir($dir);
0 ignored issues
show
Security File Exposure introduced by
$dir can contain request data and is used in file inclusion context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_GET
    in includes/libraries/protect/SuperGlobal/SuperGlobal.php on line 45
  2. SuperGlobal::get() returns tainted data, and $session_abspath is assigned
    in install/install.queries.php on line 130
  3. $session_abspath is passed to chmodRecursive()
    in install/install.queries.php on line 1145

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
2087
    $res = true;
2088
    while ($file = readdir($pointer_dir)) {
2089
        if (($file == ".") || ($file == "..")) {
2090
            continue;
2091
        }
2092
2093
        $fullPath = $dir."/".$file;
2094
2095
        if (is_dir($fullPath)) {
2096
            if ($res = @chmod($fullPath, $dirPermissions)) {
0 ignored issues
show
Security File Manipulation introduced by
$fullPath can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_GET
    in includes/libraries/protect/SuperGlobal/SuperGlobal.php on line 45
  2. SuperGlobal::get() returns tainted data, and $session_abspath is assigned
    in install/install.queries.php on line 130
  3. $session_abspath is passed to chmodRecursive()
    in install/install.queries.php on line 1145
  4. $fullPath is assigned
    in sources/main.functions.php on line 2093

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
2097
                $res = @chmodRecursive($fullPath, $dirPermissions, $filePermissions);
2098
            }
2099
        } else {
2100
            $res = chmod($fullPath, $filePermissions);
0 ignored issues
show
Security File Manipulation introduced by
$fullPath can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_GET
    in includes/libraries/protect/SuperGlobal/SuperGlobal.php on line 45
  2. SuperGlobal::get() returns tainted data, and $session_abspath is assigned
    in install/install.queries.php on line 130
  3. $session_abspath is passed to chmodRecursive()
    in install/install.queries.php on line 1145
  4. $fullPath is assigned
    in sources/main.functions.php on line 2093

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
2101
        }
2102
        if (!$res) {
2103
            closedir($pointer_dir);
2104
            return false;
2105
        }
2106
    }
2107
    closedir($pointer_dir);
2108
    if (is_dir($dir) && $res) {
2109
        $res = @chmod($dir, $dirPermissions);
0 ignored issues
show
Security File Manipulation introduced by
$dir can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_GET
    in includes/libraries/protect/SuperGlobal/SuperGlobal.php on line 45
  2. SuperGlobal::get() returns tainted data, and $session_abspath is assigned
    in install/install.queries.php on line 130
  3. $session_abspath is passed to chmodRecursive()
    in install/install.queries.php on line 1145

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
2110
    }
2111
2112
    return $res;
2113
}
2114
2115
/**
2116
 * Check if user can access to this item
2117
 * @param $item_id
2118
 */
2119
function accessToItemIsGranted($item_id)
2120
{
2121
    // Load item data
2122
    $data = DB::queryFirstRow(
2123
        "SELECT id_tree
2124
        FROM ".prefix_table("items")."
2125
        WHERE id = %i",
2126
        $item_id
2127
    );
2128
2129
    // Check if user can access this folder
2130
    if (!in_array($data['id'], $_SESSION['groupes_visibles'])) {
2131
        return "ERR_FOLDER_NOT_ALLOWED";
2132
    }
2133
2134
    return true;
2135
}
2136