Newer
Older
backup-commander / html / inc / common.php
  1. <?php
  2. /**
  3. * COPYRIGHT © 2022 JOHN PEARCEY
  4. * All rights reserved
  5. */
  6.  
  7. const BASE64_DIGITS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz$_';
  8.  
  9. if (version_compare( PHP_VERSION, '8', '<') ){
  10. include_once __DIR__ . "/common-pre-v8.php";
  11. }
  12.  
  13. function getStackTrace(){
  14. try{
  15. throw new Exception;
  16. }catch( Exception $e ){
  17. return $e->getTraceAsString();
  18. }
  19. }
  20.  
  21. /**
  22. * e.g. split
  23. * ../db/stanhopetest/img/img_52548
  24. * into
  25. * [ ../db/stanhopetest/img/ , img_52548 ]
  26. *
  27. */
  28. function split_file_path( $ffn ){
  29. $fn = basename( $ffn ); // img_52548
  30. //$fp = substr( $ffn, 0, strlen($ffn) - strlen($fn) );
  31. $fp = dirname( $ffn ) . '/';
  32. return [ $fp, $fn ];
  33. }
  34.  
  35. /**
  36. * Returns true if it is possible to create this directory on the file system.
  37. * Includes the possibility of multiple directories.
  38. */
  39. function is_creatable_dir( $dirs ){
  40. $dir = $dirs;
  41. while(!file_exists($dir)){
  42. $dir = dirname( $dir );
  43. }
  44. return is_writable($dir);
  45. }
  46.  
  47. /**
  48. * Function to make directories and actually SET the permissions
  49. * https://www.php.net/manual/en/function.chmod.php
  50. *
  51. * $perms is an octal number
  52. * e.g. mkdirs( $dir, 02770 ); //770 and g+s
  53. */
  54. function mkdirs( $dirs, $perms ){
  55. $dir = $dirs;
  56. while(!file_exists($dir)){
  57. $dir = dirname( $dir );
  58. }
  59. $rootDir = $dir;
  60. if(!file_exists($dirs)) mkdir( $dirs, 0750, true ); //perms not always set
  61. $dir = $dirs;
  62. while( $dir!=$rootDir) {
  63. chmod( $dir, $perms );
  64. $dir = dirname( $dir );
  65. }
  66. }
  67.  
  68. /**
  69. * Return the contents of a url as a string using the curl functions.
  70. */
  71. function getContentsFromUrl( $url ){
  72. $ch = curl_init( $url );
  73. //$fp = fopen("example_homepage.txt", "w");
  74. $fp = tmpfile();
  75. curl_setopt($ch, CURLOPT_FILE, $fp);
  76. curl_setopt($ch, CURLOPT_HEADER, 0);
  77.  
  78. curl_exec($ch);
  79. $c_err = curl_error($ch);
  80. curl_close($ch);
  81. if($c_err) {
  82. error_log( $c_err );
  83. fclose($fp);
  84. return;
  85. }
  86.  
  87. $f_path = stream_get_meta_data($fp)['uri'];
  88. $rtn = file_get_contents( $f_path );
  89. fclose($fp);
  90.  
  91. return $rtn;
  92. }
  93.  
  94. /**
  95. * Set the given key-value pair.
  96. *
  97. * Returns the record ID.
  98. */
  99. function params_set( $key, $val ) {
  100.  
  101. $rec = R::findOne( 'params', 'pkey=?', [$key] );
  102. if($rec) {
  103. $rec->pval = $val;
  104. R::store( $rec );
  105. return $rec->id;
  106. }
  107.  
  108. $rec = R::dispense( 'params' );
  109. $rec->pkey = $key;
  110. $rec->pval = $val;
  111. return R::store( $rec );
  112. }
  113.  
  114. function params_get_date( $key ){
  115. return strtotime( params_get($key) );
  116. }
  117.  
  118. /**
  119. * Returns the value for the given key. Returns null if no such key exists.
  120. */
  121. function params_get( $key ){
  122.  
  123. $rec = R::findOne( 'params', 'pkey=?', [$key] );
  124. if(!$rec) return null;
  125. return $rec->pval;
  126. }
  127.  
  128. /**
  129. * A novel way of creating a unique ID each time a call is made. The new ID is
  130. * returned.
  131. *
  132. * e.g.
  133. * This can be used to give a client which might want to create temporary unique IDs. It is
  134. * called once per client refresh and used to ensure uniqueness of certain CSS data points.
  135. */
  136. function params_unique( ) {
  137.  
  138. $rec = R::dispense( 'params' );
  139. $rec->pkey = 'unique';
  140. $id = R::store( $rec );
  141. R::exec( "delete from params where id<$id and pkey='unique'" );
  142. return $id;
  143. }
  144.  
  145. /**
  146. * Return a string representation for the given dom node suitable for debugging.
  147. */
  148. function getNodeString( $rmElem ){
  149. if($rmElem==null) return "Element is null";
  150. $str="";
  151. if( $rmElem->nodeType==XML_ELEMENT_NODE){
  152. $str .= $rmElem->nodeName;
  153. $a = $rmElem->getAttribute("shb_compid");
  154. if($a){
  155. $str .= " shb_compid=$a";
  156. }
  157. }else{
  158. $str .= 'type = '.$rmElem->nodeType;
  159. }
  160. return $str;
  161. }
  162.  
  163. /**
  164. * Simple logger to write to a file. Using php error_log distorts all crlf pairs. This
  165. * is a pain when you're trying to preserve them in html.
  166. */
  167. function mylog( $msg ){
  168. global $logging_on;
  169. if(!$logging_on) return;
  170. $p = __DIR__ . "/../../shb.log";
  171. $h = fopen( $p, "a");
  172. if($h===false) return;
  173. fwrite( $h, "$msg\n");
  174. fclose($h);
  175.  
  176. }
  177.  
  178. function generateNonce( $digitCount = 12 ){
  179. // e.g. 422466a05f24b09c978fa1f6
  180. return bin2hex( random_bytes($digitCount) );
  181. }
  182.  
  183. /**
  184. * Generate a randon username starting with a letter and containing only letters and numbers.
  185. */
  186. function generateRndUserName( $digitCount = 10 ){
  187. $l1 = generateRndStrUsing( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 1 );
  188. return $l1 . generateRndStrUsing( BASE64_DIGITS, $digitCount-1 );
  189. }
  190.  
  191. /**
  192. * Generate a randon password with letters and numbers and some funny stuff.
  193. */
  194. function generateRndPwd( $digitCount = 10 ){
  195. return generateRndStrUsing( '0123456789_!"£$%^&*()_-|\?/<>#~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', $digitCount );
  196. }
  197.  
  198. /**
  199. * Generate a randon string of asc char. Default consisting of only [0-9][a-z][A-Z]
  200. */
  201. function generateRndStrUsing( $using=BASE64_DIGITS, $digitCount = 8 ){
  202. $str = '';
  203. $maxlen = strlen($using);
  204. for($i=0; $i<$digitCount; $i++){
  205. $iv = random_int(0, $maxlen-1);
  206. $str .= mb_substr( $using, $iv, 1); //use mb_substr because £ is not and asc char!
  207. }
  208. return $str;
  209. }
  210.  
  211.  
  212. /**
  213. * Remove all html from the given string returning just the text content.
  214. */
  215. function removeHtml( $str ){
  216. //txt = txt.replace(/<div>/gi, '\n');
  217. return preg_replace( '/<\/?[^>]+>/i', '', $str );
  218. }
  219.  
  220. function getHtmlOkAsString( $data ){
  221. $data = json_encode( $data );
  222. return "[\"OK\", $data ]";
  223. }
  224. function sendHtmlOk( $data="" ){
  225. echo getHtmlOkAsString( $data );
  226. }
  227.  
  228. /**
  229. * An effort to rectify my previously ill-thought out return encoding. You do not
  230. * need to encode the data before calling this method. Any arrays will be json encoded.
  231. */
  232. function sendHtmlOk_WithData( $data ){
  233. $data = json_encode( $data );
  234. echo "[\"OK\", $data ]";
  235. }
  236.  
  237. function getHtmlErrorAsString( $strErrDesc = "--blank--" ){
  238. $data = json_encode( $strErrDesc );
  239. return "[\"Error\", $data]";
  240. }
  241.  
  242. function sendHtmlError( $strErrDesc = "--blank--" ){
  243. $rtn = getHtmlErrorAsString( $strErrDesc );
  244. mylog( $rtn );
  245. echo $rtn;
  246. }
  247.  
  248. /**
  249. *
  250. */
  251. function getAttForPath( $name, $prefPath, $path){
  252. return "$name = \"$prefPath/$path\"";
  253. }
  254.  
  255. global $g_pub_path;
  256.  
  257. /**
  258. * If the browser=true, the file returned will be correct for adding to an href or src attribute so that the
  259. * browser will find the link.
  260. */
  261. function getDirForType( $filetype='html', $browser=false, $userid=-1 ){
  262. global $g_pub_path;
  263. if($g_pub_path==null){
  264. $g_pub_path = params_get('pub_path');
  265. if($g_pub_path==null){
  266. throw new Exception("Publishing now requires a valid key('pub_path') in the params table for the publishing output path");
  267. }
  268. if(str_ends_with( $g_pub_path, '/') ) $g_pub_path = substr($g_pub_path, 0, strlen($g_pub_path)-1 );
  269. //ensure all the directories exist
  270. createUserDir( 'img', $userid );
  271. createUserDir( 'css', $userid );
  272. createUserDir( 'html', $userid );
  273. createUserDir( 'js', $userid );
  274. }
  275.  
  276. return getDirForType_( $filetype, $browser, $userid );
  277.  
  278. }
  279.  
  280. function createUserDir( $dName, $userid ){
  281. if(!file_exists(getDirForType_( $dName, false, $userid ))) {
  282. $dir = getDirForType_( $dName, false, $userid );
  283. error_log("common.php: createUserDir: $dir");
  284. mkdir( $dir, 0770, true);
  285. }
  286. }
  287.  
  288. /**
  289. * Part of the new path handling system is to sepatate out path names from real files
  290. */
  291. function mkdirIfNotExists( $d ){
  292. if(!file_exists( $d ) ) {
  293. error_log("common.php: createUserDir: $d");
  294. mkdir( $d, 0770, true );
  295. }
  296. }
  297.  
  298. /**
  299. * For the moment, call getDirForType and not this function. In time, the setup routine will make the directories
  300. * and eliminate the need for the check during a user session.
  301. *
  302. * If the browser flag is set, we assuming a document root sub-dir. But in time, this will need to also cater for
  303. * a site serving the g_pub_path as root (wrt the browser).
  304. *
  305. */
  306. function getDirForType_( $filetype, $browser, $userid ){
  307. global $g_pub_path;
  308. $strPath = $g_pub_path;
  309. if($userid>0){
  310. $strPath .= "_dbg_$userid";
  311. }
  312. switch($filetype){
  313. case 'img':
  314. if($browser) return "/$strPath/img/";
  315. return fxdPth( "$strPath/img/" );
  316.  
  317. case 'js':
  318. if($browser) return "/$strPath/js/";
  319. return fxdPth( "$strPath/js/" );
  320.  
  321. case 'css':
  322. if($browser) return "/$strPath/css/";
  323. return fxdPth( "$strPath/css/" );
  324. case 'html':
  325. default:
  326. if($browser) return "/$strPath/";
  327. return fxdPth( "$strPath/" );
  328. }
  329. }
  330.  
  331.  
  332. //NO white-space