Skip to content
Snippets Groups Projects
Commit 13384dde authored by Olav Morken's avatar Olav Morken
Browse files

Module framework for request handling.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@809 44740490-163a-0410-bde0-09ae8108e29a
parent 85e4deaa
No related branches found
No related tags found
No related merge requests found
...@@ -129,6 +129,23 @@ class SimpleSAML_Module { ...@@ -129,6 +129,23 @@ class SimpleSAML_Module {
return $className; return $className;
} }
/**
* Get absolute URL to a specified module resource.
*
* This function creates an absolute URL to a resource stored under ".../modules/<module>/www/".
*
* @param string $resource Resource path, on the form "<module name>/<resource>"
* @return string The absolute URL to the given resource.
*/
public static function getModuleURL($resource) {
assert('is_string($resource)');
assert('$resource[0] !== "/"');
$config = SimpleSAML_Configuration::getInstance();
return SimpleSAML_Utilities::selfURLhost() . '/' . $config->getBaseURL() . 'module.php/' . $resource;
}
} }
?> ?>
\ No newline at end of file
...@@ -190,21 +190,8 @@ class SimpleSAML_XHTML_Template { ...@@ -190,21 +190,8 @@ class SimpleSAML_XHTML_Template {
*/ */
private function includeAtTemplateBase($file) { private function includeAtTemplateBase($file) {
$data = $this->data; $data = $this->data;
$filename = $this->configuration->getPathValue('templatedir') . $this->configuration->getValue('theme.use') . '/' . $file;
if (!file_exists($filename)) { $filename = $this->findTemplatePath($file);
SimpleSAML_Logger::error($_SERVER['PHP_SELF'].' - Template: Could not find template file [' . $file .
'] at [' . $filename . '] - Now trying at base');
$filename = $this->configuration->getPathValue('templatedir') . $this->configuration->getValue('theme.base') . '/' . $file;
if (!file_exists($filename)) {
SimpleSAML_Logger::error($_SERVER['PHP_SELF'].' - Template: Could not find template file [' . $file .
'] at [' . $filename . ']');
throw new Exception('Could not load template file [' . $file . ']');
}
}
include($filename); include($filename);
} }
...@@ -223,8 +210,16 @@ class SimpleSAML_XHTML_Template { ...@@ -223,8 +210,16 @@ class SimpleSAML_XHTML_Template {
assert('is_string($name)'); assert('is_string($name)');
if(!array_key_exists($name, $this->dictionaries)) { if(!array_key_exists($name, $this->dictionaries)) {
$dictDir = $this->configuration->getPathValue('dictionarydir'); $sepPos = strpos($name, ':');
$this->dictionaries[$name] = $this->readDictionaryFile($dictDir . $name . '.php'); if($sepPos !== FALSE) {
$module = substr($name, 0, $sepPos);
$fileName = substr($name, $sepPos + 1);
$dictDir = SimpleSAML_Module::getModuleDir($module) . '/dictionaries/';
} else {
$dictDir = $this->configuration->getPathValue('dictionarydir');
$fileName = $name;
}
$this->dictionaries[$name] = $this->readDictionaryFile($dictDir . $fileName . '.php');
} }
return $this->dictionaries[$name]; return $this->dictionaries[$name];
...@@ -249,7 +244,7 @@ class SimpleSAML_XHTML_Template { ...@@ -249,7 +244,7 @@ class SimpleSAML_XHTML_Template {
} }
/* Check whether we should use the default dictionary or a dictionary specified in the tag. */ /* Check whether we should use the default dictionary or a dictionary specified in the tag. */
if(substr($tag, 0, 1) === '{' && preg_match('/^{(\w+?):(.*)}$/', $tag, $matches)) { if(substr($tag, 0, 1) === '{' && preg_match('/^{((?:\w+:)?\w+?):(.*)}$/', $tag, $matches)) {
$dictionary = $matches[1]; $dictionary = $matches[1];
$tag = $matches[2]; $tag = $matches[2];
} else { } else {
...@@ -460,31 +455,99 @@ class SimpleSAML_XHTML_Template { ...@@ -460,31 +455,99 @@ class SimpleSAML_XHTML_Template {
* Show the template to the user. * Show the template to the user.
*/ */
public function show() { public function show() {
$filename = $this->configuration->getPathValue('templatedir') .
$this->configuration->getValue('theme.use') . '/' . $this->template;
if (!file_exists($filename)) { $filename = $this->findTemplatePath($this->template);
SimpleSAML_Logger::warning($_SERVER['PHP_SELF'].' - Template: Could not find template file [' . $this->template . '] at [' . $filename . '] - now trying the base template');
$filename = $this->configuration->getPathValue('templatedir') .
$this->configuration->getValue('theme.base') . '/' . $this->template;
if (!file_exists($filename)) {
SimpleSAML_Logger::critical($_SERVER['PHP_SELF'].' - Template: Could not find template file [' . $this->template . '] at [' . $filename . ']');
echo 'Fatal error: Could not find template file [' . $this->template . '] at [' . $filename . ']';
exit(0);
}
}
require_once($filename); require_once($filename);
} }
/**
* Find template path.
*
* This function locates the given template based on the template name.
* It will first search for the template in the current theme directory, and
* then the default theme.
*
* The template name may be on the form <module name>:<template path>, in which case
* it will search for the template file in the given module.
*
* An error will be thrown if the template file couldn't be found.
*
* @param string $template The relative path from the theme directory to the template file.
* @return string The absolute path to the template file.
*/
private function findTemplatePath($template) {
assert('is_string($template)');
$tmp = explode(':', $template, 2);
if (count($tmp) === 2) {
$templateModule = $tmp[0];
$templateName = $tmp[1];
} else {
$templateModule = 'default';
$templateName = $tmp[0];
}
$tmp = explode(':', $this->configuration->getValue('theme.use'), 2);
if (count($tmp) === 2) {
$themeModule = $tmp[0];
$themeName = $tmp[1];
} else {
$themeModule = NULL;
$themeName = $tmp[0];
}
/* First check the current theme. */
if ($themeModule !== NULL) {
/* .../module/<themeModule>/themes/<themeName>/<templateModule>/<templateName> */
$filename = SimpleSAML_Module::getModuleDir($themeModule) . '/themes/' . $themeName . '/' .
$templateModule . '/' . $templateName;
} elseif ($templateModule !== 'default') {
/* .../module/<templateModule>/templates/<themeName>/<templateName> */
$filename = SimpleSAML_Module::getModuleDir($templateModule) . '/templates/' .
$themeName . '/' . $templateName;
} else {
/* .../templates/<theme>/<templateName> */
$filename = $this->configuration->getPathValue('templatedir') . $themeName . '/' .
$templateName;
}
if (file_exists($filename)) {
return $filename;
}
/* Not found in current theme. */
SimpleSAML_Logger::info($_SERVER['PHP_SELF'].' - Template: Could not find template file [' .
$template . '] at [' . $filename . '] - now trying the base template');
/* Try default theme. */
$baseTheme = $this->configuration->getValue('theme.base');
if ($templateModule !== 'default') {
/* .../module/<templateModule>/templates/<baseTheme>/<templateName> */
$filename = SimpleSAML_Module::getModuleDir($templateModule) . '/templates/' .
$baseTheme . '/' . $templateName;
} else {
/* .../templates/<baseTheme>/<templateName> */
$filename = $this->configuration->getPathValue('templatedir') . $baseTheme . '/' .
$templateName;
}
if (file_exists($filename)) {
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);
throw new Exception($error);
}
} }
?> ?>
\ No newline at end of file
<?php
/**
* Handler for module requests.
*
* This web page receives requests for web-pages hosted by modules, and directs them to
* the RequestHandler in the module.
*
* @author Olav Morken, UNINETT AS.
* @package simpleSAMLphp
* @version $Id$
*/
require_once('_include.php');
SimpleSAML_Error_Assertion::installHandler();
/* Index pages - filenames to attempt when accessing directories. */
$indexFiles = array('index.php', 'index.html', 'index.htm', 'index.txt');
/* MIME types - key is file extension, value is MIME type. */
$mimeTypes = array(
'bml' => 'image/x-ms-bmp',
'css' => 'text/css',
'gif' => 'image/gif',
'htm' => 'text/html',
'html' => 'text/html',
'shtml' => 'text/html',
'jpe' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'jpg' => 'image/jpeg',
'js' => 'text/javascript',
'pdf' => 'application/pdf',
'png' => 'image/png',
'svg' => 'image/svg+xml',
'svgz' => 'image/svg+xml',
'swf' => 'application/x-shockwave-flash',
'swfl' => 'application/x-shockwave-flash',
'txt' => 'text/plain',
'xht' => 'application/xhtml+xml',
'xhtml' => 'application/xhtml+xml',
);
try {
if (empty($_SERVER['PATH_INFO'])) {
throw new SimpleSAML_Error_NotFound('No PATH_INFO to module.php');
}
$url = $_SERVER['PATH_INFO'];
assert('substr($url, 0, 1) === "/"');
$modEnd = strpos($url, '/', 1);
if ($modEnd === FALSE) {
/* The path must always be on the form /module/. */
throw new SimpleSAML_Error_NotFound('The URL must at least contain a module name followed by a slash.');
}
$module = substr($url, 1, $modEnd - 1);
$url = substr($url, $modEnd + 1);
if ($url === FALSE) {
$url = '';
}
if (!SimpleSAML_Module::isModuleEnabled($module)) {
throw new SimpleSAML_Error_NotFound('The module \'' . $module .
'\' was either not found, or wasn\'t enabled.');
}
/* Make sure that the request isn't suspicious (contains references to current
* directory or parent directory or anything like that. Searching for './' in the
* URL will detect both '../' and './'. Searching for '\' will detect attempts to
* use Windows-style paths.
*/
if (strpos($url, '\\')) {
throw new SimpleSAML_Error_BadRequest('Requested URL contained a backslash.');
} elseif (strpos($url, './')) {
throw new SimpleSAML_Error_BadRequest('Requested URL contained \'./\'.');
}
$path = SimpleSAML_Module::getModuleDir($module) . '/www/' . $url;
if ($path[strlen($path)-1] === '/') {
/* Path ends with a slash - directory reference. Attempt to find index file
* in directory.
*/
foreach ($indexFiles as $if) {
if (file_exists($path . $if)) {
$path .= $if;
break;
}
}
}
if (is_dir($path)) {
/* Path is a directory - maybe no index file was found in the previous step, or
* maybe the path didn't end with a slash. Either way, we don't do directory
* listings.
*/
throw new SimpleSAML_Error_NotFound('Directory listing not available.');
}
if (!file_exists($path)) {
/* File not found. */
SimpleSAML_Logger::info('Could not find file \'' . $path . '\'.');
throw new SimpleSAML_Error_NotFound('The URL wasn\'t found in the module.');
}
if (preg_match('#\.php$#', $path)) {
/* PHP file - attempt to run it. */
require($path);
exit();
}
/* Some other file type - attempt to serve it. */
/* Find MIME type for file, based on extension. */
if (preg_match('#\.([^/]+)$#', $path, $type)) {
$type = strtolower($type[1]);
if (array_key_exists($type, $mimeTypes)) {
$contentType = $mimeTypes[$type];
} else {
$contentType = mime_content_type($path);
}
} else {
$contentType = mime_content_type($path);
}
$contentLength = sprintf('%u', filesize($path)); /* Force filesize to an unsigned number. */
header('Content-Type: ' . $contentType);
header('Content-Length: ' . $contentLength);
readfile($path);
exit();
} catch(SimpleSAML_Error_Error $e) {
$e->show();
} catch(Exception $e) {
$e = new SimpleSAML_Error_Error('UNHANDLEDEXCEPTION', $e);
$e->show();
}
?>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment