Subversion Repositories oidplus

Rev

Rev 1021 | Rev 1068 | 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. use ViaThinkSoft\OIDplus\OIDplus;
  21.  
  22. function is_privatekey_encrypted($privKey) {
  23.         return strpos($privKey,'BEGIN ENCRYPTED PRIVATE KEY') !== false;
  24. }
  25.  
  26. function verify_private_public_key($privKey, $pubKey) {
  27.         if (!function_exists('openssl_public_encrypt')) return false;
  28.         try {
  29.                 if (empty($privKey)) return false;
  30.                 if (empty($pubKey)) return false;
  31.                 $data = generateRandomString(25);
  32.                 $encrypted = '';
  33.                 $decrypted = '';
  34.                 if (!@openssl_public_encrypt($data, $encrypted, $pubKey)) return false;
  35.                 if (!@openssl_private_decrypt($encrypted, $decrypted, $privKey)) return false;
  36.                 return $decrypted == $data;
  37.         } catch (\Exception $e) {
  38.                 return false;
  39.         }
  40. }
  41.  
  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,
  47.             "config" => class_exists("\\ViaThinkSoft\\OIDplus\\OIDplus") ? OIDplus::getOpenSslCnf() : @getenv('OPENSSL_CONF')
  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.  
  64. function smallhash($data) { // get 31 bits from SHA1. Values 0..2147483647
  65.         return (hexdec(substr(sha1($data),-4*2)) & 0x7FFFFFFF);
  66. }
  67.  
  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.  
  75. function originHeaders() {
  76.         // CORS
  77.         // Author: Till Wehowski
  78.         // TODO: add to class OIDplus
  79.  
  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. }
  100.  
  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. }
  135.  
  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)) {
  141.                 http_response_code(304); // 304 Not Modified
  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.  
  152. function my_vsprintf($str, $args) {
  153.         $n = 1;
  154.         foreach ($args as $val) {
  155.                 $str = str_replace("%$n", $val, $str);
  156.                 $n++;
  157.         }
  158.         $str = str_replace("%%", "%", $str);
  159.         return $str;
  160. }
  161.  
  162. function _L($str, ...$sprintfArgs) {
  163.         static $translation_array = array();
  164.         static $translation_loaded = null;
  165.  
  166.         $str = trim($str);
  167.  
  168.         if (!class_exists(OIDplus::class)) {
  169.                 return my_vsprintf($str, $sprintfArgs);
  170.         }
  171.  
  172.         $lang = OIDplus::getCurrentLang();
  173.         $ta = OIDplus::getTranslationArray($lang);
  174.         $res = (isset($ta[$lang]) && isset($ta[$lang][$str])) ? $ta[$lang][$str] : $str;
  175.  
  176.         $res = str_replace('###', OIDplus::baseConfig()->getValue('TABLENAME_PREFIX', ''), $res);
  177.  
  178.         $res = my_vsprintf($res, $sprintfArgs);
  179.  
  180.         return $res;
  181. }
  182.  
  183. function _CheckParamExists($params, $key) {
  184.         if (class_exists(OIDplusException::class)) {
  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.         }
  189. }
  190.  
  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.  
  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);
  218. }
  219.  
  220. function sha3_512($password, $raw_output=false) {
  221.         if (version_compare(PHP_VERSION, '7.1.0') >= 0) {
  222.                 return hash('sha3-512', $password, $raw_output);
  223.         } else {
  224.                 return \bb\Sha3\Sha3::hash($password, 512, $raw_output);
  225.         }
  226. }
  227.  
  228. function sha3_512_hmac($message, $key, $raw_output=false) {
  229.         // RFC 2104 HMAC
  230.         if (version_compare(PHP_VERSION, '7.1.0') >= 0) {
  231.                 return hash_hmac('sha3-512', $message, $key, $raw_output);
  232.         } else {
  233.                 return \bb\Sha3\Sha3::hash_hmac($message, $key, 512, $raw_output);
  234.         }
  235. }
  236.  
  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.  
  252. function url_get_contents($url, $userAgent='ViaThinkSoft-OIDplus/2.0') {
  253.         if (function_exists('curl_init')) {
  254.                 $ch = curl_init();
  255.                 if (class_exists(OIDplus::class)) {
  256.                         if (ini_get('curl.cainfo') == '') curl_setopt($ch, CURLOPT_CAINFO, OIDplus::localpath() . 'vendor/cacert.pem');
  257.                 }
  258.                 curl_setopt($ch, CURLOPT_URL, $url);
  259.                 curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
  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);
  264.                 $res = @curl_exec($ch);
  265.                 $error_code = @curl_getinfo($ch, CURLINFO_HTTP_CODE);
  266.                 @curl_close($ch);
  267.                 if ($error_code >= 400) return false;
  268.                 if ($res === false) return false;
  269.         } else {
  270.                 // Attention: HTTPS only works if OpenSSL extension is enabled.
  271.                 // Our supplement does not help...
  272.                 $opts = [
  273.                         "http" => [
  274.                                 "method" => "GET",
  275.                                 "header" => "User-Agent: $userAgent\r\n"
  276.                         ]
  277.                 ];
  278.                 $context = stream_context_create($opts);
  279.                 $res = @file_get_contents($url, false, $context);
  280.                 if ($res === false) return false;
  281.         }
  282.         return $res;
  283. }
  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. }
  292.