diff --git a/cache/.gitkeep b/cache/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/composer.json b/composer.json index 4ad8b361a21d7916be0c677709e62f5eb234eec0..c08fde0b78a84863699fbcae1601c6f89ffcc10f 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,8 @@ "php": ">=5.3", "simplesamlphp/saml2": "~1.9", "robrichards/xmlseclibs": "~1.4.1", - "whitehat101/apr1-md5": "~1.0" + "whitehat101/apr1-md5": "~1.0", + "twig/twig": "~1.0" }, "require-dev": { "ext-pdo_sqlite": "*", diff --git a/composer.lock b/composer.lock index 76c4b36109a31640cd0f5513f186903d89c83d4d..809b6b3e1780967a98a084f774c508ad7751ec34 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "06fd3525a3284edd8021cb03c5069506", - "content-hash": "fa599e698fbcf68e437d958914b8a6f8", + "hash": "18f459d1d127c855734985394410060a", + "content-hash": "b68e79d55659fa15285f350fd386df12", "packages": [ { "name": "psr/log", @@ -135,6 +135,67 @@ "description": "SAML2 PHP library from SimpleSAMLphp", "time": "2016-03-16 14:11:59" }, + { + "name": "twig/twig", + "version": "v1.24.1", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "3566d311a92aae4deec6e48682dc5a4528c4a512" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/3566d311a92aae4deec6e48682dc5a4528c4a512", + "reference": "3566d311a92aae4deec6e48682dc5a4528c4a512", + "shasum": "" + }, + "require": { + "php": ">=5.2.7" + }, + "require-dev": { + "symfony/debug": "~2.7", + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.24-dev" + } + }, + "autoload": { + "psr-0": { + "Twig_": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + }, + { + "name": "Twig Team", + "homepage": "http://twig.sensiolabs.org/contributors", + "role": "Contributors" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "http://twig.sensiolabs.org", + "keywords": [ + "templating" + ], + "time": "2016-05-30 09:11:59" + }, { "name": "whitehat101/apr1-md5", "version": "v1.0.0", @@ -427,21 +488,24 @@ }, { "name": "phpunit/php-timer", - "version": "1.0.7", + "version": "1.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", "shasum": "" }, "require": { "php": ">=5.3.3" }, + "require-dev": { + "phpunit/phpunit": "~4|~5" + }, "type": "library", "autoload": { "classmap": [ @@ -464,7 +528,7 @@ "keywords": [ "timer" ], - "time": "2015-06-21 08:01:12" + "time": "2016-05-12 18:03:57" }, { "name": "phpunit/php-token-stream", @@ -698,16 +762,16 @@ }, { "name": "symfony/config", - "version": "v3.0.3", + "version": "v3.1.2", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "79a97025f7bf4bbf8352b5df1905aa136a531066" + "reference": "bcf5aebabc95b56e370e13d78565f74c7d8726dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/79a97025f7bf4bbf8352b5df1905aa136a531066", - "reference": "79a97025f7bf4bbf8352b5df1905aa136a531066", + "url": "https://api.github.com/repos/symfony/config/zipball/bcf5aebabc95b56e370e13d78565f74c7d8726dc", + "reference": "bcf5aebabc95b56e370e13d78565f74c7d8726dc", "shasum": "" }, "require": { @@ -720,7 +784,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -747,20 +811,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2016-02-23 15:16:06" + "time": "2016-06-29 05:41:56" }, { "name": "symfony/console", - "version": "v3.0.3", + "version": "v3.1.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "2ed5e2706ce92313d120b8fe50d1063bcfd12e04" + "reference": "747154aa69b0f83cd02fc9aa554836dee417631a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2ed5e2706ce92313d120b8fe50d1063bcfd12e04", - "reference": "2ed5e2706ce92313d120b8fe50d1063bcfd12e04", + "url": "https://api.github.com/repos/symfony/console/zipball/747154aa69b0f83cd02fc9aa554836dee417631a", + "reference": "747154aa69b0f83cd02fc9aa554836dee417631a", "shasum": "" }, "require": { @@ -780,7 +844,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -807,20 +871,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-02-28 16:24:34" + "time": "2016-06-29 07:02:31" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.3", + "version": "v2.8.8", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "78c468665c9568c3faaa9c416a7134308f2d85c3" + "reference": "b180b70439dca70049b6b9b7e21d75e6e5d7aca9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/78c468665c9568c3faaa9c416a7134308f2d85c3", - "reference": "78c468665c9568c3faaa9c416a7134308f2d85c3", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b180b70439dca70049b6b9b7e21d75e6e5d7aca9", + "reference": "b180b70439dca70049b6b9b7e21d75e6e5d7aca9", "shasum": "" }, "require": { @@ -867,20 +931,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-01-27 05:14:19" + "time": "2016-06-29 05:29:29" }, { "name": "symfony/filesystem", - "version": "v3.0.3", + "version": "v3.1.2", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "23ae8f9648d0a7fe94a47c8e20e5bf37c489a451" + "reference": "322da5f0910d8aa0b25fa65ffccaba68dbddb890" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/23ae8f9648d0a7fe94a47c8e20e5bf37c489a451", - "reference": "23ae8f9648d0a7fe94a47c8e20e5bf37c489a451", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/322da5f0910d8aa0b25fa65ffccaba68dbddb890", + "reference": "322da5f0910d8aa0b25fa65ffccaba68dbddb890", "shasum": "" }, "require": { @@ -889,7 +953,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -916,20 +980,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2016-02-23 15:16:06" + "time": "2016-06-29 05:41:56" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.1.1", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "1289d16209491b584839022f29257ad859b8532d" + "reference": "dff51f72b0706335131b00a7f49606168c582594" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d", - "reference": "1289d16209491b584839022f29257ad859b8532d", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", + "reference": "dff51f72b0706335131b00a7f49606168c582594", "shasum": "" }, "require": { @@ -941,7 +1005,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -975,20 +1039,20 @@ "portable", "shim" ], - "time": "2016-01-20 09:13:37" + "time": "2016-05-18 14:26:46" }, { "name": "symfony/stopwatch", - "version": "v3.0.3", + "version": "v3.1.2", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "4a204804952ff267ace88cf499e0b4bb302a475e" + "reference": "bb42806b12c5f89db4ebf64af6741afe6d8457e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/4a204804952ff267ace88cf499e0b4bb302a475e", - "reference": "4a204804952ff267ace88cf499e0b4bb302a475e", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/bb42806b12c5f89db4ebf64af6741afe6d8457e1", + "reference": "bb42806b12c5f89db4ebf64af6741afe6d8457e1", "shasum": "" }, "require": { @@ -997,7 +1061,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -1024,20 +1088,20 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2016-01-03 15:35:16" + "time": "2016-06-29 05:41:56" }, { "name": "symfony/yaml", - "version": "v2.8.3", + "version": "v2.8.8", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "2a4ee40acb880c56f29fb1b8886e7ffe94f3b995" + "reference": "dba4bb5846798cd12f32e2d8f3f35d77045773c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/2a4ee40acb880c56f29fb1b8886e7ffe94f3b995", - "reference": "2a4ee40acb880c56f29fb1b8886e7ffe94f3b995", + "url": "https://api.github.com/repos/symfony/yaml/zipball/dba4bb5846798cd12f32e2d8f3f35d77045773c8", + "reference": "dba4bb5846798cd12f32e2d8f3f35d77045773c8", "shasum": "" }, "require": { @@ -1073,7 +1137,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-02-23 07:41:20" + "time": "2016-06-29 05:29:29" } ], "aliases": [], diff --git a/config-templates/config.php b/config-templates/config.php index af726301cf5561e89d1ffbacbaa9ed049675125f..26473bd3531f0c353fa09ce9dcf2aeba587d9cd9 100644 --- a/config-templates/config.php +++ b/config-templates/config.php @@ -666,6 +666,10 @@ $config = array( */ 'theme.use' => 'default', + /* + * Templating options + */ + 'template.auto_reload' => false, /********************* diff --git a/lib/SimpleSAML/Locale/Language.php b/lib/SimpleSAML/Locale/Language.php index f843da0565dd48af6c6e29af080c47c594298a47..412fc2ac9fca5d2ef57d97c1e83e1e6ab7a71be6 100644 --- a/lib/SimpleSAML/Locale/Language.php +++ b/lib/SimpleSAML/Locale/Language.php @@ -69,6 +69,52 @@ class Language */ private $customFunction; + /** + * A list of languages supported with their names localized, indexed by ISO 639-2 code. + * + * @var array + */ + private $language_names = array( + 'no' => 'BokmĂĄl', // Norwegian BokmĂĄl + 'nn' => 'Nynorsk', // Norwegian Nynorsk + 'se' => 'Sámegiella', // Northern Sami + 'sam' => 'Ă…arjelh-saemien giele', // Southern Sami + 'da' => 'Dansk', // Danish + 'en' => 'English', + 'de' => 'Deutsch', // German + 'sv' => 'Svenska', // Swedish + 'fi' => 'Suomeksi', // Finnish + 'es' => 'Español', // Spanish + 'fr' => 'Français', // French + 'it' => 'Italiano', // Italian + 'nl' => 'Nederlands', // Dutch + 'lb' => 'LĂ«tzebuergesch', // Luxembourgish + 'cs' => 'ÄŚeština', // Czech + 'sl' => 'Slovenščina', // Slovensk + 'lt' => 'LietuviĹł kalba', // Lithuanian + 'hr' => 'Hrvatski', // Croatian + 'hu' => 'Magyar', // Hungarian + 'pl' => 'JÄ™zyk polski', // Polish + 'pt' => 'PortuguĂŞs', // Portuguese + 'pt-br' => 'PortuguĂŞs brasileiro', // Portuguese + 'ru' => 'Ń€ŃŃŃкий язык', // Russian + 'et' => 'eesti keel', // Estonian + 'tr' => 'TĂĽrkçe', // Turkish + 'el' => 'ελληνικά', // Greek + 'ja' => '日本語', // Japanese + 'zh' => '简体ä¸ć–‡', // Chinese (simplified) + 'zh-tw' => 'çąé«”ä¸ć–‡', // Chinese (traditional) + 'ar' => 'العربية', // Arabic + 'fa' => 'پارسی', // Persian + 'ur' => 'اردŮ', // Urdu + 'he' => 'עִבְרִית', // Hebrew + 'id' => 'Bahasa Indonesia', // Indonesian + 'sr' => 'Srpski', // Serbian + 'lv' => 'Latviešu', // Latvian + 'ro' => 'RomâneČ™te', // Romanian + 'eu' => 'Euskara', // Basque + ); + /** * Constructor @@ -151,6 +197,19 @@ class Language } + /** + * Get the localized name of a language, by ISO 639-2 code. + * + * @param string $code The ISO 639-2 code of the language. + * + * @return string The localized name of the language. + */ + public function getLanguageLocalizedName($code) + { + return $this->language_names[$code]; + } + + /** * Get the language parameter name. * diff --git a/lib/SimpleSAML/XHTML/Template.php b/lib/SimpleSAML/XHTML/Template.php index 8214ac154b320f5d905617bc17706543fdfd0b68..1172b0f6946468bba4e0240596a18ee5747d393b 100644 --- a/lib/SimpleSAML/XHTML/Template.php +++ b/lib/SimpleSAML/XHTML/Template.php @@ -38,6 +38,11 @@ class SimpleSAML_XHTML_Template */ private $template = 'default.php'; + /* + * Main Twig namespace, to avoid misspelling it *again* + */ + private $twig_namespace = \Twig_Loader_Filesystem::MAIN_NAMESPACE; + /** * Constructor @@ -46,24 +51,229 @@ class SimpleSAML_XHTML_Template * @param string $template Which template file to load * @param string|null $defaultDictionary The default dictionary where tags will come from. */ - public function __construct(SimpleSAML_Configuration $configuration, $template, $defaultDictionary = null) + public function __construct(\SimpleSAML_Configuration $configuration, $template, $defaultDictionary = null) { $this->configuration = $configuration; $this->template = $template; // TODO: do not remove the slash from the beginning, change the templates instead! $this->data['baseurlpath'] = ltrim($this->configuration->getBasePath(), '/'); $this->translator = new SimpleSAML\Locale\Translate($configuration, $defaultDictionary); + $this->twig = $this->setupTwig(); } /** - * Return the internal translator object used by this template. + * Normalize the name of the template to one of the possible alternatives. * - * @return \SimpleSAML\Locale\Translate The translator that will be used with this template. + * @param string $templateName The template name to normalize. + * @return string The filename we need to look for. */ - public function getTranslator() + private function normalizeTemplateName($templateName) { - return $this->translator; + if (strripos($templateName, '.twig.html')) { + return $templateName; + } + $phppos = strripos($templateName, '.php'); + if ($phppos) { + $templateName = substr($templateName, 0, $phppos); + } + $tplpos = strripos($templateName, '.tpl'); + if ($tplpos) { + $templateName = substr($templateName, 0, $tplpos); + } + return $templateName.'.twig.html'; + } + + + /** + * Set up the places where twig can look for templates. + * + * @return Twig_Loader_Filesystem|false The twig template loader or false if the template does not exist. + * @throws Twig_Error_Loader In case a failure occurs. + */ + private function setupTwigTemplatepaths() + { + $filename = $this->normalizeTemplateName($this->template); + + // get namespace if any + $namespace = ''; + $split = explode(':', $filename, 2); + if (count($split) === 2) { + $namespace = $split[0]; + $filename = $split[1]; + } + $this->twig_template = $namespace ? '@'.$namespace.'/'.$filename : $filename; + $loader = new \Twig_Loader_Filesystem(); + $templateDirs = array_merge( + $this->findThemeTemplateDirs(), + $this->findModuleTemplateDirs() + ); + // default, themeless templates are checked last + $templateDirs[] = array( + $this->twig_namespace => $this->configuration->resolvePath('templates') + ); + foreach ($templateDirs as $entry) { + $loader->addPath($entry[key($entry)], key($entry)); + } + if (!$loader->exists($this->twig_template)) { + return false; + } + return $loader; + } + + + /** + * Setup twig. + */ + private function setupTwig() + { + $auto_reload = $this->configuration->getBoolean('template.auto_reload', true); + $cache = false; + if (!$auto_reload) { + // Cache only used if auto_reload = false + $cache = $this->configuration->getString('template.cache', $this->configuration->resolvePath('cache')); + } + // set up template paths + $loader = $this->setupTwigTemplatepaths(); + if (!$loader) { + return null; + } + + return new \Twig_Environment($loader, array('cache' => $cache, 'auto_reload' => $auto_reload)); + } + + /* + * Add overriding templates in configured theme + * + * @return array an array of module => templatedir lookups + */ + private function findThemeTemplateDirs() + { + // parse config to find theme and module theme is in, if any + $tmp = explode(':', $this->configuration->getString('theme.use', 'default'), 2); + if (count($tmp) === 2) { + $themeModule = $tmp[0]; + $themeName = $tmp[1]; + } else { + $themeModule = null; + $themeName = $tmp[0]; + } + // default theme in use, abort + if ($themeName == 'default') { + return array(); + } + if ($themeModule !== null) { + $moduleDir = \SimpleSAML\Module::getModuleDir($themeModule); + $themeDir = $moduleDir.'/themes/'.$themeName; + $files = scandir($themeDir); + if ($files) { + $themeTemplateDirs = array(); + foreach ($files as $file) { + if ($file == '.' || $file == '..') { + continue; + } + // set correct name for default namespace + $ns = $file == 'default' ? $this->twig_namespace : $file; + $themeTemplateDirs[] = array($ns => $themeDir.'/'.$file); + } + return $themeTemplateDirs; + } + } + // theme not found + return array(); + } + + /* + * Which enabled modules have templates? + * + * @return array an array of module => templatedir lookups + */ + private function findModuleTemplateDirs() + { + $all_modules = \SimpleSAML\Module::getModules(); + $modules = array(); + foreach ($all_modules as $module) { + if (!\SimpleSAML\Module::isModuleEnabled($module)) { + continue; + } + $moduledir = \SimpleSAML\Module::getModuleDir($module); + // check if module has a /templates dir, if so, append + $templatedir = $moduledir.'/templates'; + if (is_dir($templatedir)) { + $modules[] = array($module => $templatedir); + } + } + return $modules; + } + + + /** + * Generate an array for its use in the language bar, indexed by the ISO 639-2 codes of the languages available, + * containing their localized names and the URL that should be used in order to change to that language. + * + * @return array The array containing information of all available languages. + */ + private function generateLanguageBar() + { + $languages = $this->translator->getLanguage()->getLanguageList(); + $langmap = null; + if (count($languages) > 1) { + $parameterName = $this->getTranslator()->getLanguage()->getLanguageParameterName(); + $langmap = array(); + foreach ($languages as $lang => $current) { + $lang = strtolower($lang); + $langname = $this->translator->getLanguage()->getLanguageLocalizedName($lang); + $url = false; + if (!$current) { + $url = htmlspecialchars(\SimpleSAML\Utils\HTTP::addURLParameters( + '', + array($parameterName => $lang) + )); + } + $langmap[$lang] = array( + 'name' => $langname, + 'url' => $url, + ); + } + } + return $langmap; + } + + + /** + * Set some default context + */ + private function twigDefaultContext() + { + $this->data['currentLanguage'] = $this->translator->getLanguage()->getLanguage(); + // show language bar by default + if (!isset($this->data['hideLanguageBar'])) { + $this->data['hideLanguageBar'] = false; + } + // get languagebar + $this->data['languageBar'] = null; + if ($this->data['hideLanguageBar'] === false) { + $languageBar = $this->generateLanguageBar(); + if (is_null($languageBar)) { + $this->data['hideLanguageBar'] = true; + } else { + $this->data['languageBar'] = $languageBar; + } + } + + // assure that there is a <title> and <h1> + if (isset($this->data['header']) && !isset($this->data['pagetitle'])) { + $this->data['pagetitle'] = $this->data['header']; + } + if (!isset($this->data['pagetitle'])) { + $this->data['pagetitle'] = 'SimpleSAMLphp'; + } + + // set RTL + $this->data['isRTL'] = false; + if ($this->translator->getLanguage()->isLanguageRTL()) { + $this->data['isRTL'] = true; + } } @@ -72,8 +282,13 @@ class SimpleSAML_XHTML_Template */ public function show() { - $filename = $this->findTemplatePath($this->template); - require($filename); + if ($this->twig) { + $this->twigDefaultContext(); + echo $this->twig->render($this->twig_template, $this->data); + } else { + $filename = $this->findTemplatePath($this->template); + require($filename); + } } @@ -92,7 +307,7 @@ class SimpleSAML_XHTML_Template * * @throws Exception If the template file couldn't be found. */ - private function findTemplatePath($template) + private function findTemplatePath($template, $throw_exception = true) { assert('is_string($template)'); @@ -118,11 +333,11 @@ class SimpleSAML_XHTML_Template if ($themeModule !== null) { // .../module/<themeModule>/themes/<themeName>/<templateModule>/<templateName> - $filename = SimpleSAML_Module::getModuleDir($themeModule). + $filename = \SimpleSAML\Module::getModuleDir($themeModule). '/themes/'.$themeName.'/'.$templateModule.'/'.$templateName; } elseif ($templateModule !== 'default') { - // .../module/<templateModule>/templates/<themeName>/<templateName> - $filename = SimpleSAML_Module::getModuleDir($templateModule).'/templates/'.$templateName; + // .../module/<templateModule>/templates/<templateName> + $filename = \SimpleSAML\Module::getModuleDir($templateModule).'/templates/'.$templateName; } else { // .../templates/<theme>/<templateName> $filename = $this->configuration->getPathValue('templatedir', 'templates/').$templateName; @@ -133,15 +348,15 @@ class SimpleSAML_XHTML_Template } // not found in current theme - SimpleSAML_Logger::debug( - $_SERVER['PHP_SELF'].' - Template: Could not find template file ['. $template.'] at ['. + \SimpleSAML_Logger::debug( + $_SERVER['PHP_SELF'].' - Template: Could not find template file ['.$template.'] at ['. $filename.'] - now trying the base template' ); // try default theme if ($templateModule !== 'default') { // .../module/<templateModule>/templates/<templateName> - $filename = SimpleSAML_Module::getModuleDir($templateModule).'/templates/'.$templateName; + $filename = \SimpleSAML\Module::getModuleDir($templateModule).'/templates/'.$templateName; } else { // .../templates/<templateName> $filename = $this->configuration->getPathValue('templatedir', 'templates/').'/'.$templateName; @@ -151,11 +366,28 @@ class SimpleSAML_XHTML_Template return $filename; } - // not found in default template - log error and throw exception - $error = 'Template: Could not find template file ['.$template.'] at ['.$filename.']'; - SimpleSAML_Logger::critical($_SERVER['PHP_SELF'].' - '.$error); + // not found in default template + if ($throw_exception) { + // log error and throw exception + $error = 'Template: Could not find template file ['.$template.'] at ['.$filename.']'; + \SimpleSAML_Logger::critical($_SERVER['PHP_SELF'].' - '.$error); - throw new Exception($error); + throw new Exception($error); + } else { + // missing template expected, return NULL + return null; + } + } + + + /** + * Return the internal translator object used by this template. + * + * @return \SimpleSAML\Locale\Translate The translator that will be used with this template. + */ + public function getTranslator() + { + return $this->translator; } @@ -191,6 +423,7 @@ class SimpleSAML_XHTML_Template /** * @param $language * @param bool $setLanguageCookie + * * @deprecated This method will be removed in SSP 2.0. Please use \SimpleSAML\Locale\Language::setLanguage() * instead. */ @@ -213,6 +446,7 @@ class SimpleSAML_XHTML_Template /** * @param $language + * * @deprecated This method will be removed in SSP 2.0. Please use \SimpleSAML\Locale\Language::setLanguageCookie() * instead. */ @@ -221,10 +455,12 @@ class SimpleSAML_XHTML_Template \SimpleSAML\Locale\Language::setLanguageCookie($language); } + /** * Wraps Language->getLanguageList */ - private function getLanguageList() { + private function getLanguageList() + { return $this->translator->getLanguage()->getLanguageList(); } @@ -242,10 +478,10 @@ class SimpleSAML_XHTML_Template /** - * Temporary wrapper for SimpleSAML\Locale\Translate::getPreferredTranslation(). + * Temporary wrapper for \SimpleSAML\Locale\Translate::getPreferredTranslation(). * * @deprecated This method will be removed in SSP 2.0. Please use - * SimpleSAML\Locale\Translate::getPreferredTranslation() instead. + * \SimpleSAML\Locale\Translate::getPreferredTranslation() instead. */ public function getTranslation($translations) { @@ -258,7 +494,8 @@ class SimpleSAML_XHTML_Template * This function can be used to include headers and footers etc. * */ - private function includeAtTemplateBase($file) { + private function includeAtTemplateBase($file) + { $data = $this->data; $filename = $this->findTemplatePath($file); @@ -283,6 +520,7 @@ class SimpleSAML_XHTML_Template /** * @param $file * @param null $otherConfig + * * @deprecated This method will be removed in SSP 2.0. Please use * \SimpleSAML\Locale\Translate::includeLanguageFile() instead. */ @@ -295,7 +533,8 @@ class SimpleSAML_XHTML_Template /** * Wrap Language->isLanguageRTL */ - private function isLanguageRTL() { + private function isLanguageRTL() + { return $this->translator->getLanguage()->isLanguageRTL(); } @@ -305,6 +544,7 @@ class SimpleSAML_XHTML_Template * * @param array $def The array holding string definitions. * @param array $lang The array holding translations for every string. + * * @return array The recursive merge of both arrays. * @deprecated This method will be removed in SimpleSAMLphp 2.0. Please use array_merge_recursive() instead. */ diff --git a/modules/core/www/frontpage_config.php b/modules/core/www/frontpage_config.php index cc728ff9c2084638d6fa65a513fd189a51d5aaaf..5e082acab8940b7405ff9144e8f74a1efb74cce1 100644 --- a/modules/core/www/frontpage_config.php +++ b/modules/core/www/frontpage_config.php @@ -53,6 +53,10 @@ $links_config[] = array( 'text' => '{core:frontpage:link_phpinfo}' ); +$links_config[] = array( + 'href' => \SimpleSAML\Utils\HTTP::getBaseURL() . 'admin/sandbox.php', + 'text' => '{core:frontpage:link_sandbox}' +); diff --git a/modules/cron/templates/croninfo-tpl.php b/modules/cron/templates/croninfo.tpl.php similarity index 100% rename from modules/cron/templates/croninfo-tpl.php rename to modules/cron/templates/croninfo.tpl.php diff --git a/modules/cron/www/croninfo.php b/modules/cron/www/croninfo.php index 18d1cc9908a36099ce55ba3d2b29911d73b6172b..93b7acb5b15bc25898aaab4d587d12fbb05b791e 100644 --- a/modules/cron/www/croninfo.php +++ b/modules/cron/www/croninfo.php @@ -36,6 +36,6 @@ foreach ($tags AS $tag) { -$t = new SimpleSAML_XHTML_Template($config, 'cron:croninfo-tpl.php', 'cron:cron'); +$t = new SimpleSAML_XHTML_Template($config, 'cron:croninfo.tpl.php', 'cron:cron'); $t->data['urls'] = $urls; $t->show(); diff --git a/modules/discopower/lib/PowerIdPDisco.php b/modules/discopower/lib/PowerIdPDisco.php index 8fd2d1cbe55691cba1e02dd1d62e981e854ae864..a5b237551282abb08916cb34f50a26c68f6f993c 100644 --- a/modules/discopower/lib/PowerIdPDisco.php +++ b/modules/discopower/lib/PowerIdPDisco.php @@ -247,7 +247,7 @@ class sspmod_discopower_PowerIdPDisco extends SimpleSAML_XHTML_IdPDisco $idpList = $this->idplistStructured($this->filterList($idpList)); $preferredIdP = $this->getRecommendedIdP(); - $t = new SimpleSAML_XHTML_Template($this->config, 'discopower:disco-tpl.php', 'disco'); + $t = new SimpleSAML_XHTML_Template($this->config, 'discopower:disco.tpl.php', 'disco'); $t->data['idplist'] = $idpList; $t->data['preferredidp'] = $preferredIdP; $t->data['return'] = $this->returnURL; diff --git a/modules/discopower/templates/disco-tpl.php b/modules/discopower/templates/disco.tpl.php similarity index 100% rename from modules/discopower/templates/disco-tpl.php rename to modules/discopower/templates/disco.tpl.php diff --git a/modules/portal/lib/Portal.php b/modules/portal/lib/Portal.php index 404041a9e7961e5853912e3bd55b986f6547cdbc..72effb6367a3cbd5d0e68cfe57597e8c4b07d44b 100644 --- a/modules/portal/lib/Portal.php +++ b/modules/portal/lib/Portal.php @@ -38,7 +38,7 @@ class sspmod_portal_Portal { function getMenu($thispage) { $config = SimpleSAML_Configuration::getInstance(); - $t = new SimpleSAML_XHTML_Template($config, 'sanitycheck:check-tpl.php'); + $t = new SimpleSAML_XHTML_Template($config, 'sanitycheck:check.tpl.php'); $tabset = $this->getTabset($thispage); $logininfo = $this->getLoginInfo($t, $thispage); $text = ''; @@ -68,4 +68,4 @@ class sspmod_portal_Portal { } -} \ No newline at end of file +} diff --git a/modules/sanitycheck/templates/check-tpl.php b/modules/sanitycheck/templates/check.tpl.php similarity index 100% rename from modules/sanitycheck/templates/check-tpl.php rename to modules/sanitycheck/templates/check.tpl.php diff --git a/modules/sanitycheck/www/index.php b/modules/sanitycheck/www/index.php index c740c2137c6a4557c179d49069a8bb2c18b95e6d..708348b0126b1b968421c146747d2bcece3e4e5a 100644 --- a/modules/sanitycheck/www/index.php +++ b/modules/sanitycheck/www/index.php @@ -22,7 +22,7 @@ if (isset($_REQUEST['output']) && $_REQUEST['output'] == 'text') { exit; } -$t = new SimpleSAML_XHTML_Template($config, 'sanitycheck:check-tpl.php'); +$t = new SimpleSAML_XHTML_Template($config, 'sanitycheck:check.tpl.php'); $t->data['pageid'] = 'sanitycheck'; $t->data['errors'] = $errors; $t->data['info'] = $info; diff --git a/modules/statistics/lib/StatDataset.php b/modules/statistics/lib/StatDataset.php index 1d641309f4bdda663eb874a6063a1b4dfa137098..1c4067196d9d13fc6f3dfd7a56f5587b5db618b8 100644 --- a/modules/statistics/lib/StatDataset.php +++ b/modules/statistics/lib/StatDataset.php @@ -251,7 +251,7 @@ class sspmod_statistics_StatDataset public function getDelimiterPresentation() { $config = SimpleSAML_Configuration::getInstance(); - $t = new SimpleSAML_XHTML_Template($config, 'statistics:statistics-tpl.php'); + $t = new SimpleSAML_XHTML_Template($config, 'statistics:statistics.tpl.php'); $availdelimiters = $this->availDelimiters(); diff --git a/modules/statistics/templates/statistics-tpl.php b/modules/statistics/templates/statistics.tpl.php similarity index 100% rename from modules/statistics/templates/statistics-tpl.php rename to modules/statistics/templates/statistics.tpl.php diff --git a/modules/statistics/templates/statmeta-tpl.php b/modules/statistics/templates/statmeta.tpl.php similarity index 100% rename from modules/statistics/templates/statmeta-tpl.php rename to modules/statistics/templates/statmeta.tpl.php diff --git a/modules/statistics/www/showstats.php b/modules/statistics/www/showstats.php index ed4c443fc31801934f073ba2c5d9759319b9ef17..d15edc7cd5743f5bb9ab291a89dc293777f2299a 100644 --- a/modules/statistics/www/showstats.php +++ b/modules/statistics/www/showstats.php @@ -96,7 +96,7 @@ if (array_key_exists('output', $_REQUEST) && $_REQUEST['output'] === 'csv') { -$t = new SimpleSAML_XHTML_Template($config, 'statistics:statistics-tpl.php'); +$t = new SimpleSAML_XHTML_Template($config, 'statistics:statistics.tpl.php'); $t->data['pageid'] = 'statistics'; $t->data['header'] = 'stat'; $t->data['imgurl'] = $grapher->show($axis['axis'], $axis['axispos'], $datasets, $maxes); diff --git a/modules/statistics/www/statmeta.php b/modules/statistics/www/statmeta.php index 46c5ddb01054f74fb018ac07c7d910f999220c48..4b8a9d04b78695bf1c180801762e110f0c6fcb5a 100644 --- a/modules/statistics/www/statmeta.php +++ b/modules/statistics/www/statmeta.php @@ -10,7 +10,7 @@ $aggr->loadMetadata(); $metadata = $aggr->getMetadata(); -$t = new SimpleSAML_XHTML_Template($config, 'statistics:statmeta-tpl.php'); +$t = new SimpleSAML_XHTML_Template($config, 'statistics:statmeta.tpl.php'); $t->data['metadata'] = $metadata; $t->show(); diff --git a/templates/_footer.twig.html b/templates/_footer.twig.html new file mode 100644 index 0000000000000000000000000000000000000000..c1edf52145d4322d8128d5f24bef45454a78b882 --- /dev/null +++ b/templates/_footer.twig.html @@ -0,0 +1,6 @@ + <hr> + + <img src="/{{ baseurlpath }}resources/icons/ssplogo-fish-small.png" alt="Small fish logo" style="float: right"> + Copyright © 2007-2015 <a href="http://uninett.no/">UNINETT AS</a> + + <br style="clear: right"> diff --git a/templates/_header.twig.html b/templates/_header.twig.html new file mode 100644 index 0000000000000000000000000000000000000000..ad521520e8bc5f3c18d409424f3cc51edd90e2d2 --- /dev/null +++ b/templates/_header.twig.html @@ -0,0 +1,14 @@ +<div id="header"> + <h1><a style="text-decoration: none; color: white" href="/{{ baseurlpath }}">{{ pagetitle }}</a></h1> +</div> + +{% if not hideLanguageBar %} +<div id="languagebar"> + {% for lang in languageBar %} + + {%- if not loop.first -%} | {%- endif -%}{% if lang.url %}<a href="{{ lang.url }}">{{ lang.name }}</a>{% else %}{{ lang.name }}{% endif %} + + {% endfor %} + +</div> +{% endif %} diff --git a/templates/base.twig.html b/templates/base.twig.html new file mode 100644 index 0000000000000000000000000000000000000000..ad30a63353fc354ba7a5bf975ca3c0d674d65dee --- /dev/null +++ b/templates/base.twig.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0"> + <script type="text/javascript" src="/{{ baseurlpath }}resources/script.js"></script> + <title>{{ pagetitle }}</title> + <link rel="stylesheet" type="text/css" href="/{{ baseurlpath }}resources/default.css"> + <link rel="icon" type="image/icon" href="/{{ baseurlpath }}resources/icons/favicon.ico"> + <link rel="stylesheet" media="screen" type="text/css" href="/{{ baseurlpath }}resources/uitheme1.8/jquery-ui.css"> + {% if isRTL %}<link rel="stylesheet" type="text/css" href="/{{ baseurlpath }}resources/default-rtl.css" />{% endif %} + <meta name="robots" content="noindex, nofollow"> + {% block preload %}{% endblock %} +</head> +<body> + <div id="wrap"> + + {% block header %}{% include "_header.twig.html" %}{% endblock %} + + <div id="content"> + {% block content %}{% endblock %} + </div><!-- #content --> + + <div id="footer"> + {% block footer %}{% include "_footer.twig.html" %}{% endblock %} + </div> + + </div><!-- #wrap --> + + {% block postload %}{% endblock %} +</body></html> diff --git a/templates/index.twig.html b/templates/index.twig.html new file mode 100644 index 0000000000000000000000000000000000000000..c8889341852b9f7ce8a6fbcd7899993670a4233b --- /dev/null +++ b/templates/index.twig.html @@ -0,0 +1,33 @@ +{% extends "base.twig.html" %} +{% block content %} + <div id="portalmenu" class="ui-tabs ui-widget ui-widget-content ui-corner-all"> + <ul class="tabset_tabs ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"> + <li class="ui-state-default ui-corner-top"><a href="http://simplesaml.arrakis.uninett.no/simplesaml/module.php/core/frontpage_welcome.php">Welcome</a></li> + <li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active"><a href="#">Configuration</a></li> + <li class="ui-state-default ui-corner-top"><a href="http://simplesaml.arrakis.uninett.no/simplesaml/module.php/core/frontpage_auth.php">Authentication</a></li> + <li class="ui-state-default ui-corner-top"><a href="http://simplesaml.arrakis.uninett.no/simplesaml/module.php/core/frontpage_federation.php">Federation</a></li> + </ul> + <div id="portalcontent" class="ui-tabs-panel ui-widget-content ui-corner-bottom"> + + <div style="clear: both" class="enablebox mini"> + <table> + + <tr class="disabled"><td>SAML 2.0 IdP</td> + <td><img src="/{{ baseurlpath }}resources/icons/silk/delete.png" alt="disabled" /></td></tr> + + <tr class="disabled"><td>Shib 1.3 IdP</td> + <td><img src="/{{ baseurlpath }}resources/icons/silk/delete.png" alt="disabled" /></td></tr> + + </table> + </div> + <h2>Configuration</h2> + <ul> + {% for url, page in adminpages %} + <li> + <a href="{{ url }}">{{ page }}</a> + </li> + {% endfor %} + </ul> + </div> + </div> +{% endblock content %} diff --git a/templates/sandbox.twig.html b/templates/sandbox.twig.html new file mode 100644 index 0000000000000000000000000000000000000000..e37201e0c3667bd04c9978a7ed81adc196d31366 --- /dev/null +++ b/templates/sandbox.twig.html @@ -0,0 +1,6 @@ +{% extends "base.twig.html" %} +{% block content %} + <p>This page exists as a sandbox to play with twig without affecting anything else. The template is in ./templates.</p> + <p>{{ sometext }}</p> + <p>Current locale set: {{ currentLanguage }}</p> +{% endblock content %} diff --git a/www/admin/index.php b/www/admin/index.php new file mode 100644 index 0000000000000000000000000000000000000000..a1f9558e1446a3821ec98c9038499aaf46c4daaf --- /dev/null +++ b/www/admin/index.php @@ -0,0 +1,27 @@ +<?php + +require_once('../_include.php'); + +// Load SimpleSAMLphp, configuration +$config = SimpleSAML_Configuration::getInstance(); +$session = SimpleSAML_Session::getSessionFromRequest(); + +// Check if valid local session exists.. +//SimpleSAML\Utils\Auth::requireAdmin(); + +$adminpages = array( + 'hostnames.php' => 'Diagnostics on hostname, port and protocol', + 'phpinfo.php' => 'PHP info', + '../module.php/sanitycheck/index.php' => 'Sanity check of your SimpleSAMLphp setup', + 'sandbox.php' => 'Sandbox for testing changes to layout and css', +); + +$template = new SimpleSAML_XHTML_Template($config, 'index.php'); + +$template->data['pagetitle'] = 'Admin'; +$template->data['adminpages'] = $adminpages; +$template->data['remaining'] = $session->getAuthData('admin', 'Expire') - time(); +$template->data['valid'] = 'na'; +$template->data['logout'] = null; + +$template->show(); diff --git a/www/admin/sandbox.php b/www/admin/sandbox.php new file mode 100644 index 0000000000000000000000000000000000000000..ec77569cf8ebb875bfd47d361f52c815e2376ba3 --- /dev/null +++ b/www/admin/sandbox.php @@ -0,0 +1,19 @@ +<?php + +require_once('../_include.php'); + +// Load SimpleSAMLphp, configuration +$config = SimpleSAML_Configuration::getInstance(); +$session = SimpleSAML_Session::getSessionFromRequest(); + +// Check if valid local session exists.. +//SimpleSAML\Utils\Auth::requireAdmin(); + +$template = new SimpleSAML_XHTML_Template($config, 'sandbox.php'); + +$template->data['pagetitle'] = 'Sandbox'; +$template->data['sometext'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur.'; +$template->data['remaining'] = $session->getAuthData('admin', 'Expire') - time(); +$template->data['logout'] = null; + +$template->show();