Subversion Repositories oidplus

Rev

Rev 1006 | Rev 1050 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

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