Completed
Push — development ( 43c9d8...ce3960 )
by Nils
03:26
created

main.functions.php ➔ bCrypt()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 2
nop 2
dl 0
loc 13
rs 9.4285
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 $n
49
 */
50
function getBits($n)
51
{
52
    $str = '';
53
    $x = $n + 10;
54
    for ($i = 0; $i < $x; $i++) {
55
        $str .= base_convert(mt_rand(1, 36), 10, 36);
56
    }
57
    return substr($str, 0, $n);
58
}
59
60
//generate pbkdf2 compliant hash
61 View Code Duplication
function strHashPbkdf2($p, $s, $c, $kl, $a = 'sha256', $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
    $kb = $st + $kl; // Key blocks to compute
64
    $dk = ''; // Derived key
65
66
    for ($block = 1; $block <= $kb; $block++) { // Create key
67
        $ib = $h = hash_hmac($a, $s.pack('N', $block), $p, true); // Initial hash for this block
68
        for ($i = 1; $i < $c; $i++) { // Perform block iterations
69
            $ib ^= ($h = hash_hmac($a, $h, $p, true)); // XOR each iterate
70
        }
71
        $dk .= $ib; // Append iterated block
72
    }
73
    return substr($dk, $st, $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 View Code Duplication
function encryptOld($text, $personalSalt = "")
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...
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 View Code Duplication
function decryptOld($text, $personalSalt = "")
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...
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
    } else {
149
        return trim(
150
            mcrypt_decrypt(
151
                MCRYPT_RIJNDAEL_256,
152
                SALT,
153
                base64_decode($text),
154
                MCRYPT_MODE_ECB,
155
                mcrypt_create_iv(
156
                    mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
157
                    MCRYPT_RAND
158
                )
159
            )
160
        );
161
    }
162
}
163
164
/**
165
 * encrypt()
166
 *
167
 * crypt a string
168
 * @param string $decrypted
169
 */
170
function encrypt($decrypted, $personalSalt = "")
171
{
172
    global $SETTINGS;
173
174 View Code Duplication
    if (!isset($SETTINGS['cpassman_dir']) || empty($SETTINGS['cpassman_dir'])) {
175
        require_once '../includes/libraries/Encryption/PBKDF2/PasswordHash.php';
176
    } else {
177
        require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/PBKDF2/PasswordHash.php';
178
    }
179
180
    if (!empty($personalSalt)) {
181
            $staticSalt = $personalSalt;
182
    } else {
183
            $staticSalt = SALT;
184
    }
185
186
    //set our salt to a variable
187
    // Get 64 random bits for the salt for pbkdf2
188
    $pbkdf2Salt = getBits(64);
189
    // generate a pbkdf2 key to use for the encryption.
190
    $key = substr(pbkdf2('sha256', $staticSalt, $pbkdf2Salt, ITCOUNT, 16 + 32, true), 32, 16);
191
    // Build $iv and $ivBase64.  We use a block size of 256 bits (AES compliant)
192
    // and CTR mode.  (Note: ECB mode is inadequate as IV is not used.)
193
    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, 'ctr'), MCRYPT_RAND);
194
195
    //base64 trim
196
    if (strlen($ivBase64 = rtrim(base64_encode($iv), '=')) != 43) {
197
        return false;
198
    }
199
    // Encrypt $decrypted
200
    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $decrypted, 'ctr', $iv);
201
    // MAC the encrypted text
202
    $mac = hash_hmac('sha256', $encrypted, $staticSalt);
203
    // We're done!
204
    return base64_encode($ivBase64.$encrypted.$mac.$pbkdf2Salt);
205
}
206
207
/**
208
 * decrypt()
209
 *
210
 * decrypt a crypted string
211
 */
212
function decrypt($encrypted, $personalSalt = "")
213
{
214
    global $SETTINGS;
215
216 View Code Duplication
    if (!isset($SETTINGS['cpassman_dir']) || empty($SETTINGS['cpassman_dir'])) {
217
        require_once '../includes/libraries/Encryption/PBKDF2/PasswordHash.php';
218
    } else {
219
        require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/PBKDF2/PasswordHash.php';
220
    }
221
222
    if (!empty($personalSalt)) {
223
        $staticSalt = $personalSalt;
224
    } else {
225
        $staticSalt = SALT;
226
    }
227
    //base64 decode the entire payload
228
    $encrypted = base64_decode($encrypted);
229
    // get the salt
230
    $pbkdf2Salt = substr($encrypted, -64);
231
    //remove the salt from the string
232
    $encrypted = substr($encrypted, 0, -64);
233
    $key = substr(pbkdf2('sha256', $staticSalt, $pbkdf2Salt, ITCOUNT, 16 + 32, true), 32, 16);
234
    // Retrieve $iv which is the first 22 characters plus ==, base64_decoded.
235
    $iv = base64_decode(substr($encrypted, 0, 43).'==');
236
    // Remove $iv from $encrypted.
237
    $encrypted = substr($encrypted, 43);
238
    // Retrieve $mac which is the last 64 characters of $encrypted.
239
    $mac = substr($encrypted, -64);
240
    // Remove the last 64 chars from encrypted (remove MAC)
241
    $encrypted = substr($encrypted, 0, -64);
242
    //verify the sha256hmac from the encrypted data before even trying to decrypt it
243
    if (hash_hmac('sha256', $encrypted, $staticSalt) != $mac) {
244
        return false;
245
    }
246
    // Decrypt the data.
247
    $decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, 'ctr', $iv), "\0\4");
248
    // Yay!
249
    return $decrypted;
250
}
251
252
253
/**
254
 * genHash()
255
 *
256
 * Generate a hash for user login
257
 * @param string $password
258
 */
259
function bCrypt($password, $cost)
260
{
261
    $salt = sprintf('$2y$%02d$', $cost);
262
    if (function_exists('openssl_random_pseudo_bytes')) {
263
        $salt .= bin2hex(openssl_random_pseudo_bytes(11));
264
    } else {
265
        $chars = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
266
        for ($i = 0; $i < 22; $i++) {
267
            $salt .= $chars[mt_rand(0, 63)];
268
        }
269
    }
270
    return crypt($password, $salt);
271
}
272
273
function cryption_before_defuse($message, $sk, $iv, $type = null, $scope = "public")
274
{
275
    if (DEFUSE_ENCRYPTION === true) {
276
        if ($scope === "perso") {
277
            return defuse_crypto(
278
                $message,
279
                $sk,
280
                $type
281
            );
282
        } else {
283
            return defuse_crypto(
284
                $message,
285
                file_get_contents(SECUREPATH."/teampass-seckey.txt"),
286
                $type
287
            );
288
        }
289
    } else {
290
        return cryption_phpCrypt($message, $sk, $iv, $type);
291
    }
292
}
293
294
/*
295
 * cryption() - Encrypt and decrypt string based upon phpCrypt library
296
 *
297
 * Using AES_128 and mode CBC
298
 *
299
 * $key and $iv have to be given in hex format
300
 */
301
function cryption_phpCrypt($string, $key, $iv, $type)
302
{
303
    // manage key origin
304
    define('SALT', 'LEfzTjADMTzV6qHC');
305
306
    if ($key != SALT) {
307
        // check key (AES-128 requires a 16 bytes length key)
308
        if (strlen($key) < 16) {
309
            for ($x = strlen($key) + 1; $x <= 16; $x++) {
310
                $key .= chr(0);
311
            }
312
        } elseif (strlen($key) > 16) {
313
            $key = substr($key, 16);
314
        }
315
    }
316
317
    // load crypt
318
    $crypt = new PHP_Crypt($key, PHP_Crypt::CIPHER_AES_128, PHP_Crypt::MODE_CBC);
319
320
    if ($type == "encrypt") {
321
        // generate IV and encrypt
322
        $iv = $crypt->createIV();
323
        $encrypt = $crypt->encrypt($string);
324
        // return
325
        return array(
326
            "string" => bin2hex($encrypt),
327
            "iv" => bin2hex($iv),
328
            "error" => empty($encrypt) ? "ERR_ENCRYPTION_NOT_CORRECT" : ""
329
        );
330
    } elseif ($type == "decrypt") {
331
        // case if IV is empty
332
        if (empty($iv)) {
333
                    return array(
334
                'string' => "",
335
                'error' => "ERR_ENCRYPTION_NOT_CORRECT"
336
            );
337
        }
338
339
        // convert
340
        try {
341
            $string = testHex2Bin(trim($string));
342
            $iv = testHex2Bin($iv);
343
        } catch (Exception $e) {
344
            return array(
345
                'string' => "",
346
                'error' => "ERR_ENCRYPTION_NOT_CORRECT"
347
            );
348
        }
349
350
        // load IV
351
        $crypt->IV($iv);
352
        // decrypt
353
        $decrypt = $crypt->decrypt($string);
354
        // return
355
        return array(
356
            'string' => str_replace(chr(0), "", $decrypt),
357
            'error' => ""
358
        );
359
    }
360
}
361
362
function testHex2Bin($val)
363
{
364
    if (!@hex2bin($val)) {
365
        throw new Exception("ERROR");
366
    }
367
    return hex2bin($val);
368
}
369
370
/**
371
 * @param string $ascii_key
372
 * @param string $type
373
 */
374
function cryption($message, $ascii_key, $type) //defuse_crypto
375
{
376
    global $SETTINGS;
377
378
    // load PhpEncryption library
379 View Code Duplication
    if (!isset($SETTINGS['cpassman_dir']) || empty($SETTINGS['cpassman_dir'])) {
380
        $path = '../includes/libraries/Encryption/Encryption/';
381
    } else {
382
        $path = $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/Encryption/';
383
    }
384
385
    require_once $path.'Crypto.php';
386
    require_once $path.'Encoding.php';
387
    require_once $path.'DerivedKeys.php';
388
    require_once $path.'Key.php';
389
    require_once $path.'KeyOrPassword.php';
390
    require_once $path.'File.php';
391
    require_once $path.'RuntimeTests.php';
392
    require_once $path.'KeyProtectedByPassword.php';
393
    require_once $path.'Core.php';
394
395
    // init
396
    $err = '';
397
    if (empty($ascii_key)) {
398
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
399
    }
400
401
    // convert KEY
402
    $key = \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key);
403
404
    try {
405
        if ($type === "encrypt") {
406
            $text = \Defuse\Crypto\Crypto::encrypt($message, $key);
407
        } elseif ($type === "decrypt") {
408
            $text = \Defuse\Crypto\Crypto::decrypt($message, $key);
409
        }
410
    } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...fiedCiphertextException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
411
        $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.";
412
    } catch (Defuse\Crypto\Exception\BadFormatException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\BadFormatException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
413
        $err = $ex;
414
    } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...onmentIsBrokenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
415
        $err = $ex;
416
    } catch (Defuse\Crypto\Exception\CryptoException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\CryptoException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
417
        $err = $ex;
418
    } catch (Defuse\Crypto\Exception\IOException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\IOException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
419
        $err = $ex;
420
    }
421
422
    return array(
423
        'string' => isset($text) ? $text : "",
424
        'error' => $err
425
    );
426
}
427
428
function defuse_generate_key()
429
{
430
    require_once '../includes/libraries/Encryption/Encryption/Crypto.php';
431
    require_once '../includes/libraries/Encryption/Encryption/Encoding.php';
432
    require_once '../includes/libraries/Encryption/Encryption/DerivedKeys.php';
433
    require_once '../includes/libraries/Encryption/Encryption/Key.php';
434
    require_once '../includes/libraries/Encryption/Encryption/KeyOrPassword.php';
435
    require_once '../includes/libraries/Encryption/Encryption/File.php';
436
    require_once '../includes/libraries/Encryption/Encryption/RuntimeTests.php';
437
    require_once '../includes/libraries/Encryption/Encryption/KeyProtectedByPassword.php';
438
    require_once '../includes/libraries/Encryption/Encryption/Core.php';
439
440
    $key = \Defuse\Crypto\Key::createNewRandomKey();
441
    $key = $key->saveToAsciiSafeString();
442
    return $key;
443
}
444
445
function defuse_generate_personal_key($psk)
446
{
447
    require_once '../includes/libraries/Encryption/Encryption/Crypto.php';
448
    require_once '../includes/libraries/Encryption/Encryption/Encoding.php';
449
    require_once '../includes/libraries/Encryption/Encryption/DerivedKeys.php';
450
    require_once '../includes/libraries/Encryption/Encryption/Key.php';
451
    require_once '../includes/libraries/Encryption/Encryption/KeyOrPassword.php';
452
    require_once '../includes/libraries/Encryption/Encryption/File.php';
453
    require_once '../includes/libraries/Encryption/Encryption/RuntimeTests.php';
454
    require_once '../includes/libraries/Encryption/Encryption/KeyProtectedByPassword.php';
455
    require_once '../includes/libraries/Encryption/Encryption/Core.php';
456
457
    $protected_key = \Defuse\Crypto\KeyProtectedByPassword::createRandomPasswordProtectedKey($psk);
458
    $protected_key_encoded = $protected_key->saveToAsciiSafeString();
459
460
    return $protected_key_encoded; // save this in user table
461
}
462
463
/**
464
 * @param string $psk
465
 */
466
function defuse_validate_personal_key($psk, $protected_key_encoded)
467
{
468
    require_once '../includes/libraries/Encryption/Encryption/Crypto.php';
469
    require_once '../includes/libraries/Encryption/Encryption/Encoding.php';
470
    require_once '../includes/libraries/Encryption/Encryption/DerivedKeys.php';
471
    require_once '../includes/libraries/Encryption/Encryption/Key.php';
472
    require_once '../includes/libraries/Encryption/Encryption/KeyOrPassword.php';
473
    require_once '../includes/libraries/Encryption/Encryption/File.php';
474
    require_once '../includes/libraries/Encryption/Encryption/RuntimeTests.php';
475
    require_once '../includes/libraries/Encryption/Encryption/KeyProtectedByPassword.php';
476
    require_once '../includes/libraries/Encryption/Encryption/Core.php';
477
478
    try {
479
        $protected_key = \Defuse\Crypto\KeyProtectedByPassword::loadFromAsciiSafeString($protected_key_encoded);
480
        $user_key = $protected_key->unlockKey($psk);
481
        $user_key_encoded = $user_key->saveToAsciiSafeString();
482
    } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...onmentIsBrokenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
483
        return "Error - Major issue as the encryption is broken.";
484
    } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...fiedCiphertextException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

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

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1761
                    $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.";
1762
                } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...onmentIsBrokenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1763
                    $err = $ex;
1764
                } catch (Defuse\Crypto\Exception\IOException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\IOException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1765
                    $err = $ex;
1766
                }
1767
                if (empty($err) === false) {
1768
                    echo $err;
1769
                }
1770
1771
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1772
1773
                // update table
1774
                DB::update(
1775
                    prefix_table('files'),
1776
                    array(
1777
                        'status' => 'encrypted'
1778
                        ),
1779
                    "id = %i",
1780
                    $fileInfo['id']
1781
                );
1782
            }
1783
        } elseif (isset($SETTINGS['enable_attachment_encryption']) && $SETTINGS['enable_attachment_encryption'] === "0" && isset($filename_status) && $filename_status === "encrypted") {
1784
            // file needs to be decrypted
1785 View Code Duplication
            if (file_exists($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework)) {
1786
                // make a copy of file
1787
                if (!copy(
1788
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1789
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1790
                )) {
1791
                    exit;
1792
                } else {
1793
                    // do a bck
1794
                    copy(
1795
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1796
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1797
                    );
1798
                }
1799
1800
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework);
1801
1802
                // Now encrypt the file with saltkey
1803
                $err = '';
1804
                try {
1805
                    \Defuse\Crypto\File::decryptFile(
1806
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1807
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1808
                        \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1809
                    );
1810
                } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...fiedCiphertextException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1811
                    $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.";
1812
                } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...onmentIsBrokenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1813
                    $err = $ex;
1814
                } catch (Defuse\Crypto\Exception\IOException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\IOException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1815
                    $err = $ex;
1816
                }
1817
                if (empty($err) === false) {
1818
                    echo $err;
1819
                }
1820
1821
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1822
1823
                // update table
1824
                DB::update(
1825
                    prefix_table('files'),
1826
                    array(
1827
                        'status' => 'clear'
1828
                        ),
1829
                    "id = %i",
1830
                    $fileInfo['id']
1831
                );
1832
            }
1833
        }
1834
    }
1835
1836
    // Exit
1837
    return false;
1838
}
1839
1840
/**
1841
 * Will encrypte/decrypt a fil eusing Defuse
1842
 * @param  string $type        can be either encrypt or decrypt
1843
 * @param  string $source_file path to source file
1844
 * @param  string $target_file path to target file
1845
 * @return string              'true' is success or error message
1846
 */
1847
function prepareFileWithDefuse($type, $source_file, $target_file, $password = '')
1848
{
1849
    global $SETTINGS;
1850
1851
    // Load AntiXSS
1852
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXss.php';
1853
    $antiXss = new protect\AntiXSS\AntiXSS();
1854
1855
    // Protect against bad inputs
1856
    if (is_array($source_file) ||is_array($target_file)) {
1857
        return 'error_cannot_be_array';
1858
    }
1859
1860
    // Sanitize
1861
    $source_file = $antiXss->xss_clean($source_file);
1862
    $target_file = $antiXss->xss_clean($target_file);
1863
1864
    // load PhpEncryption library
1865
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Crypto.php';
1866
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Encoding.php';
1867
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'DerivedKeys.php';
1868
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Key.php';
1869
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'KeyOrPassword.php';
1870
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'File.php';
1871
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'RuntimeTests.php';
1872
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'KeyProtectedByPassword.php';
1873
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Core.php';
1874
1875
    if (empty($password) === true) {
1876
    /*
1877
    File encryption/decryption is done with the SALTKEY
1878
     */
1879
1880
        // get KEY
1881
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1882
1883
        // Now perform action on the file
1884
        $err = '';
1885 View Code Duplication
        if ($type === 'decrypt') {
1886
            try {
1887
                \Defuse\Crypto\File::decryptFile(
1888
                    $source_file,
1889
                    $target_file,
1890
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1891
                );
1892
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...fiedCiphertextException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1893
                $err = "decryption_not_possible";
1894
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...onmentIsBrokenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1895
                $err = $ex;
1896
            } catch (Defuse\Crypto\Exception\IOException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\IOException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1897
                $err = $ex;
1898
            }
1899
        } elseif ($type === 'encrypt') {
1900
            try {
1901
                \Defuse\Crypto\File::encryptFile(
1902
                    $source_file,
1903
                    $target_file,
1904
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1905
                );
1906
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...fiedCiphertextException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1907
                $err = "encryption_not_possible";
1908
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...onmentIsBrokenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1909
                $err = $ex;
1910
            } catch (Defuse\Crypto\Exception\IOException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\IOException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1911
                $err = $ex;
1912
            }
1913
        }
1914
    } else {
1915
    /*
1916
    File encryption/decryption is done with special password and not the SALTKEY
1917
     */
1918
1919
        $err = '';
1920 View Code Duplication
        if ($type === 'decrypt') {
1921
            try {
1922
                \Defuse\Crypto\File::decryptFileWithPassword(
1923
                    $source_file,
1924
                    $target_file,
1925
                    $password
1926
                );
1927
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...fiedCiphertextException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1928
                $err = "wrong_key";
1929
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...onmentIsBrokenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1930
                $err = $ex;
1931
            } catch (Defuse\Crypto\Exception\IOException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\IOException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1932
                $err = $ex;
1933
            }
1934
        } elseif ($type === 'encrypt') {
1935
            try {
1936
                \Defuse\Crypto\File::encryptFileWithPassword(
1937
                    $source_file,
1938
                    $target_file,
1939
                    $password
1940
                );
1941
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...fiedCiphertextException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1942
                $err = "wrong_key";
1943
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\...onmentIsBrokenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1944
                $err = $ex;
1945
            } catch (Defuse\Crypto\Exception\IOException $ex) {
0 ignored issues
show
Bug introduced by
The class Defuse\Crypto\Exception\IOException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
1946
                $err = $ex;
1947
            }
1948
        }
1949
    }
1950
1951
    // return error
1952
    if (empty($err) === false) {
1953
        return $err;
1954
    } else {
1955
        return true;
1956
    }
1957
}
1958
1959
/*
1960
* NOT TO BE USED
1961
*/
1962
function debugTeampass($text)
1963
{
1964
    $debugFile = fopen('D:/wamp64/www/TeamPass/debug.txt', 'r+');
1965
    fputs($debugFile, $text);
1966
    fclose($debugFile);
1967
}
1968
1969
1970
/**
1971
 * DELETE the file with expected command depending on server type
1972
 * @param  string $file Path to file
1973
 * @return              Nothing
1974
 */
1975
function fileDelete($file)
1976
{
1977
    global $SETTINGS;
1978
1979
    // Load AntiXSS
1980
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXss.php';
1981
    $antiXss = new protect\AntiXSS\AntiXSS();
1982
1983
    $file = $antiXss->xss_clean($file);
1984
    if (is_file($file)) {
1985
        unlink($file);
1986
    }
1987
}
1988
1989
/*
1990
* Permits to extract the file extension
1991
*/
1992
function getFileExtension($f)
1993
{
1994
    if (strpos($f, '.') === false) {
1995
        return $f;
1996
    }
1997
1998
    return substr($f, strrpos($f, '.') + 1);
1999
}
2000
2001
/**
2002
 * array_map
2003
 * @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...
2004
 * @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...
2005
 * @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...
2006
 */
2007
function array_map_r($func, $arr)
2008
{
2009
    $newArr = array();
2010
2011
    foreach ($arr as $key => $value) {
2012
        $newArr[ $key ] = (is_array($value) ? array_map_r($func, $value) : ( is_array($func) ? call_user_func_array($func, $value) : $func( $value )));
2013
    }
2014
2015
    return $newArr;
2016
}
2017
2018
/**
2019
 * Permits to clean and sanitize text to be displayed
2020
 * @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...
2021
 * @param  string $type what clean to perform
2022
 * @return string       text cleaned up
2023
 */
2024
function cleanText($string, $type = "")
2025
{
2026
    global $SETTINGS;
2027
2028
    // Load AntiXSS
2029
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXss.php';
2030
    $antiXss = new protect\AntiXSS\AntiXSS();
2031
2032
    if ($type === "css") {
2033
        // Escape text and quotes in UTF8 format
2034
        return htmlentities($string, ENT_QUOTES | ENT_HTML5, 'UTF-8');
2035
    } elseif ($type === "html" || empty($type)) {
2036
        // Html cleaner
2037
        return $antiXss->xss_clean($string);
2038
    }
2039
}
2040