<?php
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50300) {
error(500, 'dispatch requires at least PHP 5.3 to run.');
}
function _log($message)
{
if (config('debug.enable') == true && php_sapi_name() !== 'cli') {
$file = config('debug.log');
$type = $file ? 3 : 0;
error_log("{$message}\n", $type, $file);
}
}
function site_url()
{
if (config('multi.site') == "true" || config('site.url') == null){
return rtrim(generateSiteUrl(), '/') . '/';
} else {
// Forcing the forward slash
return rtrim(config('site.url'), '/') . '/';
}
}
function generateSiteUrl()
{
$dir = trim(dirname(substr($_SERVER["SCRIPT_FILENAME"], strlen($_SERVER["DOCUMENT_ROOT"]))), '/');
if ($dir == '.' || $dir == '..') {
$dir = '';
}
$port = '';
if ($_SERVER["SERVER_PORT"] != "80" && $_SERVER["SERVER_PORT"] != "443") {
$port = ':' . $_SERVER["SERVER_PORT"];
}
$scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http';
if ($dir === '') {
return $siteUrl = $scheme . '://' . trim($_SERVER['SERVER_NAME'], "/") . $port . "/";
}
return $siteUrl = $scheme . '://' . trim($_SERVER['SERVER_NAME'], "/") . $port . "/" . $dir . '/';
}
function site_path()
{
static $_path;
if (!$_path)
$_path = rtrim(parse_url(site_url(), PHP_URL_PATH), '/');
return $_path;
}
function theme_path()
{
if (config('views.root') == null)
error(500, '[views.root] is not set');
return site_url() . rtrim(config('views.root'), '/') . '/';
}
function error($code, $message)
{
@header("HTTP/1.0 {$code} {$message}", true, $code);
die($message);
}
// Set the language
function get_language()
{
$langID = config('language');
$langFile = 'lang/'. $langID . '.ini';
// Settings for the language
if (file_exists($langFile)) {
i18n('source', $langFile);
setlocale(LC_ALL, $langID . '.utf8');
} else {
i18n('source', 'lang/en_US.ini'); // Load the English language file
setlocale(LC_ALL, 'en_US.utf8'); // Change locale to English
}
}
// i18n provides strings in the current language
function i18n($key, $value = null)
{
static $_i18n = array();
$key = strtolower($key);
if ($key === 'source') {
if (file_exists($value))
$_i18n = parse_ini_file($value, true);
else
$_i18n = parse_ini_file('lang/en_US.ini', true);
} elseif ($value == null)
return (isset($_i18n[$key]) ? $_i18n[$key] : $key);
else
$_i18n[$key] = $value;
}
function config($key, $value = null)
{
static $_config = array();
if ($key === 'source' && file_exists($value))
$_config = parse_ini_file($value, true);
elseif ($value == null)
return (isset($_config[$key]) ? $_config[$key] : null);
else
$_config[$key] = $value;
}
function save_config($data = array(), $new = array())
{
global $config_file;
$string = file_get_contents($config_file) . "\n";
foreach ($data as $word => $value) {
$value = str_replace('"', '\"', $value);
$string = preg_replace("/^" . $word . " = .+$/m", $word . ' = "' . $value . '"', $string);
}
$string = rtrim($string);
foreach ($new as $word => $value) {
$value = str_replace('"', '\"', $value);
$string .= "\n" . $word . ' = "' . $value . '"' . "\n";
}
$string = rtrim($string);
return file_put_contents($config_file, $string, LOCK_EX);
}
function to_b64($str)
{
$str = base64_encode($str);
$str = preg_replace('/\//', '_', $str);
$str = preg_replace('/\+/', '.', $str);
$str = preg_replace('/\=/', '-', $str);
return trim($str, '-');
}
function from_b64($str)
{
$str = preg_replace('/\_/', '/', $str);
$str = preg_replace('/\./', '+', $str);
$str = preg_replace('/\-/', '=', $str);
$str = base64_decode($str);
return $str;
}
if (extension_loaded('mcrypt')) {
function encrypt($decoded, $algo = MCRYPT_RIJNDAEL_256, $mode = MCRYPT_MODE_CBC)
{
if (($secret = config('cookies.secret')) == null)
error(500, '[cookies.secret] is not set');
$secret = mb_substr($secret, 0, mcrypt_get_key_size($algo, $mode));
$iv_size = mcrypt_get_iv_size($algo, $mode);
$iv_code = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM);
$encrypted = to_b64(mcrypt_encrypt($algo, $secret, $decoded, $mode, $iv_code));
return sprintf('%s|%s', $encrypted, to_b64($iv_code));
}
function decrypt($encoded, $algo = MCRYPT_RIJNDAEL_256, $mode = MCRYPT_MODE_CBC)
{
if (($secret = config('cookies.secret')) == null)
error(500, '[cookies.secret] is not set');
$secret = mb_substr($secret, 0, mcrypt_get_key_size($algo, $mode));
list($enc_str, $iv_code) = explode('|', $encoded);
$enc_str = from_b64($enc_str);
$iv_code = from_b64($iv_code);
$enc_str = mcrypt_decrypt($algo, $secret, $enc_str, $mode, $iv_code);
return rtrim($enc_str, "\0");
}
}
function set_cookie($name, $value, $expire = 31536000, $path = '/')
{
$value = (function_exists('encrypt') ? encrypt($value) : $value);
setcookie($name, $value, time() + $expire, $path);
}
function get_cookie($name)
{
$value = from($_COOKIE, $name);
if ($value)
$value = (function_exists('decrypt') ? decrypt($value) : $value);
return $value;
}
function delete_cookie()
{
$cookies = func_get_args();
foreach ($cookies as $ck)
setcookie($ck, '', -10, '/');
}
// if we have APCu loaded, enable cache functions
if (extension_loaded('apcu')) {
function cache($key, $func, $ttl = 0)
{
if (($data = apcu_fetch($key)) === false) {
$data = call_user_func($func);
if ($data !== null) {
apcu_store($key, $data, $ttl);
}
}
return $data;
}
function cache_invalidate()
{
foreach (func_get_args() as $key) {
apcu_delete($key);
}
}
}
function warn($name = null, $message = null)
{
static $warnings = array();
if ($name == '*')
return $warnings;
if (!$name)
return count(array_keys($warnings));
if (!$message)
return isset($warnings[$name]) ? $warnings[$name] : null;
$warnings[$name] = $message;
}
function _u($str)
{
return urlencode($str);
}
function _h($str, $enc = 'UTF-8', $flags = ENT_QUOTES)
{
return htmlentities($str, $flags, $enc);
}
function from($source, $name)
{
$map = array("\r\n" => "\n", "\r" => "\n");
if (is_array($name)) {
$data = array();
foreach ($name as $k)
$data[$k] = isset($source[$k]) ? trim(strtr($source[$k], $map)) : null;
return $data;
}
return isset($source[$name]) ? trim(strtr($source[$name], $map)) : null;
}
function stash($name, $value = null)
{
static $_stash = array();
if ($value === null)
return isset($_stash[$name]) ? $_stash[$name] : null;
$_stash[$name] = $value;
return $value;
}
function method($verb = null)
{
if ($verb == null || (strtoupper($verb) == strtoupper($_SERVER['REQUEST_METHOD'])))
return strtoupper($_SERVER['REQUEST_METHOD']);
error(400, 'bad request');
}
function client_ip()
{
if (isset($_SERVER['HTTP_CLIENT_IP']))
return $_SERVER['HTTP_CLIENT_IP'];
elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
return $_SERVER['HTTP_X_FORWARDED_FOR'];
return $_SERVER['REMOTE_ADDR'];
}
function redirect(/* $code_or_path, $path_or_cond, $cond */)
{
$argv = func_get_args();
$argc = count($argv);
$path = null;
$code = 302;
$cond = true;
switch ($argc) {
case 3:
list($code, $path, $cond) = $argv;
break;
case 2:
if (is_string($argv[0]) ? $argv[0] : $argv[1]) {
$code = 302;
$path = $argv[0];
$cond = $argv[1];
} else {
$code = $argv[0];
$path = $argv[1];
}
break;
case 1:
if (!is_string($argv[0]))
error(500, 'bad call to redirect()');
$path = $argv[0];
break;
default:
error(500, 'bad call to redirect()');
}
$cond = (is_callable($cond) ? !!call_user_func($cond) : !!$cond);
if (!$cond)
return;
header('Location: ' . $path, true, $code);
exit;
}
function partial($view, $locals = null)
{
if (is_array($locals) && count($locals)) {
extract($locals, EXTR_SKIP);
}
if (($view_root = config('views.root')) == null)
error(500, "[views.root] is not set");
$path = basename($view);
$view = preg_replace('/' . $path . '$/', "_{$path}", $view);
$view = "{$view_root}/{$view}.html.php";
if (file_exists($view)) {
ob_start();
require $view;
return ob_get_clean();
} else {
error(500, "partial [{$view}] not found");
}
return '';
}
function content($value = null)
{
return stash('$content$', $value);
}
function render($view, $locals = null, $layout = null)
{
if (!login()) {
$c = str_replace('/', '#', str_replace('?', '~', rawurldecode($_SERVER['REQUEST_URI'])));
$dir = 'cache/page';
$cachefile = $dir . '/' . $c . '.cache';
if (!is_dir($dir)) {
mkdir($dir, 0775, true);
}
}
if (is_array($locals) && count($locals)) {
extract($locals, EXTR_SKIP);
}
if (($view_root = config('views.root')) == null)
error(500, "[views.root] is not set");
$fnc = "{$view_root}/functions.php";
ob_start();
if (file_exists($fnc)) {
include $fnc;
}
include "{$view_root}/{$view}.html.php";
content(trim(ob_get_clean()));
if ($layout !== false) {
if ($layout == null) {
$layout = config('views.layout');
$layout = ($layout == null) ? 'layout' : $layout;
}
$layout = "{$view_root}/{$layout}.html.php";
header('Content-type: text/html; charset=utf-8');
if (config('generation.time') == 'true') {
ob_start();
require $layout;
$time = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];
$total_time = round($time, 4);
echo "\n" . '<!-- Dynamic page generated in '.$total_time.' seconds. -->';
} else {
ob_start();
require $layout;
}
if (!login() && $view != '404' && $view != '404-search' && config('cache.off') == "false") {
if (config('cache.timestamp') == 'true') {
echo "\n" . '<!-- Cached page generated on '.date('Y-m-d H:i:s').' -->';
}
if (isset($cachefile))
file_put_contents($cachefile, ob_get_contents(), LOCK_EX);
}
echo trim(ob_get_clean());
} else {
echo content();
}
}
function json($obj, $code = 200)
{
header('Content-type: application/json', true, $code);
echo json_encode($obj);
exit;
}
function save_json_pretty($filename, $arr)
{
if (defined("JSON_PRETTY_PRINT")) {
file_put_contents($filename, json_encode($arr, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), LOCK_EX);
} else {
file_put_contents($filename, json_encode($arr, JSON_UNESCAPED_UNICODE), LOCK_EX);
}
}
function file_get_data($filename)
{
$thisFile = fopen($filename, 'r');
if (flock($thisFile, LOCK_SH)) {
$fileData = file_get_contents($filename);
flock($thisFile, LOCK_UN);
} else {
$fileData = json_encode(array('flock_fail' => 'reading'));
}
fclose($thisFile);
return $fileData;
}
function condition()
{
static $cb_map = array();
$argv = func_get_args();
$argc = count($argv);
if (!$argc)
error(500, 'bad call to condition()');
$name = array_shift($argv);
$argc = $argc - 1;
if (!$argc && is_callable($cb_map[$name]))
return call_user_func($cb_map[$name]);
if (is_callable($argv[0]))
return ($cb_map[$name] = $argv[0]);
if (is_callable($cb_map[$name]))
return call_user_func_array($cb_map[$name], $argv);
error(500, 'condition [' . $name . '] is undefined');
}
function middleware($cb_or_path = null)
{
static $cb_map = array();
if ($cb_or_path == null || is_string($cb_or_path)) {
foreach ($cb_map as $cb) {
call_user_func($cb, $cb_or_path);
}
} else {
array_push($cb_map, $cb_or_path);
}
}
function filter($sym, $cb_or_val = null)
{
static $cb_map = array();
if (is_callable($cb_or_val)) {
$cb_map[$sym] = $cb_or_val;
return;
}
if (is_array($sym) && count($sym) > 0) {
foreach ($sym as $s) {
$s = substr($s, 1);
if (isset($cb_map[$s]) && isset($cb_or_val[$s]))
call_user_func($cb_map[$s], $cb_or_val[$s]);
}
return;
}
error(500, 'bad call to filter()');
}
function route_to_regex($route)
{
$route = preg_replace_callback('@:[\w]+@i', function ($matches) {
$token = str_replace(':', '', $matches[0]);
return '(?P<' . $token . '>[a-z0-9_\0-\.]+)';
}, $route);
return '@^' . rtrim($route, '/') . '$@i';
}
function route($method, $pattern, $callback = null)
{
// callback map by request type
static $route_map = array(
'GET' => array(),
'POST' => array()
);
$method = strtoupper($method);
if (!in_array($method, array('GET', 'POST')))
error(500, 'Only GET and POST are supported');
// a callback was passed, so we create a route defiition
if ($callback !== null) {
// create a route entry for this pattern
$route_map[$method][$pattern] = array(
'xp' => route_to_regex($pattern),
'cb' => $callback
);
} else {
// callback is null, so this is a route invokation. look up the callback.
foreach ($route_map[$method] as $pat => $obj) {
// if the requested uri ($pat) has a matching route, let's invoke the cb
if (!preg_match($obj['xp'], $pattern, $vals))
continue;
// call middleware
middleware($pattern);
// construct the params for the callback
array_shift($vals);
preg_match_all('@:([\w]+)@', $pat, $keys, PREG_PATTERN_ORDER);
$keys = array_shift($keys);
$argv = array();
foreach ($keys as $index => $id) {
$id = substr($id, 1);
if (isset($vals[$id])) {
array_push($argv, trim(urldecode($vals[$id])));
}
}
// call filters if we have symbols
if (count($keys)) {
filter(array_values($keys), $vals);
}
// if cb found, invoke it
if (is_callable($obj['cb'])) {
call_user_func_array($obj['cb'], $argv);
}
// leave after first match
break;
}
}
}
function get($path, $cb)
{
route('GET', $path, $cb);
}
function post($path, $cb)
{
route('POST', $path, $cb);
}
function flash($key, $msg = null, $now = false)
{
static $x = array(),
$f = null;
$f = (config('cookies.flash') ? config('cookies.flash') : '_F');
if ($c = get_cookie($f))
$c = json_decode($c, true);
else
$c = array();
if ($msg == null) {
if (isset($c[$key])) {
$x[$key] = $c[$key];
unset($c[$key]);
set_cookie($f, json_encode($c));
}
return (isset($x[$key]) ? $x[$key] : null);
}
if (!$now) {
$c[$key] = $msg;
set_cookie($f, json_encode($c));
}
$x[$key] = $msg;
}
function dispatch()
{
$path = $_SERVER['REQUEST_URI'];
if (config('site.url') !== null)
$path = preg_replace('@^' . preg_quote(site_path()) . '@', '', $path);
$parts = preg_split('/\?/', $path, -1, PREG_SPLIT_NO_EMPTY);
$uri = trim($parts[0], '/');
$uri = strlen($uri) ? $uri : 'index';
route(method(), "/{$uri}");
}