Completed
Push — development ( 7aebc9...29f013 )
by Nils
07:48
created

main.functions.php ➔ chmodRecursive()   D

Complexity

Conditions 9
Paths 13

Size

Total Lines 30
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

Loading history...
62
{
63
    $var_kb = $var_st + $var_kl; // Key blocks to compute
64
    $var_dk = ''; // Derived key
65
66
    for ($block = 1; $block <= $var_kb; $block++) { // Create key
67
        $var_ib = $var_h = hash_hmac($var_a, $var_s.pack('N', $block), $var_p, true); // Initial hash for this block
68
        for ($var_i = 1; $var_i < $var_c; $var_i++) { // Perform block iterations
69
            $var_ib ^= ($var_h = hash_hmac($var_a, $var_h, $var_p, true)); // XOR each iterate
70
        }
71
        $var_dk .= $var_ib; // Append iterated block
72
    }
73
    return substr($var_dk, $var_st, $var_kl); // Return derived key of correct length
74
}
75
76
/**
77
 * stringUtf8Decode()
78
 *
79
 * utf8_decode
80
 */
81
function stringUtf8Decode($string)
82
{
83
    return str_replace(" ", "+", utf8_decode($string));
84
}
85
86
/**
87
 * encryptOld()
88
 *
89
 * crypt a string
90
 * @param string $text
91
 */
92
function encryptOld($text, $personalSalt = "")
93
{
94
    if (empty($personalSalt) === false) {
95
        return trim(
96
            base64_encode(
97
                mcrypt_encrypt(
98
                    MCRYPT_RIJNDAEL_256,
99
                    $personalSalt,
100
                    $text,
101
                    MCRYPT_MODE_ECB,
102
                    mcrypt_create_iv(
103
                        mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
104
                        MCRYPT_RAND
105
                    )
106
                )
107
            )
108
        );
109
    }
110
111
    // If $personalSalt is not empty
112
    return trim(
113
        base64_encode(
114
            mcrypt_encrypt(
115
                MCRYPT_RIJNDAEL_256,
116
                SALT,
117
                $text,
118
                MCRYPT_MODE_ECB,
119
                mcrypt_create_iv(
120
                    mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
121
                    MCRYPT_RAND
122
                )
123
            )
124
        )
125
    );
126
}
127
128
/**
129
 * decryptOld()
130
 *
131
 * decrypt a crypted string
132
 */
133
function decryptOld($text, $personalSalt = "")
134
{
135
    if (!empty($personalSalt)) {
136
        return trim(
137
            mcrypt_decrypt(
138
                MCRYPT_RIJNDAEL_256,
139
                $personalSalt,
140
                base64_decode($text),
141
                MCRYPT_MODE_ECB,
142
                mcrypt_create_iv(
143
                    mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
144
                    MCRYPT_RAND
145
                )
146
            )
147
        );
148
    }
149
150
    // No personal SK
151
    return trim(
152
        mcrypt_decrypt(
153
            MCRYPT_RIJNDAEL_256,
154
            SALT,
155
            base64_decode($text),
156
            MCRYPT_MODE_ECB,
157
            mcrypt_create_iv(
158
                mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
159
                MCRYPT_RAND
160
            )
161
        )
162
    );
163
}
164
165
/**
166
 * encrypt()
167
 *
168
 * crypt a string
169
 * @param string $decrypted
170
 */
171
function encrypt($decrypted, $personalSalt = "")
172
{
173
    global $SETTINGS;
174
175 View Code Duplication
    if (!isset($SETTINGS['cpassman_dir']) || empty($SETTINGS['cpassman_dir'])) {
176
        require_once '../includes/libraries/Encryption/PBKDF2/PasswordHash.php';
177
    } else {
178
        require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/PBKDF2/PasswordHash.php';
179
    }
180
181
    if (!empty($personalSalt)) {
182
        $staticSalt = $personalSalt;
183
    } else {
184
        $staticSalt = SALT;
185
    }
186
187
    //set our salt to a variable
188
    // Get 64 random bits for the salt for pbkdf2
189
    $pbkdf2Salt = getBits(64);
190
    // generate a pbkdf2 key to use for the encryption.
191
    $key = substr(pbkdf2('sha256', $staticSalt, $pbkdf2Salt, ITCOUNT, 16 + 32, true), 32, 16);
192
    // Build $init_vect and $ivBase64.  We use a block size of 256 bits (AES compliant)
193
    // and CTR mode.  (Note: ECB mode is inadequate as IV is not used.)
194
    $init_vect = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, 'ctr'), MCRYPT_RAND);
195
196
    //base64 trim
197
    if (strlen($ivBase64 = rtrim(base64_encode($init_vect), '=')) != 43) {
198
        return false;
199
    }
200
    // Encrypt $decrypted
201
    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $decrypted, 'ctr', $init_vect);
202
    // MAC the encrypted text
203
    $mac = hash_hmac('sha256', $encrypted, $staticSalt);
204
    // We're done!
205
    return base64_encode($ivBase64.$encrypted.$mac.$pbkdf2Salt);
206
}
207
208
/**
209
 * decrypt()
210
 *
211
 * decrypt a crypted string
212
 */
213
function decrypt($encrypted, $personalSalt = "")
214
{
215
    global $SETTINGS;
216
217 View Code Duplication
    if (!isset($SETTINGS['cpassman_dir']) || empty($SETTINGS['cpassman_dir'])) {
218
        require_once '../includes/libraries/Encryption/PBKDF2/PasswordHash.php';
219
    } else {
220
        require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/PBKDF2/PasswordHash.php';
221
    }
222
223
    if (!empty($personalSalt)) {
224
        $staticSalt = $personalSalt;
225
    } else {
226
        $staticSalt = 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
function bCrypt($password, $cost)
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['no_access_folders'] = array();
600
        $_SESSION['groupes_visibles_list'] = "";
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) === false) {
678
                // Get allowed folders for each Role
679
                $rows = DB::query(
680
                    "SELECT folder_id FROM ".prefix_table("roles_values")." WHERE role_id=%i",
681
                    $roleId
682
                );
683
684
                if (DB::count() > 0) {
685
                    $tmp = DB::queryfirstrow(
686
                        "SELECT allow_pw_change FROM ".prefix_table("roles_title")." WHERE id = %i",
687
                        $roleId
688
                    );
689
                    foreach ($rows as $record) {
690 View Code Duplication
                        if (isset($record['folder_id']) && in_array($record['folder_id'], $listAllowedFolders) === false) {
691
                            array_push($listAllowedFolders, $record['folder_id']);
692
                        }
693
                        // Check if this group is allowed to modify any pw in allowed folders
694 View Code Duplication
                        if ($tmp['allow_pw_change'] == 1 && in_array($record['folder_id'], $listFoldersEditableByRole) === false) {
695
                            array_push($listFoldersEditableByRole, $record['folder_id']);
696
                        }
697
                    }
698
                    // Check for the users roles if some specific rights exist on items
699
                    $rows = DB::query(
700
                        "SELECT i.id_tree, r.item_id
701
                        FROM ".prefix_table("items")." as i
702
                        INNER JOIN ".prefix_table("restriction_to_roles")." as r ON (r.item_id=i.id)
703
                        WHERE r.role_id=%i
704
                        ORDER BY i.id_tree ASC",
705
                        $roleId
706
                    );
707
                    $inc = 0;
708
                    foreach ($rows as $record) {
709
                        if (isset($record['id_tree'])) {
710
                            $listFoldersLimited[$record['id_tree']][$inc] = $record['item_id'];
711
                            $inc++;
712
                        }
713
                    }
714
                }
715
            }
716
        }
717
718
        // Does this user is allowed to see other items
719
        $inc = 0;
720
        $rows = DB::query(
721
            "SELECT id, id_tree FROM ".prefix_table("items")."
722
            WHERE restricted_to LIKE %ss AND inactif=%s",
723
            $_SESSION['user_id'].';',
724
            '0'
725
        );
726
        foreach ($rows as $record) {
727
            $listRestrictedFoldersForItems[$record['id_tree']][$inc] = $record['id'];
728
            $inc++;
729
        }
730
        // => Build final lists
731
        // Clean arrays
732
        $listAllowedFolders = array_unique($listAllowedFolders);
733
        $groupesVisiblesUser = explode(';', trimElement($groupesVisiblesUser, ";"));
734
        // Add user allowed folders
735
        $allowedFoldersTmp = array_unique(
736
            array_merge($listAllowedFolders, $groupesVisiblesUser)
737
        );
738
        // Exclude from allowed folders all the specific user forbidden folders
739
        $allowedFolders = array();
740
        foreach ($allowedFoldersTmp as $ident) {
741
            if (!in_array($ident, $groupesInterditsUser) && !empty($ident)) {
742
                array_push($allowedFolders, $ident);
743
            }
744
        }
745
746
        // Clean array
747
        $listAllowedFolders = array_filter(array_unique($allowedFolders));
748
749
        // Exclude all PF
750
        $_SESSION['forbiden_pfs'] = array();
751
752
        $where = new WhereClause('and');
753
        $where->add('personal_folder=%i', 1);
754
        if (isset($SETTINGS['enable_pf_feature']) === true && $SETTINGS['enable_pf_feature'] === '1'
755
            && isset($_SESSION['personal_folder']) === true && $_SESSION['personal_folder'] === '1'
756
        ) {
757
            $where->add('title=%s', $_SESSION['user_id']);
758
            $where->negateLast();
759
        }
760
761
        $persoFlds = DB::query(
762
            "SELECT id
763
            FROM ".prefix_table("nested_tree")."
764
            WHERE %l",
765
            $where
766
        );
767
        foreach ($persoFlds as $persoFldId) {
768
            array_push($_SESSION['forbiden_pfs'], $persoFldId['id']);
769
        }
770
        // Get IDs of personal folders
771
        if (isset($SETTINGS['enable_pf_feature']) === true && $SETTINGS['enable_pf_feature'] === '1'
772
            && isset($_SESSION['personal_folder']) === true &&  $_SESSION['personal_folder'] === '1'
773
        ) {
774
            $persoFld = DB::queryfirstrow(
775
                "SELECT id
776
                FROM ".prefix_table("nested_tree")."
777
                WHERE title = %s AND personal_folder = %i",
778
                $_SESSION['user_id'],
779
                1
780
            );
781
            if (empty($persoFld['id']) === false) {
782
                if (in_array($persoFld['id'], $listAllowedFolders) === false) {
783
                    array_push($_SESSION['personal_folders'], $persoFld['id']);
784
                    // get all descendants
785
                    $ids = $tree->getDescendants($persoFld['id'], true, false);
786
                    foreach ($ids as $ident) {
787
                        array_push($listAllowedFolders, $ident->id);
788
                        array_push($_SESSION['personal_visible_groups'], $ident->id);
789
                        array_push($_SESSION['personal_folders'], $ident->id);
790
                    }
791
                }
792
            }
793
            // get list of readonly folders when pf is disabled.
794
            $_SESSION['personal_folders'] = array_unique($_SESSION['personal_folders']);
795
            // rule - if one folder is set as W or N in one of the Role, then User has access as W
796
            foreach ($listAllowedFolders as $folderId) {
797
                if (in_array($folderId, array_unique(array_merge($listReadOnlyFolders, $_SESSION['personal_folders']))) === false) {
798
                    DB::query(
799
                        "SELECT *
800
                        FROM ".prefix_table("roles_values")."
801
                        WHERE folder_id = %i AND role_id IN %li AND type IN %ls",
802
                        $folderId,
803
                        $fonctionsAssociees,
804
                        array("W", "ND", "NE", "NDNE")
805
                    );
806
                    if (DB::count() === 0 && in_array($folderId, $groupesVisiblesUser) === false) {
807
                        array_push($listReadOnlyFolders, $folderId);
808
                    }
809
                }
810
            }
811
        } else {
812
            // get list of readonly folders when pf is disabled.
813
            // rule - if one folder is set as W in one of the Role, then User has access as W
814
            foreach ($listAllowedFolders as $folderId) {
815
                if (in_array($folderId, $listReadOnlyFolders) === false) {
816
                    DB::query(
817
                        "SELECT *
818
                        FROM ".prefix_table("roles_values")."
819
                        WHERE folder_id = %i AND role_id IN %li AND type IN %ls",
820
                        $folderId,
821
                        $fonctionsAssociees,
822
                        array("W", "ND", "NE", "NDNE")
823
                    );
824
                    if (DB::count() == 0 && !in_array($folderId, $groupesVisiblesUser)) {
825
                        array_push($listReadOnlyFolders, $folderId);
826
                    }
827
                }
828
            }
829
        }
830
831
        // check if change proposals on User's items
832
        if (isset($SETTINGS['enable_suggestion']) === true && $SETTINGS['enable_suggestion'] === '1') {
833
            DB::query(
834
                "SELECT *
835
                FROM ".prefix_table("items_change")." AS c
836
                LEFT JOIN ".prefix_table("log_items")." AS i ON (c.item_id = i.id_item)
837
                WHERE i.action = %s AND i.id_user = %i",
838
                "at_creation",
839
                $_SESSION['user_id']
840
            );
841
            $_SESSION['nb_item_change_proposals'] = DB::count();
842
        } else {
843
            $_SESSION['nb_item_change_proposals'] = 0;
844
        }
845
846
        $_SESSION['all_non_personal_folders'] = $listAllowedFolders;
847
        $_SESSION['groupes_visibles'] = $listAllowedFolders;
848
        $_SESSION['groupes_visibles_list'] = implode(',', $listAllowedFolders);
849
        $_SESSION['personal_visible_groups_list'] = implode(',', $_SESSION['personal_visible_groups']);
850
        $_SESSION['read_only_folders'] = $listReadOnlyFolders;
851
        $_SESSION['no_access_folders'] = $groupesInterdits;
852
853
        $_SESSION['list_folders_limited'] = $listFoldersLimited;
854
        $_SESSION['list_folders_editable_by_role'] = $listFoldersEditableByRole;
855
        $_SESSION['list_restricted_folders_for_items'] = $listRestrictedFoldersForItems;
856
        // Folders and Roles numbers
857
        DB::queryfirstrow("SELECT id FROM ".prefix_table("nested_tree")."");
858
        $_SESSION['nb_folders'] = DB::count();
859
        DB::queryfirstrow("SELECT id FROM ".prefix_table("roles_title"));
860
        $_SESSION['nb_roles'] = DB::count();
861
    }
862
863
    // update user's timestamp
864
    DB::update(
865
        prefix_table('users'),
866
        array(
867
            'timestamp' => time()
868
        ),
869
        "id=%i",
870
        $_SESSION['user_id']
871
    );
872
}
873
874
/**
875
 * updateCacheTable()
876
 *
877
 * Update the CACHE table
878
 * @param string $action
879
 */
880
function updateCacheTable($action, $ident = "")
881
{
882
    global $server, $user, $pass, $database, $port, $encoding;
883
    global $SETTINGS;
884
885
    require_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php';
886
887
    //Connect to DB
888
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
889
    $pass = defuse_return_decrypted($pass);
890
    DB::$host = $server;
891
    DB::$user = $user;
892
    DB::$password = $pass;
893
    DB::$dbName = $database;
894
    DB::$port = $port;
895
    DB::$encoding = $encoding;
896
    DB::$error_handler = true;
897
    $link = mysqli_connect($server, $user, $pass, $database, $port);
898
    $link->set_charset($encoding);
899
900
    //Load Tree
901
    $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
902
    $tree->register();
903
    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
904
905
    // Rebuild full cache table
906
    if ($action === "reload") {
907
        // truncate table
908
        DB::query("TRUNCATE TABLE ".prefix_table("cache"));
909
910
        // reload date
911
        $rows = DB::query(
912
            "SELECT *
913
            FROM ".prefix_table('items')." as i
914
            INNER JOIN ".prefix_table('log_items')." as l ON (l.id_item = i.id)
915
            AND l.action = %s
916
            AND i.inactif = %i",
917
            'at_creation',
918
            0
919
        );
920
        foreach ($rows as $record) {
921
            // Get all TAGS
922
            $tags = "";
923
            $itemTags = DB::query("SELECT tag FROM ".prefix_table('tags')." WHERE item_id=%i", $record['id']);
924 View Code Duplication
            foreach ($itemTags as $itemTag) {
925
                if (!empty($itemTag['tag'])) {
926
                    $tags .= $itemTag['tag']." ";
927
                }
928
            }
929
            // Get renewal period
930
            $resNT = DB::queryfirstrow("SELECT renewal_period FROM ".prefix_table('nested_tree')." WHERE id=%i", $record['id_tree']);
931
932
            // form id_tree to full foldername
933
            $folder = "";
934
            $arbo = $tree->getPath($record['id_tree'], true);
935 View Code Duplication
            foreach ($arbo as $elem) {
936
                if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
937
                    $elem->title = $_SESSION['login'];
938
                }
939
                if (empty($folder)) {
940
                    $folder = stripslashes($elem->title);
941
                } else {
942
                    $folder .= " » ".stripslashes($elem->title);
943
                }
944
            }
945
            // store data
946
            DB::insert(
947
                prefix_table('cache'),
948
                array(
949
                    'id' => $record['id'],
950
                    'label' => $record['label'],
951
                    'description' => isset($record['description']) ? $record['description'] : "",
952
                    'url' => (isset($record['url']) && !empty($record['url'])) ? $record['url'] : "0",
953
                    'tags' => $tags,
954
                    'id_tree' => $record['id_tree'],
955
                    'perso' => $record['perso'],
956
                    'restricted_to' => (isset($record['restricted_to']) && !empty($record['restricted_to'])) ? $record['restricted_to'] : "0",
957
                    'login' => isset($record['login']) ? $record['login'] : "",
958
                    'folder' => $folder,
959
                    'author' => $record['id_user'],
960
                    'renewal_period' => isset($resNT['renewal_period']) ? $resNT['renewal_period'] : "0",
961
                    'timestamp' => $record['date']
962
                    )
963
            );
964
        }
965
        // UPDATE an item
966
    } elseif ($action === "update_value") {
967
        // get new value from db
968
        $data = DB::queryfirstrow(
969
            "SELECT label, description, id_tree, perso, restricted_to, login, url
970
            FROM ".prefix_table('items')."
971
            WHERE id=%i",
972
            $ident
973
        );
974
        // Get all TAGS
975
        $tags = "";
976
        $itemTags = DB::query("SELECT tag FROM ".prefix_table('tags')." WHERE item_id=%i", $ident);
977 View Code Duplication
        foreach ($itemTags as $itemTag) {
978
            if (!empty($itemTag['tag'])) {
979
                $tags .= $itemTag['tag']." ";
980
            }
981
        }
982
        // form id_tree to full foldername
983
        $folder = "";
984
        $arbo = $tree->getPath($data['id_tree'], true);
985 View Code Duplication
        foreach ($arbo as $elem) {
986
            if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
987
                $elem->title = $_SESSION['login'];
988
            }
989
            if (empty($folder)) {
990
                $folder = stripslashes($elem->title);
991
            } else {
992
                $folder .= " » ".stripslashes($elem->title);
993
            }
994
        }
995
        // finaly update
996
        DB::update(
997
            prefix_table('cache'),
998
            array(
999
                'label' => $data['label'],
1000
                'description' => $data['description'],
1001
                'tags' => $tags,
1002
                'url' => (isset($data['url']) && !empty($data['url'])) ? $data['url'] : "0",
1003
                'id_tree' => $data['id_tree'],
1004
                'perso' => $data['perso'],
1005
                'restricted_to' => (isset($data['restricted_to']) && !empty($data['restricted_to'])) ? $data['restricted_to'] : "0",
1006
                'login' => isset($data['login']) ? $data['login'] : "",
1007
                'folder' => $folder,
1008
                'author' => $_SESSION['user_id'],
1009
                ),
1010
            "id = %i",
1011
            $ident
1012
        );
1013
        // ADD an item
1014
    } elseif ($action === "add_value") {
1015
        // get new value from db
1016
        $data = DB::queryFirstRow(
1017
            "SELECT i.label, i.description, i.id_tree as id_tree, i.perso, i.restricted_to, i.id, i.login, i.url, l.date
1018
            FROM ".prefix_table('items')." as i
1019
            INNER JOIN ".prefix_table('log_items')." as l ON (l.id_item = i.id)
1020
            WHERE i.id = %i
1021
            AND l.action = %s",
1022
            $ident,
1023
            'at_creation'
1024
        );
1025
        // Get all TAGS
1026
        $tags = "";
1027
        $itemTags = DB::query("SELECT tag FROM ".prefix_table('tags')." WHERE item_id = %i", $ident);
1028 View Code Duplication
        foreach ($itemTags as $itemTag) {
1029
            if (!empty($itemTag['tag'])) {
1030
                $tags .= $itemTag['tag']." ";
1031
            }
1032
        }
1033
        // form id_tree to full foldername
1034
        $folder = "";
1035
        $arbo = $tree->getPath($data['id_tree'], true);
1036 View Code Duplication
        foreach ($arbo as $elem) {
1037
            if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
1038
                $elem->title = $_SESSION['login'];
1039
            }
1040
            if (empty($folder)) {
1041
                $folder = stripslashes($elem->title);
1042
            } else {
1043
                $folder .= " » ".stripslashes($elem->title);
1044
            }
1045
        }
1046
        // finaly update
1047
        DB::insert(
1048
            prefix_table('cache'),
1049
            array(
1050
                'id' => $data['id'],
1051
                'label' => $data['label'],
1052
                'description' => $data['description'],
1053
                'tags' => (isset($tags) && !empty($tags)) ? $tags : "None",
1054
                'url' => (isset($data['url']) && !empty($data['url'])) ? $data['url'] : "0",
1055
                'id_tree' => $data['id_tree'],
1056
                'perso' => (isset($data['perso']) && !empty($data['perso']) && $data['perso'] !== "None") ? $data['perso'] : "0",
1057
                'restricted_to' => (isset($data['restricted_to']) && !empty($data['restricted_to'])) ? $data['restricted_to'] : "0",
1058
                'login' => isset($data['login']) ? $data['login'] : "",
1059
                'folder' => $folder,
1060
                'author' => $_SESSION['user_id'],
1061
                'timestamp' => $data['date']
1062
            )
1063
        );
1064
1065
        // DELETE an item
1066
    } elseif ($action === "delete_value") {
1067
        DB::delete(prefix_table('cache'), "id = %i", $ident);
1068
    }
1069
}
1070
1071
/*
1072
*
1073
*/
1074
function getStatisticsData()
1075
{
1076
    global $SETTINGS;
1077
1078
    DB::query(
1079
        "SELECT id FROM ".prefix_table("nested_tree")." WHERE personal_folder = %i",
1080
        0
1081
    );
1082
    $counter_folders = DB::count();
1083
1084
    DB::query(
1085
        "SELECT id FROM ".prefix_table("nested_tree")." WHERE personal_folder = %i",
1086
        1
1087
    );
1088
    $counter_folders_perso = DB::count();
1089
1090
    DB::query(
1091
        "SELECT id FROM ".prefix_table("items")." WHERE perso = %i",
1092
        0
1093
    );
1094
    $counter_items = DB::count();
1095
1096
    DB::query(
1097
        "SELECT id FROM ".prefix_table("items")." WHERE perso = %i",
1098
        1
1099
    );
1100
    $counter_items_perso = DB::count();
1101
1102
    DB::query(
1103
        "SELECT id FROM ".prefix_table("users").""
1104
    );
1105
    $counter_users = DB::count();
1106
1107
    DB::query(
1108
        "SELECT id FROM ".prefix_table("users")." WHERE admin = %i",
1109
        1
1110
    );
1111
    $admins = DB::count();
1112
1113
    DB::query(
1114
        "SELECT id FROM ".prefix_table("users")." WHERE gestionnaire = %i",
1115
        1
1116
    );
1117
    $managers = DB::count();
1118
1119
    DB::query(
1120
        "SELECT id FROM ".prefix_table("users")." WHERE read_only = %i",
1121
        1
1122
    );
1123
    $readOnly = DB::count();
1124
1125
    // list the languages
1126
    $usedLang = [];
1127
    $tp_languages = DB::query(
1128
        "SELECT name FROM ".prefix_table("languages")
1129
    );
1130
    foreach ($tp_languages as $tp_language) {
1131
        DB::query(
1132
            "SELECT * FROM ".prefix_table("users")." WHERE user_language = %s",
1133
            $tp_language['name']
1134
        );
1135
        $usedLang[$tp_language['name']] = round((DB::count() * 100 / $counter_users), 0);
1136
    }
1137
1138
    // get list of ips
1139
    $usedIp = [];
1140
    $tp_ips = DB::query(
1141
        "SELECT user_ip FROM ".prefix_table("users")
1142
    );
1143
    foreach ($tp_ips as $ip) {
1144
        if (array_key_exists($ip['user_ip'], $usedIp)) {
1145
            $usedIp[$ip['user_ip']] = $usedIp[$ip['user_ip']] + 1;
1146
        } elseif (!empty($ip['user_ip']) && $ip['user_ip'] !== "none") {
1147
            $usedIp[$ip['user_ip']] = 1;
1148
        }
1149
    }
1150
1151
    return array(
1152
        "error" => "",
1153
        "stat_phpversion" => phpversion(),
1154
        "stat_folders" => $counter_folders,
1155
        "stat_folders_shared" => intval($counter_folders) - intval($counter_folders_perso),
1156
        "stat_items" => $counter_items,
1157
        "stat_items_shared" => intval($counter_items) - intval($counter_items_perso),
1158
        "stat_users" => $counter_users,
1159
        "stat_admins" => $admins,
1160
        "stat_managers" => $managers,
1161
        "stat_ro" => $readOnly,
1162
        "stat_kb" => $SETTINGS['enable_kb'],
1163
        "stat_pf" => $SETTINGS['enable_pf_feature'],
1164
        "stat_fav" => $SETTINGS['enable_favourites'],
1165
        "stat_teampassversion" => $SETTINGS['cpassman_version'],
1166
        "stat_ldap" => $SETTINGS['ldap_mode'],
1167
        "stat_agses" => $SETTINGS['agses_authentication_enabled'],
1168
        "stat_duo" => $SETTINGS['duo'],
1169
        "stat_suggestion" => $SETTINGS['enable_suggestion'],
1170
        "stat_api" => $SETTINGS['api'],
1171
        "stat_customfields" => $SETTINGS['item_extra_fields'],
1172
        "stat_syslog" => $SETTINGS['syslog_enable'],
1173
        "stat_2fa" => $SETTINGS['google_authentication'],
1174
        "stat_stricthttps" => $SETTINGS['enable_sts'],
1175
        "stat_mysqlversion" => DB::serverVersion(),
1176
        "stat_languages" => $usedLang,
1177
        "stat_country" => $usedIp
1178
    );
1179
}
1180
1181
/**
1182
 * sendEmail()
1183
 *
1184
 * @return
1185
 */
1186
function sendEmail($subject, $textMail, $email, $textMailAlt = "")
1187
{
1188
    global $LANG;
1189
    global $SETTINGS;
1190
1191
    // CAse where email not defined
1192
    if ($email === "none") {
1193
        return '"error":"" , "message":"'.$LANG['forgot_my_pw_email_sent'].'"';
1194
    }
1195
1196
    include $SETTINGS['cpassman_dir'].'/includes/config/settings.php';
1197
    //load library
1198
    $user_language = isset($_SESSION['user_language']) ? $_SESSION['user_language'] : "english";
1199
    require_once $SETTINGS['cpassman_dir'].'/includes/language/'.$user_language.'.php';
1200
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Email/Phpmailer/PHPMailerAutoload.php';
1201
1202
    // load PHPMailer
1203
    $mail = new PHPMailer();
1204
1205
    // send to user
1206
    $mail->setLanguage("en", "../includes/libraries/Email/Phpmailer/language/");
1207
    $mail->SMTPDebug = 0; //value 1 can be used to debug - 4 for debuging connections
1208
    $mail->Port = $SETTINGS['email_port']; //COULD BE USED
1209
    $mail->CharSet = "utf-8";
1210
    if ($SETTINGS['email_security'] === "tls" || $SETTINGS['email_security'] === "ssl") {
1211
        $mail->SMTPSecure = $SETTINGS['email_security'];
1212
        $SMTPAutoTLS = true;
1213
    } else {
1214
        $SMTPAutoTLS = false;
1215
        $mail->SMTPSecure = "";
1216
    }
1217
    $mail->SMTPAutoTLS = $SMTPAutoTLS;
1218
    $mail->isSmtp(); // send via SMTP
1219
    $mail->Host = $SETTINGS['email_smtp_server']; // SMTP servers
1220
    $mail->SMTPAuth = $SETTINGS['email_smtp_auth'] == '1' ? true : false; // turn on SMTP authentication
1221
    $mail->Username = $SETTINGS['email_auth_username']; // SMTP username
1222
    $mail->Password = $SETTINGS['email_auth_pwd']; // SMTP password
1223
    $mail->From = $SETTINGS['email_from'];
1224
    $mail->FromName = $SETTINGS['email_from_name'];
1225
1226
    // Prepare for each person
1227
    $dests = explode(",", $email);
1228
    foreach ($dests as $dest) {
1229
        $mail->addAddress($dest);
1230
    }
1231
1232
    $mail->WordWrap = 80; // set word wrap
1233
    $mail->isHtml(true); // send as HTML
1234
    $mail->Subject = $subject;
1235
    $mail->Body = $textMail;
1236
    $mail->AltBody = $textMailAlt;
1237
    // send email
1238
    if (!$mail->send()) {
1239
        return '"error":"error_mail_not_send" , "message":"'.str_replace(array("\n", "\t", "\r"), '', $mail->ErrorInfo).'"';
1240
    } else {
1241
        return '"error":"" , "message":"'.$LANG['forgot_my_pw_email_sent'].'"';
1242
    }
1243
}
1244
1245
/**
1246
 * generateKey()
1247
 *
1248
 * @return
1249
 */
1250
function generateKey()
1251
{
1252
    return substr(md5(rand().rand()), 0, 15);
1253
}
1254
1255
/**
1256
 * dateToStamp()
1257
 *
1258
 * @return
1259
 */
1260
function dateToStamp($date)
1261
{
1262
    global $SETTINGS;
1263
1264
    $date = date_parse_from_format($SETTINGS['date_format'], $date);
1265
    if ($date['warning_count'] == 0 && $date['error_count'] == 0) {
1266
        return mktime(23, 59, 59, $date['month'], $date['day'], $date['year']);
1267
    } else {
1268
        return false;
1269
    }
1270
}
1271
1272
function isDate($date)
1273
{
1274
    return (strtotime($date) !== false);
1275
}
1276
1277
/**
1278
 * isUTF8()
1279
 *
1280
 * @return integer is the string in UTF8 format.
1281
 */
1282
1283
function isUTF8($string)
1284
{
1285
    if (is_array($string) === true) {
1286
        $string = $string['string'];
1287
    }
1288
    return preg_match(
1289
        '%^(?:
1290
        [\x09\x0A\x0D\x20-\x7E] # ASCII
1291
        | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
1292
        | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
1293
        | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
1294
        | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
1295
        | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
1296
        | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
1297
        | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
1298
        )*$%xs',
1299
        $string
1300
    );
1301
}
1302
1303
/*
1304
* FUNCTION
1305
* permits to prepare data to be exchanged
1306
*/
1307
/**
1308
 * @param string $type
1309
 */
1310
function prepareExchangedData($data, $type)
1311
{
1312
    global $SETTINGS;
1313
1314
    //load ClassLoader
1315
    require_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php';
1316
    //Load AES
1317
    $aes = new SplClassLoader('Encryption\Crypt', $SETTINGS['cpassman_dir'].'/includes/libraries');
1318
    $aes->register();
1319
1320
    if ($type == "encode") {
1321
        if (isset($SETTINGS['encryptClientServer'])
1322
            && $SETTINGS['encryptClientServer'] === "0"
1323
        ) {
1324
            return json_encode(
1325
                $data,
1326
                JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
1327
            );
1328 View Code Duplication
        } else {
1329
            return Encryption\Crypt\aesctr::encrypt(
1330
                json_encode(
1331
                    $data,
1332
                    JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
1333
                ),
1334
                $_SESSION['key'],
1335
                256
1336
            );
1337
        }
1338
    } elseif ($type == "decode") {
1339
        if (isset($SETTINGS['encryptClientServer'])
1340
            && $SETTINGS['encryptClientServer'] === "0"
1341
        ) {
1342
            return json_decode(
1343
                $data,
1344
                true
1345
            );
1346
        } else {
1347
            return json_decode(
1348
                Encryption\Crypt\aesctr::decrypt(
1349
                    $data,
1350
                    $_SESSION['key'],
1351
                    256
1352
                ),
1353
                true
1354
            );
1355
        }
1356
    }
1357
}
1358
1359
function make_thumb($src, $dest, $desired_width)
1360
{
1361
    /* read the source image */
1362
    $source_image = imagecreatefrompng($src);
1363
    $width = imagesx($source_image);
1364
    $height = imagesy($source_image);
1365
1366
    /* find the "desired height" of this thumbnail, relative to the desired width  */
1367
    $desired_height = floor($height * ($desired_width / $width));
1368
1369
    /* create a new, "virtual" image */
1370
    $virtual_image = imagecreatetruecolor($desired_width, $desired_height);
1371
1372
    /* copy source image at a resized size */
1373
    imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $desired_width, $desired_height, $width, $height);
1374
1375
    /* create the physical thumbnail image to its destination */
1376
    imagejpeg($virtual_image, $dest);
1377
}
1378
1379
/*
1380
** check table prefix in SQL query
1381
*/
1382
/**
1383
 * @param string $table
1384
 */
1385
function prefix_table($table)
1386
{
1387
    global $pre;
1388
    $safeTable = htmlspecialchars($pre.$table);
1389
    if (!empty($safeTable)) {
1390
        // sanitize string
1391
        return $safeTable;
1392
    } else {
1393
        // stop error no table
1394
        return "table_not_exists";
1395
    }
1396
}
1397
1398
/*
1399
 * Creates a KEY using PasswordLib
1400
 */
1401
function GenerateCryptKey($size = "", $secure = false, $numerals = false, $capitalize = false, $symbols = false)
1402
{
1403
    global $SETTINGS;
1404
    require_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php';
1405
1406
    if ($secure === true) {
1407
        $numerals = true;
1408
        $capitalize = true;
1409
        $symbols = true;
1410
    }
1411
1412
    // Load libraries
1413
    $generator = new SplClassLoader('PasswordGenerator\Generator', '../includes/libraries');
1414
    $generator->register();
1415
    $generator = new PasswordGenerator\Generator\ComputerPasswordGenerator();
1416
1417
    // Can we use PHP7 random_int function?
1418
    if (version_compare(phpversion(), '7.0', '>=')) {
1419
        require_once $SETTINGS['cpassman_dir'].'/includes/libraries/PasswordGenerator/RandomGenerator/Php7RandomGenerator.php';
1420
         $generator->setRandomGenerator(new PasswordGenerator\RandomGenerator\Php7RandomGenerator());
1421
    }
1422
1423
    // init
1424
    if (!empty($size)) {
1425
        $generator->setLength(intval($size));
1426
    }
1427
    if (!empty($numerals)) {
1428
        $generator->setNumbers($numerals);
1429
    }
1430
    if (!empty($capitalize)) {
1431
        $generator->setUppercase($capitalize);
1432
    }
1433
    if (!empty($symbols)) {
1434
        $generator->setSymbols($symbols);
1435
    }
1436
1437
    // generate and send back
1438
    return $generator->generatePassword();
1439
}
1440
1441
/*
1442
* Send sysLOG message
1443
* @param string $message
1444
* @param string $host
1445
*/
1446
function send_syslog($message, $host, $port, $component = "teampass")
1447
{
1448
    $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
1449
    $syslog_message = "<123>".date('M d H:i:s ').$component.": ".$message;
1450
    socket_sendto($sock, $syslog_message, strlen($syslog_message), 0, $host, $port);
1451
    socket_close($sock);
1452
}
1453
1454
1455
1456
/**
1457
 * logEvents()
1458
 *
1459
 * permits to log events into DB
1460
 * @param string $type
1461
 * @param string $label
1462
 * @param string $field_1
1463
 */
1464
function logEvents($type, $label, $who, $login = "", $field_1 = null)
1465
{
1466
    global $server, $user, $pass, $database, $port, $encoding;
1467
    global $SETTINGS;
1468
1469
    if (empty($who)) {
1470
        $who = get_client_ip_server();
1471
    }
1472
1473
    // include librairies & connect to DB
1474
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1475
    $pass = defuse_return_decrypted($pass);
1476
    DB::$host = $server;
1477
    DB::$user = $user;
1478
    DB::$password = $pass;
1479
    DB::$dbName = $database;
1480
    DB::$port = $port;
1481
    DB::$encoding = $encoding;
1482
    DB::$error_handler = true;
1483
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1484
    $link->set_charset($encoding);
1485
1486
    DB::insert(
1487
        prefix_table("log_system"),
1488
        array(
1489
            'type' => $type,
1490
            'date' => time(),
1491
            'label' => $label,
1492
            'qui' => $who,
1493
            'field_1' => $field_1 === null ? "" : $field_1
1494
        )
1495
    );
1496
    if (isset($SETTINGS['syslog_enable']) && $SETTINGS['syslog_enable'] == 1) {
1497
        if ($type == "user_mngt") {
1498
            send_syslog(
1499
                "The User ".$login." performed the action of ".$label." to the user ".$field_1." - ".$type,
1500
                $SETTINGS['syslog_host'],
1501
                $SETTINGS['syslog_port'],
1502
                "teampass"
1503
            );
1504
        } else {
1505
            send_syslog(
1506
                "The User ".$login." performed the action of ".$label." - ".$type,
1507
                $SETTINGS['syslog_host'],
1508
                $SETTINGS['syslog_port'],
1509
                "teampass"
1510
            );
1511
        }
1512
    }
1513
}
1514
1515
/**
1516
 * @param string $item
1517
 * @param string $action
1518
 */
1519
function logItems($ident, $item, $id_user, $action, $login = "", $raison = null, $raison_iv = null, $encryption_type = "")
1520
{
1521
    global $server, $user, $pass, $database, $port, $encoding;
1522
    global $SETTINGS;
1523
1524
    // include librairies & connect to DB
1525
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1526
    $pass = defuse_return_decrypted($pass);
1527
    DB::$host = $server;
1528
    DB::$user = $user;
1529
    DB::$password = $pass;
1530
    DB::$dbName = $database;
1531
    DB::$port = $port;
1532
    DB::$encoding = $encoding;
1533
    DB::$error_handler = true;
1534
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1535
    $link->set_charset($encoding);
1536
    DB::insert(
1537
        prefix_table("log_items"),
1538
        array(
1539
            'id_item' => $ident,
1540
            'date' => time(),
1541
            'id_user' => $id_user,
1542
            'action' => $action,
1543
            'raison' => $raison,
1544
            'raison_iv' => $raison_iv,
1545
            'encryption_type' => $encryption_type
1546
        )
1547
    );
1548
    if (isset($SETTINGS['syslog_enable']) && $SETTINGS['syslog_enable'] == 1) {
1549
        send_syslog(
1550
            "The Item ".$item." was ".$action." by ".$login." ".$raison,
1551
            $SETTINGS['syslog_host'],
1552
            $SETTINGS['syslog_port'],
1553
            "teampass"
1554
        );
1555
    }
1556
}
1557
1558
/*
1559
* Function to get the client ip address
1560
 */
1561
function get_client_ip_server()
1562
{
1563
    if (getenv('HTTP_CLIENT_IP')) {
1564
            $ipaddress = getenv('HTTP_CLIENT_IP');
1565
    } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
1566
            $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
1567
    } elseif (getenv('HTTP_X_FORWARDED')) {
1568
            $ipaddress = getenv('HTTP_X_FORWARDED');
1569
    } elseif (getenv('HTTP_FORWARDED_FOR')) {
1570
            $ipaddress = getenv('HTTP_FORWARDED_FOR');
1571
    } elseif (getenv('HTTP_FORWARDED')) {
1572
            $ipaddress = getenv('HTTP_FORWARDED');
1573
    } elseif (getenv('REMOTE_ADDR')) {
1574
            $ipaddress = getenv('REMOTE_ADDR');
1575
    } else {
1576
            $ipaddress = 'UNKNOWN';
1577
    }
1578
1579
    return $ipaddress;
1580
}
1581
1582
/**
1583
 * Escape all HTML, JavaScript, and CSS
1584
 *
1585
 * @param string $input The input string
1586
 * @param string $encoding Which character encoding are we using?
1587
 * @return string
1588
 */
1589
function noHTML($input, $encoding = 'UTF-8')
1590
{
1591
    return htmlspecialchars($input, ENT_QUOTES | ENT_XHTML, $encoding, false);
1592
}
1593
1594
/**
1595
 * handleConfigFile()
1596
 *
1597
 * permits to handle the Teampass config file
1598
 * $action accepts "rebuild" and "update"
1599
 */
1600
function handleConfigFile($action, $field = null, $value = null)
1601
{
1602
    global $server, $user, $pass, $database, $port, $encoding;
1603
    global $SETTINGS;
1604
1605
    $tp_config_file = "../includes/config/tp.config.php";
1606
1607
    // Load AntiXSS
1608
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
1609
    $antiXss = new protect\AntiXSS\AntiXSS();
0 ignored issues
show
Unused Code introduced by
$antiXss is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1610
1611
    // include librairies & connect to DB
1612
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1613
    $pass = defuse_return_decrypted($pass);
1614
    DB::$host = $server;
1615
    DB::$user = $user;
1616
    DB::$password = $pass;
1617
    DB::$dbName = $database;
1618
    DB::$port = $port;
1619
    DB::$encoding = $encoding;
1620
    DB::$error_handler = true;
1621
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1622
    $link->set_charset($encoding);
1623
1624
    if (!file_exists($tp_config_file) || $action == "rebuild") {
1625
        // perform a copy
1626
        if (file_exists($tp_config_file)) {
1627
            if (!copy($tp_config_file, $tp_config_file.'.'.date("Y_m_d_His", time()))) {
1628
                return "ERROR: Could not copy file '".$tp_config_file."'";
1629
            }
1630
        }
1631
1632
        // regenerate
1633
        $data = array();
1634
        $data[0] = "<?php\n";
1635
        $data[1] = "global \$SETTINGS;\n";
1636
        $data[2] = "\$SETTINGS = array (\n";
1637
        $rows = DB::query(
1638
            "SELECT * FROM ".prefix_table("misc")." WHERE type=%s",
1639
            "admin"
1640
        );
1641
        foreach ($rows as $record) {
1642
            array_push($data, "    '".$record['intitule']."' => '".$record['valeur']."',\n");
1643
        }
1644
        array_push($data, ");\n");
1645
        $data = array_unique($data);
1646
    } elseif ($action == "update" && empty($field) === false) {
1647
        $data = file($tp_config_file);
1648
        $inc = 0;
1649
        $bFound = false;
1650
        foreach ($data as $line) {
1651
            if (stristr($line, ");")) {
1652
                break;
1653
            }
1654
1655
            //
1656
            if (stristr($line, "'".$field."' => '")) {
1657
                $data[$inc] = "    '".$field."' => '".filter_var($value, FILTER_SANITIZE_STRING)."',\n";
1658
                $bFound = true;
1659
                break;
1660
            }
1661
            $inc++;
1662
        }
1663
        if ($bFound === false) {
1664
            $data[($inc)] = "    '".$field."' => '".filter_var($value, FILTER_SANITIZE_STRING)."',\n);\n";
1665
        }
1666
    }
1667
1668
    // update file
1669
    file_put_contents($tp_config_file, implode('', isset($data) ? $data : array()));
1670
1671
    return true;
1672
}
1673
1674
/*
1675
** Permits to replace &#92; to permit correct display
1676
*/
1677
/**
1678
 * @param string $input
1679
 */
1680
function handleBackslash($input)
1681
{
1682
    return str_replace("&amp;#92;", "&#92;", $input);
1683
}
1684
1685
/*
1686
** Permits to loas settings
1687
*/
1688
function loadSettings()
1689
{
1690
    global $SETTINGS;
1691
1692
    /* LOAD CPASSMAN SETTINGS */
1693
    if (!isset($SETTINGS['loaded']) || $SETTINGS['loaded'] != 1) {
1694
        $SETTINGS['duplicate_folder'] = 0; //by default, this is set to 0;
1695
        $SETTINGS['duplicate_item'] = 0; //by default, this is set to 0;
1696
        $SETTINGS['number_of_used_pw'] = 5; //by default, this value is set to 5;
1697
        $settings = array();
1698
1699
        $rows = DB::query(
1700
            "SELECT * FROM ".prefix_table("misc")." WHERE type=%s_type OR type=%s_type2",
1701
            array(
1702
                'type' => "admin",
1703
                'type2' => "settings"
1704
            )
1705
        );
1706
        foreach ($rows as $record) {
1707
            if ($record['type'] == 'admin') {
1708
                $SETTINGS[$record['intitule']] = $record['valeur'];
1709
            } else {
1710
                $settings[$record['intitule']] = $record['valeur'];
1711
            }
1712
        }
1713
        $SETTINGS['loaded'] = 1;
1714
        $SETTINGS['default_session_expiration_time'] = 5;
1715
    }
1716
}
1717
1718
/*
1719
** check if folder has custom fields.
1720
** Ensure that target one also has same custom fields
1721
*/
1722
function checkCFconsistency($source_id, $target_id)
1723
{
1724
    $source_cf = array();
1725
    $rows = DB::QUERY(
1726
        "SELECT id_category
1727
        FROM ".prefix_table("categories_folders")."
1728
        WHERE id_folder = %i",
1729
        $source_id
1730
    );
1731
    foreach ($rows as $record) {
1732
        array_push($source_cf, $record['id_category']);
1733
    }
1734
1735
    $target_cf = array();
1736
    $rows = DB::QUERY(
1737
        "SELECT id_category
1738
        FROM ".prefix_table("categories_folders")."
1739
        WHERE id_folder = %i",
1740
        $target_id
1741
    );
1742
    foreach ($rows as $record) {
1743
        array_push($target_cf, $record['id_category']);
1744
    }
1745
1746
    $cf_diff = array_diff($source_cf, $target_cf);
1747
    if (count($cf_diff) > 0) {
1748
        return false;
1749
    }
1750
1751
    return true;
1752
}
1753
1754
/*
1755
*
1756
*/
1757
function encrypt_or_decrypt_file($filename_to_rework, $filename_status)
1758
{
1759
    global $server, $user, $pass, $database, $port, $encoding;
1760
    global $SETTINGS;
1761
1762
    // Include librairies & connect to DB
1763
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1764
    $pass = defuse_return_decrypted($pass);
1765
    DB::$host = $server;
1766
    DB::$user = $user;
1767
    DB::$password = $pass;
1768
    DB::$dbName = $database;
1769
    DB::$port = $port;
1770
    DB::$encoding = $encoding;
1771
    DB::$error_handler = true;
1772
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1773
    $link->set_charset($encoding);
1774
1775
    // Get file info in DB
1776
    $fileInfo = DB::queryfirstrow(
1777
        "SELECT id FROM ".prefix_table("files")." WHERE file = %s",
1778
        filter_var($filename_to_rework, FILTER_SANITIZE_STRING)
1779
    );
1780
    if (empty($fileInfo['id']) === false) {
1781
        // Load PhpEncryption library
1782
        $path_to_encryption = '/includes/libraries/Encryption/Encryption/';
1783
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Crypto.php';
1784
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Encoding.php';
1785
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'DerivedKeys.php';
1786
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Key.php';
1787
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyOrPassword.php';
1788
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'File.php';
1789
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'RuntimeTests.php';
1790
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyProtectedByPassword.php';
1791
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Core.php';
1792
1793
        // Get KEY
1794
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1795
1796
        if (isset($SETTINGS['enable_attachment_encryption'])
1797
            && $SETTINGS['enable_attachment_encryption'] === "1" &&
1798
            isset($filename_status)
1799
            && ($filename_status === "clear"
1800
                || $filename_status === "0")
1801
        ) {
1802
            // File needs to be encrypted
1803 View Code Duplication
            if (file_exists($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework)) {
1804
                // Make a copy of file
1805
                if (!copy(
1806
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1807
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1808
                )) {
1809
                    exit;
1810
                } else {
1811
                    // Do a bck
1812
                    copy(
1813
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1814
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1815
                    );
1816
                }
1817
1818
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework);
1819
1820
                // Now encrypt the file with saltkey
1821
                $err = '';
1822
                try {
1823
                    \Defuse\Crypto\File::encryptFile(
1824
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1825
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1826
                        \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1827
                    );
1828
                } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1829
                    $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.";
1830
                } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1831
                    $err = $ex;
1832
                } catch (Defuse\Crypto\Exception\IOException $ex) {
1833
                    $err = $ex;
1834
                }
1835
                if (empty($err) === false) {
1836
                    echo $err;
1837
                }
1838
1839
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1840
1841
                // update table
1842
                DB::update(
1843
                    prefix_table('files'),
1844
                    array(
1845
                        'status' => 'encrypted'
1846
                        ),
1847
                    "id = %i",
1848
                    $fileInfo['id']
1849
                );
1850
            }
1851
        } elseif (isset($SETTINGS['enable_attachment_encryption'])
1852
            && $SETTINGS['enable_attachment_encryption'] === "0"
1853
            && isset($filename_status)
1854
            && $filename_status === "encrypted"
1855
        ) {
1856
            // file needs to be decrypted
1857 View Code Duplication
            if (file_exists($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework)) {
1858
                // make a copy of file
1859
                if (!copy(
1860
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1861
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1862
                )) {
1863
                    exit;
1864
                } else {
1865
                    // do a bck
1866
                    copy(
1867
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1868
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1869
                    );
1870
                }
1871
1872
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework);
1873
1874
                // Now encrypt the file with saltkey
1875
                $err = '';
1876
                try {
1877
                    \Defuse\Crypto\File::decryptFile(
1878
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1879
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1880
                        \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1881
                    );
1882
                } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1883
                    $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.";
1884
                } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1885
                    $err = $ex;
1886
                } catch (Defuse\Crypto\Exception\IOException $ex) {
1887
                    $err = $ex;
1888
                }
1889
                if (empty($err) === false) {
1890
                    echo $err;
1891
                }
1892
1893
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1894
1895
                // update table
1896
                DB::update(
1897
                    prefix_table('files'),
1898
                    array(
1899
                        'status' => 'clear'
1900
                        ),
1901
                    "id = %i",
1902
                    $fileInfo['id']
1903
                );
1904
            }
1905
        }
1906
    }
1907
1908
    // Exit
1909
    return false;
1910
}
1911
1912
/**
1913
 * Will encrypte/decrypt a fil eusing Defuse
1914
 * @param  string $type        can be either encrypt or decrypt
1915
 * @param  string $source_file path to source file
1916
 * @param  string $target_file path to target file
1917
 * @return string              'true' is success or error message
1918
 */
1919
function prepareFileWithDefuse($type, $source_file, $target_file, $password = '')
1920
{
1921
    global $SETTINGS;
1922
1923
    // Load AntiXSS
1924
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
1925
    $antiXss = new protect\AntiXSS\AntiXSS();
1926
1927
    // Protect against bad inputs
1928
    if (is_array($source_file) ||is_array($target_file)) {
1929
        return 'error_cannot_be_array';
1930
    }
1931
1932
    // Sanitize
1933
    $source_file = $antiXss->xss_clean($source_file);
1934
    $target_file = $antiXss->xss_clean($target_file);
1935
1936
    // load PhpEncryption library
1937
    $path_to_encryption = '/includes/libraries/Encryption/Encryption/';
1938
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Crypto.php';
1939
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Encoding.php';
1940
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'DerivedKeys.php';
1941
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Key.php';
1942
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyOrPassword.php';
1943
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'File.php';
1944
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'RuntimeTests.php';
1945
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyProtectedByPassword.php';
1946
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Core.php';
1947
1948
    if (empty($password) === true) {
1949
    /*
1950
    File encryption/decryption is done with the SALTKEY
1951
     */
1952
1953
        // get KEY
1954
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1955
1956
        // Now perform action on the file
1957
        $err = '';
1958 View Code Duplication
        if ($type === 'decrypt') {
1959
            try {
1960
                \Defuse\Crypto\File::decryptFile(
1961
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1933 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...
1962
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1934 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...
1963
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1964
                );
1965
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1966
                $err = "decryption_not_possible";
1967
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1968
                $err = $ex;
1969
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1970
                $err = $ex;
1971
            }
1972
        } elseif ($type === 'encrypt') {
1973
            try {
1974
                \Defuse\Crypto\File::encryptFile(
1975
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1933 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...
1976
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1934 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...
1977
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1978
                );
1979
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1980
                $err = "encryption_not_possible";
1981
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1982
                $err = $ex;
1983
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1984
                $err = $ex;
1985
            }
1986
        }
1987
    } else {
1988
    /*
1989
    File encryption/decryption is done with special password and not the SALTKEY
1990
     */
1991
1992
        $err = '';
1993 View Code Duplication
        if ($type === 'decrypt') {
1994
            try {
1995
                \Defuse\Crypto\File::decryptFileWithPassword(
1996
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1933 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...
1997
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1934 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...
1998
                    $password
1999
                );
2000
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
2001
                $err = "wrong_key";
2002
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
2003
                $err = $ex;
2004
            } catch (Defuse\Crypto\Exception\IOException $ex) {
2005
                $err = $ex;
2006
            }
2007
        } elseif ($type === 'encrypt') {
2008
            try {
2009
                \Defuse\Crypto\File::encryptFileWithPassword(
2010
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1933 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...
2011
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1934 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...
2012
                    $password
2013
                );
2014
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
2015
                $err = "wrong_key";
2016
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
2017
                $err = $ex;
2018
            } catch (Defuse\Crypto\Exception\IOException $ex) {
2019
                $err = $ex;
2020
            }
2021
        }
2022
    }
2023
2024
    // return error
2025
    if (empty($err) === false) {
2026
        return $err;
2027
    } else {
2028
        return true;
2029
    }
2030
}
2031
2032
/*
2033
* NOT TO BE USED
2034
*/
2035
function debugTeampass($text)
2036
{
2037
    $debugFile = fopen('D:/wamp64/www/TeamPass/debug.txt', 'r+');
2038
    fputs($debugFile, $text);
2039
    fclose($debugFile);
2040
}
2041
2042
2043
/**
2044
 * DELETE the file with expected command depending on server type
2045
 * @param  string $file Path to file
2046
 * @return              Nothing
2047
 */
2048
function fileDelete($file)
2049
{
2050
    global $SETTINGS;
2051
2052
    // Load AntiXSS
2053
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
2054
    $antiXss = new protect\AntiXSS\AntiXSS();
2055
2056
    $file = $antiXss->xss_clean($file);
2057
    if (is_file($file)) {
2058
        unlink($file);
2059
    }
2060
}
2061
2062
/*
2063
* Permits to extract the file extension
2064
*/
2065
function getFileExtension($file)
2066
{
2067
    if (strpos($file, '.') === false) {
2068
        return $file;
2069
    }
2070
2071
    return substr($file, strrpos($file, '.') + 1);
2072
}
2073
2074
/**
2075
 * array_map
2076
 * @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...
2077
 * @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...
2078
 * @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...
2079
 */
2080
function array_map_r($func, $arr)
2081
{
2082
    $newArr = array();
2083
2084
    foreach ($arr as $key => $value) {
2085
        $newArr[ $key ] = (is_array($value) ? array_map_r($func, $value) : ( is_array($func) ? call_user_func_array($func, $value) : $func( $value )));
2086
    }
2087
2088
    return $newArr;
2089
}
2090
2091
/**
2092
 * Permits to clean and sanitize text to be displayed
2093
 * @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...
2094
 * @param  string $type what clean to perform
2095
 * @return string       text cleaned up
2096
 */
2097
function cleanText($string, $type = "")
2098
{
2099
    global $SETTINGS;
2100
2101
    // Load AntiXSS
2102
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
2103
    $antiXss = new protect\AntiXSS\AntiXSS();
2104
2105
    if ($type === "css") {
2106
        // Escape text and quotes in UTF8 format
2107
        return htmlentities($string, ENT_QUOTES | ENT_HTML5, 'UTF-8');
2108
    } elseif ($type === "html" || empty($type)) {
2109
        // Html cleaner
2110
        return $antiXss->xss_clean($string);
2111
    }
2112
}
2113
2114
/**
2115
 * Performs chmod operation on subfolders
2116
 * @param  string  $dir             Parent folder
2117
 * @param  integer $dirPermissions  New permission on folders
2118
 * @param  integer $filePermissions New permission on files
2119
 * @return boolean                  Success/Failure
2120
 */
2121
function chmodRecursive($dir, $dirPermissions, $filePermissions)
2122
{
2123
    $pointer_dir = opendir($dir);
2124
    $res = true;
2125
    while ($file = readdir($pointer_dir)) {
2126
        if (($file == ".") || ($file == "..")) {
2127
            continue;
2128
        }
2129
2130
        $fullPath = $dir."/".$file;
2131
2132
        if (is_dir($fullPath)) {
2133
            if ($res = @chmod($fullPath, $dirPermissions)) {
2134
                $res = @chmodRecursive($fullPath, $dirPermissions, $filePermissions);
2135
            }
2136
        } else {
2137
            $res = chmod($fullPath, $filePermissions);
2138
        }
2139
        if (!$res) {
2140
            closedir($pointer_dir);
2141
            return false;
2142
        }
2143
    }
2144
    closedir($pointer_dir);
2145
    if (is_dir($dir) && $res) {
2146
        $res = @chmod($dir, $dirPermissions);
2147
    }
2148
2149
    return $res;
2150
}
2151
2152
/**
2153
 * Check if user can access to this item
2154
 * @param $item_id
2155
 */
2156
function accessToItemIsGranted($item_id)
2157
{
2158
    global $SETTINGS;
2159
2160
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
2161
    $superGlobal = new protect\SuperGlobal\SuperGlobal();
2162
2163
    // Prepare superGlobal variables
2164
    $session_groupes_visibles = $superGlobal->get("groupes_visibles", "SESSION");
2165
    $session_list_restricted_folders_for_items = $superGlobal->get("list_restricted_folders_for_items", "SESSION");
2166
2167
    // Load item data
2168
    $data = DB::queryFirstRow(
2169
        "SELECT id_tree
2170
        FROM ".prefix_table("items")."
2171
        WHERE id = %i",
2172
        $item_id
2173
    );
2174
2175
    // Check if user can access this folder
2176
    if (in_array($data['id_tree'], $session_groupes_visibles) === false) {
2177
        // Now check if this folder is restricted to user
2178
        if (isset($session_list_restricted_folders_for_items[$data['id_tree']])
2179
            && !in_array($item_id, $session_list_restricted_folders_for_items[$data['id_tree']])
2180
        ) {
2181
            return "ERR_FOLDER_NOT_ALLOWED";
2182
        } else {
2183
            return "ERR_FOLDER_NOT_ALLOWED";
2184
        }
2185
    }
2186
2187
    return true;
2188
}
2189