Subversion Repositories php_utils

Rev

Rev 63 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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