Some very old PHP code originally intended to become an image management tool.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

595 lines
13 KiB

<?php
/**
*
* Error constants.
*
*/
define('SAVANT2_ERROR_ASSIGN', -1);
define('SAVANT2_ERROR_ASSIGNREF', -2);
define('SAVANT2_ERROR_COMPILER', -3);
define('SAVANT2_ERROR_NOFILTER', -4);
define('SAVANT2_ERROR_NOPLUGIN', -5);
define('SAVANT2_ERROR_NOSCRIPT', -6);
define('SAVANT2_ERROR_NOTEMPLATE', -7);
define('SAVANT2_ERROR_COMPILE_FAIL', -8);
/**
*
* Error messages.
*
*/
if (! isset($GLOBALS['_SAVANT2']['error'])) {
$GLOBALS['_SAVANT2']['error'] = array(
SAVANT2_ERROR_ASSIGN => 'assign() parameters not correct',
SAVANT2_ERROR_ASSIGNREF => 'assignRef() parameters not correct',
SAVANT2_ERROR_COMPILER => 'compiler not an object or has no compile() method',
SAVANT2_ERROR_NOFILTER => 'filter file not found',
SAVANT2_ERROR_NOPLUGIN => 'plugin file not found',
SAVANT2_ERROR_NOSCRIPT => 'compiled template script file not found',
SAVANT2_ERROR_NOTEMPLATE => 'template source file not found',
SAVANT2_ERROR_COMPILE_FAIL => 'template source failed to compile'
);
}
class Savant2_Error {
var $code = null;
var $info = array();
var $text = null;
var $backtrace = null;
function Savant2_Error($conf = array())
{
// set public properties
foreach ($conf as $key => $val) {
$this->$key = $val;
}
// generate a backtrace
if (function_exists('debug_backtrace')) {
$this->backtrace = debug_backtrace();
}
// extended behaviors
$this->_genError();
}
function _genError()
{
}
}
/**
*
* This is totally based on Savent by Paul M. Jones <pmjones@ciaweb.net>.
* But is made much smaller...
*/
class SavantSmall {
var $_error = null;
var $_escape = array('htmlspecialchars');
var $_output = null;
var $_path = array(
'resource' => array(),
'template' => array()
);
var $_restrict = false;
var $_template = null;
// -----------------------------------------------------------------
//
// Constructor and general property setters
//
// -----------------------------------------------------------------
function __construct($conf = array())
{
// set the default template search dirs
if (isset($conf['template_path'])) {
// user-defined dirs
$this->setPath('template', $conf['template_path']);
} else {
// default directory only
$this->setPath('template', null);
}
// set the error class
if (isset($conf['error'])) {
$this->setError($conf['error']);
}
// set the restrict flag
if (isset($conf['restrict'])) {
$this->setRestrict($conf['restrict']);
}
// set the default template
if (isset($conf['template'])) {
$this->setTemplate($conf['template']);
}
// set the output escaping callbacks
if (isset($config['escape'])) {
call_user_func_array(
array($this, 'setEscape'),
(array) $config['escape']
);
}
}
function setError($error)
{
if (! $error) {
$this->_error = null;
} else {
$this->_error = $error;
}
}
function setRestrict($flag = false)
{
if ($flag) {
$this->_restrict = true;
} else {
$this->_restrict = false;
}
}
function setTemplate($template)
{
$this->_template = $template;
}
// -----------------------------------------------------------------
//
// Output escaping and management.
//
// -----------------------------------------------------------------
function setEscape()
{
$this->_escape = func_get_args();
}
function addEscape()
{
$args = func_get_args();
$this->_escape = array_merge($this->_escape, $args);
}
function getEscape()
{
return $this->_escape;
}
function escape($value)
{
// if value is not set return
if (! isset ($value))
return $value;
// were custom callbacks passed?
if (func_num_args() == 1) {
// no, only a value was passed.
// loop through the predefined callbacks.
foreach ($this->_escape as $func) {
$value = call_user_func($func, $value);
}
} else {
// yes, use the custom callbacks instead.
$callbacks = func_get_args();
// drop $value
array_shift($callbacks);
// loop through custom callbacks.
foreach ($callbacks as $func) {
$value = call_user_func($func, $value);
}
}
return $value;
}
function eprint($value)
{
$args = func_get_args();
echo call_user_func_array(
array($this, 'escape'),
$args
);
}
function _($value)
{
$args = func_get_args();
return call_user_func_array(
array($this, 'eprint'),
$args
);
}
// -----------------------------------------------------------------
//
// Path management and file finding
//
// -----------------------------------------------------------------
function setPath($type, $new)
{
// clear out the prior search dirs
$this->_path[$type] = array();
// convert from string to path
if (is_string($new) && ! strpos('://', $new)) {
// the search config is a string, and it's not a stream
// identifier (the "://" piece), add it as a path
// string.
$new = explode(PATH_SEPARATOR, $new);
} else {
// force to array
settype($new, 'array');
}
// always add the fallback directories as last resort
switch (strtolower($type)) {
case 'template':
$this->addPath($type, '.');
break;
case 'resource':
$this->addPath($type, dirname(__FILE__) . '/Savant2/');
break;
}
// actually add the user-specified directories
foreach ($new as $dir) {
$this->addPath($type, $dir);
}
}
function addPath($type, $dir)
{
// no surrounding spaces allowed!
$dir = trim($dir);
// add trailing separators as needed
if (strpos($dir, '://') && substr($dir, -1) != '/') {
// stream
$dir .= '/';
} elseif (substr($dir, -1) != DIRECTORY_SEPARATOR) {
// directory
$dir .= DIRECTORY_SEPARATOR;
}
// add to the top of the search dirs
array_unshift($this->_path[$type], $dir);
}
function getPath($type = null)
{
if (! $type) {
return $this->_path;
} else {
return $this->_path[$type];
}
}
function findFile($type, $file)
{
// get the set of paths
$set = $this->getPath($type);
// start looping through them
foreach ($set as $path) {
// get the path to the file
$fullname = $path . $file;
// are we doing path checks?
if (! $this->_restrict) {
// no. this is faster but less secure.
if (file_exists($fullname) && is_readable($fullname)) {
return $fullname;
}
} else {
// yes. this is slower, but attempts to restrict
// access only to defined paths.
// is the path based on a stream?
if (strpos('://', $path) === false) {
// not a stream, so do a realpath() to avoid
// directory traversal attempts on the local file
// system. Suggested by Ian Eure, initially
// rejected, but then adopted when the secure
// compiler was added.
$path = realpath($path); // needed for substr() later
$fullname = realpath($fullname);
}
// the substr() check added by Ian Eure to make sure
// that the realpath() results in a directory registered
// with Savant so that non-registered directores are not
// accessible via directory traversal attempts.
if (file_exists($fullname) && is_readable($fullname) &&
substr($fullname, 0, strlen($path)) == $path) {
return $fullname;
}
}
}
// could not find the file in the set of paths
return false;
}
// -----------------------------------------------------------------
//
// Variable and reference assignment
//
// -----------------------------------------------------------------
function assign()
{
// this method is overloaded.
$arg = func_get_args();
// must have at least one argument. no error, just do nothing.
if (! isset($arg[0])) {
return;
}
// assign by object
if (is_object($arg[0])) {
// assign public properties
foreach (get_object_vars($arg[0]) as $key => $val) {
if (substr($key, 0, 1) != '_') {
$this->$key = $val;
}
}
return;
}
// assign by associative array
if (is_array($arg[0])) {
foreach ($arg[0] as $key => $val) {
if (substr($key, 0, 1) != '_') {
$this->$key = $val;
}
}
return;
}
// assign by string name and mixed value.
//
// we use array_key_exists() instead of isset() becuase isset()
// fails if the value is set to null.
if (is_string($arg[0]) &&
substr($arg[0], 0, 1) != '_' &&
array_key_exists(1, $arg)) {
$this->$arg[0] = $arg[1];
} else {
return $this->_genError(SAVANT2_ERROR_ASSIGN, $arg);
}
}
function assignRef($key, &$val)
{
if (is_string($key) && substr($key, 0, 1) != '_') {
$this->$key =& $val;
} else {
return $this->_genError(
SAVANT2_ERROR_ASSIGNREF,
array('key' => $key, 'val' => $val)
);
}
}
function clear($var = null)
{
if (is_null($var)) {
// clear all variables
$var = array_keys(get_object_vars($this));
} else {
// clear specific variables
settype($var, 'array');
}
// clear out the selected variables
foreach ($var as $name) {
if (substr($name, 0, 1) != '_' && isset($this->$name)) {
unset($this->$name);
}
}
}
function getVars($key = null)
{
if (is_null($key)) {
$key = array_keys(get_object_vars($this));
}
if (is_array($key)) {
// return a series of vars
$tmp = array();
foreach ($key as $var) {
if (substr($var, 0, 1) != '_' && isset($this->$var)) {
$tmp[$var] = $this->$var;
}
}
return $tmp;
} else {
// return a single var
if (substr($key, 0, 1) != '_' && isset($this->$key)) {
return $this->$key;
}
}
}
// -----------------------------------------------------------------
//
// Template processing
//
// -----------------------------------------------------------------
function loadTemplate($tpl = null, $setScript = false)
{
// set to default template if none specified.
if (is_null($tpl)) {
$tpl = $this->_template;
}
// find the template source.
$file = $this->findFile('template', $tpl);
if (! $file) {
return $this->_genError(
SAVANT2_ERROR_NOTEMPLATE,
array('template' => $tpl)
);
}
// no compiling requested, return the source path
$this->_script = $file;
return $file;
}
function findTemplate($tpl = null)
{
return $this->loadTemplate($tpl, false);
}
function fetch($_tpl = null)
{
// clear prior output
$this->_output = null;
// load the template script
$_result = $this->loadTemplate($_tpl, true);
// is there a template script to be processed?
if ($this->isError($_result)) {
return $_result;
}
// unset so as not to introduce into template scope
unset($_tpl);
unset($_result);
// never allow a 'this' property
if (isset($this->this)) {
unset($this->this);
}
// start capturing output into a buffer
ob_start();
// include the requested template filename in the local scope
// (this will execute the view logic).
include $this->_script;
// done with the requested template; get the buffer and
// clear it.
$this->_output = ob_get_contents();
ob_end_clean();
// done!
return $this->_output;
}
function display($tpl = null)
{
$result = $this->fetch($tpl);
if ($this->isError($result)) {
return $result;
} else {
echo $result;
}
}
// -----------------------------------------------------------------
//
// Error handling
//
// -----------------------------------------------------------------
function &_genError($code, $info = array())
{
// the error config array
$conf = array(
'code' => $code,
'text' => 'Savant2: ',
'info' => (array) $info
);
// set an error message from the globals
if (isset($GLOBALS['_SAVANT2']['error'][$code])) {
$conf['text'] .= $GLOBALS['_SAVANT2']['error'][$code];
} else {
$conf['text'] .= '???';
}
// set up the error class name
if ($this->_error) {
$class = 'Savant2_Error_' . $this->_error;
} else {
$class = 'Savant2_Error';
}
// set up the error class file name
$file = $class . '.php';
// is it loaded?
if (! class_exists($class)) {
// find the error class
$result = $this->findFile('resource', $file);
if (! $result) {
// could not find the custom error class, revert to
// Savant_Error base class.
$class = 'Savant2_Error';
$result = dirname(__FILE__) . '/Savant2/Error.php';
}
// include the error class
include_once $result;
}
// instantiate and return the error class
$err = new $class($conf);
return $err;
}
function isError(&$obj)
{
if (is_object($obj)) {
if ($obj instanceof Savant2_Error ||
is_subclass_of($obj, 'Savant2_Error')) {
return true;
}
}
return false;
}
}
?>