Completed
Push — master ( 47bfcf...552113 )
by Lorenzo
02:43
created

helpers.php ➔ isCloudFlareIp()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 32
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 22
nc 4
nop 1
dl 0
loc 32
rs 8.5806
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
 * @return string
146
 */
147
function bytes2HumanSize($bytes)
148
{
149
    if ($bytes >= 1125899906842624) {
150
        $bytes = number_format($bytes / 1073741824, 2) . ' PB';
151
    } elseif ($bytes >= 1099511627776) {
152
        $bytes = number_format($bytes / 1073741824, 2) . ' TB';
153
    } elseif ($bytes >= 1073741824) {
154
        $bytes = number_format($bytes / 1073741824, 2) . ' GB';
155
    } elseif ($bytes >= 1048576) {
156
        $bytes = number_format($bytes / 1048576, 2) . ' MB';
157
    } elseif ($bytes >= 1024) {
158
        $bytes = number_format($bytes / 1024, 2) . ' kB';
159
    } elseif ($bytes > 1) {
160
        $bytes .= ' bytes';
161
    } elseif ($bytes == 1) {
162
        $bytes .= ' byte';
163
    } else {
164
        $bytes = '0 bytes';
165
    }
166
167
    return $bytes;
168
}
169
170
/**
171
 * This function transforms the php.ini notation for numbers (like '2M')
172
 * to an integer (2*1024*1024 in this case)
173
 * @param string $sSize
174
 * @return int|string
175
 */
176
function convertPHPSizeToBytes($sSize)
177
{
178
    if (is_numeric($sSize)) {
179
        return $sSize;
180
    }
181
    $sSuffix = substr($sSize, -1);
182
    $iValue = substr($sSize, 0, -1);
183
184
    switch (strtoupper($sSuffix)) {
185
        case 'P':
186
            $iValue *= 1024;
187
        //PB multiplier
188
        case 'T':
189
            $iValue *= 1024;
190
        //TB multiplier
191
        case 'G':
192
            $iValue *= 1024;
193
        //GB multiplier
194
        case 'M':
195
            $iValue *= 1024;
196
        //MB multiplier
197
        case 'K':
198
            $iValue *= 1024;
199
            //KB multiplier
200
            break;
201
    }
202
    return $iValue;
203
}
204
205
/**
206
 * Return the Max upload size in bytes.
207
 * @param bool $humanFormat if set to true return size in human format (MB, kB, etc..) otherwise return in bytes.
208
 * @return int
209
 */
210
function getMaximumFileUploadSize(bool $humanFormat = false)
211
{
212
    $size = min(convertPHPSizeToBytes(ini_get('post_max_size')), convertPHPSizeToBytes(ini_get('upload_max_filesize')));
213
214
    if (!$humanFormat) {
215
        return $size;
216
    }
217
218
    return bytes2HumanSize($size);
219
}
220
221
/**
222
 * Encrypt string in asymmetrical way.
223
 * @param string $string to encrypt.
224
 * @param string $chiave the key to encrypt. if empty generate a random key on the fly.
225
 * @return string
226
 */
227
function encryptString(string $string, string $chiave = '')
228
{
229
    if ($chiave == '') {
230
        $chiave = str_random(64);
231
    }
232
233
    $key = pack('H*', $chiave);
234
235
    $plaintext = $string;
236
237
    # create a random IV to use with CBC encoding
238
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
239
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
240
241
    # creates a cipher text compatible with AES (Rijndael block size = 128)
242
    # to keep the text confidential
243
    # only suitable for encoded input that never ends with value 00h
244
    # (because of default zero padding)
245
    $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $iv);
246
247
    # prepend the IV for it to be available for decryption
248
    $ciphertext = $iv . $ciphertext;
249
250
    # encode the resulting cipher text so it can be represented by a string
251
    $ciphertext_base64 = base64_encode($ciphertext);
252
253
    return $ciphertext_base64;
254
}
255
256
/**
257
 * Get a Website favicon url.
258
 *
259
 * @param string $url website url
260
 *
261
 * @return string containing complete image tag
262
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
263
 */
264
function getFaviconUrl($url) : string
265
{
266
    $apiUrl = 'https://www.google.com/s2/favicons?domain=';
267
    if (strpos($url, 'http') !== false) {
268
        $url = str_replace('http://', '', $url);
269
    }
270
    return $apiUrl . $url;
271
}
272
273
/**
274
 * Get a Website favicon image tag.
275
 *
276
 * @param string $url website url
277
 * @param array $attributes Optional, additional key/value attributes to include in the IMG tag
278
 *
279
 * @return string containing complete image tag
280
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
281
 */
282
function getFaviconImgTag($url, array $attributes = []) : string
283
{
284
    $urlFav = getFaviconUrl($url);
285
    $attr = arrayToString($attributes);
286
    return '<img src="' . $urlFav . '" ' . trim($attr) . ' />';
287
}
288
289
/**
290
 * Check to see if the current page is being server over SSL or not.
291
 * Support HTTP_X_FORWARDED_PROTO to check ssl over proxy/load balancer.
292
 *
293
 * @return bool
294
 */
295
function isHttps()
296
{
297
    $key = 'HTTPS';
298
    if (isNotNullOrEmptyArrayKey($_SERVER, 'HTTP_X_FORWARDED_PROTO')) {
299
        $key = 'HTTP_X_FORWARDED_PROTO';
300
    }
301
    return isNotNullOrEmptyArrayKey($_SERVER, $key) && strtolower($_SERVER[$key]) !== 'off';
302
}
303
304
/**
305
 * Get a QR code.
306
 *
307
 * @param string $string String to generate QR code for.
308
 * @param int $width QR code width
309
 * @param int $height QR code height
310
 * @param array $attributes Optional, additional key/value attributes to include in the IMG tag
311
 *
312
 * @return string containing complete image tag
313
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
314
 */
315
function getQRcode($string, int $width = 150, int $height = 150, array $attributes = []) : string
316
{
317
    $attr = arrayToString($attributes);
318
    $apiUrl = getQRcodeUrl($string, $width, $height);
319
    return '<img src="' . $apiUrl . '" ' . trim($attr) . ' />';
320
}
321
322
/**
323
 * Get a QR code Url.
324
 *
325
 * @param string $string String to generate QR code for.
326
 * @param int $width QR code width
327
 * @param int $height QR code height
328
 *
329
 * @return string containing complete image url
330
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
331
 */
332
function getQRcodeUrl($string, int $width = 150, int $height = 150) : string
333
{
334
    $protocol = 'http://';
335
    if (isHttps()) {
336
        $protocol = 'https://';
337
    }
338
    return $protocol . 'chart.apis.google.com/chart?chs=' . $width . 'x' . $height . '&cht=qr&chl=' . urlencode($string);
339
}
340
341
if (!function_exists('gravatarUrl')) {
342
    /**
343
     * Get a Gravatar URL from email.
344
     *
345
     * @param string $email The email address
346
     * @param int $size in pixels, defaults to 80px [ 1 - 2048 ]
347
     * @param string $default imageset to use [ 404 | mm | identicon | monsterid | wavatar ]
348
     * @param string $rating (inclusive) [ g | pg | r | x ]
349
     * @return string
350
     * @source http://gravatar.com/site/implement/images/php/
351
     */
352
    function gravatarUrl($email, $size = 80, $default = 'mm', $rating = 'g')
353
    {
354
        $url = 'https://www.gravatar.com';
355
        $url .= '/avatar/' . md5(strtolower(trim($email))) . '?default=' . $default . '&size=' . $size . '&rating=' . $rating;
356
        return $url;
357
    }
358
}
359
360
if (!function_exists('gravatar')) {
361
    /**
362
     * Get a Gravatar img tag from email.
363
     *
364
     * @param string $email The email address
365
     * @param int $size in pixels, defaults to 80px [ 1 - 2048 ]
366
     * @param string $default imageset to use [ 404 | mm | identicon | monsterid | wavatar ]
367
     * @param string $rating (inclusive) [ g | pg | r | x ]
368
     * @param array $attributes Optional, additional key/value attributes to include in the IMG tag
369
     * @return string
370
     * @source http://gravatar.com/site/implement/images/php/
371
     */
372
    function gravatar($email, $size = 80, $default = 'mm', $rating = 'g', $attributes = [])
373
    {
374
        $attr = arrayToString($attributes);
375
        $url = gravatarUrl($email, $size, $default, $rating);
376
        return '<img src="' . $url . '" width="' . $size . 'px" height="' . $size . 'px" ' . trim($attr) . ' />';
377
    }
378
}
379
380
if (!function_exists('isAjax')) {
381
382
    /**
383
     * Determine if current page request type is ajax.
384
     *
385
     * @return bool
386
     */
387
    function isAjax()
388
    {
389
        return isNotNullOrEmptyArrayKey($_SERVER, 'HTTP_X_REQUESTED_WITH')
390
        && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
391
    }
392
}
393
394
if (!function_exists('isNumberOdd')) {
395
396
    /**
397
     * Check if number is odd.
398
     *
399
     * @param int $num integer to check
400
     *
401
     * @return bool
402
     * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
403
     */
404
    function isNumberOdd($num)
405
    {
406
        return $num % 2 !== 0;
407
    }
408
}
409
410
if (!function_exists('isNumberEven')) {
411
412
    /**
413
     * Check if number is even.
414
     *
415
     * @param int $num integer to check
416
     *
417
     * @return bool
418
     * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
419
     */
420
    function isNumberEven($num)
421
    {
422
        return $num % 2 == 0;
423
    }
424
}
425
426
if (!function_exists('getCurrentUrlPageName')) {
427
428
    /**
429
     * Returns The Current URL PHP File Name.
430
     * Ex.: http://www.dummy.com/one/two/index.php?one=1&two=2 return index.php
431
     *
432
     * @return string
433
     */
434
    function getCurrentUrlPageName() : string
435
    {
436
        return isNotNullOrEmptyArrayKey($_SERVER, 'PHP_SELF') ? basename($_SERVER['PHP_SELF']) : '';
437
    }
438
}
439
440
if (!function_exists('getCurrentUrlQuerystring')) {
441
442
    /**
443
     * Returns The Current URL querystring.
444
     * Ex.: http://www.dummy.com/one/two/index.php?one=1&two=2 return one=1&two=2
445
     *
446
     * @return string
447
     */
448
    function getCurrentUrlQuerystring() : string
449
    {
450
        return isNotNullOrEmptyArrayKey($_SERVER, 'QUERY_STRING') ? $_SERVER['QUERY_STRING'] : '';
451
    }
452
}
453
454
if (!function_exists('getCurrentUrlDirName')) {
455
456
    /**
457
     * Returns The Current URL Path Name.
458
     * Ex.: http://www.dummy.com/one/two/index.php?one=1&two=2 return /one/two
459
     *
460
     * @return string
461
     */
462
    function getCurrentUrlDirName() : string
463
    {
464
        if (isNotNullOrEmptyArrayKey($_SERVER, 'REQUEST_URI')) {
465
            return dirname($_SERVER['REQUEST_URI']);
466
        }
467
        return isNotNullOrEmptyArrayKey($_SERVER, 'PHP_SELF') ? dirname($_SERVER['PHP_SELF']) : '';
468
    }
469
}
470
471
if (!function_exists('getCurrentUrlDirAbsName')) {
472
473
    /**
474
     * Returns The Current URL Absolute Path Name.
475
     * Ex.: http://www.dummy.com/one/two/index.php?one=1&two=2 return /home/user/www/one/two
476
     *
477
     * @return string
478
     */
479
    function getCurrentUrlDirAbsName() : string
480
    {
481
        return isNotNullOrEmptyArrayKey($_SERVER, 'SCRIPT_FILENAME') ? dirname($_SERVER['SCRIPT_FILENAME']) : '';
482
    }
483
}
484
485
if (!function_exists('getCurrentURL')) {
486
487
    /**
488
     * Return the current URL.
489
     * Ex.: http://www.dummy.com/one/two/index.php?one=1&two=2
490
     * Or
491
     * Ex.: https://username:[email protected]:443/one/two/index.php?one=1&two=2
492
     * @return string
493
     * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
494
     */
495
    function getCurrentURL()
496
    {
497
        $url = 'http://';
498
        if (isHttps()) {
499
            $url = 'https://';
500
        }
501
        if (array_key_exists_safe($_SERVER, 'PHP_AUTH_USER')) {
502
            $url .= $_SERVER['PHP_AUTH_USER'];
503
            if (array_key_exists_safe($_SERVER, 'PHP_AUTH_PW')) {
504
                $url .= ':' . $_SERVER['PHP_AUTH_PW'];
505
            }
506
            $url .= '@';
507
        }
508
        if (array_key_exists_safe($_SERVER, 'HTTP_HOST')) {
509
            $url .= $_SERVER['HTTP_HOST'];
510
        }
511
        if (array_key_exists_safe($_SERVER, 'SERVER_PORT') && $_SERVER['SERVER_PORT'] != 80) {
512
            $url .= ':' . $_SERVER['SERVER_PORT'];
513
        }
514
        if (!array_key_exists_safe($_SERVER, 'REQUEST_URI')) {
515
            $url .= substr($_SERVER['PHP_SELF'], 1);
516
            if (array_key_exists_safe($_SERVER, 'QUERY_STRING')):
517
                $url .= '?' . $_SERVER['QUERY_STRING'];
518
            endif;
519
        } else {
520
            $url .= $_SERVER['REQUEST_URI'];
521
        }
522
        return $url;
523
    }
524
}
525
526
if (!function_exists('isMobile')) {
527
528
    /**
529
     * Detect if user is on mobile device.
530
     *
531
     * @return bool
532
     */
533
    function isMobile()
534
    {
535
        $useragent = $_SERVER['HTTP_USER_AGENT'];
536
        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',
537
            $useragent)
538
        || 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',
539
            substr($useragent, 0, 4));
540
    }
541
}
542
543
/**
544
 * Get user browser.
545
 *
546
 * @return string
547
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
548
 */
549
function getBrowser()
550
{
551
    $u_agent = $_SERVER['HTTP_USER_AGENT'];
552
    $browserName = $ub = $platform = 'Unknown';
553
    if (preg_match('/linux/i', $u_agent)) {
554
        $platform = 'Linux';
555
    } elseif (preg_match('/macintosh|mac os x/i', $u_agent)) {
556
        $platform = 'Mac OS';
557
    } elseif (preg_match('/windows|win32/i', $u_agent)) {
558
        $platform = 'Windows';
559
    }
560
    if (preg_match('/MSIE/i', $u_agent) && !preg_match('/Opera/i', $u_agent)) {
561
        $browserName = 'Internet Explorer';
562
        $ub = 'MSIE';
563
    } elseif (preg_match('/Firefox/i', $u_agent)) {
564
        $browserName = 'Mozilla Firefox';
565
        $ub = 'Firefox';
566
    } elseif (preg_match('/Chrome/i', $u_agent)) {
567
        $browserName = 'Google Chrome';
568
        $ub = 'Chrome';
569
    } elseif (preg_match('/Safari/i', $u_agent)) {
570
        $browserName = 'Apple Safari';
571
        $ub = 'Safari';
572
    } elseif (preg_match('/Opera/i', $u_agent)) {
573
        $browserName = 'Opera';
574
        $ub = 'Opera';
575
    } elseif (preg_match('/Netscape/i', $u_agent)) {
576
        $browserName = 'Netscape';
577
        $ub = 'Netscape';
578
    }
579
    $known = ['Version', $ub, 'other'];
580
    $pattern = '#(?<browser>' . implode('|', $known) . ')[/ ]+(?<version>[0-9.|a-zA-Z.]*)#';
581
    preg_match_all($pattern, $u_agent, $matches);
582
    $i = count($matches['browser']);
583
    if ($i != 1) {
584
        if (strripos($u_agent, 'Version') < strripos($u_agent, $ub)) {
585
            $version = $matches['version'][0];
586
        } else {
587
            $version = $matches['version'][1];
588
        }
589
    } else {
590
        $version = $matches['version'][0];
591
    }
592
    if ($version == null || $version == '') {
593
        $version = '?';
594
    }
595
    return implode(', ', [$browserName, 'Version: ' . $version, $platform]);
596
}
597
598
/**
599
 * Shorten URL via tinyurl.com service.
600
 * It support http or https.
601
 * @param string $url URL to shorten
602
 *
603
 * @return string shortend url or empty string if it fails.
604
 */
605
function getTinyUrl(string $url) : string
606
{
607
    if (!starts_with($url, 'http')) {
608
        $url = (isHttps() ? 'https://' : 'http://') . $url;
609
    }
610
    $gettiny = curl('http://tinyurl.com/api-create.php?url=' . $url);
611
    if (isNullOrEmpty($gettiny) && isNullOrEmptyArray($gettiny)) {
612
        return '';
613
    }
614
    if (isHttps()) {
615
        $gettiny = str_replace('http://', 'https://', $gettiny);
616
    }
617
    return $gettiny;
618
}
619
620
/**
621
 * Get information on a short URL. Find out where it goes.
622
 *
623
 * @param string $shortURL shortened URL
624
 *
625
 * @return string full url or empty string
626
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
627
 */
628
function expandShortUrl(string $shortURL) : string
629
{
630
    if (isNullOrEmpty($shortURL)) {
631
        return '';
632
    }
633
    $headers = get_headers($shortURL, 1);
634
    if (array_key_exists_safe($headers, 'Location')) {
635
        return $headers['Location'];
636
    }
637
    $data = curl($shortURL);
638
    preg_match_all('/<[\s]*meta[\s]*http-equiv="?' . '([^>"]*)"?[\s]*' . 'content="?([^>"]*)"?[\s]*[\/]?[\s]*>/si',
639
        $data, $match);
640
    if (isNullOrEmptyArray($match) || count($match) != 3
641
        || isNullOrEmptyArray($match[0]) || isNullOrEmptyArray($match[1]) || isNullOrEmptyArray($match[2])
642
        || count($match[0]) != count($match[1]) || count($match[1]) != count($match[2])
643
    ) {
644
        return '';
645
    }
646
    $originals = $match[0];
647
    $names = $match[1];
648
    $values = $match[2];
649
    $metaTags = [];
650
    for ($i = 0, $limit = count($names); $i < $limit; $i++) {
651
        $metaTags[$names[$i]] = ['html' => htmlentities($originals[$i]), 'value' => $values[$i]];
652
    }
653
    if (!isset($metaTags['refresh']['value']) || empty($metaTags['refresh']['value'])) {
654
        return '';
655
    }
656
    $returnData = explode('=', $metaTags['refresh']['value']);
657
    if (!isset($returnData[1]) || empty($returnData[1])) {
658
        return '';
659
    }
660
    return $returnData[1];
661
}
662
663
if (!function_exists('curl')) {
664
665
    /**
666
     * Make Curl call.
667
     *
668
     * @param string $url URL to curl
669
     * @param string $method GET or POST, Default GET
670
     * @param mixed $data Data to post, Default false
671
     * @param string[] $headers Additional headers, example: array ("Accept: application/json")
672
     * @param bool $returnInfo Whether or not to retrieve curl_getinfo()
673
     * @param string $user
674
     * @param string $password
675
     * @param bool $sslNotVerifyHostAndPeer is set to true do not check SSL certificate.
676
     * @param bool $followLocation
677
     * @param int $timeout
678
     * @param string $logPath if not empty write log to this file
679
     * @param string $referer
680
     * @param string $userAgent default 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0'
681
     * and ignore $returnInfo (i.e. call curl_getinfo even if $returnInfo is set to false).
682
     *
683
     * @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
684
     * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
685
     */
686
    function curl(
687
        $url,
688
        $method = 'GET',
689
        $data = false,
690
        array $headers = [],
691
        bool $returnInfo = false,
692
        string $user = '',
693
        string $password = '',
694
        bool $sslNotVerifyHostAndPeer = false,
695
        bool $followLocation = false,
696
        int $timeout = 10,
697
        string $logPath = '',
698
        string $referer = '',
699
        string $userAgent = 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0'
700
    ) {
701
        $log = false;
702
        if (isNotNullOrEmpty($logPath)) {
703
            $log = true;
704
            $msg = "REQUEST_URI: " . (isNotNullOrEmptyArrayKey($_SERVER,
705
                    'REQUEST_URI') ? $_SERVER['REQUEST_URI'] : '') . "\r\n"
706
                . "SCRIPT_NAME: " . (isNotNullOrEmptyArrayKey($_SERVER,
707
                    'SCRIPT_NAME') ? $_SERVER['SCRIPT_NAME'] : '') . "\r\n"
708
                . "REMOTE ADDR: " . (isNotNullOrEmptyArrayKey($_SERVER,
709
                    'REMOTE_ADDR') ? $_SERVER['REMOTE_ADDR'] : '') . "\r\n"
710
                . "HTTP_HOST: " . (isNotNullOrEmptyArrayKey($_SERVER,
711
                    'HTTP_HOST') ? $_SERVER['HTTP_HOST'] : '') . "\r\n"
712
                . "SERVER_NAME: " . (isNotNullOrEmptyArrayKey($_SERVER,
713
                    'SERVER_NAME') ? $_SERVER['SERVER_NAME'] : '') . "\r\n"
714
                . "HTTP_X_FORWARDED_FOR: " . (isNotNullOrEmptyArrayKey($_SERVER,
715
                    'HTTP_X_FORWARDED_FOR') ? $_SERVER['HTTP_X_FORWARDED_FOR'] : '') . "\r\n"
716
                . "SERVER_ADDR: " . (isNotNullOrEmptyArrayKey($_SERVER,
717
                    'SERVER_ADDR') ? $_SERVER['SERVER_ADDR'] : '') . "\r\n"
718
                . "REMOTE_PORT: " . (isNotNullOrEmptyArrayKey($_SERVER,
719
                    'REMOTE_PORT') ? $_SERVER['REMOTE_PORT'] : '') . "\r\n"
720
                . "HTTPS: " . (isNotNullOrEmptyArrayKey($_SERVER, 'HTTPS') ? $_SERVER['HTTPS'] : '') . "\r\n"
721
                . "HTTP_X_FORWARDED_PROTO: " . (isNotNullOrEmptyArrayKey($_SERVER,
722
                    'HTTP_X_FORWARDED_PROTO') ? $_SERVER['HTTP_X_FORWARDED_PROTO'] : '') . "\r\n"
723
                . "data: " . get_var_dump_output($data) . "\r\n"
724
                . "headers: " . get_var_dump_output($headers) . "\r\n"
725
                . "returnInfo: " . $returnInfo . "\r\n"
726
                . "url: " . $url . "\r\n"
727
                . "method: " . $method . "\r\n"
728
                . "user: " . $user . "\r\n"
729
                . "password: " . (strlen($password) > 2 ? substr($password, 0, 2) . str_repeat('x',
730
                        10) . substr($password, -1) : 'xx') . "\r\n"
731
                . "sslNotVerifyHostAndPeer: " . $sslNotVerifyHostAndPeer . "\r\n"
732
                . "followLocation: " . $followLocation . "\r\n"
733
                . "timeout: " . $timeout . "\r\n"
734
                . "logPath: " . $logPath . "\r\n"
735
                . "referer: " . $referer . "\r\n"
736
                . "userAgent: " . $userAgent . "\r\n"
737
                . "\r\n";
738
            logToFile($logPath, $msg);
739
        }
740
        if (!function_exists('curl_init') || isNullOrEmpty($url)) {
741
            if ($log) {
742
                logToFile($logPath,
743
                    isNullOrEmpty($url) ? 'url is empty.curl abort.' : 'curl_init not exists.Probabily CURL is not installed.');
744
            }
745
            return '';
746
        }
747
        $ch = curl_init();
748
        $info = null;
749
        if (strtoupper($method) == 'POST') {
750
            curl_setopt($ch, CURLOPT_POST, true);
751
            if ($data !== false) {
752
                curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
753
            }
754
        } elseif ($data !== false) {
755
            if (is_array($data)) {
756
                $dataTokens = [];
757
                foreach ($data as $key => $value) {
758
                    $dataTokens[] = urlencode($key) . '=' . urlencode($value);
759
                }
760
                $data = implode('&', $dataTokens);
761
            }
762
            $url .= (strpos($url, '?') === false ? '&' : '?') . $data;
763
        }
764
        curl_setopt($ch, CURLOPT_URL, $url);
765
        curl_setopt($ch, CURLOPT_HEADER, false);
766
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
767
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $followLocation ? true : false);
768
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout <= 1 ? 10 : $timeout);
769
        if ($sslNotVerifyHostAndPeer && starts_with($url, 'https://')) {
770
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
771
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
772
        }
773
        if (isNotNullOrEmptyArray($headers)) {
774
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
775
        }
776
        if (isNotNullOrEmpty($user) && isNotNullOrEmpty($password)) {
777
            curl_setopt($ch, CURLOPT_USERPWD, $user . ':' . $password);
778
        }
779
        if (isNotNullOrEmpty($referer)) {
780
            curl_setopt($ch, CURLOPT_REFERER, $referer);
781
        }
782
        if (isNotNullOrEmpty($userAgent)) {
783
            curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
784
        }
785
786
        if ($log) {
787
            logToFile($logPath, date('Y-m-d H:i:s') . "Start curl\r\n");
788
        }
789
        $contents = curl_exec($ch);
790
        if ($log) {
791
            logToFile($logPath, date('Y-m-d H:i:s') . "FINISH curl\r\n");
792
        }
793
794
        if ($returnInfo || $log || $contents === false || curl_errno($ch) > 0) {
795
            $info = curl_getinfo($ch);
796
            if ($log) {
797
                logToFile($logPath, $info, true);
798
            }
799
        }
800
801
        if ($contents === false || curl_errno($ch) > 0
802
            || !array_key_exists_safe($info === null ? [] : $info, 'http_code') || $info['http_code'] != 200
803
        ) {
804
            if ($log) {
805
                logToFile($logPath, "Error during exec CURL \r\n curl_error: " . curl_error($ch)
806
                    . "\r\n curl_errno: " . curl_errno($ch) . "\r\n");
807
            }
808
        } elseif ($log) {
809
            logToFile($logPath, "CURL IS OK\r\n RESPONSE: \r\n" . $contents);
810
        }
811
812
        curl_close($ch);
813
        return ($returnInfo ? ['contents' => $contents, 'info' => $info] : $contents);
814
    }
815
}
816
817
818
if (!function_exists('curl_internal_server_behind_load_balancer')) {
819
820
    /**
821
     * Make Curl call to one of the server behinds load balancer.
822
     *
823
     * @param string $url URL to curl
824
     * @param string $server_name The host name of the domain from the call will start.
825
     * if empty try to resolve from SERVER_NAME
826
     * @param string $localServerIpAddress the IP of one server to call that behinds load balancer.
827
     * if empty try to resolve from SERVER_ADDR
828
     * @param string $method GET or POST, Default GET
829
     * @param mixed $data Data to post, Default false
830
     * @param array $headers Additional headers, example: array ("Accept: application/json")
831
     * @param bool $returnInfo Whether or not to retrieve curl_getinfo()
832
     * @param string $user
833
     * @param string $password
834
     * @param bool $sslNotVerifyHostAndPeer is set to true do not check SSL certificate.
835
     * @param bool $followLocation
836
     * @param int $timeout
837
     * @param string $logPath if not empty write log to this file
838
     * @param string $referer
839
     * @param string $userAgent default 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0'
840
     * and ignore $returnInfo (i.e. call curl_getinfo even if $returnInfo is set to false).
841
     *
842
     * @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
843
     */
844
    function curl_internal_server_behind_load_balancer(
845
        $url,
846
        $server_name = '',
847
        $localServerIpAddress = '',
848
        $method = 'GET',
849
        $data = false,
850
        array $headers = [],
851
        bool $returnInfo = false,
852
        string $user = '',
853
        string $password = '',
854
        bool $sslNotVerifyHostAndPeer = false,
855
        bool $followLocation = false,
856
        int $timeout = 10,
857
        string $logPath = '',
858
        string $referer = '',
859
        string $userAgent = 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0'
860
    ) {
861
        if (isNullOrEmpty($server_name) && isNotNullOrEmptyArrayKey($_SERVER, 'SERVER_NAME')) {
862
            $server_name = $_SERVER['SERVER_NAME'];
863
        }
864
865 View Code Duplication
        if (isNullOrEmpty($server_name) && isNotNullOrEmpty($logPath)) {
866
            $msg = 'No server name given for calling curl ' . $url . ' behind proxy or LB';
867
            logToFile($logPath, $msg);
868
            return false;
869
        }
870
871
        if (isNullOrEmpty($localServerIpAddress) && isNotNullOrEmptyArrayKey($_SERVER, 'SERVER_ADDR')) {
872
            $localServerIpAddress = $_SERVER['SERVER_ADDR'];
873
        }
874
875 View Code Duplication
        if (isNullOrEmpty($localServerIpAddress) && isNotNullOrEmpty($logPath)) {
876
            $msg = 'No localIPAddress given for calling curl ' . $url . ' behind proxy or LB';
877
            logToFile($logPath, $msg);
878
            return false;
879
        }
880
881
        $url = str_replace($server_name, $localServerIpAddress, $url);
882
883
        //Using the host header to bypass a load balancer
884
        if (!is_array($headers)) {
885
            $headers = array();
886
        }
887
        $headers[] = 'Host: ' . $server_name;
888
889
        return curl($url, $method, $data, $headers, $returnInfo, $user, $password, $sslNotVerifyHostAndPeer,
890
            $followLocation, $timeout, $logPath, $referer, $userAgent);
891
    }
892
}
893
894
if (!function_exists('startLayoutCapture')) {
895
896
    /**
897
     * Turn On the output buffering.
898
     * @return bool
899
     */
900
    function startLayoutCapture() : bool
901
    {
902
        return ob_start();
903
    }
904
}
905
906
if (!function_exists('endLayoutCapture')) {
907
908
    /**
909
     * Get the buffer contents for the topmost buffer and clean it.
910
     * @return string
911
     */
912
    function endLayoutCapture() : string
913
    {
914
        $data = ob_get_contents();
915
        ob_end_clean();
916
        return $data === false ? '' : $data;
917
    }
918
}
919
920
if (!function_exists('get_var_dump_output')) {
921
922
    /**
923
     * Capture var dump $var output and return it.
924
     * @param $var
925
     * @return string
926
     */
927
    function get_var_dump_output($var)
928
    {
929
        startLayoutCapture();
930
        $myfunc = "var_dump";
931
        $myfunc($var);
932
        return endLayoutCapture();
933
    }
934
}
935
936
if (!function_exists('debug')) {
937
938
    /**
939
     * Dump information about a variable.
940
     *
941
     * @param mixed $variable Variable to debug
942
     *
943
     * @return void
944
     * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
945
     */
946
    function debug($variable)
947
    {
948
        $output = get_var_dump_output($variable);
949
        $maps = [
950
            'string' => "/(string\((?P<length>\d+)\)) (?P<value>\"(?<!\\\).*\")/i",
951
            'array' => "/\[\"(?P<key>.+)\"(?:\:\"(?P<class>[a-z0-9_\\\]+)\")?(?:\:(?P<scope>public|protected|private))?\]=>/Ui",
952
            'countable' => "/(?P<type>array|int|string)\((?P<count>\d+)\)/",
953
            'resource' => "/resource\((?P<count>\d+)\) of type \((?P<class>[a-z0-9_\\\]+)\)/",
954
            'bool' => "/bool\((?P<value>true|false)\)/",
955
            'float' => "/float\((?P<value>[0-9\.]+)\)/",
956
            'object' => "/object\((?P<class>\S+)\)\#(?P<id>\d+) \((?P<count>\d+)\)/i"
957
        ];
958
        foreach ($maps as $function => $pattern) {
959
            $output = preg_replace_callback($pattern, function ($matches) use ($function) {
960
                switch ($function) {
961
                    case 'string':
962
                        $matches['value'] = htmlspecialchars($matches['value']);
963
                        return '<span style="color: #0000FF;">string</span>(<span style="color: #1287DB;">' . $matches['length'] . ')</span> <span style="color: #6B6E6E;">' . $matches['value'] . '</span>';
964
                    case 'array':
965
                        $key = '<span style="color: #008000;">"' . $matches['key'] . '"</span>';
966
                        $class = '';
967
                        $scope = '';
968
                        if (isset($matches['class']) && !empty($matches['class'])) {
969
                            $class = ':<span style="color: #4D5D94;">"' . $matches['class'] . '"</span>';
970
                        }
971
                        if (isset($matches['scope']) && !empty($matches['scope'])) {
972
                            $scope = ':<span style="color: #666666;">' . $matches['scope'] . '</span>';
973
                        }
974
                        return '[' . $key . $class . $scope . ']=>';
975
                    case 'countable':
976
                        $type = '<span style="color: #0000FF;">' . $matches['type'] . '</span>';
977
                        $count = '(<span style="color: #1287DB;">' . $matches['count'] . '</span>)';
978
                        return $type . $count;
979
                    case 'bool':
980
                        return '<span style="color: #0000FF;">bool</span>(<span style="color: #0000FF;">' . $matches['value'] . '</span>)';
981
                    case 'float':
982
                        return '<span style="color: #0000FF;">float</span>(<span style="color: #1287DB;">' . $matches['value'] . '</span>)';
983
                    case 'resource':
984
                        return '<span style="color: #0000FF;">resource</span>(<span style="color: #1287DB;">' . $matches['count'] . '</span>) of type (<span style="color: #4D5D94;">' . $matches['class'] . '</span>)';
985
                    case 'object':
986
                        return '<span style="color: #0000FF;">object</span>(<span style="color: #4D5D94;">' . $matches['class'] . '</span>)#' . $matches['id'] . ' (<span style="color: #1287DB;">' . $matches['count'] . '</span>)';
987
                }
988
            }, $output);
989
        }
990
        $header = '';
991
        list($debugfile) = debug_backtrace();
992
        if (!empty($debugfile['file'])) {
993
            $header = '<h4 style="border-bottom:1px solid #bbb;font-weight:bold;margin:0 0 10px 0;padding:3px 0 10px 0">' . $debugfile['file'] . '</h4>';
994
        }
995
        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>';
996
    }
997
}
998
999
if (!function_exists('getReferer')) {
1000
1001
    /**
1002
     * Return referer page if exists otherwise return empty string.
1003
     *
1004
     * @return string
1005
     */
1006
    function getReferer() : string
1007
    {
1008
        return isNotNullOrEmptyArrayKey($_SERVER, 'HTTP_REFERER') ? $_SERVER['HTTP_REFERER'] : '';
1009
    }
1010
}
1011
1012
if (!function_exists('isZlibOutputCompressionActive')) {
1013
1014
    /**
1015
     * Check if zlib output compression was active
1016
     * @return bool
1017
     */
1018
    function isZlibOutputCompressionActive() : bool
1019
    {
1020
        return ini_get('zlib.output_compression') == 'On'
1021
        || ini_get('zlib.output_compression_level') > 0
1022
        || ini_get('output_handler') == 'ob_gzhandler';
1023
    }
1024
}
1025
1026
if (!function_exists('isZlibLoaded')) {
1027
1028
    /**
1029
     * Check if zlib extension was loaded
1030
     * @return bool
1031
     */
1032
    function isZlibLoaded() : bool
1033
    {
1034
        return extension_loaded('zlib');
1035
    }
1036
}
1037
1038
if (!function_exists('isClientAcceptGzipEncoding')) {
1039
1040
    /**
1041
     * Check if client accept gzip encoding
1042
     * @return bool
1043
     */
1044
    function isClientAcceptGzipEncoding() : bool
1045
    {
1046
        return isNotNullOrEmptyArrayKey($_SERVER, 'HTTP_ACCEPT_ENCODING')
1047
        && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false;
1048
    }
1049
}
1050
1051
if (!function_exists('compressHtmlPage')) {
1052
1053
    /**
1054
     * Captures output via ob_get_contents(), tries to enable gzip,
1055
     * removes whitespace from captured output and echos back
1056
     *
1057
     * @return string whitespace stripped output
1058
     * @see https://github.com/ngfw/Recipe/
1059
     */
1060
    function compressHtmlPage() : string
1061
    {
1062
        register_shutdown_function(function () {
1063
            $buffer = str_html_compress(ob_get_contents());
1064
            ob_end_clean();
1065
            if (!isZlibOutputCompressionActive() &&
1066
                isClientAcceptGzipEncoding() &&
1067
                isZlibLoaded()
1068
            ) {
1069
                ob_start('ob_gzhandler');
1070
            }
1071
            echo $buffer;
1072
        });
1073
    }
1074
}
1075
1076
if (!function_exists('get_http_response_code')) {
1077
1078
    /**
1079
     * @param string $theURL
1080
     * @param bool $useGet if set to true use a GET request, otherwise use a HEAD request (more fast).
1081
     * @return int return the http status or 999 if it fails.
1082
     */
1083
    function get_http_response_code(string $theURL, bool $useGet = false) : int
1084
    {
1085
        if (isNullOrEmpty($theURL)) {
1086
            return 999;
1087
        }
1088
        if (!$useGet) {
1089
            // By default get_headers uses a GET request to fetch the headers. If you
1090
            // want to send a HEAD request instead, you can do so using a stream context:
1091
            stream_context_set_default(
1092
                array(
1093
                    'http' => array(
1094
                        'method' => 'HEAD'
1095
                    )
1096
                )
1097
            );
1098
        }
1099
        $headers = @get_headers($theURL);
1100
1101
        if ($headers === false || isNullOrEmptyArray($headers) || strlen($headers[0]) < 12) {
1102
            return 999;
1103
        }
1104
        $status = substr($headers[0], 9, 3);
1105
        return isInteger($status) ? $status : 999;
1106
    }
1107
}
1108
1109
if (!function_exists('url_exists')) {
1110
1111
    /**
1112
     * Check if URL exists (return http status code <400
1113
     * @param string $url
1114
     * @return bool
1115
     */
1116
    function url_exists(string $url) : bool
1117
    {
1118
        return get_http_response_code($url) < 400;
1119
    }
1120
}
1121
1122
if (!function_exists('logToFile')) {
1123
1124
    /**
1125
     * Log variable into log file.
1126
     * @param string $pathFile full path with file name.
1127
     * @param mixed $value value to log
1128
     * @param bool $varDump default false. if set to true,
1129
     * grab var dump output of $value and write it to log, otherwise append it to log.
1130
     */
1131
    function logToFile(string $pathFile, $value, bool $varDump = false)
1132
    {
1133
        if ($varDump) {
1134
            $value = get_var_dump_output($value);
1135
        }
1136
        $f = fopen($pathFile, 'ab');
1137
        fwrite($f, date(DATE_RFC822) . "\r\n" . $value . "\r\n----------------------------------------------\r\n");
1138
        fclose($f);
1139
    }
1140
}
1141
1142
/**
1143
 * Check if an extension is an image type.
1144
 * @param  string $ext extension to check
1145
 * @return boolean
1146
 * @see https://github.com/kohana/ohanzee-helpers/blob/master/src/Mime.php
1147
 */
1148
function isImageExtension(string $ext) : bool
1149
{
1150
    return in_array(strtolower($ext), getImageExtensions());
1151
}
1152
1153
/**
1154
 * Get a list of common image extensions. Only types that can be read by
1155
 * PHP's internal image methods are included!
1156
 * @return string[]
1157
 */
1158
function getImageExtensions() : array
1159
{
1160
    return [
1161
        'bmp',
1162
        'gif',
1163
        'jpeg',
1164
        'jpg',
1165
        'png',
1166
        'tif',
1167
        'tiff',
1168
        'swf',
1169
    ];
1170
}
1171
1172
/**
1173
 * Very simple 'template' parser. Replaces (for example) {name} with the value of $vars['name'] in strings
1174
 *
1175
 * @param        $str
1176
 * @param array $vars
1177
 * @param string $openDelimiter
1178
 * @param string $closeDelimiter
1179
 *
1180
 * @return string
1181
 * @see https://github.com/laradic/support/blob/master/src/Util.php
1182
 * @example
1183
 * <?php
1184
 * $result = template('This is the best template parser. Created by {developerName}', ['developerName' => 'Radic']);
1185
 * echo $result; // This is the best template parser. Created by Radic
1186
 */
1187
function template($str, array $vars = [], $openDelimiter = '{', $closeDelimiter = '}')
1188
{
1189
    foreach ($vars as $k => $var) {
1190
        if (is_array($var)) {
1191
            $str = template($str, $var);
1192
        } elseif (is_string($var)) {
1193
            $str = str_replace($openDelimiter . $k . $closeDelimiter, $var, $str);
1194
        }
1195
    }
1196
    return $str;
1197
}
1198
1199
/**
1200
 * @param int $percent
1201
 * @return bool
1202
 * @see https://github.com/laradic/support/blob/master/src/Util.php
1203
 */
1204
function randomChance(int $percent = 50) : bool
1205
{
1206
    return random_int(0, 100) > 100 - $percent;
1207
}
1208
1209
/**
1210
 * @param Throwable $exception
1211
 * @return string
1212
 */
1213
function getExceptionTraceAsString(\Throwable $exception)
1214
{
1215
    $rtn = "";
1216
    $count = 0;
1217
    foreach ($exception->getTrace() as $frame) {
1218
        $args = "";
1219
        if (isset($frame['args'])) {
1220
            $args = [];
1221
            foreach ($frame['args'] as $arg) {
1222
                if (is_string($arg)) {
1223
                    $args[] = "'" . $arg . "'";
1224
                } elseif (is_array($arg)) {
1225
                    $args[] = "Array";
1226
                } elseif (is_null($arg)) {
1227
                    $args[] = 'NULL';
1228
                } elseif (is_bool($arg)) {
1229
                    $args[] = ($arg) ? "true" : "false";
1230
                } elseif (is_object($arg)) {
1231
                    $args[] = get_class($arg);
1232
                } elseif (is_resource($arg)) {
1233
                    $args[] = get_resource_type($arg);
1234
                } else {
1235
                    $args[] = $arg;
1236
                }
1237
            }
1238
            $args = implode(", ", $args);
1239
        }
1240
        $rtn .= sprintf("#%s %s(%s): %s(%s)\n",
1241
            $count,
1242
            isset($frame['file']) ? $frame['file'] : '',
1243
            isset($frame['line']) ? $frame['line'] : '',
1244
            $frame['function'],
1245
            $args);
1246
        $count++;
1247
    }
1248
    return $rtn;
1249
}
1250
1251
if (!function_exists('windows_os')) {
1252
    /**
1253
     * Determine whether the current environment is Windows based.
1254
     *
1255
     * @return bool
1256
     *
1257
     * @see https://github.com/illuminate/support/blob/master/helpers.php
1258
     */
1259
    function windows_os() : bool
1260
    {
1261
        return strtolower(substr(PHP_OS, 0, 3)) === 'win';
1262
    }
1263
}
1264
1265
if (!function_exists('getConsoleColorTagForStatusCode')) {
1266
    /**
1267
     * Get the color tag for the given status code to be use in symfony/laravel console.
1268
     *
1269
     * @param string $code
1270
     *
1271
     * @return string
1272
     *
1273
     * @see https://github.com/spatie/http-status-check/blob/master/src/CrawlLogger.php#L96
1274
     */
1275
    function getConsoleColorTagForStatusCode($code)
1276
    {
1277
        if (starts_with($code, '2')) {
1278
            return 'info';
1279
        }
1280
        if (starts_with($code, '3')) {
1281
            return 'comment';
1282
        }
1283
        return 'error';
1284
    }
1285
}
1286
1287
if (!function_exists('is_32bit')) {
1288
    /**
1289
     * Check if the OS architecture is 32bit.
1290
     *
1291
     * @return bool
1292
     *
1293
     * @see http://stackoverflow.com/questions/6303241/find-windows-32-or-64-bit-using-php
1294
     */
1295
    function is_32bit() : bool
1296
    {
1297
        return get_os_architecture()==32;
1298
    }
1299
}
1300
1301
if (!function_exists('is_64bit')) {
1302
    /**
1303
     * Check if the OS architecture is 64bit.
1304
     *
1305
     * @return bool
1306
     *
1307
     * @see http://stackoverflow.com/questions/6303241/find-windows-32-or-64-bit-using-php
1308
     */
1309
    function is_64bit() : bool
1310
    {
1311
        return get_os_architecture()==64;
1312
    }
1313
}
1314
1315
if (!function_exists('get_os_architecture')) {
1316
    /**
1317
     * Get the OS architecture 32 or 64 bit.
1318
     *
1319
     * @return int return 32 or 64 if ok, otherwise return 0.
1320
     *
1321
     * @see http://stackoverflow.com/questions/6303241/find-windows-32-or-64-bit-using-php
1322
     */
1323
    function get_os_architecture() : int
1324
    {
1325
        switch(PHP_INT_SIZE) {
1326
            case 4:
1327
                return 32;
1328
            case 8:
1329
                return 64;
1330
            default:
1331
                return 0;
1332
        }
1333
    }
1334
}
1335
1336
1337
if (!function_exists('isRequestFromCloudFlare')) {
1338
1339
    /**
1340
     * Check if request (by given $_SERVER) is a cloudflare request
1341
     * @param $server
1342
     * @return bool
1343
     */
1344
    function isRequestFromCloudFlare(array $server) : bool
1345
    {
1346
        if (!isset($server['HTTP_CF_CONNECTING_IP']) || !isIP($server['HTTP_CF_CONNECTING_IP'])) {
1347
            return false;
1348
        }
1349
1350
        if (isCloudFlareIp($server['REMOTE_ADDR'])) {
1351
            return true;
1352
        }
1353
1354
        //in case proxy or load balancer in front the server web
1355
        //the chained passed IPs are in the HTTP_X_FORWARDED_FOR var in these two possible ways:
1356
        //2.38.87.88
1357
        //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...
1358
        if (empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
1359
            return false;
1360
        }
1361
1362
        if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',') === false) {
1363
            return isCloudFlareIp($server['HTTP_X_FORWARDED_FOR']);
1364
        }
1365
1366
        $IPs = explode(",", $_SERVER['HTTP_X_FORWARDED_FOR']);
1367
        if (empty($IPs) || !is_array($IPs) || count($IPs) < 1) {
1368
            return false;
1369
        }
1370
1371
        //usually the cloudflare ip are the last IP in the stack, so start loop by last entries
1372
        for ($i = count($IPs) - 1; $i >= 0; $i--) {
1373
            $ip = trim($IPs[$i]);
1374
            if (isCloudFlareIp($ip)) {
1375
                return true;
1376
            }
1377
        }
1378
1379
        return false;
1380
    }
1381
}
1382
1383
if (!function_exists('isCloudFlareIp')) {
1384
1385
    /**
1386
     * Check if given ip is a valid cloudflare ip.
1387
     * @param $ip
1388
     * @return bool
1389
     */
1390
    function isCloudFlareIp($ip) : bool
1391
    {
1392
        if (!isIP($ip)) {
1393
            return false;
1394
        }
1395
1396
        //array given from https://www.cloudflare.com/ips-v4
1397
        $cf_ip_ranges = array(
1398
            '103.21.244.0/22',
1399
            '103.22.200.0/22',
1400
            '103.31.4.0/22',
1401
            '104.16.0.0/12',
1402
            '108.162.192.0/18',
1403
            '131.0.72.0/22',
1404
            '141.101.64.0/18',
1405
            '162.158.0.0/15',
1406
            '172.64.0.0/13',
1407
            '173.245.48.0/20',
1408
            '188.114.96.0/20',
1409
            '190.93.240.0/20',
1410
            '197.234.240.0/22',
1411
            '198.41.128.0/17',
1412
        );
1413
1414
        foreach ($cf_ip_ranges as $range) {
1415
            if (ipInRange($ip, $range)) {
1416
                return true;
1417
            }
1418
        }
1419
1420
        return false;
1421
    }
1422
}
1423