Completed
Push — master ( b2b287...c5c110 )
by Lorenzo
02:00
created

helpers.php ➔ gzCompressFile()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 22
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 18
nc 6
nop 2
dl 0
loc 22
rs 8.6737
c 0
b 0
f 0
1
<?php
2
3
if (!function_exists('rgb2hex')) {
4
5
    /**
6
     * @param int $red
7
     * @param int $green
8
     * @param int $blue
9
     * @return string
10
     * @see https://gist.github.com/Pushplaybang/5432844
11
     */
12
    function rgb2hex(int $red, int $green, int $blue):  string
13
    {
14
        $hex = "#";
15
        $hex .= str_pad(dechex($red), 2, "0", STR_PAD_LEFT);
16
        $hex .= str_pad(dechex($green), 2, "0", STR_PAD_LEFT);
17
        $hex .= str_pad(dechex($blue), 2, "0", STR_PAD_LEFT);
18
19
        return $hex; // returns the hex value including the number sign (#)
20
    }
21
}
22
23
if (!function_exists('hex2rgb')) {
24
25
    /**
26
     * Takes HEX color code value and converts to a RGB value.
27
     *
28
     * @param string $color Color hex value, example: #000000, #000 or 000000, 000
29
     *
30
     * @return string color rbd value
31
     */
32
    function hex2rgb($color)
33
    {
34
        $color = str_replace('#', '', $color);
35
        if (strlen($color) == 3):
36
            list($r, $g, $b) = [$color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2]];
37
        else:
38
            list($r, $g, $b) = [$color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5]];
39
        endif;
40
        $r = hexdec($r);
41
        $g = hexdec($g);
42
        $b = hexdec($b);
43
        return 'rgb(' . $r . ', ' . $g . ', ' . $b . ')';
44
    }
45
}
46
47
/**
48
 * @param float $val
49
 * @param int $precision
50
 * @param string $simbol
51
 * @param bool $prepend if true (default) prefix with $simbol, otherwise suffix with $simbol.
52
 * @return string
53
 */
54
function format_money(float $val = 0.00, int $precision = 2, string $simbol = "", bool $prepend=true) : string
55
{
56
    $prefix = $simbol.' ';
57
    $suffix = '';
58
    if(!$prepend){
59
        $prefix = '';
60
        $suffix = ' '.$simbol;
61
    }
62
    return $prefix . number_format($val, $precision, ',', '.').$suffix;
63
}
64
65
/**
66
 * Format float 1125.86 into string '&euro 1.125,86'
67
 * @param float $val
68
 * @param bool $prepend if true (default) prefix with '&euro; ', otherwise suffix with ' &euro;'.
69
 * @return string
70
 */
71
function format_euro(float $val = 0.00, bool $prepend=true) : string
72
{
73
    return format_money($val, 2, '&euro; ', $prepend);
74
}
75
76
if (!function_exists('ordinal')) {
77
78
    /**
79
     * Given a number, return the number + 'th' or 'rd' etc
80
     * @param $cdnl
81
     * @return string
82
     */
83
    function ordinal($cdnl)
84
    {
85
        $test_c = abs($cdnl) % 10;
86
        $ext = ((abs($cdnl) % 100 < 21 && abs($cdnl) % 100 > 4) ? 'th'
87
            : (($test_c < 4) ? ($test_c < 3) ? ($test_c < 2) ? ($test_c < 1)
88
                ? 'th' : 'st' : 'nd' : 'rd' : 'th'));
89
        return $cdnl . $ext;
90
    }
91
}
92
93
if (!function_exists('value')) {
94
    /**
95
     * Return the default value of the given value.
96
     *
97
     * @param  mixed $value
98
     * @return mixed
99
     */
100
    function value($value)
101
    {
102
        return $value instanceof Closure ? $value() : $value;
103
    }
104
}
105
if (!function_exists('with')) {
106
    /**
107
     * Return the given object. Useful for chaining.
108
     *
109
     * @param  mixed $object
110
     * @return mixed
111
     */
112
    function with($object)
113
    {
114
        return $object;
115
    }
116
}
117
118
/**
119
 * Set the default configuration of erro reporting for production.
120
 */
121
function setErrorReportingForProduction()
122
{
123
    if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
124
        error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT);
125
    } elseif (version_compare(PHP_VERSION, '5.3.0') >= 0) {
126
        error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED);
127
    } else {
128
        error_reporting(E_ALL ^ E_NOTICE);
129
    }
130
}
131
132
/**
133
 * Check if PHP script was executed by shell.
134
 * @return bool
135
 */
136
function isExecutedByCLI() : bool
137
{
138
    return php_sapi_name() == 'cli';
139
}
140
141
/**
142
 * Convert the output of PHP's filesize() function
143
 * to a nice format with PB, TB, GB, MB, kB, bytes.
144
 * @param $bytes
145
 * @param int $decimals [optional] default 0. Sets the number of decimal points.
146
 * @return string
147
 */
148
function bytes2HumanSize($bytes, $decimals=0)
149
{
150
    if(!isIntegerPositiveOrZero($decimals)){
151
        $decimals = 0;
152
    }
153
154
    if ($bytes >= 1125899906842624) {
155
        $bytes = number_format($bytes / 1073741824, $decimals) . ' PB';
156
    } elseif ($bytes >= 1099511627776) {
157
        $bytes = number_format($bytes / 1073741824, $decimals) . ' TB';
158
    } elseif ($bytes >= 1073741824) {
159
        $bytes = number_format($bytes / 1073741824, $decimals) . ' GB';
160
    } elseif ($bytes >= 1048576) {
161
        $bytes = number_format($bytes / 1048576, $decimals) . ' MB';
162
    } elseif ($bytes >= 1024) {
163
        $bytes = number_format($bytes / 1024, $decimals) . ' kB';
164
    } elseif ($bytes > 1) {
165
        $bytes .= ' bytes';
166
    } elseif ($bytes == 1) {
167
        $bytes .= ' byte';
168
    } else {
169
        $bytes = '0 bytes';
170
    }
171
172
    return $bytes;
173
}
174
175
/**
176
 * This function transforms the php.ini notation for numbers (like '2M')
177
 * to an integer (2*1024*1024 in this case)
178
 * @param string $sSize
179
 * @return int|string
180
 */
181
function convertPHPSizeToBytes($sSize)
182
{
183
    if (is_numeric($sSize)) {
184
        return $sSize;
185
    }
186
    $sSuffix = substr($sSize, -1);
187
    $iValue = substr($sSize, 0, -1);
188
189
    switch (strtoupper($sSuffix)) {
190
        case 'P':
191
            $iValue *= 1024;
192
        //PB multiplier
193
        case 'T':
194
            $iValue *= 1024;
195
        //TB multiplier
196
        case 'G':
197
            $iValue *= 1024;
198
        //GB multiplier
199
        case 'M':
200
            $iValue *= 1024;
201
        //MB multiplier
202
        case 'K':
203
            $iValue *= 1024;
204
            //KB multiplier
205
            break;
206
    }
207
    return $iValue;
208
}
209
210
/**
211
 * Return the Max upload size in bytes.
212
 * @param bool $humanFormat if set to true return size in human format (MB, kB, etc..) otherwise return in bytes.
213
 * @return int
214
 */
215
function getMaximumFileUploadSize(bool $humanFormat = false)
216
{
217
    $size = min(convertPHPSizeToBytes(ini_get('post_max_size')), convertPHPSizeToBytes(ini_get('upload_max_filesize')));
218
219
    if (!$humanFormat) {
220
        return $size;
221
    }
222
223
    return bytes2HumanSize($size);
224
}
225
226
/**
227
 * Encrypt string in asymmetrical way.
228
 * @param string $string to encrypt.
229
 * @param string $chiave the key to encrypt. if empty generate a random key on the fly.
230
 * @return string
231
 */
232
function encryptString(string $string, string $chiave = '')
233
{
234
    if ($chiave == '') {
235
        $chiave = str_random(64);
236
    }
237
238
    $key = pack('H*', $chiave);
239
240
    $plaintext = $string;
241
242
    # create a random IV to use with CBC encoding
243
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
244
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
245
246
    # creates a cipher text compatible with AES (Rijndael block size = 128)
247
    # to keep the text confidential
248
    # only suitable for encoded input that never ends with value 00h
249
    # (because of default zero padding)
250
    $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $iv);
251
252
    # prepend the IV for it to be available for decryption
253
    $ciphertext = $iv . $ciphertext;
254
255
    # encode the resulting cipher text so it can be represented by a string
256
    $ciphertext_base64 = base64_encode($ciphertext);
257
258
    return $ciphertext_base64;
259
}
260
261
/**
262
 * Get a Website favicon url.
263
 *
264
 * @param string $url website url
265
 *
266
 * @return string containing complete image tag
267
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
268
 */
269
function getFaviconUrl($url) : string
270
{
271
    $apiUrl = 'https://www.google.com/s2/favicons?domain=';
272
    if (strpos($url, 'http') !== false) {
273
        $url = str_replace('http://', '', $url);
274
    }
275
    return $apiUrl . $url;
276
}
277
278
/**
279
 * Get a Website favicon image tag.
280
 *
281
 * @param string $url website url
282
 * @param array $attributes Optional, additional key/value attributes to include in the IMG tag
283
 *
284
 * @return string containing complete image tag
285
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
286
 */
287
function getFaviconImgTag($url, array $attributes = []) : string
288
{
289
    $urlFav = getFaviconUrl($url);
290
    $attr = arrayToString($attributes);
291
    return '<img src="' . $urlFav . '" ' . trim($attr) . ' />';
292
}
293
294
/**
295
 * Check to see if the current page is being server over SSL or not.
296
 * Support HTTP_X_FORWARDED_PROTO to check ssl over proxy/load balancer.
297
 *
298
 * @return bool
299
 */
300
function isHttps()
301
{
302
    $key = 'HTTPS';
303
    if (isNotNullOrEmptyArrayKey($_SERVER, 'HTTP_X_FORWARDED_PROTO')) {
304
        $key = 'HTTP_X_FORWARDED_PROTO';
305
    }
306
    return isNotNullOrEmptyArrayKey($_SERVER, $key) && strtolower($_SERVER[$key]) !== 'off';
307
}
308
309
/**
310
 * Get a QR code.
311
 *
312
 * @param string $string String to generate QR code for.
313
 * @param int $width QR code width
314
 * @param int $height QR code height
315
 * @param array $attributes Optional, additional key/value attributes to include in the IMG tag
316
 *
317
 * @return string containing complete image tag
318
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
319
 */
320
function getQRcode($string, int $width = 150, int $height = 150, array $attributes = []) : string
321
{
322
    $attr = arrayToString($attributes);
323
    $apiUrl = getQRcodeUrl($string, $width, $height);
324
    return '<img src="' . $apiUrl . '" ' . trim($attr) . ' />';
325
}
326
327
/**
328
 * Get a QR code Url.
329
 *
330
 * @param string $string String to generate QR code for.
331
 * @param int $width QR code width
332
 * @param int $height QR code height
333
 *
334
 * @return string containing complete image url
335
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
336
 */
337
function getQRcodeUrl($string, int $width = 150, int $height = 150) : string
338
{
339
    $protocol = 'http://';
340
    if (isHttps()) {
341
        $protocol = 'https://';
342
    }
343
    return $protocol . 'chart.apis.google.com/chart?chs=' . $width . 'x' . $height . '&cht=qr&chl=' . urlencode($string);
344
}
345
346
if (!function_exists('gravatarUrl')) {
347
    /**
348
     * Get a Gravatar URL from email.
349
     *
350
     * @param string $email The email address
351
     * @param int $size in pixels, defaults to 80px [ 1 - 2048 ]
352
     * @param string $default imageset to use [ 404 | mm | identicon | monsterid | wavatar ]
353
     * @param string $rating (inclusive) [ g | pg | r | x ]
354
     * @return string
355
     * @source http://gravatar.com/site/implement/images/php/
356
     */
357
    function gravatarUrl($email, $size = 80, $default = 'mm', $rating = 'g')
358
    {
359
        $url = 'https://www.gravatar.com';
360
        $url .= '/avatar/' . md5(strtolower(trim($email))) . '?default=' . $default . '&size=' . $size . '&rating=' . $rating;
361
        return $url;
362
    }
363
}
364
365
if (!function_exists('gravatar')) {
366
    /**
367
     * Get a Gravatar img tag from email.
368
     *
369
     * @param string $email The email address
370
     * @param int $size in pixels, defaults to 80px [ 1 - 2048 ]
371
     * @param string $default imageset to use [ 404 | mm | identicon | monsterid | wavatar ]
372
     * @param string $rating (inclusive) [ g | pg | r | x ]
373
     * @param array $attributes Optional, additional key/value attributes to include in the IMG tag
374
     * @return string
375
     * @source http://gravatar.com/site/implement/images/php/
376
     */
377
    function gravatar($email, $size = 80, $default = 'mm', $rating = 'g', $attributes = [])
378
    {
379
        $attr = arrayToString($attributes);
380
        $url = gravatarUrl($email, $size, $default, $rating);
381
        return '<img src="' . $url . '" width="' . $size . 'px" height="' . $size . 'px" ' . trim($attr) . ' />';
382
    }
383
}
384
385
if (!function_exists('isAjax')) {
386
387
    /**
388
     * Determine if current page request type is ajax.
389
     *
390
     * @return bool
391
     */
392
    function isAjax()
393
    {
394
        return isNotNullOrEmptyArrayKey($_SERVER, 'HTTP_X_REQUESTED_WITH')
395
        && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
396
    }
397
}
398
399
if (!function_exists('isNumberOdd')) {
400
401
    /**
402
     * Check if number is odd.
403
     *
404
     * @param int $num integer to check
405
     *
406
     * @return bool
407
     * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
408
     */
409
    function isNumberOdd($num)
410
    {
411
        return $num % 2 !== 0;
412
    }
413
}
414
415
if (!function_exists('isNumberEven')) {
416
417
    /**
418
     * Check if number is even.
419
     *
420
     * @param int $num integer to check
421
     *
422
     * @return bool
423
     * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
424
     */
425
    function isNumberEven($num)
426
    {
427
        return $num % 2 == 0;
428
    }
429
}
430
431
if (!function_exists('getCurrentUrlPageName')) {
432
433
    /**
434
     * Returns The Current URL PHP File Name.
435
     * Ex.: http://www.dummy.com/one/two/index.php?one=1&two=2 return index.php
436
     *
437
     * @return string
438
     */
439
    function getCurrentUrlPageName() : string
440
    {
441
        return isNotNullOrEmptyArrayKey($_SERVER, 'PHP_SELF') ? basename($_SERVER['PHP_SELF']) : '';
442
    }
443
}
444
445
if (!function_exists('getCurrentUrlQuerystring')) {
446
447
    /**
448
     * Returns The Current URL querystring.
449
     * Ex.: http://www.dummy.com/one/two/index.php?one=1&two=2 return one=1&two=2
450
     *
451
     * @return string
452
     */
453
    function getCurrentUrlQuerystring() : string
454
    {
455
        return isNotNullOrEmptyArrayKey($_SERVER, 'QUERY_STRING') ? $_SERVER['QUERY_STRING'] : '';
456
    }
457
}
458
459
if (!function_exists('getCurrentUrlDirName')) {
460
461
    /**
462
     * Returns The Current URL Path Name.
463
     * Ex.: http://www.dummy.com/one/two/index.php?one=1&two=2 return /one/two
464
     *
465
     * @return string
466
     */
467
    function getCurrentUrlDirName() : string
468
    {
469
        if (isNotNullOrEmptyArrayKey($_SERVER, 'REQUEST_URI')) {
470
            return dirname($_SERVER['REQUEST_URI']);
471
        }
472
        return isNotNullOrEmptyArrayKey($_SERVER, 'PHP_SELF') ? dirname($_SERVER['PHP_SELF']) : '';
473
    }
474
}
475
476
if (!function_exists('getCurrentUrlDirAbsName')) {
477
478
    /**
479
     * Returns The Current URL Absolute Path Name.
480
     * Ex.: http://www.dummy.com/one/two/index.php?one=1&two=2 return /home/user/www/one/two
481
     *
482
     * @return string
483
     */
484
    function getCurrentUrlDirAbsName() : string
485
    {
486
        return isNotNullOrEmptyArrayKey($_SERVER, 'SCRIPT_FILENAME') ? dirname($_SERVER['SCRIPT_FILENAME']) : '';
487
    }
488
}
489
490
if (!function_exists('getCurrentURL')) {
491
492
    /**
493
     * Return the current URL.
494
     * Ex.: http://www.dummy.com/one/two/index.php?one=1&two=2
495
     * Or
496
     * Ex.: https://username:[email protected]:443/one/two/index.php?one=1&two=2
497
     * @return string
498
     * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
499
     */
500
    function getCurrentURL()
501
    {
502
        $url = 'http://';
503
        if (isHttps()) {
504
            $url = 'https://';
505
        }
506
        if (array_key_exists_safe($_SERVER, 'PHP_AUTH_USER')) {
507
            $url .= $_SERVER['PHP_AUTH_USER'];
508
            if (array_key_exists_safe($_SERVER, 'PHP_AUTH_PW')) {
509
                $url .= ':' . $_SERVER['PHP_AUTH_PW'];
510
            }
511
            $url .= '@';
512
        }
513
        if (array_key_exists_safe($_SERVER, 'HTTP_HOST')) {
514
            $url .= $_SERVER['HTTP_HOST'];
515
        }
516
        if (array_key_exists_safe($_SERVER, 'SERVER_PORT') && $_SERVER['SERVER_PORT'] != 80) {
517
            $url .= ':' . $_SERVER['SERVER_PORT'];
518
        }
519
        if (!array_key_exists_safe($_SERVER, 'REQUEST_URI')) {
520
            $url .= substr($_SERVER['PHP_SELF'], 1);
521
            if (array_key_exists_safe($_SERVER, 'QUERY_STRING')):
522
                $url .= '?' . $_SERVER['QUERY_STRING'];
523
            endif;
524
        } else {
525
            $url .= $_SERVER['REQUEST_URI'];
526
        }
527
        return $url;
528
    }
529
}
530
531
if (!function_exists('isMobile')) {
532
533
    /**
534
     * Detect if user is on mobile device.
535
     *
536
     * @return bool
537
     */
538
    function isMobile()
539
    {
540
        $useragent = $_SERVER['HTTP_USER_AGENT'];
541
        return preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i',
542
            $useragent)
543
        || preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i',
544
            substr($useragent, 0, 4));
545
    }
546
}
547
548
/**
549
 * Get user browser.
550
 *
551
 * @return string
552
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
553
 */
554
function getBrowser()
555
{
556
    $u_agent = $_SERVER['HTTP_USER_AGENT'];
557
    $browserName = $ub = $platform = 'Unknown';
558
    if (preg_match('/linux/i', $u_agent)) {
559
        $platform = 'Linux';
560
    } elseif (preg_match('/macintosh|mac os x/i', $u_agent)) {
561
        $platform = 'Mac OS';
562
    } elseif (preg_match('/windows|win32/i', $u_agent)) {
563
        $platform = 'Windows';
564
    }
565
    if (preg_match('/MSIE/i', $u_agent) && !preg_match('/Opera/i', $u_agent)) {
566
        $browserName = 'Internet Explorer';
567
        $ub = 'MSIE';
568
    } elseif (preg_match('/Firefox/i', $u_agent)) {
569
        $browserName = 'Mozilla Firefox';
570
        $ub = 'Firefox';
571
    } elseif (preg_match('/Chrome/i', $u_agent)) {
572
        $browserName = 'Google Chrome';
573
        $ub = 'Chrome';
574
    } elseif (preg_match('/Safari/i', $u_agent)) {
575
        $browserName = 'Apple Safari';
576
        $ub = 'Safari';
577
    } elseif (preg_match('/Opera/i', $u_agent)) {
578
        $browserName = 'Opera';
579
        $ub = 'Opera';
580
    } elseif (preg_match('/Netscape/i', $u_agent)) {
581
        $browserName = 'Netscape';
582
        $ub = 'Netscape';
583
    }
584
    $known = ['Version', $ub, 'other'];
585
    $pattern = '#(?<browser>' . implode('|', $known) . ')[/ ]+(?<version>[0-9.|a-zA-Z.]*)#';
586
    preg_match_all($pattern, $u_agent, $matches);
587
    $i = count($matches['browser']);
588
    if ($i != 1) {
589
        if (strripos($u_agent, 'Version') < strripos($u_agent, $ub)) {
590
            $version = $matches['version'][0];
591
        } else {
592
            $version = $matches['version'][1];
593
        }
594
    } else {
595
        $version = $matches['version'][0];
596
    }
597
    if ($version == null || $version == '') {
598
        $version = '?';
599
    }
600
    return implode(', ', [$browserName, 'Version: ' . $version, $platform]);
601
}
602
603
/**
604
 * Shorten URL via tinyurl.com service.
605
 * It support http or https.
606
 * @param string $url URL to shorten
607
 *
608
 * @return string shortend url or empty string if it fails.
609
 */
610
function getTinyUrl(string $url) : string
611
{
612
    if (!starts_with($url, 'http')) {
613
        $url = (isHttps() ? 'https://' : 'http://') . $url;
614
    }
615
    $gettiny = curl('http://tinyurl.com/api-create.php?url=' . $url);
616
    if (isNullOrEmpty($gettiny) && isNullOrEmptyArray($gettiny)) {
617
        return '';
618
    }
619
    if (isHttps()) {
620
        $gettiny = str_replace('http://', 'https://', $gettiny);
621
    }
622
    return $gettiny;
623
}
624
625
/**
626
 * Get information on a short URL. Find out where it goes.
627
 *
628
 * @param string $shortURL shortened URL
629
 *
630
 * @return string full url or empty string
631
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
632
 */
633
function expandShortUrl(string $shortURL) : string
634
{
635
    if (isNullOrEmpty($shortURL)) {
636
        return '';
637
    }
638
    $headers = get_headers($shortURL, 1);
639
    if (array_key_exists_safe($headers, 'Location')) {
640
        return $headers['Location'];
641
    }
642
    $data = curl($shortURL);
643
    preg_match_all('/<[\s]*meta[\s]*http-equiv="?' . '([^>"]*)"?[\s]*' . 'content="?([^>"]*)"?[\s]*[\/]?[\s]*>/si',
644
        $data, $match);
645
    if (isNullOrEmptyArray($match) || count($match) != 3
646
        || isNullOrEmptyArray($match[0]) || isNullOrEmptyArray($match[1]) || isNullOrEmptyArray($match[2])
647
        || count($match[0]) != count($match[1]) || count($match[1]) != count($match[2])
648
    ) {
649
        return '';
650
    }
651
    $originals = $match[0];
652
    $names = $match[1];
653
    $values = $match[2];
654
    $metaTags = [];
655
    for ($i = 0, $limit = count($names); $i < $limit; $i++) {
656
        $metaTags[$names[$i]] = ['html' => htmlentities($originals[$i]), 'value' => $values[$i]];
657
    }
658
    if (!isset($metaTags['refresh']['value']) || empty($metaTags['refresh']['value'])) {
659
        return '';
660
    }
661
    $returnData = explode('=', $metaTags['refresh']['value']);
662
    if (!isset($returnData[1]) || empty($returnData[1])) {
663
        return '';
664
    }
665
    return $returnData[1];
666
}
667
668
if (!function_exists('curl')) {
669
670
    /**
671
     * Make Curl call.
672
     *
673
     * @param string $url URL to curl
674
     * @param string $method GET or POST, Default GET
675
     * @param mixed $data Data to post, Default false
676
     * @param string[] $headers Additional headers, example: array ("Accept: application/json")
677
     * @param bool $returnInfo Whether or not to retrieve curl_getinfo()
678
     * @param string $user
679
     * @param string $password
680
     * @param bool $sslNotVerifyHostAndPeer is set to true do not check SSL certificate.
681
     * @param bool $followLocation
682
     * @param int $timeout
683
     * @param string $logPath if not empty write log to this file
684
     * @param string $referer
685
     * @param string $userAgent default 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0'
686
     * and ignore $returnInfo (i.e. call curl_getinfo even if $returnInfo is set to false).
687
     *
688
     * @return string|array if $returnInfo is set to True, array is returned with two keys, contents (will contain response) and info (information regarding a specific transfer), otherwise response content is returned
689
     * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
690
     */
691
    function curl(
692
        $url,
693
        $method = 'GET',
694
        $data = false,
695
        array $headers = [],
696
        bool $returnInfo = false,
697
        string $user = '',
698
        string $password = '',
699
        bool $sslNotVerifyHostAndPeer = false,
700
        bool $followLocation = false,
701
        int $timeout = 10,
702
        string $logPath = '',
703
        string $referer = '',
704
        string $userAgent = 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0'
705
    ) {
706
        $log = false;
707
        if (isNotNullOrEmpty($logPath)) {
708
            $log = true;
709
            $msg = "REQUEST_URI: " . (isNotNullOrEmptyArrayKey($_SERVER,
710
                    'REQUEST_URI') ? $_SERVER['REQUEST_URI'] : '') . "\r\n"
711
                . "SCRIPT_NAME: " . (isNotNullOrEmptyArrayKey($_SERVER,
712
                    'SCRIPT_NAME') ? $_SERVER['SCRIPT_NAME'] : '') . "\r\n"
713
                . "REMOTE ADDR: " . (isNotNullOrEmptyArrayKey($_SERVER,
714
                    'REMOTE_ADDR') ? $_SERVER['REMOTE_ADDR'] : '') . "\r\n"
715
                . "HTTP_HOST: " . (isNotNullOrEmptyArrayKey($_SERVER,
716
                    'HTTP_HOST') ? $_SERVER['HTTP_HOST'] : '') . "\r\n"
717
                . "SERVER_NAME: " . (isNotNullOrEmptyArrayKey($_SERVER,
718
                    'SERVER_NAME') ? $_SERVER['SERVER_NAME'] : '') . "\r\n"
719
                . "HTTP_X_FORWARDED_FOR: " . (isNotNullOrEmptyArrayKey($_SERVER,
720
                    'HTTP_X_FORWARDED_FOR') ? $_SERVER['HTTP_X_FORWARDED_FOR'] : '') . "\r\n"
721
                . "SERVER_ADDR: " . (isNotNullOrEmptyArrayKey($_SERVER,
722
                    'SERVER_ADDR') ? $_SERVER['SERVER_ADDR'] : '') . "\r\n"
723
                . "REMOTE_PORT: " . (isNotNullOrEmptyArrayKey($_SERVER,
724
                    'REMOTE_PORT') ? $_SERVER['REMOTE_PORT'] : '') . "\r\n"
725
                . "HTTPS: " . (isNotNullOrEmptyArrayKey($_SERVER, 'HTTPS') ? $_SERVER['HTTPS'] : '') . "\r\n"
726
                . "HTTP_X_FORWARDED_PROTO: " . (isNotNullOrEmptyArrayKey($_SERVER,
727
                    'HTTP_X_FORWARDED_PROTO') ? $_SERVER['HTTP_X_FORWARDED_PROTO'] : '') . "\r\n"
728
                . "data: " . get_var_dump_output($data) . "\r\n"
729
                . "headers: " . get_var_dump_output($headers) . "\r\n"
730
                . "returnInfo: " . $returnInfo . "\r\n"
731
                . "url: " . $url . "\r\n"
732
                . "method: " . $method . "\r\n"
733
                . "user: " . $user . "\r\n"
734
                . "password: " . (strlen($password) > 2 ? substr($password, 0, 2) . str_repeat('x',
735
                        10) . substr($password, -1) : 'xx') . "\r\n"
736
                . "sslNotVerifyHostAndPeer: " . $sslNotVerifyHostAndPeer . "\r\n"
737
                . "followLocation: " . $followLocation . "\r\n"
738
                . "timeout: " . $timeout . "\r\n"
739
                . "logPath: " . $logPath . "\r\n"
740
                . "referer: " . $referer . "\r\n"
741
                . "userAgent: " . $userAgent . "\r\n"
742
                . "\r\n";
743
            logToFile($logPath, $msg);
744
        }
745
        if (!function_exists('curl_init') || isNullOrEmpty($url)) {
746
            if ($log) {
747
                logToFile($logPath,
748
                    isNullOrEmpty($url) ? 'url is empty.curl abort.' : 'curl_init not exists.Probabily CURL is not installed.');
749
            }
750
            return '';
751
        }
752
        $ch = curl_init();
753
        $info = null;
754
        if (strtoupper($method) == 'POST') {
755
            curl_setopt($ch, CURLOPT_POST, true);
756
            if ($data !== false) {
757
                curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
758
            }
759
        } elseif ($data !== false) {
760
            if (is_array($data)) {
761
                $dataTokens = [];
762
                foreach ($data as $key => $value) {
763
                    $dataTokens[] = urlencode($key) . '=' . urlencode($value);
764
                }
765
                $data = implode('&', $dataTokens);
766
            }
767
            $url .= (strpos($url, '?') === false ? '&' : '?') . $data;
768
        }
769
        curl_setopt($ch, CURLOPT_URL, $url);
770
        curl_setopt($ch, CURLOPT_HEADER, false);
771
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
772
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $followLocation ? true : false);
773
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout <= 1 ? 10 : $timeout);
774
        if ($sslNotVerifyHostAndPeer && starts_with($url, 'https://')) {
775
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
776
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
777
        }
778
        if (isNotNullOrEmptyArray($headers)) {
779
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
780
        }
781
        if (isNotNullOrEmpty($user) && isNotNullOrEmpty($password)) {
782
            curl_setopt($ch, CURLOPT_USERPWD, $user . ':' . $password);
783
        }
784
        if (isNotNullOrEmpty($referer)) {
785
            curl_setopt($ch, CURLOPT_REFERER, $referer);
786
        }
787
        if (isNotNullOrEmpty($userAgent)) {
788
            curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
789
        }
790
791
        if ($log) {
792
            logToFile($logPath, date('Y-m-d H:i:s') . "Start curl\r\n");
793
        }
794
        $contents = curl_exec($ch);
795
        if ($log) {
796
            logToFile($logPath, date('Y-m-d H:i:s') . "FINISH curl\r\n");
797
        }
798
799
        if ($returnInfo || $log || $contents === false || curl_errno($ch) > 0) {
800
            $info = curl_getinfo($ch);
801
            if ($log) {
802
                logToFile($logPath, $info, true);
803
            }
804
        }
805
806
        if ($contents === false || curl_errno($ch) > 0
807
            || !array_key_exists_safe($info === null ? [] : $info, 'http_code') || $info['http_code'] != 200
808
        ) {
809
            if ($log) {
810
                logToFile($logPath, "Error during exec CURL \r\n curl_error: " . curl_error($ch)
811
                    . "\r\n curl_errno: " . curl_errno($ch) . "\r\n");
812
            }
813
        } elseif ($log) {
814
            logToFile($logPath, "CURL IS OK\r\n RESPONSE: \r\n" . $contents);
815
        }
816
817
        curl_close($ch);
818
        return ($returnInfo ? ['contents' => $contents, 'info' => $info] : $contents);
819
    }
820
}
821
822
823
if (!function_exists('curl_internal_server_behind_load_balancer')) {
824
825
    /**
826
     * Make Curl call to one of the server behinds load balancer.
827
     *
828
     * @param string $url URL to curl
829
     * @param string $server_name The host name of the domain from the call will start.
830
     * if empty try to resolve from SERVER_NAME
831
     * @param string $localServerIpAddress the IP of one server to call that behinds load balancer.
832
     * if empty try to resolve from SERVER_ADDR
833
     * @param string $method GET or POST, Default GET
834
     * @param mixed $data Data to post, Default false
835
     * @param array $headers Additional headers, example: array ("Accept: application/json")
836
     * @param bool $returnInfo Whether or not to retrieve curl_getinfo()
837
     * @param string $user
838
     * @param string $password
839
     * @param bool $sslNotVerifyHostAndPeer is set to true do not check SSL certificate.
840
     * @param bool $followLocation
841
     * @param int $timeout
842
     * @param string $logPath if not empty write log to this file
843
     * @param string $referer
844
     * @param string $userAgent default 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0'
845
     * and ignore $returnInfo (i.e. call curl_getinfo even if $returnInfo is set to false).
846
     *
847
     * @return string|array if $returnInfo is set to True, array is returned with two keys, contents (will contain response) and info (information regarding a specific transfer), otherwise response content is returned
848
     */
849
    function curl_internal_server_behind_load_balancer(
850
        $url,
851
        $server_name = '',
852
        $localServerIpAddress = '',
853
        $method = 'GET',
854
        $data = false,
855
        array $headers = [],
856
        bool $returnInfo = false,
857
        string $user = '',
858
        string $password = '',
859
        bool $sslNotVerifyHostAndPeer = false,
860
        bool $followLocation = false,
861
        int $timeout = 10,
862
        string $logPath = '',
863
        string $referer = '',
864
        string $userAgent = 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0'
865
    ) {
866
        if (isNullOrEmpty($server_name) && isNotNullOrEmptyArrayKey($_SERVER, 'SERVER_NAME')) {
867
            $server_name = $_SERVER['SERVER_NAME'];
868
        }
869
870 View Code Duplication
        if (isNullOrEmpty($server_name) && isNotNullOrEmpty($logPath)) {
871
            $msg = 'No server name given for calling curl ' . $url . ' behind proxy or LB';
872
            logToFile($logPath, $msg);
873
            return false;
874
        }
875
876
        if (isNullOrEmpty($localServerIpAddress) && isNotNullOrEmptyArrayKey($_SERVER, 'SERVER_ADDR')) {
877
            $localServerIpAddress = $_SERVER['SERVER_ADDR'];
878
        }
879
880 View Code Duplication
        if (isNullOrEmpty($localServerIpAddress) && isNotNullOrEmpty($logPath)) {
881
            $msg = 'No localIPAddress given for calling curl ' . $url . ' behind proxy or LB';
882
            logToFile($logPath, $msg);
883
            return false;
884
        }
885
886
        $url = str_replace($server_name, $localServerIpAddress, $url);
887
888
        //Using the host header to bypass a load balancer
889
        if (!is_array($headers)) {
890
            $headers = array();
891
        }
892
        $headers[] = 'Host: ' . $server_name;
893
894
        return curl($url, $method, $data, $headers, $returnInfo, $user, $password, $sslNotVerifyHostAndPeer,
895
            $followLocation, $timeout, $logPath, $referer, $userAgent);
896
    }
897
}
898
899
if (!function_exists('startLayoutCapture')) {
900
901
    /**
902
     * Turn On the output buffering.
903
     * @return bool
904
     */
905
    function startLayoutCapture() : bool
906
    {
907
        return ob_start();
908
    }
909
}
910
911
if (!function_exists('endLayoutCapture')) {
912
913
    /**
914
     * Get the buffer contents for the topmost buffer and clean it.
915
     * @return string
916
     */
917
    function endLayoutCapture() : string
918
    {
919
        $data = ob_get_contents();
920
        ob_end_clean();
921
        return $data === false ? '' : $data;
922
    }
923
}
924
925
if (!function_exists('get_var_dump_output')) {
926
927
    /**
928
     * Capture var dump $var output and return it.
929
     * @param $var
930
     * @return string
931
     */
932
    function get_var_dump_output($var)
933
    {
934
        startLayoutCapture();
935
        $myfunc = "var_dump";
936
        $myfunc($var);
937
        return endLayoutCapture();
938
    }
939
}
940
941
if (!function_exists('debug')) {
942
943
    /**
944
     * Dump information about a variable.
945
     *
946
     * @param mixed $variable Variable to debug
947
     *
948
     * @return void
949
     * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
950
     */
951
    function debug($variable)
952
    {
953
        $output = get_var_dump_output($variable);
954
        $maps = [
955
            'string' => "/(string\((?P<length>\d+)\)) (?P<value>\"(?<!\\\).*\")/i",
956
            'array' => "/\[\"(?P<key>.+)\"(?:\:\"(?P<class>[a-z0-9_\\\]+)\")?(?:\:(?P<scope>public|protected|private))?\]=>/Ui",
957
            'countable' => "/(?P<type>array|int|string)\((?P<count>\d+)\)/",
958
            'resource' => "/resource\((?P<count>\d+)\) of type \((?P<class>[a-z0-9_\\\]+)\)/",
959
            'bool' => "/bool\((?P<value>true|false)\)/",
960
            'float' => "/float\((?P<value>[0-9\.]+)\)/",
961
            'object' => "/object\((?P<class>\S+)\)\#(?P<id>\d+) \((?P<count>\d+)\)/i"
962
        ];
963
        foreach ($maps as $function => $pattern) {
964
            $output = preg_replace_callback($pattern, function ($matches) use ($function) {
965
                switch ($function) {
966
                    case 'string':
967
                        $matches['value'] = htmlspecialchars($matches['value']);
968
                        return '<span style="color: #0000FF;">string</span>(<span style="color: #1287DB;">' . $matches['length'] . ')</span> <span style="color: #6B6E6E;">' . $matches['value'] . '</span>';
969
                    case 'array':
970
                        $key = '<span style="color: #008000;">"' . $matches['key'] . '"</span>';
971
                        $class = '';
972
                        $scope = '';
973
                        if (isset($matches['class']) && !empty($matches['class'])) {
974
                            $class = ':<span style="color: #4D5D94;">"' . $matches['class'] . '"</span>';
975
                        }
976
                        if (isset($matches['scope']) && !empty($matches['scope'])) {
977
                            $scope = ':<span style="color: #666666;">' . $matches['scope'] . '</span>';
978
                        }
979
                        return '[' . $key . $class . $scope . ']=>';
980
                    case 'countable':
981
                        $type = '<span style="color: #0000FF;">' . $matches['type'] . '</span>';
982
                        $count = '(<span style="color: #1287DB;">' . $matches['count'] . '</span>)';
983
                        return $type . $count;
984
                    case 'bool':
985
                        return '<span style="color: #0000FF;">bool</span>(<span style="color: #0000FF;">' . $matches['value'] . '</span>)';
986
                    case 'float':
987
                        return '<span style="color: #0000FF;">float</span>(<span style="color: #1287DB;">' . $matches['value'] . '</span>)';
988
                    case 'resource':
989
                        return '<span style="color: #0000FF;">resource</span>(<span style="color: #1287DB;">' . $matches['count'] . '</span>) of type (<span style="color: #4D5D94;">' . $matches['class'] . '</span>)';
990
                    case 'object':
991
                        return '<span style="color: #0000FF;">object</span>(<span style="color: #4D5D94;">' . $matches['class'] . '</span>)#' . $matches['id'] . ' (<span style="color: #1287DB;">' . $matches['count'] . '</span>)';
992
                }
993
            }, $output);
994
        }
995
        $header = '';
996
        list($debugfile) = debug_backtrace();
997
        if (!empty($debugfile['file'])) {
998
            $header = '<h4 style="border-bottom:1px solid #bbb;font-weight:bold;margin:0 0 10px 0;padding:3px 0 10px 0">' . $debugfile['file'] . '</h4>';
999
        }
1000
        echo '<pre style="background-color: #CDDCF4;border: 1px solid #bbb;border-radius: 4px;-moz-border-radius:4px;-webkit-border-radius\:4px;font-size:12px;line-height:1.4em;margin:30px;padding:7px">' . $header . $output . '</pre>';
1001
    }
1002
}
1003
1004
if (!function_exists('getReferer')) {
1005
1006
    /**
1007
     * Return referer page if exists otherwise return empty string.
1008
     *
1009
     * @return string
1010
     */
1011
    function getReferer() : string
1012
    {
1013
        return isNotNullOrEmptyArrayKey($_SERVER, 'HTTP_REFERER') ? $_SERVER['HTTP_REFERER'] : '';
1014
    }
1015
}
1016
1017
if (!function_exists('isZlibOutputCompressionActive')) {
1018
1019
    /**
1020
     * Check if zlib output compression was active
1021
     * @return bool
1022
     */
1023
    function isZlibOutputCompressionActive() : bool
1024
    {
1025
        return ini_get('zlib.output_compression') == 'On'
1026
        || ini_get('zlib.output_compression_level') > 0
1027
        || ini_get('output_handler') == 'ob_gzhandler';
1028
    }
1029
}
1030
1031
if (!function_exists('isZlibLoaded')) {
1032
1033
    /**
1034
     * Check if zlib extension was loaded
1035
     * @return bool
1036
     */
1037
    function isZlibLoaded() : bool
1038
    {
1039
        return extension_loaded('zlib');
1040
    }
1041
}
1042
1043
if (!function_exists('isClientAcceptGzipEncoding')) {
1044
1045
    /**
1046
     * Check if client accept gzip encoding
1047
     * @return bool
1048
     */
1049
    function isClientAcceptGzipEncoding() : bool
1050
    {
1051
        return isNotNullOrEmptyArrayKey($_SERVER, 'HTTP_ACCEPT_ENCODING')
1052
        && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false;
1053
    }
1054
}
1055
1056
if (!function_exists('compressHtmlPage')) {
1057
1058
    /**
1059
     * Captures output via ob_get_contents(), tries to enable gzip,
1060
     * removes whitespace from captured output and echos back
1061
     *
1062
     * @return string whitespace stripped output
1063
     * @see https://github.com/ngfw/Recipe/
1064
     */
1065
    function compressHtmlPage() : string
1066
    {
1067
        register_shutdown_function(function () {
1068
            $buffer = str_html_compress(ob_get_contents());
1069
            ob_end_clean();
1070
            if (!isZlibOutputCompressionActive() &&
1071
                isClientAcceptGzipEncoding() &&
1072
                isZlibLoaded()
1073
            ) {
1074
                ob_start('ob_gzhandler');
1075
            }
1076
            echo $buffer;
1077
        });
1078
    }
1079
}
1080
1081
if (!function_exists('get_http_response_code')) {
1082
1083
    /**
1084
     * @param string $theURL
1085
     * @param bool $useGet if set to true use a GET request, otherwise use a HEAD request (more fast).
1086
     * @return int return the http status or 999 if it fails.
1087
     */
1088
    function get_http_response_code(string $theURL, bool $useGet = false) : int
1089
    {
1090
        if (isNullOrEmpty($theURL)) {
1091
            return 999;
1092
        }
1093
        if (!$useGet) {
1094
            // By default get_headers uses a GET request to fetch the headers. If you
1095
            // want to send a HEAD request instead, you can do so using a stream context:
1096
            stream_context_set_default(
1097
                array(
1098
                    'http' => array(
1099
                        'method' => 'HEAD'
1100
                    )
1101
                )
1102
            );
1103
        }
1104
        $headers = @get_headers($theURL);
1105
1106
        if ($headers === false || isNullOrEmptyArray($headers) || strlen($headers[0]) < 12) {
1107
            return 999;
1108
        }
1109
        $status = substr($headers[0], 9, 3);
1110
        return isInteger($status) ? $status : 999;
1111
    }
1112
}
1113
1114
if (!function_exists('url_exists')) {
1115
1116
    /**
1117
     * Check if URL exists (return http status code <400
1118
     * @param string $url
1119
     * @return bool
1120
     */
1121
    function url_exists(string $url) : bool
1122
    {
1123
        return get_http_response_code($url) < 400;
1124
    }
1125
}
1126
1127
if (!function_exists('logToFile')) {
1128
1129
    /**
1130
     * Log variable into log file.
1131
     * @param string $pathFile full path with file name.
1132
     * @param mixed $value value to log
1133
     * @param bool $varDump default false. if set to true,
1134
     * grab var dump output of $value and write it to log, otherwise append it to log.
1135
     */
1136
    function logToFile(string $pathFile, $value, bool $varDump = false)
1137
    {
1138
        if ($varDump) {
1139
            $value = get_var_dump_output($value);
1140
        }
1141
        $f = fopen($pathFile, 'ab');
1142
        fwrite($f, date(DATE_RFC822) . "\r\n" . $value . "\r\n----------------------------------------------\r\n");
1143
        fclose($f);
1144
    }
1145
}
1146
1147
/**
1148
 * Check if an extension is an image type.
1149
 * @param  string $ext extension to check
1150
 * @return boolean
1151
 * @see https://github.com/kohana/ohanzee-helpers/blob/master/src/Mime.php
1152
 */
1153
function isImageExtension(string $ext) : bool
1154
{
1155
    return in_array(strtolower($ext), getImageExtensions());
1156
}
1157
1158
/**
1159
 * Get a list of common image extensions. Only types that can be read by
1160
 * PHP's internal image methods are included!
1161
 * @return string[]
1162
 */
1163
function getImageExtensions() : array
1164
{
1165
    return [
1166
        'bmp',
1167
        'gif',
1168
        'jpeg',
1169
        'jpg',
1170
        'png',
1171
        'tif',
1172
        'tiff',
1173
        'swf',
1174
    ];
1175
}
1176
1177
/**
1178
 * Very simple 'template' parser. Replaces (for example) {name} with the value of $vars['name'] in strings
1179
 *
1180
 * @param        $str
1181
 * @param array $vars
1182
 * @param string $openDelimiter
1183
 * @param string $closeDelimiter
1184
 *
1185
 * @return string
1186
 * @see https://github.com/laradic/support/blob/master/src/Util.php
1187
 * @example
1188
 * <?php
1189
 * $result = template('This is the best template parser. Created by {developerName}', ['developerName' => 'Radic']);
1190
 * echo $result; // This is the best template parser. Created by Radic
1191
 */
1192
function template($str, array $vars = [], $openDelimiter = '{', $closeDelimiter = '}')
1193
{
1194
    foreach ($vars as $k => $var) {
1195
        if (is_array($var)) {
1196
            $str = template($str, $var);
1197
        } elseif (is_string($var)) {
1198
            $str = str_replace($openDelimiter . $k . $closeDelimiter, $var, $str);
1199
        }
1200
    }
1201
    return $str;
1202
}
1203
1204
/**
1205
 * @param int $percent
1206
 * @return bool
1207
 * @see https://github.com/laradic/support/blob/master/src/Util.php
1208
 */
1209
function randomChance(int $percent = 50) : bool
1210
{
1211
    return random_int(0, 100) > 100 - $percent;
1212
}
1213
1214
/**
1215
 * @param Throwable $exception
1216
 * @return string
1217
 */
1218
function getExceptionTraceAsString(\Throwable $exception)
1219
{
1220
    $rtn = "";
1221
    $count = 0;
1222
    foreach ($exception->getTrace() as $frame) {
1223
        $args = "";
1224
        if (isset($frame['args'])) {
1225
            $args = [];
1226
            foreach ($frame['args'] as $arg) {
1227
                if (is_string($arg)) {
1228
                    $args[] = "'" . $arg . "'";
1229
                } elseif (is_array($arg)) {
1230
                    $args[] = "Array";
1231
                } elseif (is_null($arg)) {
1232
                    $args[] = 'NULL';
1233
                } elseif (is_bool($arg)) {
1234
                    $args[] = ($arg) ? "true" : "false";
1235
                } elseif (is_object($arg)) {
1236
                    $args[] = get_class($arg);
1237
                } elseif (is_resource($arg)) {
1238
                    $args[] = get_resource_type($arg);
1239
                } else {
1240
                    $args[] = $arg;
1241
                }
1242
            }
1243
            $args = implode(", ", $args);
1244
        }
1245
        $rtn .= sprintf("#%s %s(%s): %s(%s)\n",
1246
            $count,
1247
            isset($frame['file']) ? $frame['file'] : '',
1248
            isset($frame['line']) ? $frame['line'] : '',
1249
            $frame['function'],
1250
            $args);
1251
        $count++;
1252
    }
1253
    return $rtn;
1254
}
1255
1256
if (!function_exists('windows_os')) {
1257
    /**
1258
     * Determine whether the current environment is Windows based.
1259
     *
1260
     * @return bool
1261
     *
1262
     * @see https://github.com/illuminate/support/blob/master/helpers.php
1263
     */
1264
    function windows_os() : bool
1265
    {
1266
        return strtolower(substr(PHP_OS, 0, 3)) === 'win';
1267
    }
1268
}
1269
1270
if (!function_exists('getConsoleColorTagForStatusCode')) {
1271
    /**
1272
     * Get the color tag for the given status code to be use in symfony/laravel console.
1273
     *
1274
     * @param string $code
1275
     *
1276
     * @return string
1277
     *
1278
     * @see https://github.com/spatie/http-status-check/blob/master/src/CrawlLogger.php#L96
1279
     */
1280
    function getConsoleColorTagForStatusCode($code)
1281
    {
1282
        if (starts_with($code, '2')) {
1283
            return 'info';
1284
        }
1285
        if (starts_with($code, '3')) {
1286
            return 'comment';
1287
        }
1288
        return 'error';
1289
    }
1290
}
1291
1292
if (!function_exists('is_32bit')) {
1293
    /**
1294
     * Check if the OS architecture is 32bit.
1295
     *
1296
     * @return bool
1297
     *
1298
     * @see http://stackoverflow.com/questions/6303241/find-windows-32-or-64-bit-using-php
1299
     */
1300
    function is_32bit() : bool
1301
    {
1302
        return get_os_architecture()==32;
1303
    }
1304
}
1305
1306
if (!function_exists('is_64bit')) {
1307
    /**
1308
     * Check if the OS architecture is 64bit.
1309
     *
1310
     * @return bool
1311
     *
1312
     * @see http://stackoverflow.com/questions/6303241/find-windows-32-or-64-bit-using-php
1313
     */
1314
    function is_64bit() : bool
1315
    {
1316
        return get_os_architecture()==64;
1317
    }
1318
}
1319
1320
if (!function_exists('get_os_architecture')) {
1321
    /**
1322
     * Get the OS architecture 32 or 64 bit.
1323
     *
1324
     * @return int return 32 or 64 if ok, otherwise return 0.
1325
     *
1326
     * @see http://stackoverflow.com/questions/6303241/find-windows-32-or-64-bit-using-php
1327
     */
1328
    function get_os_architecture() : int
1329
    {
1330
        switch(PHP_INT_SIZE) {
1331
            case 4:
1332
                return 32;
1333
            case 8:
1334
                return 64;
1335
            default:
1336
                return 0;
1337
        }
1338
    }
1339
}
1340
1341
1342
if (!function_exists('isRequestFromCloudFlare')) {
1343
1344
    /**
1345
     * Check if request (by given $_SERVER) is a cloudflare request
1346
     * @param $server
1347
     * @return bool
1348
     */
1349
    function isRequestFromCloudFlare(array $server) : bool
1350
    {
1351
        if (!isset($server['HTTP_CF_CONNECTING_IP']) || !isIP($server['HTTP_CF_CONNECTING_IP'])) {
1352
            return false;
1353
        }
1354
1355
        if (isCloudFlareIp($server['REMOTE_ADDR'])) {
1356
            return true;
1357
        }
1358
1359
        //in case proxy or load balancer in front the server web
1360
        //the chained passed IPs are in the HTTP_X_FORWARDED_FOR var in these two possible ways:
1361
        //2.38.87.88
1362
        //2.38.87.88, 188.114.101.5
0 ignored issues
show
Unused Code Comprehensibility introduced by
88% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1363
        if (empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
1364
            return false;
1365
        }
1366
1367
        if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',') === false) {
1368
            return isCloudFlareIp($server['HTTP_X_FORWARDED_FOR']);
1369
        }
1370
1371
        $IPs = explode(",", $_SERVER['HTTP_X_FORWARDED_FOR']);
1372
        if (empty($IPs) || !is_array($IPs) || count($IPs) < 1) {
1373
            return false;
1374
        }
1375
1376
        //usually the cloudflare ip are the last IP in the stack, so start loop by last entries
1377
        for ($i = count($IPs) - 1; $i >= 0; $i--) {
1378
            $ip = trim($IPs[$i]);
1379
            if (isCloudFlareIp($ip)) {
1380
                return true;
1381
            }
1382
        }
1383
1384
        return false;
1385
    }
1386
}
1387
1388
if (!function_exists('isCloudFlareIp')) {
1389
1390
    /**
1391
     * Check if given ip is a valid cloudflare ip.
1392
     * @param $ip
1393
     * @return bool
1394
     */
1395
    function isCloudFlareIp($ip) : bool
1396
    {
1397
        if (!isIP($ip)) {
1398
            return false;
1399
        }
1400
1401
        //array given from https://www.cloudflare.com/ips-v4
1402
        $cf_ip_ranges = array(
1403
            '103.21.244.0/22',
1404
            '103.22.200.0/22',
1405
            '103.31.4.0/22',
1406
            '104.16.0.0/12',
1407
            '108.162.192.0/18',
1408
            '131.0.72.0/22',
1409
            '141.101.64.0/18',
1410
            '162.158.0.0/15',
1411
            '172.64.0.0/13',
1412
            '173.245.48.0/20',
1413
            '188.114.96.0/20',
1414
            '190.93.240.0/20',
1415
            '197.234.240.0/22',
1416
            '198.41.128.0/17',
1417
        );
1418
1419
        foreach ($cf_ip_ranges as $range) {
1420
            if (ipInRange($ip, $range)) {
1421
                return true;
1422
            }
1423
        }
1424
1425
        return false;
1426
    }
1427
}
1428
1429
if (!function_exists('gzCompressFile')) {
1430
1431
    /**
1432
     * GZIPs a file on disk (appending .gz to the name)
1433
     *
1434
     * From http://stackoverflow.com/questions/6073397/how-do-you-create-a-gz-file-using-php
1435
     * Based on function by Kioob at:
1436
     * http://www.php.net/manual/en/function.gzwrite.php#34955
1437
     *
1438
     * @param string $source Path to file that should be compressed
1439
     * @param integer $level GZIP compression level (default: 9)
1440
     * @return string New filename (with .gz appended) if success, or false if operation fails
1441
     */
1442
    function gzCompressFile($source, $level = 9)
1443
    {
1444
        $dest = $source . '.gz';
1445
        $mode = 'wb' . $level;
1446
        $error = false;
1447
        if ($fp_out = gzopen($dest, $mode)) {
1448
            if ($fp_in = fopen($source, 'rb')) {
1449
                while (!feof($fp_in))
1450
                    gzwrite($fp_out, fread($fp_in, 1024 * 512));
1451
                fclose($fp_in);
1452
            } else {
1453
                $error = true;
1454
            }
1455
            gzclose($fp_out);
1456
        } else {
1457
            $error = true;
1458
        }
1459
        if ($error)
1460
            return false;
1461
        else
1462
            return $dest;
1463
    }
1464
}
1465