Subversion Repositories oidplus

Rev

Rev 824 | Rev 847 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
773 daniel-mar 5
 * Copyright 2019 - 2022 Daniel Marschall, ViaThinkSoft
2 daniel-mar 6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
 
20
function insertWhitespace($str, $index) {
21
        return substr($str, 0, $index) . ' ' . substr($str, $index);
22
}
23
 
24
function js_escape($data) {
25
        // TODO.... json_encode??
289 daniel-mar 26
        $data = str_replace('\\', '\\\\', $data);
27
        $data = str_replace('\'', '\\\'', $data);
28
        return "'" . $data . "'";
2 daniel-mar 29
}
30
 
11 daniel-mar 31
function trim_br($html) {
386 daniel-mar 32
        $count = 0;
11 daniel-mar 33
        do { $html = preg_replace('@^\s*<\s*br\s*/{0,1}\s*>@isU', '', $html, -1, $count); } while ($count > 0); // left trim
34
        do { $html = preg_replace('@<\s*br\s*/{0,1}\s*>\s*$@isU', '', $html, -1, $count); } while ($count > 0); // right trim
35
        return $html;
36
}
74 daniel-mar 37
 
453 daniel-mar 38
function generateRandomString($length) {
653 daniel-mar 39
        // Note: This function can be used in temporary file names, so you
40
        // may not generate illegal file name characters.
453 daniel-mar 41
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
42
        $charactersLength = strlen($characters);
43
        $randomString = '';
44
        for ($i = 0; $i < $length; $i++) {
45
                $randomString .= $characters[rand(0, $charactersLength - 1)];
46
        }
47
        return $randomString;
48
}
49
 
830 daniel-mar 50
function is_privatekey_encrypted($privKey) {
51
        return strpos($privKey,'BEGIN ENCRYPTED PRIVATE KEY') !== false;
52
}
53
 
74 daniel-mar 54
function verify_private_public_key($privKey, $pubKey) {
721 daniel-mar 55
        if (!function_exists('openssl_public_encrypt')) return false;
74 daniel-mar 56
        try {
57
                if (empty($privKey)) return false;
58
                if (empty($pubKey)) return false;
453 daniel-mar 59
                $data = generateRandomString(25);
386 daniel-mar 60
                $encrypted = '';
61
                $decrypted = '';
74 daniel-mar 62
                if (!@openssl_public_encrypt($data, $encrypted, $pubKey)) return false;
63
                if (!@openssl_private_decrypt($encrypted, $decrypted, $privKey)) return false;
64
                return $decrypted == $data;
65
        } catch (Exception $e) {
66
                return false;
67
        }
68
}
69
 
830 daniel-mar 70
function change_private_key_passphrase($privKeyOld, $passphrase_old, $passphrase_new) {
71
        $pkey_config = array(
72
            //"digest_alg" => "sha512",
73
            //"private_key_bits" => 2048,
74
            //"private_key_type" => OPENSSL_KEYTYPE_RSA,
75
            "config" => class_exists("OIDplus") ? OIDplus::getOpenSslCnf() : @getenv('OPENSSL_CONF')
76
        );
77
        $privKeyNew = @openssl_pkey_get_private($privKeyOld, $passphrase_old);
78
        if ($privKeyNew === false) return false;
79
        @openssl_pkey_export($privKeyNew, $privKeyNewExport, $passphrase_new, $pkey_config);
80
        if ($privKeyNewExport === false) return false;
81
        return $privKeyNewExport."";
82
}
83
 
84
function decrypt_private_key($privKey, $passphrase) {
85
        return change_private_key_passphrase($privKey, $passphrase, null);
86
}
87
 
88
function encrypt_private_key($privKey, $passphrase) {
89
        return change_private_key_passphrase($privKey, null, $passphrase);
90
}
91
 
74 daniel-mar 92
function smallhash($data) { // get 31 bits from SHA1. Values 0..2147483647
250 daniel-mar 93
        return (hexdec(substr(sha1($data),-4*2)) & 0x7FFFFFFF);
74 daniel-mar 94
}
180 daniel-mar 95
 
182 daniel-mar 96
function split_firstname_lastname($name) {
97
        $ary = explode(' ', $name);
98
        $last_name = array_pop($ary);
99
        $first_name = implode(' ', $ary);
100
        return array($first_name, $last_name);
101
}
102
 
180 daniel-mar 103
function originHeaders() {
104
        // CORS
105
        // Author: Till Wehowski
426 daniel-mar 106
        // TODO: add to class OIDplus
182 daniel-mar 107
 
180 daniel-mar 108
        header("Access-Control-Allow-Credentials: true");
109
        header("Access-Control-Allow-Origin: ".strip_tags(((isset($_SERVER['HTTP_ORIGIN'])) ? $_SERVER['HTTP_ORIGIN'] : "*")));
110
 
111
        header("Access-Control-Allow-Headers: If-None-Match, X-Requested-With, Origin, X-Frdlweb-Bugs, Etag, X-Forgery-Protection-Token, X-CSRF-Token");
112
 
113
        if (isset($_SERVER['HTTP_ORIGIN'])) {
114
                header('X-Frame-Options: ALLOW-FROM '.$_SERVER['HTTP_ORIGIN']);
115
        } else {
116
                header_remove("X-Frame-Options");
117
        }
118
 
119
        $expose = array('Etag', 'X-CSRF-Token');
120
        foreach (headers_list() as $num => $header) {
121
                $h = explode(':', $header);
122
                $expose[] = trim($h[0]);
123
        }
124
        header("Access-Control-Expose-Headers: ".implode(',',$expose));
125
 
126
        header("Vary: Origin");
127
}
236 daniel-mar 128
 
129
function get_calling_function() {
130
        $ex = new Exception();
131
        $trace = $ex->getTrace();
360 daniel-mar 132
        if (!isset($trace[2])) return _L('(main)');
236 daniel-mar 133
        $final_call = $trace[2];
134
        return $final_call['file'].':'.$final_call['line'].'/'.$final_call['function'].'()';
135
}
346 daniel-mar 136
 
137
if (!function_exists('mb_wordwrap')) {
138
        function mb_wordwrap($str, $width = 75, $break = "\n", $cut = false) {
139
                // https://stackoverflow.com/a/4988494/488539
140
                $lines = explode($break, $str);
141
                foreach ($lines as &$line) {
142
                        $line = rtrim($line);
143
                        if (mb_strlen($line) <= $width) {
144
                                continue;
145
                        }
146
                        $words = explode(' ', $line);
147
                        $line = '';
148
                        $actual = '';
149
                        foreach ($words as $word) {
150
                                if (mb_strlen($actual.$word) <= $width) {
151
                                        $actual .= $word.' ';
152
                                } else {
153
                                        if ($actual != '') {
154
                                                $line .= rtrim($actual).$break;
155
                                        }
156
                                        $actual = $word;
157
                                        if ($cut) {
158
                                                while (mb_strlen($actual) > $width) {
159
                                                        $line .= mb_substr($actual, 0, $width).$break;
160
                                                        $actual = mb_substr($actual, $width);
161
                                                }
162
                                        }
163
                                        $actual .= ' ';
164
                                }
165
                        }
166
                        $line .= trim($actual);
167
                }
168
                return implode($break, $lines);
169
        }
170
}
355 daniel-mar 171
 
379 daniel-mar 172
function httpOutWithETag($out, $contentType, $filename='') {
173
        $etag = md5($out);
174
        header("Etag: $etag");
175
        header("Content-MD5: $etag"); // RFC 2616 clause 14.15
176
        if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && (trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag)) {
177
                header("HTTP/1.1 304 Not Modified");
178
        } else {
179
                header("Content-Type: $contentType");
180
                if (!empty($filename)) {
181
                        header('Content-Disposition:inline; filename="'.$filename.'"');
182
                }
183
                echo $out;
184
        }
185
        die();
186
}
187
 
360 daniel-mar 188
function my_vsprintf($str, $args) {
189
        $n = 1;
190
        foreach ($args as $val) {
191
                $str = str_replace("%$n", $val, $str);
192
                $n++;
193
        }
370 daniel-mar 194
        $str = str_replace("%%", "%", $str);
360 daniel-mar 195
        return $str;
196
}
197
 
355 daniel-mar 198
function _L($str, ...$sprintfArgs) {
401 daniel-mar 199
        static $translation_array = array();
200
        static $translation_loaded = null;
201
 
506 daniel-mar 202
        $str = trim($str);
203
 
438 daniel-mar 204
        if (!class_exists('OIDplus')) {
205
                return my_vsprintf($str, $sprintfArgs);
206
        }
207
 
360 daniel-mar 208
        $lang = OIDplus::getCurrentLang();
468 daniel-mar 209
        $ta = OIDplus::getTranslationArray($lang);
210
        $res = (isset($ta[$lang]) && isset($ta[$lang][$str])) ? $ta[$lang][$str] : $str;
360 daniel-mar 211
 
212
        $res = str_replace('###', OIDplus::baseConfig()->getValue('TABLENAME_PREFIX', ''), $res);
213
 
214
        $res = my_vsprintf($res, $sprintfArgs);
215
 
216
        return $res;
370 daniel-mar 217
}
386 daniel-mar 218
 
552 daniel-mar 219
function _CheckParamExists($params, $key) {
698 daniel-mar 220
        if (class_exists('OIDplusException')) {
221
                if (!isset($params[$key])) throw new OIDplusException(_L('Parameter %1 is missing', $key));
222
        } else {
223
                if (!isset($params[$key])) throw new Exception(_L('Parameter %1 is missing', $key));
224
        }
552 daniel-mar 225
}
226
 
721 daniel-mar 227
function convert_to_utf8_no_bom($cont) {
725 daniel-mar 228
        if (mb_detect_encoding($cont, "auto", true) != 'UTF-8') {
229
                # $cont = mb_convert_encoding($cont, 'UTF-8', 'Windows-1252');
230
                # $cont = mb_convert_encoding($cont, 'UTF-8', 'auto');
231
                $cont = mb_convert_encoding($cont, 'UTF-8');
721 daniel-mar 232
        }
233
 
234
        // Remove BOM
386 daniel-mar 235
        $bom = pack('H*','EFBBBF');
236
        $cont = preg_replace("/^$bom/", '', $cont);
721 daniel-mar 237
        return $cont;
238
}
386 daniel-mar 239
 
821 daniel-mar 240
function stripHtmlComments($html) {
824 daniel-mar 241
        // https://stackoverflow.com/questions/11337332/how-to-remove-html-comments-in-php
242
        $html = preg_replace("~<!--(?!<!)[^\[>].*?-->~s", "", $html);
821 daniel-mar 243
        return $html;
244
}
245
 
721 daniel-mar 246
function extractHtmlContents($cont) {
247
        // make sure the program works even if the user provided HTML is not UTF-8
248
        $cont = convert_to_utf8_no_bom($cont);
249
 
386 daniel-mar 250
        $out_js = '';
251
        $m = array();
252
        preg_match_all('@<script[^>]*>(.+)</script>@ismU', $cont, $m);
253
        foreach ($m[1] as $x) {
254
                $out_js = $x . "\n\n";
255
        }
256
 
257
        $out_css = '';
258
        $m = array();
259
        preg_match_all('@<style[^>]*>(.+)</style>@ismU', $cont, $m);
260
        foreach ($m[1] as $x) {
261
                $out_css = $x . "\n\n";
262
        }
263
 
264
        $out_html = $cont;
265
        $out_html = preg_replace('@^(.+)<body[^>]*>@isU', '', $out_html);
266
        $out_html = preg_replace('@</body>.+$@isU', '', $out_html);
267
        $out_html = preg_replace('@<title>.+</title>@isU', '', $out_html);
268
        $out_html = preg_replace('@<h1>.+</h1>@isU', '', $out_html, 1);
269
        $out_html = preg_replace('@<script[^>]*>(.+)</script>@ismU', '', $out_html);
270
        $out_html = preg_replace('@<style[^>]*>(.+)</style>@ismU', '', $out_html);
271
 
272
        return array($out_html, $out_js, $out_css);
392 daniel-mar 273
}
274
 
400 daniel-mar 275
function sha3_512($password, $raw_output=false) {
392 daniel-mar 276
        if (version_compare(PHP_VERSION, '7.1.0') >= 0) {
400 daniel-mar 277
                return hash('sha3-512', $password, $raw_output);
392 daniel-mar 278
        } else {
400 daniel-mar 279
                return bb\Sha3\Sha3::hash($password, 512, $raw_output);
392 daniel-mar 280
        }
281
}
486 daniel-mar 282
 
710 daniel-mar 283
function sha3_512_hmac($message, $key, $raw_output=false) {
284
        // RFC 2104 HMAC
285
                if (version_compare(PHP_VERSION, '7.1.0') >= 0) {
286
                                return hash_hmac('sha3-512', $message, $key, $raw_output);
287
                } else {
288
                $blocksize = 576; // block size of sha-512!
289
 
290
                if (strlen($key) > ($blocksize/8)) {
291
                        $k_ = sha3_512($key,true);
292
                } else {
293
                        $k_ = $key;
294
                }
295
 
296
                $k_opad = str_repeat(chr(0x5C),($blocksize/8));
297
                $k_ipad = str_repeat(chr(0x36),($blocksize/8));
298
                for ($i=0; $i<strlen($k_); $i++) {
299
                        $k_opad[$i] = $k_opad[$i] ^ $k_[$i];
300
                        $k_ipad[$i] = $k_ipad[$i] ^ $k_[$i];
301
                }
302
 
303
                return sha3_512($k_opad . sha3_512($k_ipad . $message, true));
304
                }
305
}
306
 
625 daniel-mar 307
if (!function_exists('str_ends_with')) {
308
        // PHP 7.x compatibility
309
        function str_ends_with($haystack, $needle) {
310
                $length = strlen($needle);
311
                return $length > 0 ? substr($haystack, -$length) === $needle : true;
312
        }
313
}
314
 
315
if (!function_exists('str_starts_with')) {
316
        // PHP 7.x compatibility
317
        function str_starts_with($haystack, $needle) {
318
                return strpos($haystack, $needle) === 0;
319
        }
320
}
321
 
632 daniel-mar 322
function rec_is_dir($dir) {
719 daniel-mar 323
        $dirs = @glob($dir);
324
        if ($dirs) foreach ($dirs as $dir) {
632 daniel-mar 325
                if (is_dir($dir)) return true;
326
        }
327
        return false;
328
}
329
 
641 daniel-mar 330
function isInternetExplorer() {
331
        // see also includes/oidplus_base.js
332
        $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
333
        return ((strpos($ua,'MSIE ') !== false) || (strpos($ua,'Trident/') !== false));
334
}
653 daniel-mar 335
 
336
function url_get_contents($url) {
337
        if (function_exists('curl_init')) {
338
                $ch = curl_init();
698 daniel-mar 339
                if (class_exists('OIDplus')) {
340
                        if (ini_get('curl.cainfo') == '') curl_setopt($ch, CURLOPT_CAINFO, OIDplus::localpath() . 'vendor/cacert.pem');
341
                }
653 daniel-mar 342
                curl_setopt($ch, CURLOPT_URL, $url);
715 daniel-mar 343
                curl_setopt($ch, CURLOPT_USERAGENT, 'ViaThinkSoft-OIDplus/2.0');
653 daniel-mar 344
                curl_setopt($ch, CURLOPT_POST, 0);
345
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
346
                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
347
                curl_setopt($ch, CURLOPT_AUTOREFERER, true);
348
                if (!($res = @curl_exec($ch))) return false;
807 daniel-mar 349
                if (@curl_getinfo($ch, CURLINFO_HTTP_CODE) >= 400) return false;
350
                @curl_close($ch);
653 daniel-mar 351
        } else {
716 daniel-mar 352
                $opts = [
353
                        "http" => [
354
                                "method" => "GET",
355
                                "header" => "User-Agent: ViaThinkSoft-OIDplus/2.0\r\n"
356
                        ]
357
                ];
358
                $context = stream_context_create($opts);
359
                $res = @file_get_contents($url, false, $context);
653 daniel-mar 360
                if ($res === false) return false;
361
        }
362
        return $res;
660 daniel-mar 363
}
778 daniel-mar 364
 
365
function getSortedQuery() {
366
        // https://stackoverflow.com/a/51777249/488539
367
        $url = [];
368
        parse_str($_SERVER['QUERY_STRING'], $url);
369
        ksort($url);
370
        return http_build_query($url);
371
}