Passed
Push — devel-3.0 ( 2581df...bf8280 )
by Rubén
03:03
created

Util::logout()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * sysPass
4
 *
5
 * @author    nuxsmin
6
 * @link      https://syspass.org
7
 * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
8
 *
9
 * This file is part of sysPass.
10
 *
11
 * sysPass is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation, either version 3 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * sysPass is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 *  along with sysPass.  If not, see <http://www.gnu.org/licenses/>.
23
 */
24
25
namespace SP\Util;
26
27
use Defuse\Crypto\Core;
28
use Defuse\Crypto\Encoding;
29
30
defined('APP_ROOT') || die();
31
32
/**
33
 * Clase con utilizades para la aplicación
34
 */
35
final class Util
36
{
37
    /**
38
     * Generar una clave aleatoria
39
     *
40
     * @param int  $length     Longitud de la clave
41
     * @param bool $useNumbers Usar números
42
     * @param bool $useSpecial Usar carácteres especiales
43
     * @param bool $checKStrength
44
     *
45
     * @return string
46
     */
47
    public static function randomPassword($length = 16, $useNumbers = true, $useSpecial = true, $checKStrength = true)
48
    {
49
        $charsLower = 'abcdefghijklmnopqrstuwxyz';
50
        $charsUpper = 'ABCDEFGHIJKLMNOPQRSTUWXYZ';
51
52
        $alphabet = $charsLower . $charsUpper;
53
54
        if ($useSpecial === true) {
55
            $charsSpecial = '@$%&/()!_:.;{}^';
56
            $alphabet .= $charsSpecial;
57
        }
58
59
        if ($useNumbers === true) {
60
            $charsNumbers = '0123456789';
61
            $alphabet .= $charsNumbers;
62
        }
63
64
        /**
65
         * @return array
66
         */
67
        $passGen = function () use ($alphabet, $length) {
68
            $pass = [];
69
            $alphaLength = strlen($alphabet) - 1; //put the length -1 in cache
70
71
            for ($i = 0; $i < $length; $i++) {
72
                $n = mt_rand(0, $alphaLength);
73
                $pass[] = $alphabet[$n];
74
            }
75
76
            return $pass;
77
        };
78
79
        if ($checKStrength === true) {
80
            do {
81
                $pass = $passGen();
82
                $strength = ['lower' => 0, 'upper' => 0, 'special' => 0, 'number' => 0];
83
84
                foreach ($pass as $char) {
85
                    if (strpos($charsLower, $char) !== false) {
86
                        $strength['lower']++;
87
                    } elseif (strpos($charsUpper, $char) !== false) {
88
                        $strength['upper']++;
89
                    } elseif ($useSpecial === true && strpos($charsSpecial, $char) !== false) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $charsSpecial does not seem to be defined for all execution paths leading up to this point.
Loading history...
90
                        $strength['special']++;
91
                    } elseif ($useNumbers === true && strpos($charsNumbers, $char) !== false) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $charsNumbers does not seem to be defined for all execution paths leading up to this point.
Loading history...
92
                        $strength['number']++;
93
                    }
94
                }
95
96
                if ($useSpecial === false) {
97
                    unset($strength['special']);
98
                }
99
100
                if ($useNumbers === false) {
101
                    unset($strength['number']);
102
                }
103
            } while (in_array(0, $strength, true));
104
105
            return implode($pass);
106
        }
107
108
        return implode($passGen());
109
    }
110
111
    /**
112
     * Generar una cadena aleatoria usuando criptografía.
113
     *
114
     * @param int $length opcional, con la longitud de la cadena
115
     *
116
     * @return string
117
     * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException
118
     */
119
    public static function generateRandomBytes($length = 30)
120
    {
121
        return Encoding::binToHex(Core::secureRandom($length));
122
    }
123
124
    /**
125
     * Comprueba y devuelve un directorio temporal válido
126
     *
127
     * @return bool|string
128
     */
129
    public static function getTempDir()
130
    {
131
        $sysTmp = sys_get_temp_dir();
132
        $appTmp = APP_PATH . DIRECTORY_SEPARATOR . 'temp';
133
        $file = 'syspass.test';
134
135
        $checkDir = function ($dir) use ($file) {
136
            if (file_exists($dir . DIRECTORY_SEPARATOR . $file)) {
137
                return $dir;
138
            }
139
140
            if (is_dir($dir) || @mkdir($dir)) {
141
                if (touch($dir . DIRECTORY_SEPARATOR . $file)) {
142
                    return $dir;
143
                }
144
            }
145
146
            return false;
147
        };
148
149
        if ($checkDir($appTmp)) {
150
            return $appTmp;
151
        }
152
153
        return $checkDir($sysTmp);
154
    }
155
156
    /**
157
     * Realiza el proceso de logout.
158
     *
159
     * FIXME
160
     */
161
    public static function logout()
162
    {
163
        exit('<script>sysPassApp.actions.main.logout();</script>');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
164
    }
165
166
    /**
167
     * Obtener el tamaño máximo de subida de PHP.
168
     */
169
    public static function getMaxUpload()
170
    {
171
        $max_upload = (int)ini_get('upload_max_filesize');
172
        $max_post = (int)ini_get('post_max_size');
173
        $memory_limit = (int)ini_get('memory_limit');
174
175
        return min($max_upload, $max_post, $memory_limit);
176
    }
177
178
    /**
179
     * Checks a variable to see if it should be considered a boolean true or false.
180
     * Also takes into account some text-based representations of true of false,
181
     * such as 'false','N','yes','on','off', etc.
182
     *
183
     * @author Samuel Levy <[email protected]>
184
     *
185
     * @param mixed $in     The variable to check
186
     * @param bool  $strict If set to false, consider everything that is not false to
187
     *                      be true.
188
     *
189
     * @return bool The boolean equivalent or null (if strict, and no exact equivalent)
190
     */
191
    public static function boolval($in, $strict = false)
192
    {
193
        $in = is_string($in) ? strtolower($in) : $in;
194
195
        // if not strict, we only have to check if something is false
196
        if (in_array($in, ['false', 'no', 'n', '0', 'off', false, 0], true) || !$in) {
197
            return false;
198
        }
199
200
        if ($strict && in_array($in, ['true', 'yes', 'y', '1', 'on', true, 1], true)) {
201
            return true;
202
        }
203
204
        // not strict? let the regular php bool check figure it out (will
205
        // largely default to true)
206
        return ($in ? true : false);
207
    }
208
209
    /**
210
     * Cast an object to another class, keeping the properties, but changing the methods
211
     *
212
     * @param string        $dstClass Class name
213
     * @param string|object $serialized
214
     * @param string        $srcClass Nombre de la clase serializada
215
     *
216
     * @return mixed
217
     * @link http://blog.jasny.net/articles/a-dark-corner-of-php-class-casting/
218
     */
219
    public static function unserialize($dstClass, $serialized, $srcClass = null)
220
    {
221
        if (!is_object($serialized)) {
222
            preg_match('/^O:\d+:"(?P<class>[^"]++)"/', $serialized, $matches);
223
224
            if (class_exists($matches['class'])
225
                && $matches['class'] === $dstClass
226
            ) {
227
                return unserialize($serialized);
228
            }
229
230
            // Si se indica la clase origen, se elimina el nombre
231
            // de la clase en los métodos privados
232
            if ($srcClass !== null) {
233
                $serializedOut = preg_replace_callback(
234
                    '/:\d+:"\x00' . preg_quote($srcClass, '/') . '\x00(\w+)"/',
235
                    function ($matches) {
236
                        return ':' . strlen($matches[1]) . ':"' . $matches[1] . '"';
237
                    },
238
                    $serialized);
239
240
                return self::castToClass($serializedOut, $dstClass);
241
            }
242
243
            if ($matches['class'] !== $dstClass) {
244
                return self::castToClass($serialized, $dstClass);
245
            }
246
        }
247
248
        return $serialized;
249
    }
250
251
    /**
252
     * Cast an object to another class
253
     *
254
     * @param $object
255
     * @param $class
256
     *
257
     * @return mixed
258
     */
259
    public static function castToClass($object, $class)
260
    {
261
        // should avoid '__PHP_Incomplete_Class'?
262
263
        if (is_object($object)) {
264
            return unserialize(preg_replace('/^O:\d+:"[^"]++"/', 'O:' . strlen($class) . ':"' . $class . '"', serialize($object)));
265
        }
266
267
        return unserialize(preg_replace('/^O:\d+:"[^"]++"/', 'O:' . strlen($class) . ':"' . $class . '"', $object));
268
    }
269
270
    /**
271
     * Bloquear la aplicación
272
     *
273
     * @param int    $userId
274
     * @param string $subject
275
     *
276
     * @return bool
277
     */
278
    public static function lockApp($userId, $subject)
279
    {
280
        $data = ['time' => time(), 'userId' => (int)$userId, 'subject' => $subject];
281
282
        return file_put_contents(LOCK_FILE, json_encode($data));
0 ignored issues
show
Bug Best Practice introduced by
The expression return file_put_contents...LE, json_encode($data)) returns the type integer which is incompatible with the documented return type boolean.
Loading history...
283
    }
284
285
    /**
286
     * Desbloquear la aplicación
287
     *
288
     * @return bool
289
     */
290
    public static function unlockApp()
291
    {
292
        return @unlink(LOCK_FILE);
293
    }
294
295
    /**
296
     * Comprueba si la aplicación está bloqueada
297
     *
298
     * @return int
299
     */
300
    public static function getAppLock()
301
    {
302
        if (file_exists(LOCK_FILE)
303
            && ($data = file_get_contents(LOCK_FILE)) !== false
304
        ) {
305
            return json_decode($data) ?: false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return json_decode($data) ?: false could also return false which is incompatible with the documented return type integer. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
306
        }
307
308
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
309
    }
310
311
    /**
312
     * Devolver el tiempo aproximado en segundos de una operación
313
     *
314
     * @param $startTime
315
     * @param $numItems
316
     * @param $totalItems
317
     *
318
     * @return array Con el tiempo estimado y los elementos por segundo
319
     */
320
    public static function getETA($startTime, $numItems, $totalItems)
321
    {
322
        if ($numItems > 0 && $totalItems > 0) {
323
            $runtime = time() - $startTime;
324
            $eta = (int)((($totalItems * $runtime) / $numItems) - $runtime);
325
326
            return [$eta, $numItems / $runtime];
327
        }
328
329
        return [0, 0];
330
    }
331
}
332