Completed
Push — development ( 3f8e8f...d5d7d3 )
by Nils
07:59
created

main.functions.php ➔ sendEmail()   B

Complexity

Conditions 7
Paths 17

Size

Total Lines 52
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 38
nc 17
nop 4
dl 0
loc 52
rs 7.2396
c 0
b 0
f 0

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

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

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...
2109
    $res = true;
2110
    while ($file = readdir($pointer_dir)) {
2111
        if (($file == ".") || ($file == "..")) {
2112
            continue;
2113
        }
2114
2115
        $fullPath = $dir."/".$file;
2116
2117
        if (is_dir($fullPath)) {
2118
            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 1147
  4. $fullPath is assigned
    in sources/main.functions.php on line 2115

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...
2119
                $res = @chmodRecursive($fullPath, $dirPermissions, $filePermissions);
2120
            }
2121
        } else {
2122
            $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 1147
  4. $fullPath is assigned
    in sources/main.functions.php on line 2115

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...
2123
        }
2124
        if (!$res) {
2125
            closedir($pointer_dir);
2126
            return false;
2127
        }
2128
    }
2129
    closedir($pointer_dir);
2130
    if (is_dir($dir) && $res) {
2131
        $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 1147

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...
2132
    }
2133
2134
    return $res;
2135
}
2136
2137
/**
2138
 * Check if user can access to this item
2139
 * @param $item_id
2140
 */
2141
function accessToItemIsGranted($item_id)
2142
{
2143
    global $SETTINGS;
2144
2145
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
2146
    $superGlobal = new protect\SuperGlobal\SuperGlobal();
2147
2148
    // Prepare superGlobal variables
2149
    $session_groupes_visibles = $superGlobal->get("groupes_visibles", "SESSION");
2150
    $session_list_restricted_folders_for_items = $superGlobal->get("list_restricted_folders_for_items", "SESSION");
2151
2152
    // Load item data
2153
    $data = DB::queryFirstRow(
2154
        "SELECT id_tree
2155
        FROM ".prefix_table("items")."
2156
        WHERE id = %i",
2157
        $item_id
2158
    );
2159
2160
    // Check if user can access this folder
2161
    if (in_array($data['id_tree'], $session_groupes_visibles) === false) {
2162
        // Now check if this folder is restricted to user
2163
        if (isset($session_list_restricted_folders_for_items[$data['id_tree']])
2164
            && !in_array($item_id, $session_list_restricted_folders_for_items[$data['id_tree']])
2165
        ) {
2166
            return "ERR_FOLDER_NOT_ALLOWED";
2167
        } else {
2168
            return "ERR_FOLDER_NOT_ALLOWED";
2169
        }
2170
    }
2171
2172
    return true;
2173
}
2174