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