Subversion Repositories oidplus

Rev

Rev 1021 | Rev 1068 | 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
 
1050 daniel-mar 20
use ViaThinkSoft\OIDplus\OIDplus;
21
 
830 daniel-mar 22
function is_privatekey_encrypted($privKey) {
23
        return strpos($privKey,'BEGIN ENCRYPTED PRIVATE KEY') !== false;
24
}
25
 
74 daniel-mar 26
function verify_private_public_key($privKey, $pubKey) {
721 daniel-mar 27
        if (!function_exists('openssl_public_encrypt')) return false;
74 daniel-mar 28
        try {
29
                if (empty($privKey)) return false;
30
                if (empty($pubKey)) return false;
453 daniel-mar 31
                $data = generateRandomString(25);
386 daniel-mar 32
                $encrypted = '';
33
                $decrypted = '';
74 daniel-mar 34
                if (!@openssl_public_encrypt($data, $encrypted, $pubKey)) return false;
35
                if (!@openssl_private_decrypt($encrypted, $decrypted, $privKey)) return false;
36
                return $decrypted == $data;
1050 daniel-mar 37
        } catch (\Exception $e) {
74 daniel-mar 38
                return false;
39
        }
40
}
41
 
830 daniel-mar 42
function change_private_key_passphrase($privKeyOld, $passphrase_old, $passphrase_new) {
43
        $pkey_config = array(
44
            //"digest_alg" => "sha512",
45
            //"private_key_bits" => 2048,
46
            //"private_key_type" => OPENSSL_KEYTYPE_RSA,
1050 daniel-mar 47
            "config" => class_exists("\\ViaThinkSoft\\OIDplus\\OIDplus") ? OIDplus::getOpenSslCnf() : @getenv('OPENSSL_CONF')
830 daniel-mar 48
        );
49
        $privKeyNew = @openssl_pkey_get_private($privKeyOld, $passphrase_old);
50
        if ($privKeyNew === false) return false;
51
        @openssl_pkey_export($privKeyNew, $privKeyNewExport, $passphrase_new, $pkey_config);
52
        if ($privKeyNewExport === false) return false;
53
        return $privKeyNewExport."";
54
}
55
 
56
function decrypt_private_key($privKey, $passphrase) {
57
        return change_private_key_passphrase($privKey, $passphrase, null);
58
}
59
 
60
function encrypt_private_key($privKey, $passphrase) {
61
        return change_private_key_passphrase($privKey, null, $passphrase);
62
}
63
 
74 daniel-mar 64
function smallhash($data) { // get 31 bits from SHA1. Values 0..2147483647
250 daniel-mar 65
        return (hexdec(substr(sha1($data),-4*2)) & 0x7FFFFFFF);
74 daniel-mar 66
}
180 daniel-mar 67
 
182 daniel-mar 68
function split_firstname_lastname($name) {
69
        $ary = explode(' ', $name);
70
        $last_name = array_pop($ary);
71
        $first_name = implode(' ', $ary);
72
        return array($first_name, $last_name);
73
}
74
 
180 daniel-mar 75
function originHeaders() {
76
        // CORS
77
        // Author: Till Wehowski
426 daniel-mar 78
        // TODO: add to class OIDplus
182 daniel-mar 79
 
180 daniel-mar 80
        header("Access-Control-Allow-Credentials: true");
81
        header("Access-Control-Allow-Origin: ".strip_tags(((isset($_SERVER['HTTP_ORIGIN'])) ? $_SERVER['HTTP_ORIGIN'] : "*")));
82
 
83
        header("Access-Control-Allow-Headers: If-None-Match, X-Requested-With, Origin, X-Frdlweb-Bugs, Etag, X-Forgery-Protection-Token, X-CSRF-Token");
84
 
85
        if (isset($_SERVER['HTTP_ORIGIN'])) {
86
                header('X-Frame-Options: ALLOW-FROM '.$_SERVER['HTTP_ORIGIN']);
87
        } else {
88
                header_remove("X-Frame-Options");
89
        }
90
 
91
        $expose = array('Etag', 'X-CSRF-Token');
92
        foreach (headers_list() as $num => $header) {
93
                $h = explode(':', $header);
94
                $expose[] = trim($h[0]);
95
        }
96
        header("Access-Control-Expose-Headers: ".implode(',',$expose));
97
 
98
        header("Vary: Origin");
99
}
236 daniel-mar 100
 
346 daniel-mar 101
if (!function_exists('mb_wordwrap')) {
102
        function mb_wordwrap($str, $width = 75, $break = "\n", $cut = false) {
103
                // https://stackoverflow.com/a/4988494/488539
104
                $lines = explode($break, $str);
105
                foreach ($lines as &$line) {
106
                        $line = rtrim($line);
107
                        if (mb_strlen($line) <= $width) {
108
                                continue;
109
                        }
110
                        $words = explode(' ', $line);
111
                        $line = '';
112
                        $actual = '';
113
                        foreach ($words as $word) {
114
                                if (mb_strlen($actual.$word) <= $width) {
115
                                        $actual .= $word.' ';
116
                                } else {
117
                                        if ($actual != '') {
118
                                                $line .= rtrim($actual).$break;
119
                                        }
120
                                        $actual = $word;
121
                                        if ($cut) {
122
                                                while (mb_strlen($actual) > $width) {
123
                                                        $line .= mb_substr($actual, 0, $width).$break;
124
                                                        $actual = mb_substr($actual, $width);
125
                                                }
126
                                        }
127
                                        $actual .= ' ';
128
                                }
129
                        }
130
                        $line .= trim($actual);
131
                }
132
                return implode($break, $lines);
133
        }
134
}
355 daniel-mar 135
 
379 daniel-mar 136
function httpOutWithETag($out, $contentType, $filename='') {
137
        $etag = md5($out);
138
        header("Etag: $etag");
139
        header("Content-MD5: $etag"); // RFC 2616 clause 14.15
140
        if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && (trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag)) {
849 daniel-mar 141
                http_response_code(304); // 304 Not Modified
379 daniel-mar 142
        } else {
143
                header("Content-Type: $contentType");
144
                if (!empty($filename)) {
145
                        header('Content-Disposition:inline; filename="'.$filename.'"');
146
                }
147
                echo $out;
148
        }
149
        die();
150
}
151
 
360 daniel-mar 152
function my_vsprintf($str, $args) {
153
        $n = 1;
154
        foreach ($args as $val) {
155
                $str = str_replace("%$n", $val, $str);
156
                $n++;
157
        }
370 daniel-mar 158
        $str = str_replace("%%", "%", $str);
360 daniel-mar 159
        return $str;
160
}
161
 
355 daniel-mar 162
function _L($str, ...$sprintfArgs) {
401 daniel-mar 163
        static $translation_array = array();
164
        static $translation_loaded = null;
165
 
506 daniel-mar 166
        $str = trim($str);
167
 
1050 daniel-mar 168
        if (!class_exists(OIDplus::class)) {
438 daniel-mar 169
                return my_vsprintf($str, $sprintfArgs);
170
        }
171
 
360 daniel-mar 172
        $lang = OIDplus::getCurrentLang();
468 daniel-mar 173
        $ta = OIDplus::getTranslationArray($lang);
174
        $res = (isset($ta[$lang]) && isset($ta[$lang][$str])) ? $ta[$lang][$str] : $str;
360 daniel-mar 175
 
176
        $res = str_replace('###', OIDplus::baseConfig()->getValue('TABLENAME_PREFIX', ''), $res);
177
 
178
        $res = my_vsprintf($res, $sprintfArgs);
179
 
180
        return $res;
370 daniel-mar 181
}
386 daniel-mar 182
 
552 daniel-mar 183
function _CheckParamExists($params, $key) {
1050 daniel-mar 184
        if (class_exists(OIDplusException::class)) {
698 daniel-mar 185
                if (!isset($params[$key])) throw new OIDplusException(_L('Parameter %1 is missing', $key));
186
        } else {
187
                if (!isset($params[$key])) throw new Exception(_L('Parameter %1 is missing', $key));
188
        }
552 daniel-mar 189
}
190
 
721 daniel-mar 191
function extractHtmlContents($cont) {
192
        // make sure the program works even if the user provided HTML is not UTF-8
193
        $cont = convert_to_utf8_no_bom($cont);
194
 
386 daniel-mar 195
        $out_js = '';
196
        $m = array();
197
        preg_match_all('@<script[^>]*>(.+)</script>@ismU', $cont, $m);
198
        foreach ($m[1] as $x) {
199
                $out_js = $x . "\n\n";
200
        }
201
 
202
        $out_css = '';
203
        $m = array();
204
        preg_match_all('@<style[^>]*>(.+)</style>@ismU', $cont, $m);
205
        foreach ($m[1] as $x) {
206
                $out_css = $x . "\n\n";
207
        }
208
 
209
        $out_html = $cont;
210
        $out_html = preg_replace('@^(.+)<body[^>]*>@isU', '', $out_html);
211
        $out_html = preg_replace('@</body>.+$@isU', '', $out_html);
212
        $out_html = preg_replace('@<title>.+</title>@isU', '', $out_html);
213
        $out_html = preg_replace('@<h1>.+</h1>@isU', '', $out_html, 1);
214
        $out_html = preg_replace('@<script[^>]*>(.+)</script>@ismU', '', $out_html);
215
        $out_html = preg_replace('@<style[^>]*>(.+)</style>@ismU', '', $out_html);
216
 
217
        return array($out_html, $out_js, $out_css);
392 daniel-mar 218
}
219
 
400 daniel-mar 220
function sha3_512($password, $raw_output=false) {
392 daniel-mar 221
        if (version_compare(PHP_VERSION, '7.1.0') >= 0) {
400 daniel-mar 222
                return hash('sha3-512', $password, $raw_output);
392 daniel-mar 223
        } else {
1021 daniel-mar 224
                return \bb\Sha3\Sha3::hash($password, 512, $raw_output);
392 daniel-mar 225
        }
226
}
486 daniel-mar 227
 
710 daniel-mar 228
function sha3_512_hmac($message, $key, $raw_output=false) {
229
        // RFC 2104 HMAC
847 daniel-mar 230
        if (version_compare(PHP_VERSION, '7.1.0') >= 0) {
231
                return hash_hmac('sha3-512', $message, $key, $raw_output);
232
        } else {
1021 daniel-mar 233
                return \bb\Sha3\Sha3::hash_hmac($message, $key, 512, $raw_output);
847 daniel-mar 234
        }
710 daniel-mar 235
}
236
 
625 daniel-mar 237
if (!function_exists('str_ends_with')) {
238
        // PHP 7.x compatibility
239
        function str_ends_with($haystack, $needle) {
240
                $length = strlen($needle);
241
                return $length > 0 ? substr($haystack, -$length) === $needle : true;
242
        }
243
}
244
 
245
if (!function_exists('str_starts_with')) {
246
        // PHP 7.x compatibility
247
        function str_starts_with($haystack, $needle) {
248
                return strpos($haystack, $needle) === 0;
249
        }
250
}
251
 
963 daniel-mar 252
function url_get_contents($url, $userAgent='ViaThinkSoft-OIDplus/2.0') {
653 daniel-mar 253
        if (function_exists('curl_init')) {
254
                $ch = curl_init();
1050 daniel-mar 255
                if (class_exists(OIDplus::class)) {
698 daniel-mar 256
                        if (ini_get('curl.cainfo') == '') curl_setopt($ch, CURLOPT_CAINFO, OIDplus::localpath() . 'vendor/cacert.pem');
257
                }
653 daniel-mar 258
                curl_setopt($ch, CURLOPT_URL, $url);
963 daniel-mar 259
                curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
653 daniel-mar 260
                curl_setopt($ch, CURLOPT_POST, 0);
261
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
262
                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
263
                curl_setopt($ch, CURLOPT_AUTOREFERER, true);
1006 daniel-mar 264
                $res = @curl_exec($ch);
963 daniel-mar 265
                $error_code = @curl_getinfo($ch, CURLINFO_HTTP_CODE);
1006 daniel-mar 266
                @curl_close($ch);
963 daniel-mar 267
                if ($error_code >= 400) return false;
1006 daniel-mar 268
                if ($res === false) return false;
653 daniel-mar 269
        } else {
963 daniel-mar 270
                // Attention: HTTPS only works if OpenSSL extension is enabled.
271
                // Our supplement does not help...
716 daniel-mar 272
                $opts = [
273
                        "http" => [
274
                                "method" => "GET",
963 daniel-mar 275
                                "header" => "User-Agent: $userAgent\r\n"
716 daniel-mar 276
                        ]
277
                ];
278
                $context = stream_context_create($opts);
279
                $res = @file_get_contents($url, false, $context);
653 daniel-mar 280
                if ($res === false) return false;
281
        }
282
        return $res;
660 daniel-mar 283
}
778 daniel-mar 284
 
285
function getSortedQuery() {
286
        // https://stackoverflow.com/a/51777249/488539
287
        $url = [];
288
        parse_str($_SERVER['QUERY_STRING'], $url);
289
        ksort($url);
290
        return http_build_query($url);
291
}