Completed
Pull Request — development (#1959)
by Nils
14:46 queued 07:00
created

main.functions.php ➔ trimElement()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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

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...
2103
                $res = @chmodRecursive($fullPath, $dirPermissions, $filePermissions);
2104
            }
2105
        } else {
2106
            $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 2099

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...
2107
        }
2108
        if (!$res) {
2109
            closedir($pointer_dir);
2110
            return false;
2111
        }
2112
    }
2113
    closedir($pointer_dir);
2114
    if (is_dir($dir) && $res) {
2115
        $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...
2116
    }
2117
2118
    return $res;
2119
}
2120
2121
/**
2122
 * Check if user can access to this item
2123
 * @param $item_id
2124
 */
2125
function accessToItemIsGranted($item_id)
2126
{
2127
    // Load item data
2128
    $data = DB::queryFirstRow(
2129
        "SELECT id_tree
2130
        FROM ".prefix_table("items")."
2131
        WHERE id = %i",
2132
        $item_id
2133
    );
2134
2135
    // Check if user can access this folder
2136
    if (!in_array($data['id_tree'], $_SESSION['groupes_visibles'])) {
2137
        // Now check if this folder is restricted to user
2138
        if (isset($_SESSION['list_restricted_folders_for_items'][$data['id_tree']])
2139
            && !in_array($item_id, $_SESSION['list_restricted_folders_for_items'][$data['id_tree']])
2140
        ) {
2141
            return "ERR_FOLDER_NOT_ALLOWED";
2142
        } else {
2143
            return "ERR_FOLDER_NOT_ALLOWED";
2144
        }
2145
    }
2146
2147
    return true;
2148
}
2149