File modules/cms/output/UIOutput.class.php

Last commit: Mon Feb 13 22:46:58 2023 +0100	Jan Dankert	Show server error messages in the UI notice window.
1 <?php 2 3 namespace cms\output; 4 5 use BadMethodCallException; 6 use cms\action\RequestParams; 7 use cms\base\Configuration;use cms\base\Language as L; 8 use cms\base\Startup;use cms\Dispatcher; 9 use cms\output\BaseOutput; 10 use Exception; 11 use template_engine\engine\TemplateRunner; 12 use util\Http; 13 use logger\Logger; 14 use LogicException; 15 use \util\exception\ObjectNotFoundException; 16 use util\exception\UIException; 17 use util\exception\SecurityException; 18 use template_engine\engine\TemplateEngine; 19 use util\Request;use util\Session;use util\text\TextMessage; 20 21 22 /** 23 * The HTML output is calling a template for the user interface. 24 */ 25 class UIOutput extends BaseOutput 26 { 27 /** 28 * Preparing the client... 29 */ 30 protected function beforeAction($request) 31 { 32 // Sending the Content-Security-Policy. 33 self::setContentSecurityPolicy(); 34 35 if ( @$_REQUEST['scope']=='openid' ) { 36 $request->redirectActionAndMethod('login','oidc'); 37 } 38 elseif (empty($request->action)) { 39 $request->redirectActionAndMethod('index','show' ); 40 } 41 42 if ( $request->isAction ) 43 throw new \RuntimeException('The HTML output driver does not accept POST requests'); 44 45 } 46 47 48 49 protected function outputData($request, $data) 50 { 51 // The action is able to change its method and action name. 52 $subaction = $request->method; 53 $action = $request->action; 54 55 56 $this::outputTemplate($request,$action, $subaction, $data['output'] ); 57 } 58 59 60 61 /** 62 * Sets the timezone so that dates in the UI are displayed in the correct timezone. 63 */ 64 protected static function setTimezone() { 65 66 if ( $timezone = self::getCustomTimezone() ) { 67 68 date_default_timezone_set( $timezone ); 69 70 if ( DEVELOPMENT ) 71 header('X-OR-custom-timezone: '.$timezone ); 72 } 73 74 // Default: Unchanged, so /etc/timezone or /etc/localtime is used by PHP. 75 } 76 77 78 /** 79 * Gets the custom timezone of the user or the configured timezone. 80 */ 81 protected static function getCustomTimezone() { 82 83 $user = Request::getUser(); // the user timezone has precedence. 84 if ( $user && $user->timezone && in_array( $user->timezone,timezone_identifiers_list() ) ) // user is set and a timezone is set and timezone is valid 85 return( $user->timezone ); // Timezone from user setting 86 elseif ( $configuredTimezone = Configuration::subset('ui')->get('timezone') ) 87 return $configuredTimezone; // Timezone from configuration 88 89 return null; 90 } 91 92 93 /** 94 * Executes and outputs an HTML template. 95 * 96 * @param $request RequestParams 97 * @param $action string action 98 * @param $subaction string method 99 * @param $outputData array Output data 100 */ 101 private static function outputTemplate($request, $action, $subaction, $outputData) 102 { 103 $outputData += [ 104 // the following special data is used in FormComponent for filling the form. 105 '_id' => $request->id, 106 '_token' => Session::token(), 107 ]; 108 109 $templateFile = Startup::MODULE_DIR . 'cms/ui/themes/default/html/views/' . $action.'/'.$subaction . '.php'; 110 111 self::setTimezone(); 112 113 if ( DEVELOPMENT ) { 114 header('X-OR-Template: '.$templateFile ); 115 116 $outputDataClone = $outputData; 117 array_walk_recursive($outputDataClone, function(&$v) { $v = htmlspecialchars($v); }); 118 //array_walk_recursive($outputDataClone, function(&$v) { if(is_string($v)) $v = htmlspecialchars($v); }); 119 echo "<!-- \n".var_export($outputDataClone,true)."\n-->"; 120 } 121 122 $engine = new TemplateRunner(); 123 //$engine->request = $request; 124 $engine->executeTemplate( $templateFile, $outputData ); 125 } 126 127 128 /** 129 * Content-Security-Policy. 130 */ 131 private static function setContentSecurityPolicy() 132 { 133 // config is not loaded yet. Allow nothing... 134 header('Content-Security-Policy: default-src \'none\'' ); 135 136 // This will be overwritten by the index action 137 } 138 139 140 /** 141 * @param $text 142 * @param $cause Exception the cause, or <code>null</code> if not available. 143 */ 144 protected function setError($text, $cause) 145 { 146 if ( !headers_sent() ) 147 // The following HTML contains inline CSS code, so we have to allow inline CSS. 148 header('Content-Security-Policy: style-src: inline; default: self'); 149 150 ?><!DOCTYPE html> 151 <html lang="en"> 152 <head> 153 <meta charset="utf-8"/> 154 <meta name="viewport" content="width=device-width, initial-scale=1"/> 155 <title><?php echo $text ?></title> 156 <style type="text/css"> 157 158 header, main { 159 display: block 160 } 161 162 body { 163 width: 100%; 164 height: 100%; 165 background-color: rgba(13,8,5,0.58); 166 color: white; 167 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 168 line-height: 1.4; 169 font-size: 1.5em; 170 text-align: center; 171 } 172 173 pre { 174 margin:10%; 175 width: 80%; 176 overflow: visible; 177 height: 40%; 178 color: silver; 179 text-align: left; 180 font-size: 0.6rem; 181 } 182 183 h1 { 184 font-size: 2em; 185 } 186 </style> 187 </head> 188 <body> 189 190 <header> 191 <h1 id="cms-error-message"><?php echo $text ?></h1> 192 </header> 193 194 <main> 195 <p>Something went terribly wrong &#x1F61E;</p> 196 197 <pre id="cms-error-log"><?php // Display exceptions only in development mode, because they may contain sensitive internal information like passwords. 198 if ($cause) { 199 if (defined('DEVELOPMENT') && DEVELOPMENT ) { 200 echo $cause->__toString(); 201 } 202 else { 203 while (true) { 204 echo($cause->getMessage()); 205 $previous = $cause->getPrevious(); 206 if ($previous) { 207 echo "\n\n" . 'Caused by:'."\n"; 208 $cause = $previous; 209 } else 210 break; 211 } 212 } 213 } 214 ?></pre> 215 </main> 216 217 </body> 218 </html><?php 219 220 } 221 222 public function getContentType() 223 { 224 return 'text/html'; 225 } 226 }
Download modules/cms/output/UIOutput.class.php
History Mon, 13 Feb 2023 22:46:58 +0100 Jan Dankert Show server error messages in the UI notice window. Sat, 28 Jan 2023 19:10:47 +0100 Jan Dankert New: Templates may be rendered as Mustache, Script and Script template. Fri, 15 Apr 2022 14:51:22 +0200 dankert Refactoring: User,Config and Database info is now stored in the Request, because so there is no session required for clients which are using Basic Authorization. Fri, 18 Mar 2022 00:30:30 +0100 dankert Fix: Test if stored timezone value is valid in the actual server environment. Tue, 15 Mar 2022 20:00:51 +0100 dankert Deleted commented code. Fri, 11 Mar 2022 19:33:58 +0100 dankert Better solution to escape the output data. Fri, 11 Mar 2022 19:25:58 +0100 dankert Fix: HTML in Comments must be escaped. Wed, 9 Mar 2022 01:57:45 +0100 dankert Fix: Do not write the language to a cookie. Wed, 9 Mar 2022 00:53:10 +0100 dankert Fix: Setting the correct timezone from the user property. Mon, 14 Feb 2022 00:06:35 +0100 dankert Documentation... Mon, 14 Feb 2022 00:01:10 +0100 dankert Fix: UI needs output data "_token" and "_id". Sun, 13 Feb 2022 19:39:49 +0100 dankert Refactoring: Special output type "preview" for previewing pages and files.