|
1
|
|
|
<?php |
|
|
|
|
|
|
2
|
|
|
/** |
|
3
|
|
|
* @copyright Copyright (c) 2016, ownCloud, Inc. |
|
4
|
|
|
* |
|
5
|
|
|
* @author Bart Visscher <[email protected]> |
|
6
|
|
|
* @author Brice Maron <[email protected]> |
|
7
|
|
|
* @author Christoph Wurst <[email protected]> |
|
8
|
|
|
* @author Frank Karlitschek <[email protected]> |
|
9
|
|
|
* @author Individual IT Services <[email protected]> |
|
10
|
|
|
* @author Jakob Sack <[email protected]> |
|
11
|
|
|
* @author Jan-Christoph Borchardt <[email protected]> |
|
12
|
|
|
* @author Joas Schilling <[email protected]> |
|
13
|
|
|
* @author John Molakvoæ <[email protected]> |
|
14
|
|
|
* @author Jörn Friedrich Dreyer <[email protected]> |
|
15
|
|
|
* @author Lukas Reschke <[email protected]> |
|
16
|
|
|
* @author Marin Treselj <[email protected]> |
|
17
|
|
|
* @author Michael Letzgus <[email protected]> |
|
18
|
|
|
* @author Morris Jobke <[email protected]> |
|
19
|
|
|
* @author Robin Appelman <[email protected]> |
|
20
|
|
|
* @author Roeland Jago Douma <[email protected]> |
|
21
|
|
|
* @author Thomas Müller <[email protected]> |
|
22
|
|
|
* @author Vincent Petry <[email protected]> |
|
23
|
|
|
* |
|
24
|
|
|
* @license AGPL-3.0 |
|
25
|
|
|
* |
|
26
|
|
|
* This code is free software: you can redistribute it and/or modify |
|
27
|
|
|
* it under the terms of the GNU Affero General Public License, version 3, |
|
28
|
|
|
* as published by the Free Software Foundation. |
|
29
|
|
|
* |
|
30
|
|
|
* This program is distributed in the hope that it will be useful, |
|
31
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
32
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
33
|
|
|
* GNU Affero General Public License for more details. |
|
34
|
|
|
* |
|
35
|
|
|
* You should have received a copy of the GNU Affero General Public License, version 3, |
|
36
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/> |
|
37
|
|
|
* |
|
38
|
|
|
*/ |
|
39
|
|
|
|
|
40
|
|
|
use OC\TemplateLayout; |
|
41
|
|
|
|
|
42
|
|
|
require_once __DIR__.'/template/functions.php'; |
|
43
|
|
|
|
|
44
|
|
|
/** |
|
45
|
|
|
* This class provides the templates for ownCloud. |
|
46
|
|
|
*/ |
|
47
|
|
|
class OC_Template extends \OC\Template\Base { |
|
|
|
|
|
|
48
|
|
|
|
|
49
|
|
|
/** @var string */ |
|
50
|
|
|
private $renderAs; // Create a full page? |
|
51
|
|
|
|
|
52
|
|
|
/** @var string */ |
|
53
|
|
|
private $path; // The path to the template |
|
54
|
|
|
|
|
55
|
|
|
/** @var array */ |
|
56
|
|
|
private $headers = array(); //custom headers |
|
57
|
|
|
|
|
58
|
|
|
/** @var string */ |
|
59
|
|
|
protected $app; // app id |
|
60
|
|
|
|
|
61
|
|
|
protected static $initTemplateEngineFirstRun = true; |
|
62
|
|
|
|
|
63
|
|
|
/** |
|
64
|
|
|
* Constructor |
|
65
|
|
|
* |
|
66
|
|
|
* @param string $app app providing the template |
|
67
|
|
|
* @param string $name of the template file (without suffix) |
|
68
|
|
|
* @param string $renderAs If $renderAs is set, OC_Template will try to |
|
69
|
|
|
* produce a full page in the according layout. For |
|
70
|
|
|
* now, $renderAs can be set to "guest", "user" or |
|
71
|
|
|
* "admin". |
|
72
|
|
|
* @param bool $registerCall = true |
|
73
|
|
|
*/ |
|
74
|
|
|
public function __construct( $app, $name, $renderAs = "", $registerCall = true ) { |
|
75
|
|
|
// Read the selected theme from the config file |
|
76
|
|
|
self::initTemplateEngine($renderAs); |
|
77
|
|
|
|
|
78
|
|
|
$theme = OC_Util::getTheme(); |
|
79
|
|
|
|
|
80
|
|
|
$requestToken = (OC::$server->getSession() && $registerCall) ? \OCP\Util::callRegister() : ''; |
|
81
|
|
|
|
|
82
|
|
|
$parts = explode('/', $app); // fix translation when app is something like core/lostpassword |
|
83
|
|
|
$l10n = \OC::$server->getL10N($parts[0]); |
|
84
|
|
|
/** @var \OCP\Defaults $themeDefaults */ |
|
85
|
|
|
$themeDefaults = \OC::$server->query(\OCP\Defaults::class); |
|
86
|
|
|
|
|
87
|
|
|
list($path, $template) = $this->findTemplate($theme, $app, $name); |
|
88
|
|
|
|
|
89
|
|
|
// Set the private data |
|
90
|
|
|
$this->renderAs = $renderAs; |
|
91
|
|
|
$this->path = $path; |
|
92
|
|
|
$this->app = $app; |
|
93
|
|
|
|
|
94
|
|
|
parent::__construct($template, $requestToken, $l10n, $themeDefaults); |
|
95
|
|
|
} |
|
96
|
|
|
|
|
97
|
|
|
/** |
|
98
|
|
|
* @param string $renderAs |
|
99
|
|
|
*/ |
|
100
|
|
|
public static function initTemplateEngine($renderAs) { |
|
101
|
|
|
if (self::$initTemplateEngineFirstRun){ |
|
102
|
|
|
|
|
103
|
|
|
//apps that started before the template initialization can load their own scripts/styles |
|
104
|
|
|
//so to make sure this scripts/styles here are loaded first we use OC_Util::addScript() with $prepend=true |
|
105
|
|
|
//meaning the last script/style in this list will be loaded first |
|
106
|
|
|
if (\OC::$server->getSystemConfig()->getValue ('installed', false) && $renderAs !== 'error' && !\OCP\Util::needUpgrade()) { |
|
107
|
|
|
if (\OC::$server->getConfig ()->getAppValue ( 'core', 'backgroundjobs_mode', 'ajax' ) == 'ajax') { |
|
108
|
|
|
OC_Util::addScript ( 'backgroundjobs', null, true ); |
|
109
|
|
|
} |
|
110
|
|
|
} |
|
111
|
|
|
|
|
112
|
|
|
OC_Util::addStyle('css-variables', null, true); |
|
113
|
|
|
OC_Util::addStyle('server', null, true); |
|
114
|
|
|
OC_Util::addStyle('jquery-ui-fixes',null,true); |
|
115
|
|
|
OC_Util::addVendorStyle('jquery-ui/themes/base/jquery-ui',null,true); |
|
116
|
|
|
OC_Util::addVendorStyle('select2/select2', null, true); |
|
117
|
|
|
OC_Util::addStyle('jquery.ocdialog'); |
|
118
|
|
|
OC_Util::addTranslations("core", null, true); |
|
119
|
|
|
OC_Util::addStyle('search', 'results'); |
|
120
|
|
|
OC_Util::addScript('search', 'search', true); |
|
121
|
|
|
OC_Util::addScript('search', 'searchprovider'); |
|
122
|
|
|
OC_Util::addScript('merged-template-prepend', null, true); |
|
123
|
|
|
OC_Util::addScript('jquery-ui-fixes'); |
|
124
|
|
|
OC_Util::addScript('files/fileinfo'); |
|
125
|
|
|
OC_Util::addScript('files/client'); |
|
126
|
|
|
OC_Util::addScript('contactsmenu'); |
|
127
|
|
|
|
|
128
|
|
|
if (\OC::$server->getConfig()->getSystemValue('debug')) { |
|
129
|
|
|
// Add the stuff we need always |
|
130
|
|
|
// following logic will import all vendor libraries that are |
|
131
|
|
|
// specified in core/js/core.json |
|
132
|
|
|
$fileContent = file_get_contents(OC::$SERVERROOT . '/core/js/core.json'); |
|
133
|
|
|
if($fileContent !== false) { |
|
134
|
|
|
$coreDependencies = json_decode($fileContent, true); |
|
135
|
|
|
foreach(array_reverse($coreDependencies['vendor']) as $vendorLibrary) { |
|
136
|
|
|
//remove trailing ".js" as addVendorScript will append it |
|
137
|
|
|
OC_Util::addVendorScript( |
|
138
|
|
|
substr($vendorLibrary, 0, -3),null,true); |
|
139
|
|
|
} |
|
140
|
|
|
} else { |
|
141
|
|
|
throw new \Exception('Cannot read core/js/core.json'); |
|
142
|
|
|
} |
|
143
|
|
|
} else { |
|
144
|
|
|
// Import all (combined) default vendor libraries |
|
145
|
|
|
OC_Util::addVendorScript('core', null, true); |
|
146
|
|
|
} |
|
147
|
|
|
|
|
148
|
|
|
if (\OC::$server->getRequest()->isUserAgent([\OC\AppFramework\Http\Request::USER_AGENT_IE])) { |
|
149
|
|
|
// polyfill for btoa/atob for IE friends |
|
150
|
|
|
OC_Util::addVendorScript('base64/base64'); |
|
151
|
|
|
// shim for the davclient.js library |
|
152
|
|
|
\OCP\Util::addScript('files/iedavclient'); |
|
153
|
|
|
} |
|
154
|
|
|
|
|
155
|
|
|
self::$initTemplateEngineFirstRun = false; |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
} |
|
159
|
|
|
|
|
160
|
|
|
|
|
161
|
|
|
/** |
|
162
|
|
|
* find the template with the given name |
|
163
|
|
|
* @param string $name of the template file (without suffix) |
|
164
|
|
|
* |
|
165
|
|
|
* Will select the template file for the selected theme. |
|
166
|
|
|
* Checking all the possible locations. |
|
167
|
|
|
* @param string $theme |
|
168
|
|
|
* @param string $app |
|
169
|
|
|
* @return string[] |
|
170
|
|
|
*/ |
|
171
|
|
|
protected function findTemplate($theme, $app, $name) { |
|
172
|
|
|
// Check if it is a app template or not. |
|
173
|
|
|
if( $app !== '' ) { |
|
174
|
|
|
$dirs = $this->getAppTemplateDirs($theme, $app, OC::$SERVERROOT, OC_App::getAppPath($app)); |
|
175
|
|
|
} else { |
|
176
|
|
|
$dirs = $this->getCoreTemplateDirs($theme, OC::$SERVERROOT); |
|
177
|
|
|
} |
|
178
|
|
|
$locator = new \OC\Template\TemplateFileLocator( $dirs ); |
|
179
|
|
|
$template = $locator->find($name); |
|
180
|
|
|
$path = $locator->getPath(); |
|
181
|
|
|
return array($path, $template); |
|
182
|
|
|
} |
|
183
|
|
|
|
|
184
|
|
|
/** |
|
185
|
|
|
* Add a custom element to the header |
|
186
|
|
|
* @param string $tag tag name of the element |
|
187
|
|
|
* @param array $attributes array of attributes for the element |
|
188
|
|
|
* @param string $text the text content for the element. If $text is null then the |
|
189
|
|
|
* element will be written as empty element. So use "" to get a closing tag. |
|
190
|
|
|
*/ |
|
191
|
|
View Code Duplication |
public function addHeader($tag, $attributes, $text=null) { |
|
192
|
|
|
$this->headers[]= array( |
|
193
|
|
|
'tag' => $tag, |
|
194
|
|
|
'attributes' => $attributes, |
|
195
|
|
|
'text' => $text |
|
196
|
|
|
); |
|
197
|
|
|
} |
|
198
|
|
|
|
|
199
|
|
|
/** |
|
200
|
|
|
* Process the template |
|
201
|
|
|
* @return boolean|string |
|
202
|
|
|
* |
|
203
|
|
|
* This function process the template. If $this->renderAs is set, it |
|
204
|
|
|
* will produce a full page. |
|
205
|
|
|
*/ |
|
206
|
|
|
public function fetchPage($additionalParams = null) { |
|
207
|
|
|
$data = parent::fetchPage($additionalParams); |
|
208
|
|
|
|
|
209
|
|
|
if( $this->renderAs ) { |
|
210
|
|
|
$page = new TemplateLayout($this->renderAs, $this->app); |
|
211
|
|
|
|
|
212
|
|
|
if(is_array($additionalParams)) { |
|
213
|
|
|
foreach ($additionalParams as $key => $value) { |
|
214
|
|
|
$page->assign($key, $value); |
|
215
|
|
|
} |
|
216
|
|
|
} |
|
217
|
|
|
|
|
218
|
|
|
// Add custom headers |
|
219
|
|
|
$headers = ''; |
|
220
|
|
|
foreach(OC_Util::$headers as $header) { |
|
221
|
|
|
$headers .= '<'.\OCP\Util::sanitizeHTML($header['tag']); |
|
222
|
|
|
if ( strcasecmp($header['tag'], 'script') === 0 && in_array('src', array_map('strtolower', array_keys($header['attributes']))) ) { |
|
223
|
|
|
$headers .= ' defer'; |
|
224
|
|
|
} |
|
225
|
|
|
foreach($header['attributes'] as $name=>$value) { |
|
226
|
|
|
$headers .= ' '.\OCP\Util::sanitizeHTML($name).'="'.\OCP\Util::sanitizeHTML($value).'"'; |
|
227
|
|
|
} |
|
228
|
|
|
if ($header['text'] !== null) { |
|
229
|
|
|
$headers .= '>'.\OCP\Util::sanitizeHTML($header['text']).'</'.\OCP\Util::sanitizeHTML($header['tag']).'>'; |
|
230
|
|
|
} else { |
|
231
|
|
|
$headers .= '/>'; |
|
232
|
|
|
} |
|
233
|
|
|
} |
|
234
|
|
|
|
|
235
|
|
|
$page->assign('headers', $headers); |
|
236
|
|
|
|
|
237
|
|
|
$page->assign('content', $data); |
|
238
|
|
|
return $page->fetchPage($additionalParams); |
|
|
|
|
|
|
239
|
|
|
} |
|
240
|
|
|
|
|
241
|
|
|
return $data; |
|
242
|
|
|
} |
|
243
|
|
|
|
|
244
|
|
|
/** |
|
245
|
|
|
* Include template |
|
246
|
|
|
* |
|
247
|
|
|
* @param string $file |
|
248
|
|
|
* @param array|null $additionalParams |
|
249
|
|
|
* @return string returns content of included template |
|
250
|
|
|
* |
|
251
|
|
|
* Includes another template. use <?php echo $this->inc('template'); ?> to |
|
252
|
|
|
* do this. |
|
253
|
|
|
*/ |
|
254
|
|
|
public function inc( $file, $additionalParams = null ) { |
|
255
|
|
|
return $this->load($this->path.$file.'.php', $additionalParams); |
|
256
|
|
|
} |
|
257
|
|
|
|
|
258
|
|
|
/** |
|
259
|
|
|
* Shortcut to print a simple page for users |
|
260
|
|
|
* @param string $application The application we render the template for |
|
261
|
|
|
* @param string $name Name of the template |
|
262
|
|
|
* @param array $parameters Parameters for the template |
|
263
|
|
|
* @return boolean|null |
|
264
|
|
|
*/ |
|
265
|
|
View Code Duplication |
public static function printUserPage( $application, $name, $parameters = array() ) { |
|
266
|
|
|
$content = new OC_Template( $application, $name, "user" ); |
|
267
|
|
|
foreach( $parameters as $key => $value ) { |
|
268
|
|
|
$content->assign( $key, $value ); |
|
269
|
|
|
} |
|
270
|
|
|
print $content->printPage(); |
|
271
|
|
|
} |
|
272
|
|
|
|
|
273
|
|
|
/** |
|
274
|
|
|
* Shortcut to print a simple page for admins |
|
275
|
|
|
* @param string $application The application we render the template for |
|
276
|
|
|
* @param string $name Name of the template |
|
277
|
|
|
* @param array $parameters Parameters for the template |
|
278
|
|
|
* @return bool |
|
279
|
|
|
*/ |
|
280
|
|
View Code Duplication |
public static function printAdminPage( $application, $name, $parameters = array() ) { |
|
281
|
|
|
$content = new OC_Template( $application, $name, "admin" ); |
|
282
|
|
|
foreach( $parameters as $key => $value ) { |
|
283
|
|
|
$content->assign( $key, $value ); |
|
284
|
|
|
} |
|
285
|
|
|
return $content->printPage(); |
|
286
|
|
|
} |
|
287
|
|
|
|
|
288
|
|
|
/** |
|
289
|
|
|
* Shortcut to print a simple page for guests |
|
290
|
|
|
* @param string $application The application we render the template for |
|
291
|
|
|
* @param string $name Name of the template |
|
292
|
|
|
* @param array|string $parameters Parameters for the template |
|
293
|
|
|
* @return bool |
|
294
|
|
|
*/ |
|
295
|
|
View Code Duplication |
public static function printGuestPage( $application, $name, $parameters = array() ) { |
|
296
|
|
|
$content = new OC_Template( $application, $name, "guest" ); |
|
297
|
|
|
foreach( $parameters as $key => $value ) { |
|
|
|
|
|
|
298
|
|
|
$content->assign( $key, $value ); |
|
299
|
|
|
} |
|
300
|
|
|
return $content->printPage(); |
|
301
|
|
|
} |
|
302
|
|
|
|
|
303
|
|
|
/** |
|
304
|
|
|
* Print a fatal error page and terminates the script |
|
305
|
|
|
* @param string $error_msg The error message to show |
|
306
|
|
|
* @param string $hint An optional hint message - needs to be properly escape |
|
307
|
|
|
* @param int $statusCode |
|
308
|
|
|
* @suppress PhanAccessMethodInternal |
|
309
|
|
|
*/ |
|
310
|
|
|
public static function printErrorPage( $error_msg, $hint = '', $statusCode = 500) { |
|
311
|
|
|
if (\OC::$server->getAppManager()->isEnabledForUser('theming') && !\OC_App::isAppLoaded('theming')) { |
|
312
|
|
|
\OC_App::loadApp('theming'); |
|
313
|
|
|
} |
|
314
|
|
|
|
|
315
|
|
|
|
|
316
|
|
|
if ($error_msg === $hint) { |
|
317
|
|
|
// If the hint is the same as the message there is no need to display it twice. |
|
318
|
|
|
$hint = ''; |
|
319
|
|
|
} |
|
320
|
|
|
|
|
321
|
|
|
http_response_code($statusCode); |
|
322
|
|
|
try { |
|
323
|
|
|
$content = new \OC_Template( '', 'error', 'error', false ); |
|
324
|
|
|
$errors = array(array('error' => $error_msg, 'hint' => $hint)); |
|
325
|
|
|
$content->assign( 'errors', $errors ); |
|
326
|
|
|
$content->printPage(); |
|
327
|
|
|
} catch (\Exception $e) { |
|
328
|
|
|
$logger = \OC::$server->getLogger(); |
|
329
|
|
|
$logger->error("$error_msg $hint", ['app' => 'core']); |
|
330
|
|
|
$logger->logException($e, ['app' => 'core']); |
|
|
|
|
|
|
331
|
|
|
|
|
332
|
|
|
header('Content-Type: text/plain; charset=utf-8'); |
|
333
|
|
|
print("$error_msg $hint"); |
|
334
|
|
|
} |
|
335
|
|
|
die(); |
|
|
|
|
|
|
336
|
|
|
} |
|
337
|
|
|
|
|
338
|
|
|
/** |
|
339
|
|
|
* print error page using Exception details |
|
340
|
|
|
* @param Exception|Throwable $exception |
|
341
|
|
|
* @param int $statusCode |
|
342
|
|
|
* @return bool|string |
|
343
|
|
|
* @suppress PhanAccessMethodInternal |
|
344
|
|
|
*/ |
|
345
|
|
|
public static function printExceptionErrorPage($exception, $statusCode = 503) { |
|
346
|
|
|
http_response_code($statusCode); |
|
347
|
|
|
try { |
|
348
|
|
|
$request = \OC::$server->getRequest(); |
|
349
|
|
|
$content = new \OC_Template('', 'exception', 'error', false); |
|
350
|
|
|
$content->assign('errorClass', get_class($exception)); |
|
351
|
|
|
$content->assign('errorMsg', $exception->getMessage()); |
|
352
|
|
|
$content->assign('errorCode', $exception->getCode()); |
|
353
|
|
|
$content->assign('file', $exception->getFile()); |
|
354
|
|
|
$content->assign('line', $exception->getLine()); |
|
355
|
|
|
$content->assign('trace', $exception->getTraceAsString()); |
|
356
|
|
|
$content->assign('debugMode', \OC::$server->getSystemConfig()->getValue('debug', false)); |
|
357
|
|
|
$content->assign('remoteAddr', $request->getRemoteAddress()); |
|
358
|
|
|
$content->assign('requestID', $request->getId()); |
|
359
|
|
|
$content->printPage(); |
|
360
|
|
|
} catch (\Exception $e) { |
|
361
|
|
|
$logger = \OC::$server->getLogger(); |
|
362
|
|
|
$logger->logException($exception, ['app' => 'core']); |
|
|
|
|
|
|
363
|
|
|
$logger->logException($e, ['app' => 'core']); |
|
|
|
|
|
|
364
|
|
|
|
|
365
|
|
|
header('Content-Type: text/plain; charset=utf-8'); |
|
366
|
|
|
print("Internal Server Error\n\n"); |
|
367
|
|
|
print("The server encountered an internal error and was unable to complete your request.\n"); |
|
368
|
|
|
print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n"); |
|
369
|
|
|
print("More details can be found in the server log.\n"); |
|
370
|
|
|
} |
|
371
|
|
|
die(); |
|
|
|
|
|
|
372
|
|
|
} |
|
373
|
|
|
} |
|
374
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.