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