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

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

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

    return array();
}

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

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

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

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

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

    return array();
}

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

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

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

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

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

    return array();
}

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

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

Loading history...
1960
                    $password
1961
                );
1962
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1963
                $err = "wrong_key";
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::encryptFileWithPassword(
1972
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1895 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...
1973
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1896 can also be of type array; however, Defuse\Crypto\File::encryptFileWithPassword() does only seem to accept string, maybe add an additional type check?

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

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

    return array();
}

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

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

Loading history...
1974
                    $password
1975
                );
1976
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1977
                $err = "wrong_key";
1978
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1979
                $err = $ex;
1980
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1981
                $err = $ex;
1982
            }
1983
        }
1984
    }
1985
1986
    // return error
1987
    if (empty($err) === false) {
1988
        return $err;
1989
    } else {
1990
        return true;
1991
    }
1992
}
1993
1994
/*
1995
* NOT TO BE USED
1996
*/
1997
function debugTeampass($text)
1998
{
1999
    $debugFile = fopen('D:/wamp64/www/TeamPass/debug.txt', 'r+');
2000
    fputs($debugFile, $text);
2001
    fclose($debugFile);
2002
}
2003
2004
2005
/**
2006
 * DELETE the file with expected command depending on server type
2007
 * @param  string $file Path to file
2008
 * @return              Nothing
2009
 */
2010
function fileDelete($file)
2011
{
2012
    global $SETTINGS;
2013
2014
    // Load AntiXSS
2015
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
2016
    $antiXss = new protect\AntiXSS\AntiXSS();
2017
2018
    $file = $antiXss->xss_clean($file);
2019
    if (is_file($file)) {
2020
        unlink($file);
2021
    }
2022
}
2023
2024
/*
2025
* Permits to extract the file extension
2026
*/
2027
function getFileExtension($file)
2028
{
2029
    if (strpos($file, '.') === false) {
2030
        return $file;
2031
    }
2032
2033
    return substr($file, strrpos($file, '.') + 1);
2034
}
2035
2036
/**
2037
 * array_map
2038
 * @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...
2039
 * @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...
2040
 * @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...
2041
 */
2042
function array_map_r($func, $arr)
2043
{
2044
    $newArr = array();
2045
2046
    foreach ($arr as $key => $value) {
2047
        $newArr[ $key ] = (is_array($value) ? array_map_r($func, $value) : ( is_array($func) ? call_user_func_array($func, $value) : $func( $value )));
2048
    }
2049
2050
    return $newArr;
2051
}
2052
2053
/**
2054
 * Permits to clean and sanitize text to be displayed
2055
 * @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...
2056
 * @param  string $type what clean to perform
2057
 * @return string       text cleaned up
2058
 */
2059
function cleanText($string, $type = "")
2060
{
2061
    global $SETTINGS;
2062
2063
    // Load AntiXSS
2064
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
2065
    $antiXss = new protect\AntiXSS\AntiXSS();
2066
2067
    if ($type === "css") {
2068
        // Escape text and quotes in UTF8 format
2069
        return htmlentities($string, ENT_QUOTES | ENT_HTML5, 'UTF-8');
2070
    } elseif ($type === "html" || empty($type)) {
2071
        // Html cleaner
2072
        return $antiXss->xss_clean($string);
2073
    }
2074
}
2075
2076
/**
2077
 * Performs chmod operation on subfolders
2078
 * @param  string  $dir             Parent folder
2079
 * @param  integer $dirPermissions  New permission on folders
2080
 * @param  integer $filePermissions New permission on files
2081
 * @return boolean                  Success/Failure
2082
 */
2083
function chmodRecursive($dir, $dirPermissions, $filePermissions)
2084
{
2085
    $pointer_dir = opendir($dir);
2086
    $res = true;
2087
    while ($file = readdir($pointer_dir)) {
2088
        if (($file == ".") || ($file == "..")) {
2089
            continue;
2090
        }
2091
2092
        $fullPath = $dir."/".$file;
2093
2094
        if (is_dir($fullPath)) {
2095
            if ($res = @chmod($fullPath, $dirPermissions)) {
2096
                $res = @chmodRecursive($fullPath, $dirPermissions, $filePermissions);
2097
            }
2098
        } else {
2099
            $res = chmod($fullPath, $filePermissions);
2100
        }
2101
        if (!$res) {
2102
            closedir($pointer_dir);
2103
            return false;
2104
        }
2105
    }
2106
    closedir($pointer_dir);
2107
    if (is_dir($dir) && $res) {
2108
        $res = @chmod($dir, $dirPermissions);
2109
    }
2110
2111
    return $res;
2112
}
2113