- <?php
- /**
- * COPYRIGHT © 2022 JOHN PEARCEY
- * All rights reserved
- */
-
- const BASE64_DIGITS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz$_';
-
- if (version_compare( PHP_VERSION, '8', '<') ){
- include_once __DIR__ . "/common-pre-v8.php";
- }
-
- function getStackTrace(){
- try{
- throw new Exception;
- }catch( Exception $e ){
- return $e->getTraceAsString();
- }
- }
-
- /**
- * e.g. split
- * ../db/stanhopetest/img/img_52548
- * into
- * [ ../db/stanhopetest/img/ , img_52548 ]
- *
- */
- function split_file_path( $ffn ){
- $fn = basename( $ffn ); // img_52548
- //$fp = substr( $ffn, 0, strlen($ffn) - strlen($fn) );
- $fp = dirname( $ffn ) . '/';
- return [ $fp, $fn ];
- }
-
- /**
- * Returns true if it is possible to create this directory on the file system.
- * Includes the possibility of multiple directories.
- */
- function is_creatable_dir( $dirs ){
- $dir = $dirs;
- while(!file_exists($dir)){
- $dir = dirname( $dir );
- }
- return is_writable($dir);
- }
-
- /**
- * Function to make directories and actually SET the permissions
- * https://www.php.net/manual/en/function.chmod.php
- *
- * $perms is an octal number
- * e.g. mkdirs( $dir, 02770 ); //770 and g+s
- */
- function mkdirs( $dirs, $perms ){
- $dir = $dirs;
- while(!file_exists($dir)){
- $dir = dirname( $dir );
- }
- $rootDir = $dir;
- if(!file_exists($dirs)) mkdir( $dirs, 0750, true ); //perms not always set
- $dir = $dirs;
- while( $dir!=$rootDir) {
- chmod( $dir, $perms );
- $dir = dirname( $dir );
- }
- }
-
- /**
- * Return the contents of a url as a string using the curl functions.
- */
- function getContentsFromUrl( $url ){
-
- $ch = curl_init( $url );
- //$fp = fopen("example_homepage.txt", "w");
- $fp = tmpfile();
-
- curl_setopt($ch, CURLOPT_FILE, $fp);
- curl_setopt($ch, CURLOPT_HEADER, 0);
-
- curl_exec($ch);
- $c_err = curl_error($ch);
- curl_close($ch);
- if($c_err) {
- error_log( $c_err );
- fclose($fp);
- return;
- }
-
- $f_path = stream_get_meta_data($fp)['uri'];
- $rtn = file_get_contents( $f_path );
- fclose($fp);
-
- return $rtn;
- }
-
- /**
- * Set the given key-value pair.
- *
- * Returns the record ID.
- */
- function params_set( $key, $val ) {
-
- $rec = R::findOne( 'params', 'pkey=?', [$key] );
- if($rec) {
- $rec->pval = $val;
- R::store( $rec );
- return $rec->id;
- }
-
- $rec = R::dispense( 'params' );
- $rec->pkey = $key;
- $rec->pval = $val;
- return R::store( $rec );
- }
-
- function params_get_date( $key ){
- return strtotime( params_get($key) );
- }
-
- /**
- * Returns the value for the given key. Returns null if no such key exists.
- */
- function params_get( $key ){
-
- $rec = R::findOne( 'params', 'pkey=?', [$key] );
- if(!$rec) return null;
- return $rec->pval;
- }
-
- /**
- * A novel way of creating a unique ID each time a call is made. The new ID is
- * returned.
- *
- * e.g.
- * This can be used to give a client which might want to create temporary unique IDs. It is
- * called once per client refresh and used to ensure uniqueness of certain CSS data points.
- */
- function params_unique( ) {
-
- $rec = R::dispense( 'params' );
- $rec->pkey = 'unique';
- $id = R::store( $rec );
- R::exec( "delete from params where id<$id and pkey='unique'" );
- return $id;
- }
-
- /**
- * Return a string representation for the given dom node suitable for debugging.
- */
- function getNodeString( $rmElem ){
-
- if($rmElem==null) return "Element is null";
- $str="";
- if( $rmElem->nodeType==XML_ELEMENT_NODE){
- $str .= $rmElem->nodeName;
- $a = $rmElem->getAttribute("shb_compid");
- if($a){
- $str .= " shb_compid=$a";
- }
- }else{
- $str .= 'type = '.$rmElem->nodeType;
- }
- return $str;
- }
-
- /**
- * Simple logger to write to a file. Using php error_log distorts all crlf pairs. This
- * is a pain when you're trying to preserve them in html.
- */
- function mylog( $msg ){
-
- global $logging_on;
-
- if(!$logging_on) return;
- $p = __DIR__ . "/../../shb.log";
- $h = fopen( $p, "a");
- if($h===false) return;
- fwrite( $h, "$msg\n");
- fclose($h);
-
- }
-
- function generateNonce( $digitCount = 12 ){
- // e.g. 422466a05f24b09c978fa1f6
- return bin2hex( random_bytes($digitCount) );
- }
-
- /**
- * Generate a randon username starting with a letter and containing only letters and numbers.
- */
- function generateRndUserName( $digitCount = 10 ){
- $l1 = generateRndStrUsing( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 1 );
- return $l1 . generateRndStrUsing( BASE64_DIGITS, $digitCount-1 );
- }
-
- /**
- * Generate a randon password with letters and numbers and some funny stuff.
- */
- function generateRndPwd( $digitCount = 10 ){
- return generateRndStrUsing( '0123456789_!"£$%^&*()_-|\?/<>#~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', $digitCount );
- }
-
- /**
- * Generate a randon string of asc char. Default consisting of only [0-9][a-z][A-Z]
- */
- function generateRndStrUsing( $using=BASE64_DIGITS, $digitCount = 8 ){
-
- $str = '';
- $maxlen = strlen($using);
- for($i=0; $i<$digitCount; $i++){
- $iv = random_int(0, $maxlen-1);
- $str .= mb_substr( $using, $iv, 1); //use mb_substr because £ is not and asc char!
- }
- return $str;
- }
-
-
- /**
- * Remove all html from the given string returning just the text content.
- */
- function removeHtml( $str ){
- //txt = txt.replace(/<div>/gi, '\n');
- return preg_replace( '/<\/?[^>]+>/i', '', $str );
- }
-
- function getHtmlOkAsString( $data ){
- $data = json_encode( $data );
- return "[\"OK\", $data ]";
- }
-
- function sendHtmlOk( $data="" ){
- echo getHtmlOkAsString( $data );
- }
-
- /**
- * An effort to rectify my previously ill-thought out return encoding. You do not
- * need to encode the data before calling this method. Any arrays will be json encoded.
- */
- function sendHtmlOk_WithData( $data ){
- $data = json_encode( $data );
- echo "[\"OK\", $data ]";
- }
-
- function getHtmlErrorAsString( $strErrDesc = "--blank--" ){
- $data = json_encode( $strErrDesc );
- return "[\"Error\", $data]";
- }
-
- function sendHtmlError( $strErrDesc = "--blank--" ){
- $rtn = getHtmlErrorAsString( $strErrDesc );
- mylog( $rtn );
- echo $rtn;
- }
-
- /**
- *
- */
- function getAttForPath( $name, $prefPath, $path){
- return "$name = \"$prefPath/$path\"";
- }
-
- global $g_pub_path;
-
- /**
- * If the browser=true, the file returned will be correct for adding to an href or src attribute so that the
- * browser will find the link.
- */
- function getDirForType( $filetype='html', $browser=false, $userid=-1 ){
-
- global $g_pub_path;
-
- if($g_pub_path==null){
- $g_pub_path = params_get('pub_path');
- if($g_pub_path==null){
- throw new Exception("Publishing now requires a valid key('pub_path') in the params table for the publishing output path");
- }
-
- if(str_ends_with( $g_pub_path, '/') ) $g_pub_path = substr($g_pub_path, 0, strlen($g_pub_path)-1 );
-
- //ensure all the directories exist
- createUserDir( 'img', $userid );
- createUserDir( 'css', $userid );
- createUserDir( 'html', $userid );
- createUserDir( 'js', $userid );
-
- }
-
- return getDirForType_( $filetype, $browser, $userid );
-
- }
-
- function createUserDir( $dName, $userid ){
-
- if(!file_exists(getDirForType_( $dName, false, $userid ))) {
- $dir = getDirForType_( $dName, false, $userid );
- error_log("common.php: createUserDir: $dir");
- mkdir( $dir, 0770, true);
- }
- }
-
- /**
- * Part of the new path handling system is to sepatate out path names from real files
- */
- function mkdirIfNotExists( $d ){
- if(!file_exists( $d ) ) {
- error_log("common.php: createUserDir: $d");
- mkdir( $d, 0770, true );
- }
- }
-
- /**
- * For the moment, call getDirForType and not this function. In time, the setup routine will make the directories
- * and eliminate the need for the check during a user session.
- *
- * If the browser flag is set, we assuming a document root sub-dir. But in time, this will need to also cater for
- * a site serving the g_pub_path as root (wrt the browser).
- *
- */
- function getDirForType_( $filetype, $browser, $userid ){
-
- global $g_pub_path;
- $strPath = $g_pub_path;
-
-
- if($userid>0){
- $strPath .= "_dbg_$userid";
- }
-
- switch($filetype){
-
- case 'img':
- if($browser) return "/$strPath/img/";
- return fxdPth( "$strPath/img/" );
-
- case 'js':
- if($browser) return "/$strPath/js/";
- return fxdPth( "$strPath/js/" );
-
- case 'css':
- if($browser) return "/$strPath/css/";
- return fxdPth( "$strPath/css/" );
-
- case 'html':
- default:
- if($browser) return "/$strPath/";
- return fxdPth( "$strPath/" );
-
- }
- }
-
-
- //NO white-space