Completed
Push — development ( 7dd9f6...98e1f6 )
by Nils
08:52
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
function defuse_return_decrypted($value)
491
{
492
    if (substr($value, 0, 3) === "def") {
493
        $value = cryption($value, "", "decrypt")['string'];
494
    }
495
    return $value;
496
}
497
498
/**
499
 * trimElement()
500
 *
501
 * trim a string depending on a specific string
502
 * @param string $element
503
 * @return string
504
 */
505
function trimElement($chaine, $element)
506
{
507
    if (!empty($chaine)) {
508
        $chaine = trim($chaine);
509
        if (substr($chaine, 0, 1) == $element) {
510
            $chaine = substr($chaine, 1);
511
        }
512
        if (substr($chaine, strlen($chaine) - 1, 1) == $element) {
513
            $chaine = substr($chaine, 0, strlen($chaine) - 1);
514
        }
515
    }
516
    return $chaine;
517
}
518
519
/**
520
 * cleanString()
521
 *
522
 * permits to suppress all "special" characters from string
523
 */
524
function cleanString($string, $special = false)
525
{
526
    // Create temporary table for special characters escape
527
    $tabSpecialChar = array();
528
    for ($i = 0; $i <= 31; $i++) {
529
        $tabSpecialChar[] = chr($i);
530
    }
531
    array_push($tabSpecialChar, "<br />");
532
    if ($special == "1") {
533
        $tabSpecialChar = array_merge($tabSpecialChar, array("</li>", "<ul>", "<ol>"));
534
    }
535
536
    return str_replace($tabSpecialChar, "\n", $string);
537
}
538
539
function db_error_handler($params)
540
{
541
    echo "Error: ".$params['error']."<br>\n";
542
    echo "Query: ".$params['query']."<br>\n";
543
    throw new Exception("Error - Query", 1);
544
}
545
546
/**
547
 * [identifyUserRights description]
548
 * @param  string $groupesVisiblesUser  [description]
549
 * @param  string $groupesInterditsUser [description]
550
 * @param  string $isAdmin              [description]
551
 * @param  string $idFonctions          [description]
552
 * @return string                       [description]
553
 */
554
function identifyUserRights($groupesVisiblesUser, $groupesInterditsUser, $isAdmin, $idFonctions)
555
{
556
    global $server, $user, $pass, $database, $port, $encoding;
557
    global $SETTINGS;
558
559
    //load ClassLoader
560
    require_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php';
561
562
    //Connect to DB
563
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
564
    $pass = defuse_return_decrypted($pass);
565
    DB::$host = $server;
566
    DB::$user = $user;
567
    DB::$password = $pass;
568
    DB::$dbName = $database;
569
    DB::$port = $port;
570
    DB::$encoding = $encoding;
571
    DB::$error_handler = true;
572
    $link = mysqli_connect($server, $user, $pass, $database, $port);
573
    $link->set_charset($encoding);
574
575
    //Build tree
576
    $tree = new SplClassLoader('Tree\NestedTree', $SETTINGS['cpassman_dir'].'/includes/libraries');
577
    $tree->register();
578
    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
579
580
    // Check if user is ADMINISTRATOR
581
    if ($isAdmin == 1) {
582
        $groupesVisibles = array();
583
        $_SESSION['personal_folders'] = array();
584
        $_SESSION['groupes_visibles'] = array();
585
        $_SESSION['groupes_interdits'] = array();
586
        $_SESSION['personal_visible_groups'] = array();
587
        $_SESSION['read_only_folders'] = array();
588
        $_SESSION['list_restricted_folders_for_items'] = array();
589
        $_SESSION['list_folders_editable_by_role'] = array();
590
        $_SESSION['list_folders_limited'] = array();
591
        $_SESSION['groupes_visibles_list'] = "";
592
        $_SESSION['list_folders_limited'] = "";
593
        $rows = DB::query("SELECT id FROM ".prefix_table("nested_tree")." WHERE personal_folder = %i", 0);
594
        foreach ($rows as $record) {
595
            array_push($groupesVisibles, $record['id']);
596
        }
597
        $_SESSION['groupes_visibles'] = $groupesVisibles;
598
        $_SESSION['all_non_personal_folders'] = $groupesVisibles;
599
        // Exclude all PF
600
        $_SESSION['forbiden_pfs'] = array();
601
        $where = new WhereClause('and'); // create a WHERE statement of pieces joined by ANDs
602
        $where->add('personal_folder=%i', 1);
603
        if (isset($SETTINGS['enable_pf_feature']) && $SETTINGS['enable_pf_feature'] == 1) {
604
            $where->add('title=%s', $_SESSION['user_id']);
605
            $where->negateLast();
606
        }
607
        // Get ID of personal folder
608
        $persfld = DB::queryfirstrow(
609
            "SELECT id FROM ".prefix_table("nested_tree")." WHERE title = %s",
610
            $_SESSION['user_id']
611
        );
612
        if (!empty($persfld['id'])) {
613
            if (!in_array($persfld['id'], $_SESSION['groupes_visibles'])) {
614
                array_push($_SESSION['groupes_visibles'], $persfld['id']);
615
                array_push($_SESSION['personal_visible_groups'], $persfld['id']);
616
                // get all descendants
617
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
618
                $tree->rebuild();
619
                $tst = $tree->getDescendants($persfld['id']);
620
                foreach ($tst as $t) {
621
                    array_push($_SESSION['groupes_visibles'], $t->id);
622
                    array_push($_SESSION['personal_visible_groups'], $t->id);
623
                }
624
            }
625
        }
626
627
        // get complete list of ROLES
628
        $tmp = explode(";", $_SESSION['fonction_id']);
629
        $rows = DB::query(
630
            "SELECT * FROM ".prefix_table("roles_title")."
631
            ORDER BY title ASC"
632
        );
633
        foreach ($rows as $record) {
634
            if (!empty($record['id']) && !in_array($record['id'], $tmp)) {
635
                array_push($tmp, $record['id']);
636
            }
637
        }
638
        $_SESSION['fonction_id'] = implode(";", $tmp);
639
640
        $_SESSION['groupes_visibles_list'] = implode(',', $_SESSION['groupes_visibles']);
641
        $_SESSION['is_admin'] = $isAdmin;
642
        // Check if admin has created Folders and Roles
643
        DB::query("SELECT * FROM ".prefix_table("nested_tree")."");
644
        $_SESSION['nb_folders'] = DB::count();
645
        DB::query("SELECT * FROM ".prefix_table("roles_title"));
646
        $_SESSION['nb_roles'] = DB::count();
647
    } else {
648
        // init
649
        $_SESSION['groupes_visibles'] = array();
650
        $_SESSION['personal_folders'] = array();
651
        $_SESSION['groupes_interdits'] = array();
652
        $_SESSION['personal_visible_groups'] = array();
653
        $_SESSION['read_only_folders'] = array();
654
        $groupesInterdits = array();
655
        if (!is_array($groupesInterditsUser)) {
656
            $groupesInterditsUser = explode(';', trimElement($groupesInterditsUser, ";"));
657
        }
658
        if (!empty($groupesInterditsUser) && count($groupesInterditsUser) > 0) {
659
            $groupesInterdits = $groupesInterditsUser;
660
        }
661
        $_SESSION['is_admin'] = $isAdmin;
662
        $fonctionsAssociees = explode(';', trimElement($idFonctions, ";"));
663
664
        $listAllowedFolders = $listFoldersLimited = $listFoldersEditableByRole = $listRestrictedFoldersForItems = $listReadOnlyFolders = array();
665
666
        // rechercher tous les groupes visibles en fonction des roles de l'utilisateur
667
        foreach ($fonctionsAssociees as $roleId) {
668
            if (!empty($roleId)) {
669
                // Get allowed folders for each Role
670
                $rows = DB::query("SELECT folder_id FROM ".prefix_table("roles_values")." WHERE role_id=%i", $roleId);
671
672
                if (DB::count() > 0) {
673
                    $tmp = DB::queryfirstrow("SELECT allow_pw_change FROM ".prefix_table("roles_title")." WHERE id = %i", $roleId);
674
                    foreach ($rows as $record) {
675
                        if (isset($record['folder_id']) && !in_array($record['folder_id'], $listAllowedFolders)) {
676
                            array_push($listAllowedFolders, $record['folder_id']);
677
                        }
678
                        // Check if this group is allowed to modify any pw in allowed folders
679
                        if ($tmp['allow_pw_change'] == 1 && !in_array($record['folder_id'], $listFoldersEditableByRole)) {
680
                            array_push($listFoldersEditableByRole, $record['folder_id']);
681
                        }
682
                    }
683
                    // Check for the users roles if some specific rights exist on items
684
                    $rows = DB::query(
685
                        "SELECT i.id_tree, r.item_id
686
                        FROM ".prefix_table("items")." as i
687
                        INNER JOIN ".prefix_table("restriction_to_roles")." as r ON (r.item_id=i.id)
688
                        WHERE r.role_id=%i
689
                        ORDER BY i.id_tree ASC",
690
                        $roleId
691
                    );
692
                    $inc = 0;
693
                    foreach ($rows as $record) {
694
                        if (isset($record['id_tree'])) {
695
                            $listFoldersLimited[$record['id_tree']][$inc] = $record['item_id'];
696
                            $inc++;
697
                        }
698
                    }
699
                }
700
            }
701
        }
702
703
        // Does this user is allowed to see other items
704
        $inc = 0;
705
        $rows = DB::query(
706
            "SELECT id, id_tree FROM ".prefix_table("items")."
707
            WHERE restricted_to LIKE %ss AND inactif=%s",
708
            $_SESSION['user_id'].';',
709
            '0'
710
        );
711
        foreach ($rows as $record) {
712
            $listRestrictedFoldersForItems[$record['id_tree']][$inc] = $record['id'];
713
            $inc++;
714
        }
715
        // => Build final lists
716
        // Clean arrays
717
        $listAllowedFolders = array_unique($listAllowedFolders);
718
        $groupesVisiblesUser = explode(';', trimElement($groupesVisiblesUser, ";"));
719
        // Add user allowed folders
720
        $allowedFoldersTmp = array_unique(
721
            array_merge($listAllowedFolders, $groupesVisiblesUser)
722
        );
723
        // Exclude from allowed folders all the specific user forbidden folders
724
        $allowedFolders = array();
725
        foreach ($allowedFoldersTmp as $ident) {
726
            if (!in_array($ident, $groupesInterditsUser) && !empty($ident)) {
727
                array_push($allowedFolders, $ident);
728
            }
729
        }
730
731
        // Clean array
732
        $listAllowedFolders = array_filter(array_unique($allowedFolders));
733
734
        // Exclude all PF
735
        $_SESSION['forbiden_pfs'] = array();
736
737
        $where = new WhereClause('and');
738
        $where->add('personal_folder=%i', 1);
739
        if (isset($SETTINGS['enable_pf_feature']) &&
740
            $SETTINGS['enable_pf_feature'] == 1 &&
741
            isset($_SESSION['personal_folder']) &&
742
            $_SESSION['personal_folder'] == 1
743
        ) {
744
            $where->add('title=%s', $_SESSION['user_id']);
745
            $where->negateLast();
746
        }
747
748
        $persoFlds = DB::query("SELECT id FROM ".prefix_table("nested_tree")." WHERE %l", $where);
749
        foreach ($persoFlds as $persoFldId) {
750
            array_push($_SESSION['forbiden_pfs'], $persoFldId['id']);
751
        }
752
        // Get IDs of personal folders
753
        if (isset($SETTINGS['enable_pf_feature']) &&
754
            $SETTINGS['enable_pf_feature'] == 1 &&
755
            isset($_SESSION['personal_folder']) &&
756
            $_SESSION['personal_folder'] == 1
757
        ) {
758
            $persoFld = DB::queryfirstrow("SELECT id FROM ".prefix_table("nested_tree")." WHERE title = %s", $_SESSION['user_id']);
759
            if (!empty($persoFld['id'])) {
760
                if (!in_array($persoFld['id'], $listAllowedFolders)) {
761
                    array_push($_SESSION['personal_folders'], $persoFld['id']);
762
                    // get all descendants
763
                    $ids = $tree->getDescendants($persoFld['id'], true, false);
764
                    foreach ($ids as $ident) {
765
                        array_push($listAllowedFolders, $ident->id);
766
                        array_push($_SESSION['personal_visible_groups'], $ident->id);
767
                        array_push($_SESSION['personal_folders'], $ident->id);
768
                    }
769
                }
770
            }
771
            // get list of readonly folders when pf is disabled.
772
            // rule - if one folder is set as W or N in one of the Role, then User has access as W
773
            foreach ($listAllowedFolders as $folderId) {
774
                if (!in_array($folderId, array_unique(array_merge($listReadOnlyFolders, $_SESSION['personal_folders'])))) {   //
775
                    DB::query(
776
                        "SELECT *
777
                        FROM ".prefix_table("roles_values")."
778
                        WHERE folder_id = %i AND role_id IN %li AND type IN %ls",
779
                        $folderId,
780
                        $fonctionsAssociees,
781
                        array("W", "ND", "NE", "NDNE")
782
                    );
783
                    if (DB::count() == 0 && !in_array($folderId, $groupesVisiblesUser)) {
784
                        array_push($listReadOnlyFolders, $folderId);
785
                    }
786
                }
787
            }
788
        } else {
789
            // get list of readonly folders when pf is disabled.
790
            // rule - if one folder is set as W in one of the Role, then User has access as W
791
            foreach ($listAllowedFolders as $folderId) {
792
                if (!in_array($folderId, $listReadOnlyFolders)) {
793
                    DB::query(
794
                        "SELECT *
795
                        FROM ".prefix_table("roles_values")."
796
                        WHERE folder_id = %i AND role_id IN %li AND type IN %ls",
797
                        $folderId,
798
                        $fonctionsAssociees,
799
                        array("W", "ND", "NE", "NDNE")
800
                    );
801
                    if (DB::count() == 0 && !in_array($folderId, $groupesVisiblesUser)) {
802
                        array_push($listReadOnlyFolders, $folderId);
803
                    }
804
                }
805
            }
806
        }
807
808
        // check if change proposals on User's items
809
        if (isset($SETTINGS['enable_suggestion']) && $SETTINGS['enable_suggestion'] == 1) {
810
            DB::query(
811
                "SELECT *
812
                FROM ".prefix_table("items_change")." AS c
813
                LEFT JOIN ".prefix_table("log_items")." AS i ON (c.item_id = i.id_item)
814
                WHERE i.action = %s AND i.id_user = %i",
815
                "at_creation",
816
                $_SESSION['user_id']
817
            );
818
            $_SESSION['nb_item_change_proposals'] = DB::count();
819
        } else {
820
            $_SESSION['nb_item_change_proposals'] = 0;
821
        }
822
823
        $_SESSION['all_non_personal_folders'] = $listAllowedFolders;
824
        $_SESSION['groupes_visibles'] = $listAllowedFolders;
825
        $_SESSION['groupes_visibles_list'] = implode(',', $listAllowedFolders);
826
        $_SESSION['personal_visible_groups_list'] = implode(',', $_SESSION['personal_visible_groups']);
827
        $_SESSION['read_only_folders'] = $listReadOnlyFolders;
828
        $_SESSION['no_access_folders'] = $groupesInterdits;
829
830
        $_SESSION['list_folders_limited'] = $listFoldersLimited;
831
        $_SESSION['list_folders_editable_by_role'] = $listFoldersEditableByRole;
832
        $_SESSION['list_restricted_folders_for_items'] = $listRestrictedFoldersForItems;
833
        // Folders and Roles numbers
834
        DB::queryfirstrow("SELECT id FROM ".prefix_table("nested_tree")."");
835
        $_SESSION['nb_folders'] = DB::count();
836
        DB::queryfirstrow("SELECT id FROM ".prefix_table("roles_title"));
837
        $_SESSION['nb_roles'] = DB::count();
838
    }
839
840
    // update user's timestamp
841
    DB::update(
842
        prefix_table('users'),
843
        array(
844
            'timestamp' => time()
845
        ),
846
        "id=%i",
847
        $_SESSION['user_id']
848
    );
849
}
850
851
/**
852
 * updateCacheTable()
853
 *
854
 * Update the CACHE table
855
 * @param string $action
856
 */
857
function updateCacheTable($action, $ident = "")
858
{
859
    global $server, $user, $pass, $database, $port, $encoding;
860
    global $SETTINGS;
861
862
    require_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php';
863
864
    //Connect to DB
865
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
866
    $pass = defuse_return_decrypted($pass);
867
    DB::$host = $server;
868
    DB::$user = $user;
869
    DB::$password = $pass;
870
    DB::$dbName = $database;
871
    DB::$port = $port;
872
    DB::$encoding = $encoding;
873
    DB::$error_handler = true;
874
    $link = mysqli_connect($server, $user, $pass, $database, $port);
875
    $link->set_charset($encoding);
876
877
    //Load Tree
878
    $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
879
    $tree->register();
880
    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
881
882
    // Rebuild full cache table
883
    if ($action === "reload") {
884
        // truncate table
885
        DB::query("TRUNCATE TABLE ".prefix_table("cache"));
886
887
        // reload date
888
        $rows = DB::query(
889
            "SELECT *
890
            FROM ".prefix_table('items')." as i
891
            INNER JOIN ".prefix_table('log_items')." as l ON (l.id_item = i.id)
892
            AND l.action = %s
893
            AND i.inactif = %i",
894
            'at_creation',
895
            0
896
        );
897
        foreach ($rows as $record) {
898
            // Get all TAGS
899
            $tags = "";
900
            $itemTags = DB::query("SELECT tag FROM ".prefix_table('tags')." WHERE item_id=%i", $record['id']);
901 View Code Duplication
            foreach ($itemTags as $itemTag) {
902
                if (!empty($itemTag['tag'])) {
903
                    $tags .= $itemTag['tag']." ";
904
                }
905
            }
906
            // Get renewal period
907
            $resNT = DB::queryfirstrow("SELECT renewal_period FROM ".prefix_table('nested_tree')." WHERE id=%i", $record['id_tree']);
908
909
            // form id_tree to full foldername
910
            $folder = "";
911
            $arbo = $tree->getPath($record['id_tree'], true);
912 View Code Duplication
            foreach ($arbo as $elem) {
913
                if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
914
                    $elem->title = $_SESSION['login'];
915
                }
916
                if (empty($folder)) {
917
                    $folder = stripslashes($elem->title);
918
                } else {
919
                    $folder .= " » ".stripslashes($elem->title);
920
                }
921
            }
922
            // store data
923
            DB::insert(
924
                prefix_table('cache'),
925
                array(
926
                    'id' => $record['id'],
927
                    'label' => $record['label'],
928
                    'description' => isset($record['description']) ? $record['description'] : "",
929
                    'url' => (isset($record['url']) && !empty($record['url'])) ? $record['url'] : "0",
930
                    'tags' => $tags,
931
                    'id_tree' => $record['id_tree'],
932
                    'perso' => $record['perso'],
933
                    'restricted_to' => (isset($record['restricted_to']) && !empty($record['restricted_to'])) ? $record['restricted_to'] : "0",
934
                    'login' => isset($record['login']) ? $record['login'] : "",
935
                    'folder' => $folder,
936
                    'author' => $record['id_user'],
937
                    'renewal_period' => isset($resNT['renewal_period']) ? $resNT['renewal_period'] : "0",
938
                    'timestamp' => $record['date']
939
                    )
940
            );
941
        }
942
        // UPDATE an item
943
    } elseif ($action === "update_value") {
944
        // get new value from db
945
        $data = DB::queryfirstrow(
946
            "SELECT label, description, id_tree, perso, restricted_to, login, url
947
            FROM ".prefix_table('items')."
948
            WHERE id=%i",
949
            $ident
950
        );
951
        // Get all TAGS
952
        $tags = "";
953
        $itemTags = DB::query("SELECT tag FROM ".prefix_table('tags')." WHERE item_id=%i", $ident);
954 View Code Duplication
        foreach ($itemTags as $itemTag) {
955
            if (!empty($itemTag['tag'])) {
956
                $tags .= $itemTag['tag']." ";
957
            }
958
        }
959
        // form id_tree to full foldername
960
        $folder = "";
961
        $arbo = $tree->getPath($data['id_tree'], true);
962 View Code Duplication
        foreach ($arbo as $elem) {
963
            if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
964
                $elem->title = $_SESSION['login'];
965
            }
966
            if (empty($folder)) {
967
                $folder = stripslashes($elem->title);
968
            } else {
969
                $folder .= " » ".stripslashes($elem->title);
970
            }
971
        }
972
        // finaly update
973
        DB::update(
974
            prefix_table('cache'),
975
            array(
976
                'label' => $data['label'],
977
                'description' => $data['description'],
978
                'tags' => $tags,
979
                'url' => (isset($data['url']) && !empty($data['url'])) ? $data['url'] : "0",
980
                'id_tree' => $data['id_tree'],
981
                'perso' => $data['perso'],
982
                'restricted_to' => (isset($data['restricted_to']) && !empty($data['restricted_to'])) ? $data['restricted_to'] : "0",
983
                'login' => isset($data['login']) ? $data['login'] : "",
984
                'folder' => $folder,
985
                'author' => $_SESSION['user_id'],
986
                ),
987
            "id = %i",
988
            $ident
989
        );
990
        // ADD an item
991
    } elseif ($action === "add_value") {
992
        // get new value from db
993
        $data = DB::queryFirstRow(
994
            "SELECT i.label, i.description, i.id_tree as id_tree, i.perso, i.restricted_to, i.id, i.login, i.url, l.date
995
            FROM ".prefix_table('items')." as i
996
            INNER JOIN ".prefix_table('log_items')." as l ON (l.id_item = i.id)
997
            WHERE i.id = %i
998
            AND l.action = %s",
999
            $ident,
1000
            'at_creation'
1001
        );
1002
        // Get all TAGS
1003
        $tags = "";
1004
        $itemTags = DB::query("SELECT tag FROM ".prefix_table('tags')." WHERE item_id = %i", $ident);
1005 View Code Duplication
        foreach ($itemTags as $itemTag) {
1006
            if (!empty($itemTag['tag'])) {
1007
                $tags .= $itemTag['tag']." ";
1008
            }
1009
        }
1010
        // form id_tree to full foldername
1011
        $folder = "";
1012
        $arbo = $tree->getPath($data['id_tree'], true);
1013 View Code Duplication
        foreach ($arbo as $elem) {
1014
            if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
1015
                $elem->title = $_SESSION['login'];
1016
            }
1017
            if (empty($folder)) {
1018
                $folder = stripslashes($elem->title);
1019
            } else {
1020
                $folder .= " » ".stripslashes($elem->title);
1021
            }
1022
        }
1023
        // finaly update
1024
        DB::insert(
1025
            prefix_table('cache'),
1026
            array(
1027
                'id' => $data['id'],
1028
                'label' => $data['label'],
1029
                'description' => $data['description'],
1030
                'tags' => (isset($tags) && !empty($tags)) ? $tags : "None",
1031
                'url' => (isset($data['url']) && !empty($data['url'])) ? $data['url'] : "0",
1032
                'id_tree' => $data['id_tree'],
1033
                'perso' => (isset($data['perso']) && !empty($data['perso']) && $data['perso'] !== "None") ? $data['perso'] : "0",
1034
                'restricted_to' => (isset($data['restricted_to']) && !empty($data['restricted_to'])) ? $data['restricted_to'] : "None",
1035
                'login' => isset($data['login']) ? $data['login'] : "",
1036
                'folder' => $folder,
1037
                'author' => $_SESSION['user_id'],
1038
                'timestamp' => $data['date']
1039
            )
1040
        );
1041
1042
        // DELETE an item
1043
    } elseif ($action === "delete_value") {
1044
        DB::delete(prefix_table('cache'), "id = %i", $ident);
1045
    }
1046
}
1047
1048
/*
1049
*
1050
*/
1051
function getStatisticsData()
1052
{
1053
    global $SETTINGS;
1054
1055
    DB::query(
1056
        "SELECT id FROM ".prefix_table("nested_tree")." WHERE personal_folder = %i",
1057
        0
1058
    );
1059
    $counter_folders = DB::count();
1060
1061
    DB::query(
1062
        "SELECT id FROM ".prefix_table("nested_tree")." WHERE personal_folder = %i",
1063
        1
1064
    );
1065
    $counter_folders_perso = DB::count();
1066
1067
    DB::query(
1068
        "SELECT id FROM ".prefix_table("items")." WHERE perso = %i",
1069
        0
1070
    );
1071
    $counter_items = DB::count();
1072
1073
    DB::query(
1074
        "SELECT id FROM ".prefix_table("items")." WHERE perso = %i",
1075
        1
1076
    );
1077
    $counter_items_perso = DB::count();
1078
1079
    DB::query(
1080
        "SELECT id FROM ".prefix_table("users").""
1081
    );
1082
    $counter_users = DB::count();
1083
1084
    DB::query(
1085
        "SELECT id FROM ".prefix_table("users")." WHERE admin = %i",
1086
        1
1087
    );
1088
    $admins = DB::count();
1089
1090
    DB::query(
1091
        "SELECT id FROM ".prefix_table("users")." WHERE gestionnaire = %i",
1092
        1
1093
    );
1094
    $managers = DB::count();
1095
1096
    DB::query(
1097
        "SELECT id FROM ".prefix_table("users")." WHERE read_only = %i",
1098
        1
1099
    );
1100
    $readOnly = DB::count();
1101
1102
    // list the languages
1103
    $usedLang = [];
1104
    $tp_languages = DB::query(
1105
        "SELECT name FROM ".prefix_table("languages")
1106
    );
1107
    foreach ($tp_languages as $tp_language) {
1108
        DB::query(
1109
            "SELECT * FROM ".prefix_table("users")." WHERE user_language = %s",
1110
            $tp_language['name']
1111
        );
1112
        $usedLang[$tp_language['name']] = round((DB::count() * 100 / $counter_users), 0);
1113
    }
1114
1115
    // get list of ips
1116
    $usedIp = [];
1117
    $tp_ips = DB::query(
1118
        "SELECT user_ip FROM ".prefix_table("users")
1119
    );
1120
    foreach ($tp_ips as $ip) {
1121
        if (array_key_exists($ip['user_ip'], $usedIp)) {
1122
            $usedIp[$ip['user_ip']] = $usedIp[$ip['user_ip']] + 1;
1123
        } elseif (!empty($ip['user_ip']) && $ip['user_ip'] !== "none") {
1124
            $usedIp[$ip['user_ip']] = 1;
1125
        }
1126
    }
1127
1128
    return array(
1129
        "error" => "",
1130
        "stat_phpversion" => phpversion(),
1131
        "stat_folders" => $counter_folders,
1132
        "stat_folders_shared" => intval($counter_folders) - intval($counter_folders_perso),
1133
        "stat_items" => $counter_items,
1134
        "stat_items_shared" => intval($counter_items) - intval($counter_items_perso),
1135
        "stat_users" => $counter_users,
1136
        "stat_admins" => $admins,
1137
        "stat_managers" => $managers,
1138
        "stat_ro" => $readOnly,
1139
        "stat_kb" => $SETTINGS['enable_kb'],
1140
        "stat_pf" => $SETTINGS['enable_pf_feature'],
1141
        "stat_fav" => $SETTINGS['enable_favourites'],
1142
        "stat_teampassversion" => $SETTINGS['cpassman_version'],
1143
        "stat_ldap" => $SETTINGS['ldap_mode'],
1144
        "stat_agses" => $SETTINGS['agses_authentication_enabled'],
1145
        "stat_duo" => $SETTINGS['duo'],
1146
        "stat_suggestion" => $SETTINGS['enable_suggestion'],
1147
        "stat_api" => $SETTINGS['api'],
1148
        "stat_customfields" => $SETTINGS['item_extra_fields'],
1149
        "stat_syslog" => $SETTINGS['syslog_enable'],
1150
        "stat_2fa" => $SETTINGS['google_authentication'],
1151
        "stat_stricthttps" => $SETTINGS['enable_sts'],
1152
        "stat_mysqlversion" => DB::serverVersion(),
1153
        "stat_languages" => $usedLang,
1154
        "stat_country" => $usedIp
1155
    );
1156
}
1157
1158
/**
1159
 * sendEmail()
1160
 *
1161
 * @return
1162
 */
1163
function sendEmail($subject, $textMail, $email, $textMailAlt = "")
1164
{
1165
    global $LANG;
1166
    global $SETTINGS;
1167
1168
    include $SETTINGS['cpassman_dir'].'/includes/config/settings.php';
1169
    //load library
1170
    $user_language = isset($_SESSION['user_language']) ? $_SESSION['user_language'] : "english";
1171
    require_once $SETTINGS['cpassman_dir'].'/includes/language/'.$user_language.'.php';
1172
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Email/Phpmailer/PHPMailerAutoload.php';
1173
1174
    // load PHPMailer
1175
    $mail = new PHPMailer();
1176
1177
    // send to user
1178
    $mail->setLanguage("en", "../includes/libraries/Email/Phpmailer/language/");
1179
    $mail->SMTPDebug = 0; //value 1 can be used to debug
1180
    $mail->Port = $SETTINGS['email_port']; //COULD BE USED
1181
    $mail->CharSet = "utf-8";
1182
    if ($SETTINGS['email_security'] === "tls" || $SETTINGS['email_security'] === "ssl") {
1183
        $mail->SMTPSecure = $SETTINGS['email_security'];
1184
    }
1185
    $mail->isSmtp(); // send via SMTP
1186
    $mail->Host = $SETTINGS['email_smtp_server']; // SMTP servers
1187
    $mail->SMTPAuth = $SETTINGS['email_smtp_auth'] == '1' ? true : false; // turn on SMTP authentication
1188
    $mail->Username = $SETTINGS['email_auth_username']; // SMTP username
1189
    $mail->Password = $SETTINGS['email_auth_pwd']; // SMTP password
1190
    $mail->From = $SETTINGS['email_from'];
1191
    $mail->FromName = $SETTINGS['email_from_name'];
1192
    $mail->addAddress($email); //Destinataire
1193
    $mail->WordWrap = 80; // set word wrap
1194
    $mail->isHtml(true); // send as HTML
1195
    $mail->Subject = $subject;
1196
    $mail->Body = $textMail;
1197
    $mail->AltBody = $textMailAlt;
1198
    // send email
1199
    if (!$mail->send()) {
1200
        return '"error":"error_mail_not_send" , "message":"'.str_replace(array("\n", "\t", "\r"), '', $mail->ErrorInfo).'"';
1201
    } else {
1202
        return '"error":"" , "message":"'.$LANG['forgot_my_pw_email_sent'].'"';
1203
    }
1204
}
1205
1206
/**
1207
 * generateKey()
1208
 *
1209
 * @return
1210
 */
1211
function generateKey()
1212
{
1213
    return substr(md5(rand().rand()), 0, 15);
1214
}
1215
1216
/**
1217
 * dateToStamp()
1218
 *
1219
 * @return
1220
 */
1221
function dateToStamp($date)
1222
{
1223
    $date = date_parse_from_format($SETTINGS['date_format'], $date);
0 ignored issues
show
Bug introduced by
The variable $SETTINGS does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1224
    if ($date['warning_count'] == 0 && $date['error_count'] == 0) {
1225
        return mktime(23, 59, 59, $date['month'], $date['day'], $date['year']);
1226
    } else {
1227
        return false;
1228
    }
1229
}
1230
1231
function isDate($date)
1232
{
1233
    return (strtotime($date) !== false);
1234
}
1235
1236
/**
1237
 * isUTF8()
1238
 *
1239
 * @return integer is the string in UTF8 format.
1240
 */
1241
1242
function isUTF8($string)
1243
{
1244
    if (is_array($string) === true) {
1245
        $string = $string['string'];
1246
    }
1247
    return preg_match(
1248
        '%^(?:
1249
        [\x09\x0A\x0D\x20-\x7E] # ASCII
1250
        | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
1251
        | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
1252
        | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
1253
        | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
1254
        | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
1255
        | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
1256
        | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
1257
        )*$%xs',
1258
        $string
1259
    );
1260
}
1261
1262
/*
1263
* FUNCTION
1264
* permits to prepare data to be exchanged
1265
*/
1266
/**
1267
 * @param string $type
1268
 */
1269
function prepareExchangedData($data, $type)
1270
{
1271
    global $SETTINGS;
1272
1273
    //load ClassLoader
1274
    require_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php';
1275
    //Load AES
1276
    $aes = new SplClassLoader('Encryption\Crypt', '../includes/libraries');
1277
    $aes->register();
1278
1279
    if ($type == "encode") {
1280
        if (isset($SETTINGS['encryptClientServer'])
1281
            && $SETTINGS['encryptClientServer'] === "0"
1282
        ) {
1283
            return json_encode(
1284
                $data,
1285
                JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
1286
            );
1287
        } else {
1288
            return Encryption\Crypt\aesctr::encrypt(
1289
                json_encode(
1290
                    $data,
1291
                    JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
1292
                ),
1293
                $_SESSION['key'],
1294
                256
1295
            );
1296
        }
1297
    } elseif ($type == "decode") {
1298
        if (isset($SETTINGS['encryptClientServer'])
1299
            && $SETTINGS['encryptClientServer'] === "0"
1300
        ) {
1301
            return json_decode(
1302
                $data,
1303
                true
1304
            );
1305
        } else {
1306
            return json_decode(
1307
                Encryption\Crypt\aesctr::decrypt(
1308
                    $data,
1309
                    $_SESSION['key'],
1310
                    256
1311
                ),
1312
                true
1313
            );
1314
        }
1315
    }
1316
}
1317
1318
function make_thumb($src, $dest, $desired_width)
1319
{
1320
    /* read the source image */
1321
    $source_image = imagecreatefrompng($src);
1322
    $width = imagesx($source_image);
1323
    $height = imagesy($source_image);
1324
1325
    /* find the "desired height" of this thumbnail, relative to the desired width  */
1326
    $desired_height = floor($height * ($desired_width / $width));
1327
1328
    /* create a new, "virtual" image */
1329
    $virtual_image = imagecreatetruecolor($desired_width, $desired_height);
1330
1331
    /* copy source image at a resized size */
1332
    imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $desired_width, $desired_height, $width, $height);
1333
1334
    /* create the physical thumbnail image to its destination */
1335
    imagejpeg($virtual_image, $dest);
1336
}
1337
1338
/*
1339
** check table prefix in SQL query
1340
*/
1341
/**
1342
 * @param string $table
1343
 */
1344
function prefix_table($table)
1345
{
1346
    global $pre;
1347
    $safeTable = htmlspecialchars($pre.$table);
1348
    if (!empty($safeTable)) {
1349
        // sanitize string
1350
        return $safeTable;
1351
    } else {
1352
        // stop error no table
1353
        return "table_not_exists";
1354
    }
1355
}
1356
1357
/*
1358
 * Creates a KEY using PasswordLib
1359
 */
1360
function GenerateCryptKey($size = "", $secure = false, $numerals = false, $capitalize = false, $ambiguous = false, $symbols = false)
1361
{
1362
    // load library
1363
    $pwgen = new SplClassLoader('Encryption\PwGen', '../includes/libraries');
1364
    $pwgen->register();
1365
    $pwgen = new Encryption\PwGen\pwgen();
1366
1367
    // init
1368
    if (!empty($size)) {
1369
        $pwgen->setLength($size);
1370
    }
1371
    if (!empty($secure)) {
1372
        $pwgen->setSecure($secure);
1373
    }
1374
    if (!empty($numerals)) {
1375
        $pwgen->setNumerals($numerals);
1376
    }
1377
    if (!empty($capitalize)) {
1378
        $pwgen->setCapitalize($capitalize);
1379
    }
1380
    if (!empty($ambiguous)) {
1381
        $pwgen->setAmbiguous($ambiguous);
1382
    }
1383
    if (!empty($symbols)) {
1384
        $pwgen->setSymbols($symbols);
1385
    }
1386
1387
    // generate and send back
1388
    return $pwgen->generate();
1389
}
1390
1391
/*
1392
* Send sysLOG message
1393
* @param string $message
1394
* @param string $host
1395
*/
1396
function send_syslog($message, $host, $port, $component = "teampass")
1397
{
1398
    $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
1399
    $syslog_message = "<123>".date('M d H:i:s ').$component.": ".$message;
1400
    socket_sendto($sock, $syslog_message, strlen($syslog_message), 0, $host, $port);
1401
    socket_close($sock);
1402
}
1403
1404
1405
1406
/**
1407
 * logEvents()
1408
 *
1409
 * permits to log events into DB
1410
 * @param string $type
1411
 * @param string $label
1412
 * @param string $field_1
1413
 */
1414
function logEvents($type, $label, $who, $login = "", $field_1 = null)
1415
{
1416
    global $server, $user, $pass, $database, $port, $encoding;
1417
    global $SETTINGS;
1418
1419
    if (empty($who)) {
1420
        $who = get_client_ip_server();
1421
    }
1422
1423
    // include librairies & connect to DB
1424
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1425
    $pass = defuse_return_decrypted($pass);
1426
    DB::$host = $server;
1427
    DB::$user = $user;
1428
    DB::$password = $pass;
1429
    DB::$dbName = $database;
1430
    DB::$port = $port;
1431
    DB::$encoding = $encoding;
1432
    DB::$error_handler = true;
1433
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1434
    $link->set_charset($encoding);
1435
1436
    DB::insert(
1437
        prefix_table("log_system"),
1438
        array(
1439
            'type' => $type,
1440
            'date' => time(),
1441
            'label' => $label,
1442
            'qui' => $who,
1443
            'field_1' => $field_1 === null ? "" : $field_1
1444
        )
1445
    );
1446
    if (isset($SETTINGS['syslog_enable']) && $SETTINGS['syslog_enable'] == 1) {
1447
        if ($type == "user_mngt") {
1448
            send_syslog(
1449
                "The User ".$login." performed the action of ".$label." to the user ".$field_1." - ".$type,
1450
                $SETTINGS['syslog_host'],
1451
                $SETTINGS['syslog_port'],
1452
                "teampass"
1453
            );
1454
        } else {
1455
            send_syslog(
1456
                "The User ".$login." performed the action of ".$label." - ".$type,
1457
                $SETTINGS['syslog_host'],
1458
                $SETTINGS['syslog_port'],
1459
                "teampass"
1460
            );
1461
        }
1462
    }
1463
}
1464
1465
/**
1466
 * @param string $item
1467
 * @param string $action
1468
 */
1469
function logItems($ident, $item, $id_user, $action, $login = "", $raison = null, $raison_iv = null, $encryption_type = "")
1470
{
1471
    global $server, $user, $pass, $database, $port, $encoding;
1472
    global $SETTINGS;
1473
1474
    // include librairies & connect to DB
1475
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1476
    $pass = defuse_return_decrypted($pass);
1477
    DB::$host = $server;
1478
    DB::$user = $user;
1479
    DB::$password = $pass;
1480
    DB::$dbName = $database;
1481
    DB::$port = $port;
1482
    DB::$encoding = $encoding;
1483
    DB::$error_handler = true;
1484
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1485
    $link->set_charset($encoding);
1486
    DB::insert(
1487
        prefix_table("log_items"),
1488
        array(
1489
            'id_item' => $ident,
1490
            'date' => time(),
1491
            'id_user' => $id_user,
1492
            'action' => $action,
1493
            'raison' => $raison,
1494
            'raison_iv' => $raison_iv,
1495
            'encryption_type' => $encryption_type
1496
        )
1497
    );
1498
    if (isset($SETTINGS['syslog_enable']) && $SETTINGS['syslog_enable'] == 1) {
1499
        send_syslog(
1500
            "The Item ".$item." was ".$action." by ".$login." ".$raison,
1501
            $SETTINGS['syslog_host'],
1502
            $SETTINGS['syslog_port'],
1503
            "teampass"
1504
        );
1505
    }
1506
}
1507
1508
/*
1509
* Function to get the client ip address
1510
 */
1511
function get_client_ip_server()
1512
{
1513
    if (getenv('HTTP_CLIENT_IP')) {
1514
            $ipaddress = getenv('HTTP_CLIENT_IP');
1515
    } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
1516
            $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
1517
    } elseif (getenv('HTTP_X_FORWARDED')) {
1518
            $ipaddress = getenv('HTTP_X_FORWARDED');
1519
    } elseif (getenv('HTTP_FORWARDED_FOR')) {
1520
            $ipaddress = getenv('HTTP_FORWARDED_FOR');
1521
    } elseif (getenv('HTTP_FORWARDED')) {
1522
            $ipaddress = getenv('HTTP_FORWARDED');
1523
    } elseif (getenv('REMOTE_ADDR')) {
1524
            $ipaddress = getenv('REMOTE_ADDR');
1525
    } else {
1526
            $ipaddress = 'UNKNOWN';
1527
    }
1528
1529
    return $ipaddress;
1530
}
1531
1532
/**
1533
 * Escape all HTML, JavaScript, and CSS
1534
 *
1535
 * @param string $input The input string
1536
 * @param string $encoding Which character encoding are we using?
1537
 * @return string
1538
 */
1539
function noHTML($input, $encoding = 'UTF-8')
1540
{
1541
    return htmlspecialchars($input, ENT_QUOTES | ENT_XHTML, $encoding, false);
1542
}
1543
1544
/**
1545
 * handleConfigFile()
1546
 *
1547
 * permits to handle the Teampass config file
1548
 * $action accepts "rebuild" and "update"
1549
 */
1550
function handleConfigFile($action, $field = null, $value = null)
1551
{
1552
    global $server, $user, $pass, $database, $port, $encoding;
1553
    global $SETTINGS;
1554
1555
    $tp_config_file = "../includes/config/tp.config.php";
1556
1557
    // Load AntiXSS
1558
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
1559
    $antiXss = new protect\AntiXSS\AntiXSS();
1560
1561
    // include librairies & connect to DB
1562
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1563
    $pass = defuse_return_decrypted($pass);
1564
    DB::$host = $server;
1565
    DB::$user = $user;
1566
    DB::$password = $pass;
1567
    DB::$dbName = $database;
1568
    DB::$port = $port;
1569
    DB::$encoding = $encoding;
1570
    DB::$error_handler = true;
1571
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1572
    $link->set_charset($encoding);
1573
1574
    if (!file_exists($tp_config_file) || $action == "rebuild") {
1575
        // perform a copy
1576
        if (file_exists($tp_config_file)) {
1577
            if (!copy($tp_config_file, $tp_config_file.'.'.date("Y_m_d_His", time()))) {
1578
                return "ERROR: Could not copy file '".$tp_config_file."'";
1579
            }
1580
        }
1581
1582
        // regenerate
1583
        $data = array();
1584
        $data[0] = "<?php\n";
1585
        $data[1] = "global \$SETTINGS;\n";
1586
        $data[2] = "\$SETTINGS = array (\n";
1587
        $rows = DB::query(
1588
            "SELECT * FROM ".prefix_table("misc")." WHERE type=%s",
1589
            "admin"
1590
        );
1591
        foreach ($rows as $record) {
1592
            array_push($data, "    '".$record['intitule']."' => '".$record['valeur']."',\n");
1593
        }
1594
        array_push($data, ");");
1595
        $data = array_unique($data);
1596
    } elseif ($action == "update" && !empty($field)) {
1597
        $data = file($tp_config_file);
1598
        $inc = 0;
1599
        $bFound = false;
1600
        foreach ($data as $line) {
1601
            if (stristr($line, ");")) {
1602
                break;
1603
            }
1604
1605
            //
1606
            if (stristr($line, "'".$field."' => '")) {
1607
                $data[$inc] = "    '".$field."' => '".$antiXss->xss_clean($value)."',\n";
1608
                $bFound = true;
1609
                break;
1610
            }
1611
            $inc++;
1612
        }
1613
        if ($bFound === false) {
1614
            $data[($inc - 1)] = "    '".$field."' => '".$antiXss->xss_clean($value)."',\n";
1615
        }
1616
    }
1617
1618
    // update file
1619
    file_put_contents($tp_config_file, implode('', isset($data) ? $data : array()));
1620
1621
    return true;
1622
}
1623
1624
/*
1625
** Permits to replace &#92; to permit correct display
1626
*/
1627
/**
1628
 * @param string $input
1629
 */
1630
function handleBackslash($input)
1631
{
1632
    return str_replace("&amp;#92;", "&#92;", $input);
1633
}
1634
1635
/*
1636
** Permits to loas settings
1637
*/
1638
function loadSettings()
1639
{
1640
    global $SETTINGS;
1641
1642
    /* LOAD CPASSMAN SETTINGS */
1643
    if (!isset($SETTINGS['loaded']) || $SETTINGS['loaded'] != 1) {
1644
        $SETTINGS['duplicate_folder'] = 0; //by default, this is set to 0;
1645
        $SETTINGS['duplicate_item'] = 0; //by default, this is set to 0;
1646
        $SETTINGS['number_of_used_pw'] = 5; //by default, this value is set to 5;
1647
        $settings = array();
1648
1649
        $rows = DB::query(
1650
            "SELECT * FROM ".prefix_table("misc")." WHERE type=%s_type OR type=%s_type2",
1651
            array(
1652
                'type' => "admin",
1653
                'type2' => "settings"
1654
            )
1655
        );
1656
        foreach ($rows as $record) {
1657
            if ($record['type'] == 'admin') {
1658
                $SETTINGS[$record['intitule']] = $record['valeur'];
1659
            } else {
1660
                $settings[$record['intitule']] = $record['valeur'];
1661
            }
1662
        }
1663
        $SETTINGS['loaded'] = 1;
1664
        $SETTINGS['default_session_expiration_time'] = 5;
1665
    }
1666
}
1667
1668
/*
1669
** check if folder has custom fields.
1670
** Ensure that target one also has same custom fields
1671
*/
1672
function checkCFconsistency($source_id, $target_id)
1673
{
1674
    $source_cf = array();
1675
    $rows = DB::QUERY(
1676
        "SELECT id_category
1677
        FROM ".prefix_table("categories_folders")."
1678
        WHERE id_folder = %i",
1679
        $source_id
1680
    );
1681
    foreach ($rows as $record) {
1682
        array_push($source_cf, $record['id_category']);
1683
    }
1684
1685
    $target_cf = array();
1686
    $rows = DB::QUERY(
1687
        "SELECT id_category
1688
        FROM ".prefix_table("categories_folders")."
1689
        WHERE id_folder = %i",
1690
        $target_id
1691
    );
1692
    foreach ($rows as $record) {
1693
        array_push($target_cf, $record['id_category']);
1694
    }
1695
1696
    $cf_diff = array_diff($source_cf, $target_cf);
1697
    if (count($cf_diff) > 0) {
1698
        return false;
1699
    }
1700
1701
    return true;
1702
}
1703
1704
/*
1705
*
1706
*/
1707
function encrypt_or_decrypt_file($filename_to_rework, $filename_status)
1708
{
1709
    global $server, $user, $pass, $database, $port, $encoding;
1710
    global $SETTINGS;
1711
1712
    // Include librairies & connect to DB
1713
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1714
    $pass = defuse_return_decrypted($pass);
1715
    DB::$host = $server;
1716
    DB::$user = $user;
1717
    DB::$password = $pass;
1718
    DB::$dbName = $database;
1719
    DB::$port = $port;
1720
    DB::$encoding = $encoding;
1721
    DB::$error_handler = true;
1722
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1723
    $link->set_charset($encoding);
1724
1725
    // Get file info in DB
1726
    $fileInfo = DB::queryfirstrow(
1727
        "SELECT id FROM ".prefix_table("files")." WHERE file = %s",
1728
        filter_var($filename_to_rework, FILTER_SANITIZE_STRING)
1729
    );
1730
    if (empty($fileInfo['id']) === false) {
1731
        // Load PhpEncryption library
1732
        $path_to_encryption = '/includes/libraries/Encryption/Encryption/';
1733
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Crypto.php';
1734
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Encoding.php';
1735
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'DerivedKeys.php';
1736
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Key.php';
1737
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyOrPassword.php';
1738
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'File.php';
1739
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'RuntimeTests.php';
1740
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyProtectedByPassword.php';
1741
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Core.php';
1742
1743
        // Get KEY
1744
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1745
1746
        if (isset($SETTINGS['enable_attachment_encryption'])
1747
            && $SETTINGS['enable_attachment_encryption'] === "1" &&
1748
            isset($filename_status)
1749
            && ($filename_status === "clear"
1750
                || $filename_status === "0")
1751
        ) {
1752
            // File needs to be encrypted
1753 View Code Duplication
            if (file_exists($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework)) {
1754
                // Make a copy of file
1755
                if (!copy(
1756
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1757
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1758
                )) {
1759
                    exit;
1760
                } else {
1761
                    // Do a bck
1762
                    copy(
1763
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1764
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1765
                    );
1766
                }
1767
1768
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework);
1769
1770
                // Now encrypt the file with saltkey
1771
                $err = '';
1772
                try {
1773
                    \Defuse\Crypto\File::encryptFile(
1774
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1775
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1776
                        \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1777
                    );
1778
                } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1779
                    $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.";
1780
                } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1781
                    $err = $ex;
1782
                } catch (Defuse\Crypto\Exception\IOException $ex) {
1783
                    $err = $ex;
1784
                }
1785
                if (empty($err) === false) {
1786
                    echo $err;
1787
                }
1788
1789
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1790
1791
                // update table
1792
                DB::update(
1793
                    prefix_table('files'),
1794
                    array(
1795
                        'status' => 'encrypted'
1796
                        ),
1797
                    "id = %i",
1798
                    $fileInfo['id']
1799
                );
1800
            }
1801
        } elseif (isset($SETTINGS['enable_attachment_encryption'])
1802
            && $SETTINGS['enable_attachment_encryption'] === "0"
1803
            && isset($filename_status)
1804
            && $filename_status === "encrypted"
1805
        ) {
1806
            // file needs to be decrypted
1807 View Code Duplication
            if (file_exists($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework)) {
1808
                // make a copy of file
1809
                if (!copy(
1810
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1811
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1812
                )) {
1813
                    exit;
1814
                } else {
1815
                    // do a bck
1816
                    copy(
1817
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1818
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1819
                    );
1820
                }
1821
1822
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework);
1823
1824
                // Now encrypt the file with saltkey
1825
                $err = '';
1826
                try {
1827
                    \Defuse\Crypto\File::decryptFile(
1828
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1829
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1830
                        \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1831
                    );
1832
                } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1833
                    $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.";
1834
                } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1835
                    $err = $ex;
1836
                } catch (Defuse\Crypto\Exception\IOException $ex) {
1837
                    $err = $ex;
1838
                }
1839
                if (empty($err) === false) {
1840
                    echo $err;
1841
                }
1842
1843
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1844
1845
                // update table
1846
                DB::update(
1847
                    prefix_table('files'),
1848
                    array(
1849
                        'status' => 'clear'
1850
                        ),
1851
                    "id = %i",
1852
                    $fileInfo['id']
1853
                );
1854
            }
1855
        }
1856
    }
1857
1858
    // Exit
1859
    return false;
1860
}
1861
1862
/**
1863
 * Will encrypte/decrypt a fil eusing Defuse
1864
 * @param  string $type        can be either encrypt or decrypt
1865
 * @param  string $source_file path to source file
1866
 * @param  string $target_file path to target file
1867
 * @return string              'true' is success or error message
1868
 */
1869
function prepareFileWithDefuse($type, $source_file, $target_file, $password = '')
1870
{
1871
    global $SETTINGS;
1872
1873
    // Load AntiXSS
1874
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
1875
    $antiXss = new protect\AntiXSS\AntiXSS();
1876
1877
    // Protect against bad inputs
1878
    if (is_array($source_file) ||is_array($target_file)) {
1879
        return 'error_cannot_be_array';
1880
    }
1881
1882
    // Sanitize
1883
    $source_file = $antiXss->xss_clean($source_file);
1884
    $target_file = $antiXss->xss_clean($target_file);
1885
1886
    // load PhpEncryption library
1887
    $path_to_encryption = '/includes/libraries/Encryption/Encryption/';
1888
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Crypto.php';
1889
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Encoding.php';
1890
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'DerivedKeys.php';
1891
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Key.php';
1892
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyOrPassword.php';
1893
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'File.php';
1894
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'RuntimeTests.php';
1895
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyProtectedByPassword.php';
1896
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Core.php';
1897
1898
    if (empty($password) === true) {
1899
    /*
1900
    File encryption/decryption is done with the SALTKEY
1901
     */
1902
1903
        // get KEY
1904
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1905
1906
        // Now perform action on the file
1907
        $err = '';
1908 View Code Duplication
        if ($type === 'decrypt') {
1909
            try {
1910
                \Defuse\Crypto\File::decryptFile(
1911
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1883 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...
1912
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1884 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...
1913
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1914
                );
1915
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1916
                $err = "decryption_not_possible";
1917
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1918
                $err = $ex;
1919
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1920
                $err = $ex;
1921
            }
1922
        } elseif ($type === 'encrypt') {
1923
            try {
1924
                \Defuse\Crypto\File::encryptFile(
1925
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1883 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...
1926
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1884 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...
1927
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1928
                );
1929
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1930
                $err = "encryption_not_possible";
1931
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1932
                $err = $ex;
1933
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1934
                $err = $ex;
1935
            }
1936
        }
1937
    } else {
1938
    /*
1939
    File encryption/decryption is done with special password and not the SALTKEY
1940
     */
1941
1942
        $err = '';
1943 View Code Duplication
        if ($type === 'decrypt') {
1944
            try {
1945
                \Defuse\Crypto\File::decryptFileWithPassword(
1946
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1883 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...
1947
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1884 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...
1948
                    $password
1949
                );
1950
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1951
                $err = "wrong_key";
1952
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1953
                $err = $ex;
1954
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1955
                $err = $ex;
1956
            }
1957
        } elseif ($type === 'encrypt') {
1958
            try {
1959
                \Defuse\Crypto\File::encryptFileWithPassword(
1960
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1883 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...
1961
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1884 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...
1962
                    $password
1963
                );
1964
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1965
                $err = "wrong_key";
1966
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1967
                $err = $ex;
1968
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1969
                $err = $ex;
1970
            }
1971
        }
1972
    }
1973
1974
    // return error
1975
    if (empty($err) === false) {
1976
        return $err;
1977
    } else {
1978
        return true;
1979
    }
1980
}
1981
1982
/*
1983
* NOT TO BE USED
1984
*/
1985
function debugTeampass($text)
1986
{
1987
    $debugFile = fopen('D:/wamp64/www/TeamPass/debug.txt', 'r+');
1988
    fputs($debugFile, $text);
1989
    fclose($debugFile);
1990
}
1991
1992
1993
/**
1994
 * DELETE the file with expected command depending on server type
1995
 * @param  string $file Path to file
1996
 * @return              Nothing
1997
 */
1998
function fileDelete($file)
1999
{
2000
    global $SETTINGS;
2001
2002
    // Load AntiXSS
2003
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
2004
    $antiXss = new protect\AntiXSS\AntiXSS();
2005
2006
    $file = $antiXss->xss_clean($file);
2007
    if (is_file($file)) {
2008
        unlink($file);
2009
    }
2010
}
2011
2012
/*
2013
* Permits to extract the file extension
2014
*/
2015
function getFileExtension($file)
2016
{
2017
    if (strpos($file, '.') === false) {
2018
        return $file;
2019
    }
2020
2021
    return substr($file, strrpos($file, '.') + 1);
2022
}
2023
2024
/**
2025
 * array_map
2026
 * @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...
2027
 * @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...
2028
 * @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...
2029
 */
2030
function array_map_r($func, $arr)
2031
{
2032
    $newArr = array();
2033
2034
    foreach ($arr as $key => $value) {
2035
        $newArr[ $key ] = (is_array($value) ? array_map_r($func, $value) : ( is_array($func) ? call_user_func_array($func, $value) : $func( $value )));
2036
    }
2037
2038
    return $newArr;
2039
}
2040
2041
/**
2042
 * Permits to clean and sanitize text to be displayed
2043
 * @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...
2044
 * @param  string $type what clean to perform
2045
 * @return string       text cleaned up
2046
 */
2047
function cleanText($string, $type = "")
2048
{
2049
    global $SETTINGS;
2050
2051
    // Load AntiXSS
2052
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
2053
    $antiXss = new protect\AntiXSS\AntiXSS();
2054
2055
    if ($type === "css") {
2056
        // Escape text and quotes in UTF8 format
2057
        return htmlentities($string, ENT_QUOTES | ENT_HTML5, 'UTF-8');
2058
    } elseif ($type === "html" || empty($type)) {
2059
        // Html cleaner
2060
        return $antiXss->xss_clean($string);
2061
    }
2062
}
2063
2064
/**
2065
 * Performs chmod operation on subfolders
2066
 * @param  string  $dir             Parent folder
2067
 * @param  integer $dirPermissions  New permission on folders
2068
 * @param  integer $filePermissions New permission on files
2069
 * @return boolean                  Success/Failure
2070
 */
2071
function chmodRecursive($dir, $dirPermissions, $filePermissions)
2072
{
2073
    $pointer_dir = opendir($dir);
2074
    $res = true;
2075
    while ($file = readdir($pointer_dir)) {
2076
        if (($file == ".") || ($file == "..")) {
2077
            continue;
2078
        }
2079
2080
        $fullPath = $dir."/".$file;
2081
2082
        if (is_dir($fullPath)) {
2083
            if ($res = @chmod($fullPath, $dirPermissions)) {
2084
                $res = @chmodRecursive($fullPath, $dirPermissions, $filePermissions);
2085
            }
2086
        } else {
2087
            $res = chmod($fullPath, $filePermissions);
2088
        }
2089
        if (!$res) {
2090
            closedir($pointer_dir);
2091
            return false;
2092
        }
2093
    }
2094
    closedir($pointer_dir);
2095
    if (is_dir($dir) && $res) {
2096
            $res = @chmod($dir, $dirPermissions);
2097
    }
2098
2099
    return $res;
2100
}
2101