Subversion Repositories php_utils

Rev

Rev 63 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
38 daniel-mar 1
<?php
2
 
3
/*
4
 * PHP Utilities - Misc functions
63 daniel-mar 5
 * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft
85 daniel-mar 6
 * Revision: 2023-08-01
38 daniel-mar 7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
 
21
// array(89,51,10,10) => 'Y3\012\012'
22
function c_literal($byte_array) {
23
        $out = "'";
24
        foreach ($byte_array as $c) {
25
                if (is_string($c)) $c = ord($c);
26
                if ((($c >= 0x00) && ($c <= 0x1F)) || ($c >= 0x7F)) {
27
                        // For non-printable characters use octal notation:
28
                        // \000 ... \377
39 daniel-mar 29
                        $out .= "\\".str_pad(base_convert(''.$c,10,8), 3, '0', STR_PAD_LEFT);
38 daniel-mar 30
                } else {
31
                        if (chr($c) == "'") $out .= '\\';
32
                        $out .= chr($c);
33
                }
34
        }
35
        $out .= "'";
36
        return $out;
37
}
38
 
39
function c_literal_hexstr($hexstr) {
40
        $odd_char = (strlen($hexstr)%2 != 0) ? '0x'.substr($hexstr,-1).'<<4' : '';
39 daniel-mar 41
        $hexstr = substr($hexstr,0,2*(int)floor(strlen($hexstr)/2));
38 daniel-mar 42
        if ($hexstr != '') {
43
                $ary = str_split(hex2bin($hexstr));
44
                foreach ($ary as &$a) $a = ord($a);
45
                return rtrim(c_literal($ary).' '.$odd_char);
46
        } else {
47
                return $odd_char;
48
        }
49
}
50
 
51
function generateRandomString($length) {
52
        // Note: This function can be used in temporary file names, so you
53
        // may not generate illegal file name characters.
54
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
55
        $charactersLength = strlen($characters);
56
        $randomString = '';
57
        for ($i = 0; $i < $length; $i++) {
58
                $randomString .= $characters[rand(0, $charactersLength - 1)];
59
        }
60
        return $randomString;
61
}
62
 
63
function trim_br($html) {
64
        $count = 0;
65
        do { $html = preg_replace('@^\s*<\s*br\s*/{0,1}\s*>@isU', '', $html, -1, $count); } while ($count > 0); // left trim
66
        do { $html = preg_replace('@<\s*br\s*/{0,1}\s*>\s*$@isU', '', $html, -1, $count); } while ($count > 0); // right trim
67
        return $html;
68
}
69
 
70
function insertWhitespace($str, $index) {
71
        return substr($str, 0, $index) . ' ' . substr($str, $index);
72
}
73
 
74
function js_escape($data) {
75
        // TODO.... json_encode??
76
        $data = str_replace('\\', '\\\\', $data);
77
        $data = str_replace('\'', '\\\'', $data);
78
        return "'" . $data . "'";
79
}
80
 
81
function get_calling_function() {
82
        $ex = new Exception();
83
        $trace = $ex->getTrace();
39 daniel-mar 84
        if (!isset($trace[2])) return '(main)';
38 daniel-mar 85
        $final_call = $trace[2];
86
        return $final_call['file'].':'.$final_call['line'].'/'.$final_call['function'].'()';
87
}
88
 
89
function convert_to_utf8_no_bom($cont) {
52 daniel-mar 90
        $cont = vts_utf8_encode($cont);
38 daniel-mar 91
 
92
        // Remove BOM
93
        $bom = pack('H*','EFBBBF');
94
        $cont = preg_replace("/^$bom/", '', $cont);
95
        return $cont;
96
}
97
 
52 daniel-mar 98
function vts_utf8_encode($text) {
99
        $enc = mb_detect_encoding($text, null, true);
100
        if ($enc === false) $enc = mb_detect_encoding($text, ['ASCII', 'UTF-8', 'Windows-1252', 'ISO-8859-1'], true);
101
        if ($enc === false) $enc = null;
102
 
103
        if ($enc === 'UTF-8') return $text;
104
 
105
        $res = mb_convert_encoding($text, 'UTF-8', $enc);
106
        if ($res === false) $res = iconv('UTF-8', 'UTF-8//IGNORE', $text);
107
 
108
        return $res;
109
}
110
 
56 daniel-mar 111
function vts_utf8_decode($text) {
112
        $enc = mb_detect_encoding($text, null, true);
113
        if ($enc === false) $enc = mb_detect_encoding($text, ['ASCII', 'UTF-8', 'Windows-1252', 'ISO-8859-1'], true);
114
        if ($enc === false) $enc = null;
115
 
116
        if ($enc !== 'UTF-8') return $text;
117
 
118
        $res = mb_convert_encoding($text, 'Windows-1252', $enc);
119
        if ($res === false) $res = iconv('Windows-1252', 'Windows-1252//IGNORE', $text);
120
 
121
        return $res;
122
}
123
 
38 daniel-mar 124
function stripHtmlComments($html) {
125
        // https://stackoverflow.com/questions/11337332/how-to-remove-html-comments-in-php
126
        $html = preg_replace("~<!--(?!<!)[^\[>].*?-->~s", "", $html);
127
        return $html;
128
}
129
 
130
function wildcard_is_dir($dir) {
131
        // Example usage:  if (!wildcard_is_dir(OIDplus::localpath().'plugins/'.'*'.'/design/'.$value)) throw new Exception("Design does not exist")
132
        $dirs = @glob($dir);
133
        if ($dirs) foreach ($dirs as $dir) {
134
                if (is_dir($dir)) return true;
135
        }
136
        return false;
137
}
138
 
139
function isInternetExplorer() {
140
        $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
141
        return ((strpos($ua,'MSIE ') !== false) || (strpos($ua,'Trident/') !== false));
39 daniel-mar 142
}
63 daniel-mar 143
 
85 daniel-mar 144
if (!function_exists('str_starts_with')) {
145
        // PHP 7.x compatibility
146
        // source: Laravel Framework
147
        // https://github.com/laravel/framework/blob/8.x/src/Illuminate/Support/Str.php
148
        function str_starts_with($haystack, $needle) {
149
                return (string)$needle !== '' && strncmp($haystack, $needle, strlen($needle)) === 0;
150
        }
151
}
152
 
63 daniel-mar 153
if (!function_exists('str_ends_with')) {
154
        // PHP 7.x compatibility
85 daniel-mar 155
        // source: Laravel Framework
156
        // https://github.com/laravel/framework/blob/8.x/src/Illuminate/Support/Str.php
63 daniel-mar 157
        function str_ends_with($haystack, $needle) {
85 daniel-mar 158
                return $needle !== '' && substr($haystack, -strlen($needle)) === (string)$needle;
63 daniel-mar 159
        }
160
}
161
 
85 daniel-mar 162
if (!function_exists('str_contains')) {
63 daniel-mar 163
        // PHP 7.x compatibility
85 daniel-mar 164
        // source: Laravel Framework
165
        // https://github.com/laravel/framework/blob/8.x/src/Illuminate/Support/Str.php
166
        function str_contains($haystack, $needle) {
167
                return $needle !== '' && mb_strpos($haystack, $needle) !== false;
63 daniel-mar 168
        }
169
}
170
 
171
function random_bytes_ex($len, $raw=true, $force_cryptographically_secure=true) {
172
        if ($len === 0) return '';
173
        assert($len > 0);
174
 
175
        if (function_exists('random_bytes')) {
176
                try {
177
                        $a = random_bytes($len);
178
                } catch (Exception $e) { $a = null; }
179
                if ($a) return $raw ? $a : bin2hex($a);
180
        }
181
 
182
        if (function_exists('openssl_random_pseudo_bytes')) {
183
                try {
184
                        $a = openssl_random_pseudo_bytes($len);
185
                } catch (Exception $e) { $a = null; }
186
                if ($a) return $raw ? $a : bin2hex($a);
187
        }
188
 
189
        if (function_exists('mcrypt_create_iv') && defined('MCRYPT_DEV_RANDOM')) {
190
                try {
191
                        $a = bin2hex(mcrypt_create_iv($len, MCRYPT_DEV_RANDOM));
192
                } catch (Exception $e) { $a = null; }
193
                if ($a) return $raw ? $a : bin2hex($a);
194
        }
195
 
196
        if ($force_cryptographically_secure) {
197
                $msg = 'Cannot find a fitting Cryptographically Secure Random Number Generator (CSRNG).';
198
                if (version_compare(PHP_VERSION, '8.2.0') >= 0) {
199
                        throw new \Random\RandomException($msg);
200
                } else {
201
                        throw new \Exception($msg);
202
                }
203
        }
204
 
205
        if (function_exists('mcrypt_create_iv') && defined('MCRYPT_DEV_URANDOM')) {
206
                // /dev/urandom uses the same entropy pool than /dev/random, but if there is not enough data
207
                // then the security is lowered.
208
                try {
209
                        $a = bin2hex(mcrypt_create_iv($len, MCRYPT_DEV_URANDOM));
210
                } catch (Exception $e) { $a = null; }
211
                if ($a) return $raw ? $a : bin2hex($a);
212
        }
213
 
214
        if (function_exists('mcrypt_create_iv') && defined('MCRYPT_RAND')) {
215
                try {
216
                        $a = bin2hex(mcrypt_create_iv($len, MCRYPT_RAND));
217
                } catch (Exception $e) { $a = null; }
218
                if ($a) return $raw ? $a : bin2hex($a);
219
        }
220
 
221
        // Fallback to non-secure RNG
222
        $a = '';
223
        while (strlen($a) < $len*2) {
224
                $a .= sha1(uniqid((string)mt_rand(), true));
225
        }
226
        $a = substr($a, 0, $len*2);
227
        return $raw ? hex2bin($a) : $a;
228
}