Adding modifications from kritbit

This commit is contained in:
Nathan Adams 2016-04-14 22:01:11 -05:00
parent 5b104d624b
commit f08b2987e1
34 changed files with 3205 additions and 2404 deletions

View File

@ -1,5 +1,5 @@
<?php <?php
$config["ADMINS"] = array(); $config["ADMINS"] = array();
return $config; return $config;

View File

@ -1,11 +1,11 @@
<?php <?php
foreach (glob("system/vendor/*.php") as $filename) foreach (glob("system/vendor/*.php") as $filename)
{ {
include $filename; include $filename;
} }
require('system/engine/core.php'); require('system/engine/core.php');
$core = new HF_Core(); $core = new HF_Core();
$core->run(); $core->run();

18
migrations.php Normal file
View File

@ -0,0 +1,18 @@
<?php
spl_autoload_extensions(".php"); // comma-separated list
spl_autoload_register();
foreach (glob("system/vendor/*.php") as $filename)
{
include $filename;
}
if (!is_cli()) {
die("This script must be ran from the command line");
}
$core = new \system\engine\HF_Core(true);
$core->runMigrations();

View File

@ -1,15 +1,15 @@
<?php <?php
$config["DEFAULT_ROUTE"] = "main"; $config["DEFAULT_ROUTE"] = "main";
$config["USE_H20_TPL"] = true; $config["USE_H20_TPL"] = true;
$config["SMTP_SERVER"] = "localhost"; $config["SMTP_SERVER"] = "localhost";
$config["SMTP_USER"] = ""; $config["SMTP_USER"] = "";
$config["SMTP_PASS"] = ""; $config["SMTP_PASS"] = "";
$config["SMTP_PORT"] = 25; $config["SMTP_PORT"] = 25;
$config["SMTP_FROM"] = "HF-noreply@yoursite.com"; $config["SMTP_FROM"] = "HF-noreply@yoursite.com";
$config["DEBUG"] = true; $config["DEBUG"] = true;
$config["USE_HF_SMTP"] = true; $config["USE_HF_SMTP"] = true;
$config["SITE_NAME"] = "default"; $config["SITE_NAME"] = "default";
$config["SITE_URL"] = ""; $config["SITE_URL"] = "";
return $config; return $config;

View File

@ -1,42 +0,0 @@
<?php
class HF_Controller
{
protected $config;
protected $tpl;
/** @var HF_Core */
protected $core;
public function __construct($config, $core, $tpl = null)
{
$this->config = $config;
$this->tpl = $tpl;
$this->core = $core;
$this->initdb();
}
protected function initdb()
{
if (isvarset($this->config["MYSQL_DBNAME"]) && isvarset($this->config["MYSQL_USER"]))
{
$pdo = new PDO(
"mysql:dbname={$this->config['MYSQL_DBNAME']};host={$this->config['MYSQL_HOST']}",
$this->config['MYSQL_USER'],
$this->config['MYSQL_PASS'],
array(
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8",
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
)
);
DB::$c = $pdo;
}
}
public function loadRender($template, $parameters=array())
{
$this->tpl->loadTemplate($template);
return $this->tpl->render($parameters);
}
}

View File

@ -1,277 +0,0 @@
<?php
include "system/engine/controller.php";
include "system/engine/SMTP.php";
include "system/engine/exceptions.php";
class HF_Core
{
private $class;
private $method;
private $classname;
private $args = array();
private $config = array();
private $tpl;
private $starttime;
public function __construct()
{
$this->starttime = microtime(true);
$config = include("system/engine/config-default.php");
if (is_file("application/config.php"))
{
$newconfig = include("application/config.php");
}
$this->config = array_merge($config, $newconfig);
if ($this->config["USE_H20_TPL"])
$this->tpl = new H2o(null, array(
"searchpath" => getcwd() . "/application/views/",
"cache_dir" => "application/tmp/",
'cache' => 'file'
));
set_error_handler("HF_Core::error_handler");
$this->findController();
}
public function getRuntime()
{
return $this->starttime - microtime(true);
}
public function siteURL()
{
if (isvarset($this->config["SITE_URL"]))
{
return $this->config["SITE_URL"];
}
$path = explode("/", $_SERVER["REQUEST_URI"]);
$path = array_filter($path, 'strlen');
if (count($path) == 0)
{
return $_SERVER["HTTP_HOST"] . "/";
} else {
if (in_array($this->classname, $path))
{
$newpath = implode("/", array_splice($path, 0, -2));
return $_SERVER["HTTP_HOST"] . "/" . $newpath . "/";
} else {
$newpath = implode("/", $path);
return $_SERVER["HTTP_HOST"] . "/" . $newpath . "/";
}
}
}
private function findController()
{
try
{
if (isvarset($_SERVER["PATH_INFO"]))
{
$request = $_SERVER["PATH_INFO"];
//$request = $_SERVER["PHP_SELF"];
$splitreq = explode("/", $request);
/*$request = "";
for($i = 0; $i < count($splitreq); $i++)
{
if ($splitreq[$i] == "index.php")
{
$request = implode("/", array_splice($splitreq, $i+1));
}
}*/
//print $request;
//$request = substr($request, 1);
//$request = substr($request, 0, -1);
} else {
$request = "";
}
if ($request == "" || $request == "/")
{
require("application/controllers/" . $this->config["DEFAULT_ROUTE"] . ".php");
$this->loadController(new $this->config["DEFAULT_ROUTE"]($this->config, $this, $this->tpl), $this->config["DEFAULT_ROUTE"], "index");
return;
}
if ($request[strlen($request)-1] == "/")
$request = substr($request, 0, -1);
$arr = explode("/", $request);
$path = "application/controllers/";
for($i = 0; $i < count($arr); $i++)
{
if (is_file($path . $arr[$i] . ".php")) // found the controller
{
include($path . $arr[$i] . ".php");
if ($i + 1 < count($arr)) // if there is a define after the controller name - this would be the method name
{
$this->loadController(new $arr[$i]($this->config, $this, $this->tpl), $arr[$i], $arr[$i+1], array_slice ($arr, 2));
} else { // call index
$this->loadController(new $arr[$i]($this->config, $this, $this->tpl), $arr[$i], "index");
}
return;
}
if (is_dir($path . $arr[$i])) // controller is hidden deeper
{
$path = $path . $arr[$i] . "/";
continue;
}
include($path . $this->config["DEFAULT_ROUTE"] . ".php");
$this->loadController(new $this->config["DEFAULT_ROUTE"]($this->config, $this, $this->tpl), $this->config["DEFAULT_ROUTE"], "index");
//$this->load404Controller();
break;
// throw exception controller not found
}
} catch (Exception $e) {
if ($this->config["DEBUG"])
echo vdump($e, $this);
else
$this->mail_admins("[Exception - " . $this->config["SITE_NAME"] . "]", vdump($e, $this), true);
}
}
private function load404Controller()
{
if (is_file(getcwd() . "/application/status.php"))
{
include_once (getcwd() . "/application/status.php");
$this->loadController(new status($this->config, $this, $this->tpl), "status", "Status404");
} else {
include_once(getcwd() . "/system/engine/status.php");
$this->loadController(new HF_Status($this->config, $this, $this->tpl), "HF_Status", "Status404");
}
}
private function load500Controller()
{
if (is_file(getcwd() . "/application/status.php"))
{
include_once (getcwd() . "/application/status.php");
$this->loadController(new status($this->config, $this, $this->tpl), "status", "Status500");
} else {
include_once (getcwd() . "/system/engine/status.php");
$this->loadController(new HF_Status($this->config, $this, $this->tpl), "HF_Status", "Status500");
}
}
private function loadController($class, $classname, $method, $args = array())
{
$this->class = $class;
$this->classname = $classname;
$this->method = $method;
$this->args = $args;
}
public function run($err=false)
{
try
{
$call = new ReflectionMethod($this->classname, $this->method);
if ($err)
{
$call->invokeArgs($this->class, $this->args);
return;
}
$numOfReqPara = $call->getNumberOfRequiredParameters();
$numOfOptPara = $call->getNumberOfParameters() - $numOfReqPara;
$remainparas = count($this->args) - $numOfReqPara;
if ($numOfReqPara == 0 || ($remainparas >= 0 && $remainparas <= $numOfOptPara))
{
$call->invokeArgs($this->class, $this->args);
}
else
{
$this->load404Controller();
$this->run(true);
}
} catch (ReflectionException $e)
{
if (strstr($e->getMessage(), "does not exist") !== false)
{
$this->load404Controller();
} else {
$this->load500Controller();
}
$this->run(true);
if ($this->config["DEBUG"])
echo vdump($e, $this);
else
$this->mail_admins("[Exception - " . $this->config["SITE_NAME"] . "]", vdump($e, $this), true);
} catch (Exception $e) {
$this->load500Controller();
$this->run(true);
if ($this->config["DEBUG"])
echo vdump($e, $this);
else
$this->mail_admins("[Exception - " . $this->config["SITE_NAME"] . "]", vdump($e, $this), true);
}
}
public function mail_admins($subject, $msg, $html = false)
{
if (array_key_exists("ADMINS", $this->config))
{
foreach($this->config["ADMINS"] as $email)
{
$this->mail_user($email, $subject, $msg, $html);
}
}
}
public function mail_user($to, $subject, $msg, $html = false)
{
if ($this->config["USE_HF_SMTP"])
{
$smtp = new HF_SMTP($this->config["SMTP_FROM"], $to, $subject, $msg, $this->config["SMTP_SERVER"], $this->config["SMTP_USER"], $this->config["SMTP_PASS"], $this->config["SMTP_PORT"]);
$smtp->send($html);
} else {
require_once "Mail.php";
$smtp = null;
if ($this->$this->config["SMTP_USER"] && $this->config["SMTP_PASS"])
$smtp = Mail::factory('smtp', array(
"host" => $this->config["SMTP_SERVER"],
"port" => $this->config["SMTP_PORT"],
"auth" => true,
'username' => $this->config["SMTP_USER"],
'password' => $this->config["SMTP_PASS"]
));
else
$smtp = Mail::factory('smtp', array(
"host" => $this->config["SMTP_SERVER"],
"port" => $this->config["SMTP_PORT"]
));
$headers = array ('From' => $this->config["SMTP_FROM"],
'To' => $to,
'Subject' => $subject);
$smtp->send($to, $headers, $msg);
}
}
public static function error_handler($err_severity, $err_msg, $err_file, $err_line, array $err_context)
{
if (0 === error_reporting()) { return false;}
switch($err_severity)
{
case E_ERROR: throw new ErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_WARNING: throw new WarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_PARSE: throw new ParseException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_NOTICE: throw new NoticeException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_CORE_ERROR: throw new CoreErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_CORE_WARNING: throw new CoreWarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_COMPILE_ERROR: throw new CompileErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_COMPILE_WARNING: throw new CoreWarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_ERROR: throw new UserErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_WARNING: throw new UserWarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_NOTICE: throw new UserNoticeException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_STRICT: throw new StrictException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_RECOVERABLE_ERROR: throw new RecoverableErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_DEPRECATED: throw new DeprecatedException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_DEPRECATED: throw new UserDeprecatedException ($err_msg, 0, $err_severity, $err_file, $err_line);
}
}
}

View File

@ -1,18 +1,20 @@
<?php <?php
//Original idea by http://www.php.net/manual/en/function.set-error-handler.php#112881 namespace system\engine;
class WarningException extends ErrorException {} //Original idea by http://www.php.net/manual/en/function.set-error-handler.php#112881
class ParseException extends ErrorException {}
class NoticeException extends ErrorException {} class WarningException extends \ErrorException {}
class CoreErrorException extends ErrorException {} class ParseException extends \ErrorException {}
class CoreWarningException extends ErrorException {} class NoticeException extends \ErrorException {}
class CompileErrorException extends ErrorException {} class CoreErrorException extends \ErrorException {}
class CompileWarningException extends ErrorException {} class CoreWarningException extends \ErrorException {}
class UserErrorException extends ErrorException {} class CompileErrorException extends \ErrorException {}
class UserWarningException extends ErrorException {} class CompileWarningException extends \ErrorException {}
class UserNoticeException extends ErrorException {} class UserErrorException extends \ErrorException {}
class StrictException extends ErrorException {} class UserWarningException extends \ErrorException {}
class RecoverableErrorException extends ErrorException {} class UserNoticeException extends \ErrorException {}
class DeprecatedException extends ErrorException {} class StrictException extends \ErrorException {}
class UserDeprecatedException extends ErrorException {} class RecoverableErrorException extends \ErrorException {}
class DeprecatedException extends \ErrorException {}
class UserDeprecatedException extends \ErrorException {}

View File

@ -0,0 +1,24 @@
<?php
namespace system\engine;
class HF_Controller
{
protected $config;
protected $tpl;
protected $core;
public function __construct($config, $core, $tpl = null)
{
$this->config = $config;
$this->tpl = $tpl;
$this->core = $core;
}
protected function loadRender($template, $parameters=array())
{
$this->tpl->loadTemplate($template);
return $this->tpl->render($parameters);
}
}

365
system/engine/hf_core.php Normal file
View File

@ -0,0 +1,365 @@
<?php
/*include "system/engine/hf_controller.php";
include "system/engine/smtp.php";
include "system/engine/exceptions.php";
include "system/engine/hf_model.php";*/
namespace system\engine;
use vendor\DB\DB;
include "exceptions.php";
class HF_Core
{
private $class;
private $method;
private $classname;
private $args = array();
private $config = array();
private $tpl;
public function __construct($migrations=false)
{
$config = include("system/engine/config-default.php");
if (is_file("application/config.php"))
{
$newconfig = include("application/config.php");
}
$this->config = array_merge($config, $newconfig);
\vendor\DB\DB::$type = $config["DATABASE_TYPE"];
if ($this->config["USE_H20_TPL"])
$this->tpl = new \H2o(null, array(
"searchpath" => getcwd() . "/application/views/",
"cache_dir" => "application/tmp/",
'cache' => 'file'
));
set_error_handler("\\system\\engine\\HF_Core::error_handler");
//set_exception_handler("\\system\\engine\\HF_Core::exception_handler");
if (!$migrations)
$this->findController();
}
public static function exception_handler($e) {
echo "Hello";
}
public function siteURL()
{
if (isvarset($this->config["SITE_URL"]))
{
return $this->config["SITE_URL"];
}
$path = explode("/", $_SERVER["REQUEST_URI"]);
$path = array_filter($path, 'strlen');
if (count($path) == 0)
{
return $_SERVER["HTTP_HOST"] . "/";
} else {
if (in_array($this->classname, $path))
{
$newpath = implode("/", array_splice($path, 0, -2));
return $_SERVER["HTTP_HOST"] . "/" . $newpath . "/";
} else {
$newpath = implode("/", $path);
return $_SERVER["HTTP_HOST"] . "/" . $newpath . "/";
}
}
}
private function findController()
{
try
{
if (isvarset($_SERVER["PATH_INFO"]))
{
$request = $_SERVER["PATH_INFO"];
//$request = $_SERVER["PHP_SELF"];
$splitreq = explode("/", $request);
/*$request = "";
for($i = 0; $i < count($splitreq); $i++)
{
if ($splitreq[$i] == "index.php")
{
$request = implode("/", array_splice($splitreq, $i+1));
}
}*/
//print $request;
//$request = substr($request, 1);
//$request = substr($request, 0, -1);
} else {
$request = "";
}
if ($request == "" || $request == "/")
{
require_once("application/controllers/" . $this->config["DEFAULT_ROUTE"] . ".php");
$this->loadController(new $this->config["DEFAULT_ROUTE"]($this->config, $this, $this->tpl), $this->config["DEFAULT_ROUTE"], "index");
return;
}
if ($request[strlen($request)-1] == "/")
$request = substr($request, 0, -1);
$arr = explode("/", $request);
$path = "application/controllers/";
for($i = 0; $i < count($arr); $i++)
{
if (is_file($path . $arr[$i] . ".php")) // found the controller
{
include_once($path . $arr[$i] . ".php");
if ($i + 1 < count($arr)) // if there is a define after the controller name - this would be the method name
{
$this->loadController(new $arr[$i]($this->config, $this, $this->tpl), $arr[$i], $arr[$i+1], array_slice ($arr, 3));
} else { // call index
$this->loadController(new $arr[$i]($this->config, $this, $this->tpl), $arr[$i], "index");
}
return;
}
if (is_dir($path . $arr[$i])) // controller is hidden deeper
{
$path = $path . $arr[$i] . "/";
continue;
}
include_once($path . $this->config["DEFAULT_ROUTE"] . ".php");
$this->loadController(new $this->config["DEFAULT_ROUTE"]($this->config, $this, $this->tpl), $this->config["DEFAULT_ROUTE"], "index");
//$this->load404Controller();
break;
// throw exception controller not found
}
} catch (\Exception $e) {
if ($this->config["DEBUG"])
echo vdump($e, $this);
else
$this->mail_admins("[Exception - " . $this->config["SITE_NAME"] . "]", vdump($e, $this), true);
}
}
private function load404Controller()
{
if (is_file(getcwd() . "/application/status.php"))
{
include_once (getcwd() . "/application/status.php");
$this->loadController(new HF_Status($this->config, $this, $this->tpl), "\\system\\engine\\HF_Status", "Status404");
} else {
include_once(getcwd() . "/system/engine/status.php");
$this->loadController(new HF_Status($this->config, $this, $this->tpl), "\\system\\engine\\HF_Status", "Status404");
}
}
private function load500Controller()
{
if (is_file(getcwd() . "/application/status.php"))
{
include_once (getcwd() . "/application/status.php");
$this->loadController(new HF_Status($this->config, $this, $this->tpl), "\\system\\engine\\HF_Status", "Status500");
} else {
include_once (getcwd() . "/system/engine/status.php");
$this->loadController(new HF_Status($this->config, $this, $this->tpl), "\\system\\engine\\HF_Status", "Status500");
}
}
private function loadController($class, $classname, $method, $args = array())
{
$this->class = $class;
$this->classname = $classname;
$this->method = $method;
$this->args = $args;
}
public function run($err=false)
{
try
{
$call = new \ReflectionMethod($this->classname, $this->method);
if ($err)
{
$call->invokeArgs($this->class, $this->args);
return;
}
$numOfReqPara = $call->getNumberOfRequiredParameters();
$numOfOptPara = $call->getNumberOfParameters() - $numOfReqPara;
$remainparas = count($this->args) - $numOfReqPara;
if ($numOfReqPara == 0 || ($remainparas >= 0 && $remainparas <= $numOfOptPara))
{
$call->invokeArgs($this->class, $this->args);
}
else
{
$this->load404Controller();
$this->run(true);
}
}
catch (\ReflectionException $e)
{
if (strstr($e->getMessage(), "does not exist") !== false)
{
$this->load404Controller();
} else {
$this->load500Controller();
}
$this->run(true);
if ($this->config["DEBUG"])
echo vdump($e, $this);
else
$this->mail_admins("[Exception - " . $this->config["SITE_NAME"] . "]", vdump($e, $this), true);
} catch (\Exception $e) {
$this->load500Controller();
$this->run(true);
if ($this->config["DEBUG"])
echo vdump($e, $this);
else
$this->mail_admins("[Exception - " . $this->config["SITE_NAME"] . "]", vdump($e, $this), true);
}
}
public function mail_admins($subject, $msg, $html = false)
{
if (array_key_exists("ADMINS", $this->config))
{
foreach($this->config["ADMINS"] as $email)
{
$this->mail_user($email, $subject, $msg, $html);
}
}
}
public function mail_user($to, $subject, $msg, $html = false)
{
if ($this->config["USE_HF_SMTP"])
{
$smtp = new HF_SMTP($this->config["SMTP_FROM"], $to, $subject, $msg, $this->config["SMTP_SERVER"], $this->config["SMTP_USER"], $this->config["SMTP_PASS"], $this->config["SMTP_PORT"]);
$smtp->send($html);
} else {
require_once "Mail.php";
$smtp = null;
if ($this->$this->config["SMTP_USER"] && $this->config["SMTP_PASS"])
$smtp = Mail::factory('smtp', array(
"host" => $this->config["SMTP_SERVER"],
"port" => $this->config["SMTP_PORT"],
"auth" => true,
'username' => $this->config["SMTP_USER"],
'password' => $this->config["SMTP_PASS"]
));
else
$smtp = Mail::factory('smtp', array(
"host" => $this->config["SMTP_SERVER"],
"port" => $this->config["SMTP_PORT"]
));
$headers = array ('From' => $this->config["SMTP_FROM"],
'To' => $to,
'Subject' => $subject);
$smtp->send($to, $headers, $msg);
}
}
public static function error_handler($err_severity, $err_msg, $err_file, $err_line, array $err_context)
{
if (0 === error_reporting()) { return false;}
switch($err_severity)
{
case E_ERROR: throw new \ErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_WARNING: throw new WarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_PARSE: throw new ParseException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_NOTICE: throw new NoticeException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_CORE_ERROR: throw new CoreErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_CORE_WARNING: throw new CoreWarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_COMPILE_ERROR: throw new CompileErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_COMPILE_WARNING: throw new CoreWarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_ERROR: throw new UserErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_WARNING: throw new UserWarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_NOTICE: throw new UserNoticeException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_STRICT: throw new StrictException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_RECOVERABLE_ERROR: throw new RecoverableErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_DEPRECATED: throw new DeprecatedException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_DEPRECATED: throw new UserDeprecatedException ($err_msg, 0, $err_severity, $err_file, $err_line);
}
}
public function setupDatabaseConnection() {
switch($this->config["DATABASE_TYPE"]) {
case "SQLITE":
DB::$c = new \PDO("sqlite:" . $this->config["DATABASE_FILE"]);
break;
case "MySQL":
DB::$c = new \PDO(
"mysql:dbname={$this->config['MYSQL_DBNAME']};host={$this->config['MYSQL_HOST']}",
$this->config['MYSQL_USER'],
$this->config['MYSQL_PASS'],
array(
\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8",
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_OBJ,
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
)
);
break;
}
DB::$c->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
}
public function runMigrations() {
global $argv;
$this->setupDatabaseConnection();
DB::query("CREATE TABLE IF NOT EXISTS migrations (
id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
migration INTEGER,
ran_at DATETIME
)");
switch ($argv[1]) {
case "show":
foreach(DB::fetch("SELECT migration, ran_at FROM migrations") as $migration) {
echo $migration["migration"] . " => " . $migration["ran_at"] . PHP_EOL;
}
break;
case "count":
echo DB::column("SELECT COUNT(id) FROM migrations");
break;
case "run":
$migrations = DB::fetch("SELECT migration FROM migrations");
$migrationArray = [];
foreach($migrations as $migration) {
$migrationArray[] = $migration["migration"];
}
foreach (glob("application/migrations/*.php") as $filename)
{
if (!in_array($filename, $migrationArray)) {
try {
include $filename;
DB::insert("migrations", ["migration" => $filename, "ran_at" => (new \DateTime())->format("Y-m-d")]);
} catch (\Exception $e) {
echo "[HF_Core] - Migration error - $e";
exit(1);
}
}
}
break;
case "clear":
DB::query("DELETE FROM migrations");
break;
case "reset":
switch($this->config["DATABASE_TYPE"]) {
case "SQLITE":
DB::$c = null;
unlink($this->config["DATABASE_FILE"]);
break;
case "MYSQL":
DB::query("DROP DATABASE " . $this->config['MYSQL_DBNAME']);
DB::query("CREATE DATABASE " . $this->config['MYSQL_DBNAME']);
break;
}
break;
}
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace system\engine;
use \vendor\DB\DB;
abstract class HF_Model {
public $id = null;
public static function create($data) {
$obj = new static();
$function = new \ReflectionClass(get_called_class());
$table = strtolower($function->getShortName());
foreach(DB::getColumns($table) as $column) {
if (isset($data[$column])) {
$obj->$column = $data[$column];
}
}
return $obj;
}
public function save() {
$fieldMap = [];
$function = new \ReflectionClass(get_called_class());
$table = strtolower($function->getShortName());
foreach(DB::getColumns($table) as $column) {
$fieldMap[$column] = $this->$column;
}
if ($fieldMap["id"] == null) {
DB::insert($table, $fieldMap);
} else {
$updateFields = $fieldMap;
unset($updateFields["id"]);
DB::update($table, $updateFields, $fieldMap["id"]);
}
}
public function update($data) {
$function = new \ReflectionClass(get_called_class());
$table = strtolower($function->getShortName());
foreach(DB::getColumns($table) as $column) {
if ($column == "id" || strpos($column, "_id") !== false) {
continue; // Don't allow to override id
}
if (isset($data[$column])) {
$this->$column = $data[$column];
}
}
return $this;
}
public function delete() {
$function = new \ReflectionClass(get_called_class());
$table = strtolower($function->getShortName());
if ($this->id) {
DB::query("DELETE FROM $table WHERE id = " . $this->id);
}
}
public function deleteRelated($tables = []) {
$function = new \ReflectionClass(get_called_class());
$table = strtolower($function->getShortName());
foreach($tables as $relatedTable) {
DB::query("DELETE FROM $relatedTable WHERE $table" . "_id = " . $this->id);
}
}
public static function getByField($field, $value) {
$function = new \ReflectionClass(get_called_class());
$table = strtolower($function->getShortName());
$fields = implode(", ", DB::getColumns($table));
return DB::fetchObject("SELECT $fields FROM $table WHERE $field = ?", get_called_class(), [$value]);
}
}

View File

@ -1,80 +1,82 @@
<?php <?php
// Based on tutorial from here: https://portal.cyberhostpro.com/knowledgebase/170/PHP-Mail-Script-with-SMTP-Authentication.html namespace system\engine;
class HF_SMTP
{ // Based on tutorial from here: https://portal.cyberhostpro.com/knowledgebase/170/PHP-Mail-Script-with-SMTP-Authentication.html
class HF_SMTP
private $from = ""; {
private $to = "";
private $subject = ""; private $from = "";
private $msg = ""; private $to = "";
private $user = null; private $subject = "";
private $password = null; private $msg = "";
private $port = 25; private $user = null;
private $server = "localhost"; private $password = null;
private $port = 25;
private $smtpserverconn = null; private $server = "localhost";
public function __construct($from, $to, $subject, $msg, $server = "localhost", $user = null, $password = null, $port = 25) private $smtpserverconn = null;
{
$this->from = $from; public function __construct($from, $to, $subject, $msg, $server = "localhost", $user = null, $password = null, $port = 25)
$this->to = $to; {
$this->subject = $subject; $this->from = $from;
$this->msg = $msg; $this->to = $to;
$this->user = $user; $this->subject = $subject;
$this->password = $password; $this->msg = $msg;
$this->port = $port; $this->user = $user;
$this->server = $server; $this->password = $password;
} $this->port = $port;
$this->server = $server;
public function send($html=false) }
{
$err = null; public function send($html=false)
$errstr = ""; {
$this->smtpserverconn = fsockopen($this->server, $this->port, $err, $errstr, 100); $err = null;
$response = fgets($this->smtpserverconn, 515); $errstr = "";
if ($response === false) $this->smtpserverconn = fsockopen($this->server, $this->port, $err, $errstr, 100);
{ $response = fgets($this->smtpserverconn, 515);
throw new Exception("Could not connect to SMTP server!"); if ($response === false)
} {
throw new Exception("Could not connect to SMTP server!");
if ($this->user != null && $this->password != null) }
{
$this->sendCommand("AUTH LOGIN"); if ($this->user != null && $this->password != null)
$this->sendCommand(base64_encode($this->user)); {
$this->sendCommand(base64_encode($this->password)); $this->sendCommand("AUTH LOGIN");
} $this->sendCommand(base64_encode($this->user));
$this->sendCommand(base64_encode($this->password));
$this->sendCommand("HELO " . $_SERVER["SERVER_NAME"]); }
$this->sendCommand("MAIL FROM: " . $this->from);
$this->sendCommand("RCPT TO: " . $this->to); $this->sendCommand("HELO " . $_SERVER["SERVER_NAME"]);
$this->sendCommand("DATA"); $this->sendCommand("MAIL FROM: " . $this->from);
$this->sendCommand("RCPT TO: " . $this->to);
if ($html) $this->sendCommand("DATA");
{
$this->sendCommand("MIME-Version: 1.0", false); if ($html)
$this->sendCommand("Content-type: text/html; charset=iso-8859-1", false); {
} $this->sendCommand("MIME-Version: 1.0", false);
$this->sendCommand("Content-type: text/html; charset=iso-8859-1", false);
$this->sendCommand("From: " . $this->from, false); }
$this->sendCommand("To: " . $this->to, false);
$this->sendCommand("Subject: " . $this->subject, false); $this->sendCommand("From: " . $this->from, false);
$this->sendCommand("To: " . $this->to, false);
$this->sendCommand("Subject: " . $this->subject, false);
$this->sendCommand($this->msg, false);
$this->sendCommand("", false); $this->sendCommand($this->msg, false);
$this->sendCommand(".", false);
$this->sendCommand("QUIT"); $this->sendCommand("", false);
$this->sendCommand(".", false);
} $this->sendCommand("QUIT");
private function sendCommand($command, $return = true) }
{
fputs($this->smtpserverconn, $command . "\r\n"); private function sendCommand($command, $return = true)
if ($return) {
return fgets($this->smtpserverconn, 515); fputs($this->smtpserverconn, $command . "\r\n");
else if ($return)
return null; return fgets($this->smtpserverconn, 515);
} else
return null;
}
} }

View File

@ -1,15 +1,17 @@
<?php <?php
class HF_Status extends HF_Controller namespace system\engine;
{
class HF_Status extends HF_Controller
public function Status404() {
{
echo "Page not found!"; public function Status404()
} {
echo "Page not found!";
public function Status500() }
{
echo "System error"; public function Status500()
} {
echo "System error";
}
} }

292
system/vendor/DB.php vendored
View File

@ -1,129 +1,165 @@
<?php <?php
/** /**
* Provides a database wrapper around the PDO service to help reduce the effort * Provides a database wrapper around the PDO service to help reduce the effort
* to interact with a RDBMS such as SQLite, MySQL, or PostgreSQL. * to interact with a RDBMS such as SQLite, MySQL, or PostgreSQL.
* *
* DB::$c = new PDO($dsn); * DB::$c = new PDO($dsn);
* *
* @author David Pennington * @author David Pennington
* @copyright (c) 2012 xeoncross.com * @copyright (c) 2012 xeoncross.com
* @license MIT License <http://www.opensource.org/licenses/mit-license.php> * @license MIT License <http://www.opensource.org/licenses/mit-license.php>
********************************** 80 Columns ********************************* ********************************** 80 Columns *********************************
*/ */
class DB
{ namespace vendor\DB;
static $q,$c,$p,$i = '`';
class DB
/** {
* Fetch a column offset from the result set (COUNT() queries) static $q,$c,$p,$i = '`';
*
* @param string $query query string static $type = "";
* @param array $params query parameters
* @param integer $key index of column offset /**
* @return array|null * Fetch a column offset from the result set (COUNT() queries)
*/ *
static function column($query, $params = NULL, $key = 0) * @param string $query query string
{ * @param array $params query parameters
if($statement = DB::query($query, $params)) * @param integer $key index of column offset
return $statement->fetchColumn($key); * @return array|null
} */
static function column($query, $params = NULL, $key = 0)
/** {
* Fetch a single query result row if($statement = DB::query($query, $params))
* return $statement->fetchColumn($key);
* @param string $query query string }
* @param array $params query parameters
* @return mixed /**
*/ * Fetch a single query result row
static function row($query, $params = NULL) *
{ * @param string $query query string
if($statement = DB::query($query, $params)) * @param array $params query parameters
return $statement->fetch(); * @return mixed
} */
static function row($query, $params = NULL)
/** {
* Fetches an associative array of all rows as key-value pairs (first if($statement = DB::query($query, $params))
* column is the key, second column is the value). return $statement->fetch();
* }
* @param string $query query string
* @param array $params query parameters /**
* @return array * Fetches an associative array of all rows as key-value pairs (first
*/ * column is the key, second column is the value).
static function pairs($query, $params = NULL) *
{ * @param string $query query string
$data = array(); * @param array $params query parameters
* @return array
if($statement = DB::query($query, $params)) */
while($row = $statement->fetch(\PDO::FETCH_NUM)) static function pairs($query, $params = NULL)
$data[$row[0]] = $row[1]; {
$data = array();
return $data;
} if($statement = DB::query($query, $params))
while($row = $statement->fetch(\PDO::FETCH_NUM))
/** $data[$row[0]] = $row[1];
* Fetch all query result rows
* return $data;
* @param string $query query string }
* @param array $params query parameters
* @param int $column the optional column to return /**
* @return array * Fetch all query result rows
*/ *
static function fetch($query, $params = NULL, $column = NULL) * @param string $query query string
{ * @param array $params query parameters
if( ! $statement = DB::query($query, $params)) return; * @param int $column the optional column to return
* @return array
// Return an array of records */
if($column === NULL) return $statement->fetchAll(); static function fetch($query, $params = NULL, $column = NULL)
{
// Fetch a certain column from all rows if( ! $statement = DB::query($query, $params)) return;
return $statement->fetchAll(\PDO::FETCH_COLUMN, $column);
} // Return an array of records
if($column === NULL) return $statement->fetchAll();
/**
* Prepare and send a query returning the PDOStatement // Fetch a certain column from all rows
* return $statement->fetchAll(\PDO::FETCH_COLUMN, $column);
* @param string $query query string }
* @param array $params query parameters
* @return object|null /**
*/ * Fetch all query result rows as object
static function query($query, $params = NULL) *
{ * @param string $query query string
$statement = static::$c->prepare(DB::$q[] = strtr($query, '`', DB::$i)); * @param array $params query parameters
$statement->execute($params); * @return array
return $statement; */
} static function fetchObject($query, $className, $params = NULL)
{
/** /** @var \PDOStatement $statement */
* Insert a row into the database if( ! $statement = DB::query($query, $params)) return null;
*
* @param string $table name return $statement->fetchAll(\PDO::FETCH_CLASS, $className);
* @param array $data }
* @return integer|null
*/ /**
static function insert($table, array $data) * Prepare and send a query returning the PDOStatement
{ *
$query = "INSERT INTO`$table`(`" . implode('`,`', array_keys($data)) * @param string $query query string
. '`)VALUES(' . rtrim(str_repeat('?,', count($data = array_values($data))), ',') . ')'; * @param array $params query parameters
return DB::$p * @return object|null
? DB::column($query . 'RETURNING`id`', $data) */
: (DB::query($query, $data) ? static::$c->lastInsertId() : NULL); static function query($query, $params = NULL)
} {
$statement = static::$c->prepare(DB::$q[] = strtr($query, '`', DB::$i));
/** $statement->execute($params);
* Update a database row return $statement;
* }
* @param string $table name
* @param array $data /**
* @param array $w where conditions * Insert a row into the database
* @return integer|null *
*/ * @param string $table name
static function update($table, $data, $value, $column = 'id') * @param array $data
{ * @return integer|null
$keys = implode('`=?,`', array_keys($data)); */
if($statement = DB::query( static function insert($table, array $data)
"UPDATE`$table`SET`$keys`=? WHERE`$column`=?", {
array_values($data + array($value)) $query = "INSERT INTO`$table`(`" . implode('`,`', array_keys($data))
)) . '`)VALUES(' . rtrim(str_repeat('?,', count($data = array_values($data))), ',') . ')';
return $statement->rowCount(); return DB::$p
} ? DB::column($query . 'RETURNING`id`', $data)
: (DB::query($query, $data) ? static::$c->lastInsertId() : NULL);
}
/**
* Update a database row
*
* @param string $table name
* @param array $data
* @param array $w where conditions
* @return integer|null
*/
static function update($table, $data, $value, $column = 'id')
{
$keys = implode('`=?,`', array_keys($data));
if($statement = DB::query(
"UPDATE`$table`SET`$keys`=? WHERE`$column`=?",
array_values($data + array($value))
))
return $statement->rowCount();
}
/**
* Returns array containing all field names
* @param $table
* @return array
*/
static function getColumns($table) {
switch (self::$type) {
case "SQLITE":
return self::fetch("PRAGMA table_info($table)", null, 1);
break;
case "MySQL":
return self::fetch("DESC $table", null, 0);
break;
}
}
} }

View File

@ -1,69 +1,69 @@
<?php <?php
// Original http://stackoverflow.com/a/4282133/195722 // Original http://stackoverflow.com/a/4282133/195722
function vdump() { function vdump() {
$args = func_get_args(); $args = func_get_args();
$backtrace = debug_backtrace(); $backtrace = debug_backtrace();
$code = file($backtrace[0]['file']); $code = file($backtrace[0]['file']);
$ret = "<pre style='background: #eee; border: 1px solid #aaa; clear: both; overflow: auto; padding: 10px; text-align: left; margin-bottom: 5px'>"; $ret = "<pre style='background: #eee; border: 1px solid #aaa; clear: both; overflow: auto; padding: 10px; text-align: left; margin-bottom: 5px'>";
$ret .- "<b>".htmlspecialchars(trim($code[$backtrace[0]['line']-1]))."</b>\n"; $ret .= "<b>".htmlspecialchars(trim($code[$backtrace[0]['line']-1]))."</b>\n";
$ret .= "\n"; $ret .= "\n";
ob_start(); ob_start();
foreach ($args as $arg) foreach ($args as $arg)
var_dump($arg); var_dump($arg);
var_dump($_SERVER); var_dump($_SERVER);
var_dump($_COOKIE); var_dump($_COOKIE);
$str = ob_get_contents(); $str = ob_get_contents();
ob_end_clean(); ob_end_clean();
$str = preg_replace('/=>(\s+)/', ' => ', $str); $str = preg_replace('/=>(\s+)/', ' => ', $str);
$str = preg_replace('/ => NULL/', ' &rarr; <b style="color: #000">NULL</b>', $str); $str = preg_replace('/ => NULL/', ' &rarr; <b style="color: #000">NULL</b>', $str);
$str = preg_replace('/}\n(\s+)\[/', "}\n\n".'$1[', $str); $str = preg_replace('/}\n(\s+)\[/', "}\n\n".'$1[', $str);
$str = preg_replace('/ (float|int)\((\-?[\d\.]+)\)/', " <span style='color: #888'>$1</span> <b style='color: brown'>$2</b>", $str); $str = preg_replace('/ (float|int)\((\-?[\d\.]+)\)/', " <span style='color: #888'>$1</span> <b style='color: brown'>$2</b>", $str);
$str = preg_replace('/array\((\d+)\) {\s+}\n/', "<span style='color: #888'>array&bull;$1</span> <b style='color: brown'>[]</b>", $str); $str = preg_replace('/array\((\d+)\) {\s+}\n/', "<span style='color: #888'>array&bull;$1</span> <b style='color: brown'>[]</b>", $str);
$str = preg_replace('/ string\((\d+)\) \"(.*)\"/', " <span style='color: #888'>str&bull;$1</span> <b style='color: brown'>'$2'</b>", $str); $str = preg_replace('/ string\((\d+)\) \"(.*)\"/', " <span style='color: #888'>str&bull;$1</span> <b style='color: brown'>'$2'</b>", $str);
$str = preg_replace('/\[\"(.+)\"\] => /', "<span style='color: purple'>'$1'</span> &rarr; ", $str); $str = preg_replace('/\[\"(.+)\"\] => /', "<span style='color: purple'>'$1'</span> &rarr; ", $str);
$str = preg_replace('/object\((\S+)\)#(\d+) \((\d+)\) {/', "<span style='color: #888'>obj&bull;$2</span> <b style='color: #0C9136'>$1[$3]</b> {", $str); $str = preg_replace('/object\((\S+)\)#(\d+) \((\d+)\) {/', "<span style='color: #888'>obj&bull;$2</span> <b style='color: #0C9136'>$1[$3]</b> {", $str);
$str = str_replace("bool(false)", "<span style='color:#888'>bool&bull;</span><span style='color: red'>false</span>", $str); $str = str_replace("bool(false)", "<span style='color:#888'>bool&bull;</span><span style='color: red'>false</span>", $str);
$str = str_replace("bool(true)", "<span style='color:#888'>bool&bull;</span><span style='color: green'>true</span>", $str); $str = str_replace("bool(true)", "<span style='color:#888'>bool&bull;</span><span style='color: green'>true</span>", $str);
$ret .= $str; $ret .= $str;
$ret .= "</pre>"; $ret .= "</pre>";
return $ret; return $ret;
} }
// Original - http://www.php.net/manual/en/function.debug-print-backtrace.php#86932 // Original - http://www.php.net/manual/en/function.debug-print-backtrace.php#86932
function debug_string_backtrace() { function debug_string_backtrace() {
ob_start(); ob_start();
debug_print_backtrace(); debug_print_backtrace();
$trace = ob_get_contents(); $trace = ob_get_contents();
ob_end_clean(); ob_end_clean();
// Remove first item from backtrace as it's this function which // Remove first item from backtrace as it's this function which
// is redundant. // is redundant.
$trace = preg_replace ('/^#0\s+' . __FUNCTION__ . "[^\n]*\n/", '', $trace, 1); $trace = preg_replace ('/^#0\s+' . __FUNCTION__ . "[^\n]*\n/", '', $trace, 1);
// Renumber backtrace items. // Renumber backtrace items.
$trace = preg_replace ('/^#(\d+)/me', '\'#\' . ($1 - 1)', $trace); $trace = preg_replace ('/^#(\d+)/me', '\'#\' . ($1 - 1)', $trace);
$trace = wordwrap($trace, 123, "<br>"); $trace = wordwrap($trace, 123, "<br>");
return $trace; return $trace;
} }

27
system/vendor/aes.php vendored Normal file
View File

@ -0,0 +1,27 @@
<?php
// Source: http://stackoverflow.com/a/8232171/195722
function aes_encrypt($key, $text) {
$realKey = "";
if (count($key) < 32) { //if it's less than 32 bits - pad it
$realKey = str_pad($key, 32 - count($key) + 1);
} else if (count($key) > 32) {
throw new \Exception("Key is too long");
} else {
$realKey = $key;
}
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $realKey, $text, MCRYPT_MODE_ECB));
}
function aes_decrypt($key, $cipherText) {
$realKey = "";
if (count($key) < 32) { //if it's less than 32 bits - pad it
$realKey = str_pad($key, 32 - count($key) + 1);
} else if (count($key) > 32) {
throw new \Exception("Key is too long");
} else {
$realKey = $key;
}
return mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $realKey, base64_decode($cipherText), MCRYPT_MODE_ECB);
}

534
system/vendor/h2o.php vendored
View File

@ -1,266 +1,268 @@
<?php <?php
define('H2O_VERSION', '0.3');
defined('DS') or define('DS', DIRECTORY_SEPARATOR); define('H2O_VERSION', '0.3');
defined('H2O_ROOT') or define('H2O_ROOT', dirname(__FILE__) . DS); defined('DS') or define('DS', DIRECTORY_SEPARATOR);
defined('H2O_ROOT') or define('H2O_ROOT', dirname(__FILE__) . DS);
require H2O_ROOT.'h2o/datatype.php';
require H2O_ROOT.'h2o/loaders.php'; require H2O_ROOT.'h2o/datatype.php';
require H2O_ROOT.'h2o/nodes.php'; require H2O_ROOT.'h2o/loaders.php';
require H2O_ROOT.'h2o/tags.php'; require H2O_ROOT.'h2o/nodes.php';
require H2O_ROOT.'h2o/errors.php'; require H2O_ROOT.'h2o/tags.php';
require H2O_ROOT.'h2o/filters.php'; require H2O_ROOT.'h2o/errors.php';
require H2O_ROOT.'h2o/context.php'; require H2O_ROOT.'h2o/filters.php';
require H2O_ROOT.'h2o/context.php';
/** require H2O_ROOT.'h2o/parser.php';
* Example:
* $h2o = new H2O('./template.html', array("loader"=>'file')); /**
* * Example:
* * $h2o = new H2O('./template.html', array("loader"=>'file'));
* $h2o = new H2O('template.html', array("loader"=>'hash')); *
*/ *
class H2o { * $h2o = new H2O('template.html', array("loader"=>'hash'));
var $searchpath; */
var $context; class H2o {
var $loader = false; var $searchpath;
var $context;
static $tags = array(); var $loader = false;
static $filters = array();
static $extensions = array(); static $tags = array();
static $filters = array();
static function getOptions($options = array()) { static $extensions = array();
return array_merge(array(
'loader' => 'file', static function getOptions($options = array()) {
'cache' => 'file', // file | apc | memcache return array_merge(array(
'cache_prefix' => 'h2o_', 'loader' => 'file',
'cache_ttl' => 3600, // file | apc | memcache 'cache' => 'file', // file | apc | memcache
'searchpath' => false, 'cache_prefix' => 'h2o_',
'autoescape' => true, 'cache_ttl' => 3600, // file | apc | memcache
'searchpath' => false,
// Enviroment setting 'autoescape' => true,
'BLOCK_START' => '{%',
'BLOCK_END' => '%}', // Enviroment setting
'VARIABLE_START' => '{{', 'BLOCK_START' => '{%',
'VARIABLE_END' => '}}', 'BLOCK_END' => '%}',
'COMMENT_START' => '{*', 'VARIABLE_START' => '{{',
'COMMENT_END' => '*}', 'VARIABLE_END' => '}}',
'TRIM_TAGS' => true 'COMMENT_START' => '{*',
), $options); 'COMMENT_END' => '*}',
} 'TRIM_TAGS' => true
), $options);
function __construct($file = null, $options = array()) { }
# Init a environment
$this->options = $this->getOptions($options); function __construct($file = null, $options = array()) {
$loader = $this->options['loader']; # Init a environment
$this->options = $this->getOptions($options);
if (!$loader) $loader = $this->options['loader'];
return true;
if (!$loader)
if (is_object($loader)) { return true;
$this->loader = $loader;
$this->loader->setOptions($this->options); if (is_object($loader)) {
} else { $this->loader = $loader;
$loader = "H2o_{$loader}_Loader"; $this->loader->setOptions($this->options);
if (!class_exists($loader, false)) } else {
throw new Exception('Invalid template loader'); $loader = "H2o_{$loader}_Loader";
if (!class_exists($loader, false))
if (isset($options['searchpath'])){ throw new Exception('Invalid template loader');
$this->searchpath = $options['searchpath'];
} else if ($file) { if (isset($options['searchpath'])){
$this->searchpath = dirname(realpath($file)).DS; $this->searchpath = $options['searchpath'];
} else { } else if ($file) {
$this->searchpath = getcwd().DS; $this->searchpath = dirname(realpath($file)).DS;
} } else {
$this->searchpath = getcwd().DS;
$loader_searchpath = is_array($this->searchpath) ? $this->searchpath : array($this->searchpath); }
$this->loader = new $loader($loader_searchpath, $this->options);
} $loader_searchpath = is_array($this->searchpath) ? $this->searchpath : array($this->searchpath);
$this->loader->runtime = $this; $this->loader = new $loader($loader_searchpath, $this->options);
}
if (isset($options['i18n'])) { $this->loader->runtime = $this;
h2o::load('i18n');
$this->i18n = new H2o_I18n($this->searchpath, $options['i18n']); if (isset($options['i18n'])) {
} h2o::load('i18n');
$this->i18n = new H2o_I18n($this->searchpath, $options['i18n']);
if ($file) { }
$this->nodelist = $this->loadTemplate($file);
} if ($file) {
} $this->nodelist = $this->loadTemplate($file);
}
function loadTemplate($file) { }
return $this->nodelist = $this->loader->read_cache($file);
} function loadTemplate($file) {
return $this->nodelist = $this->loader->read_cache($file);
function loadSubTemplate($file) { }
return $this->loader->read($file);
} function loadSubTemplate($file) {
return $this->loader->read($file);
# Build a finalized nodelist from template ready to be cached }
function parse($source, $filename = '', $env = null) {
if (!$env) # Build a finalized nodelist from template ready to be cached
$env = $this->options; function parse($source, $filename = '', $env = null) {
if (!$env)
if (!class_exists('H2o_Parser', false)) $env = $this->options;
require H2O_ROOT.'h2o/parser.php';
if (!class_exists('H2o_Parser', false))
$parser = new H2o_Parser($source, $filename, $this, $env); require H2O_ROOT.'h2o/parser.php';
$nodelist = $parser->parse();
return $nodelist; $parser = new H2o_Parser($source, $filename, $this, $env);
} $nodelist = $parser->parse();
return $nodelist;
function set($context, $value = null) { }
# replace with new context object
if (is_object($context) && $context instanceof H2o_Context) { function set($context, $value = null) {
return $this->context = $context; # replace with new context object
} if (is_object($context) && $context instanceof H2o_Context) {
return $this->context = $context;
# Init context }
if (!$this->context) {
$this->context = new H2o_Context($this->defaultContext(), $this->options); # Init context
} if (!$this->context) {
$this->context = new H2o_Context($this->defaultContext(), $this->options);
# Extend or set value }
if (is_array($context)) {
return $this->context->extend($context); # Extend or set value
} if (is_array($context)) {
elseif (is_string($context)) { return $this->context->extend($context);
return $this->context[$context] = $value; }
} elseif (is_string($context)) {
return false; return $this->context[$context] = $value;
} }
return false;
# Render the nodelist }
function render($context = array()) {
$this->set($context); # Render the nodelist
function render($context = array()) {
$this->stream = new StreamWriter; $this->set($context);
$this->nodelist->render($this->context, $this->stream);
return $this->stream->close(); $this->stream = new StreamWriter;
} $this->nodelist->render($this->context, $this->stream);
return $this->stream->close();
static function parseString($source, $options = array()) { }
$instance = new H2o(null, array_merge($options, array('loader' => false)));
$instance->nodelist = $instance->parse($source); static function parseString($source, $options = array()) {
return $instance; $instance = new H2o(null, array_merge($options, array('loader' => false)));
} $instance->nodelist = $instance->parse($source);
return $instance;
static function &createTag($tag, $args = null, $parser, $position = 0) { }
if (!isset(self::$tags[$tag])) {
throw new H2o_Error($tag . " tag doesn't exist"); static function &createTag($tag, $args = null, $parser, $position = 0) {
} if (!isset(self::$tags[$tag])) {
$tagClass = self::$tags[$tag]; throw new H2o_Error($tag . " tag doesn't exist");
$tag = new $tagClass($args, $parser, $position); }
return $tag; $tagClass = self::$tags[$tag];
} $tag = new $tagClass($args, $parser, $position);
return $tag;
/** }
* Register a new tag
* /**
* * Register a new tag
* h2o::addTag('tag_name', 'ClassName'); *
* *
* h2o::addTag(array( * h2o::addTag('tag_name', 'ClassName');
* 'tag_name' => 'MagClass', *
* 'tag_name2' => 'TagClass2' * h2o::addTag(array(
* )); * 'tag_name' => 'MagClass',
* * 'tag_name2' => 'TagClass2'
* h2o::addTag('tag_name'); // Tag_name_Tag * ));
* *
* h2o::addTag(array('tag_name', * h2o::addTag('tag_name'); // Tag_name_Tag
* @param unknown_type $tag *
* @param unknown_type $class * h2o::addTag(array('tag_name',
*/ * @param unknown_type $tag
static function addTag($tag, $class = null) { * @param unknown_type $class
$tags = array(); */
if (is_string($tag)) { static function addTag($tag, $class = null) {
if (is_null($class)) $tags = array();
$class = ucwords("{$tag}_Tag"); if (is_string($tag)) {
$tags[$tag] = $class; if (is_null($class))
} elseif (is_array($tag)) { $class = ucwords("{$tag}_Tag");
$tags = $tag; $tags[$tag] = $class;
} } elseif (is_array($tag)) {
$tags = $tag;
foreach ($tags as $tag => $tagClass) { }
if (is_integer($tag)) {
unset($tags[$tag]); foreach ($tags as $tag => $tagClass) {
$tag = $tagClass; if (is_integer($tag)) {
$tagClass = ucwords("{$tagClass}_Tag"); unset($tags[$tag]);
} $tag = $tagClass;
if (!class_exists($tagClass, false)) { $tagClass = ucwords("{$tagClass}_Tag");
throw new H2o_Error("{$tagClass} tag is not found"); }
} if (!class_exists($tagClass, false)) {
$tags[$tag] = $tagClass; throw new H2o_Error("{$tagClass} tag is not found");
} }
self::$tags = array_merge(self::$tags, $tags); $tags[$tag] = $tagClass;
} }
self::$tags = array_merge(self::$tags, $tags);
/** }
* Register a new filter to h2o runtime
* /**
* @param unknown_type $filter * Register a new filter to h2o runtime
* @param unknown_type $callback *
* @return unknown * @param unknown_type $filter
*/ * @param unknown_type $callback
static function addFilter($filter, $callback = null) { * @return unknown
if (is_array($filter)) { */
$filters = $filter; static function addFilter($filter, $callback = null) {
foreach($filters as $key => $filter) { if (is_array($filter)) {
if (is_numeric($key)) $filters = $filter;
$key = $filter; foreach($filters as $key => $filter) {
self::addFilter($key, $filter); if (is_numeric($key))
} $key = $filter;
return true; self::addFilter($key, $filter);
} elseif (is_string($filter) && class_exists($filter, false) && is_subclass_of($filter, 'FilterCollection')) { }
foreach (get_class_methods($filter) as $f) { return true;
if (is_callable(array($filter, $f))) } elseif (is_string($filter) && class_exists($filter, false) && is_subclass_of($filter, 'FilterCollection')) {
self::$filters[$f] = array($filter, $f); foreach (get_class_methods($filter) as $f) {
} if (is_callable(array($filter, $f)))
return true; self::$filters[$f] = array($filter, $f);
} }
if (is_null($callback)) return true;
$callback = $filter; }
if (is_null($callback))
if (!is_callable($callback)) { $callback = $filter;
return false;
} if (!is_callable($callback)) {
self::$filters[$filter] = $callback; return false;
} }
self::$filters[$filter] = $callback;
static function addLookup($callback) { }
if (is_callable($callback)) {
H2o_Context::$lookupTable[] = $callback; static function addLookup($callback) {
} else die('damm it'); if (is_callable($callback)) {
} H2o_Context::$lookupTable[] = $callback;
} else die('damm it');
static function load($extension, $file = null) { }
if (!$file) {
$file = H2O_ROOT.'ext'.DS.$extension.'.php'; static function load($extension, $file = null) {
} if (!$file) {
if (is_file($file)) { $file = H2O_ROOT.'ext'.DS.$extension.'.php';
include_once ($file); }
self::$extensions[$extension] = $file; if (is_file($file)) {
} include_once ($file);
} self::$extensions[$extension] = $file;
}
function defaultContext() { }
return array('h2o' => new H2o_Info);
} function defaultContext() {
} return array('h2o' => new H2o_Info);
}
/** }
* Convenient wrapper for loading template file or string
* @param $name /**
* @param $options - H2o options * Convenient wrapper for loading template file or string
* @return Instance of H2o Template * @param $name
*/ * @param $options - H2o options
function h2o($name, $options = array()) { * @return Instance of H2o Template
$is_file = '/([^\s]*?)(\.[^.\s]*$)/'; */
function h2o($name, $options = array()) {
if (!preg_match($is_file, $name)) { $is_file = '/([^\s]*?)(\.[^.\s]*$)/';
return H2o::parseString($name, $options);
} if (!preg_match($is_file, $name)) {
return H2o::parseString($name, $options);
$instance = new H2o($name, $options); }
return $instance;
} $instance = new H2o($name, $options);
return $instance;
?> }
?>

View File

@ -1,266 +1,266 @@
<?php <?php
/** /**
* Context object * Context object
* encapsulate context, resolve name * encapsulate context, resolve name
*/ */
class H2o_Context implements ArrayAccess { class H2o_Context implements ArrayAccess {
public $safeClass = array('stdClass', 'BlockContext'); public $safeClass = array('stdClass', 'BlockContext');
public $scopes; public $scopes;
public $options; public $options;
public $autoescape = true; public $autoescape = true;
private $arrayMethods = array('first'=> 0, 'last'=> 1, 'length'=> 2, 'size'=> 3); private $arrayMethods = array('first'=> 0, 'last'=> 1, 'length'=> 2, 'size'=> 3);
static $lookupTable = array(); static $lookupTable = array();
function __construct($context = array(), $options = array()){ function __construct($context = array(), $options = array()){
if (is_object($context)) if (is_object($context))
$context = get_object_vars($context); $context = get_object_vars($context);
$this->scopes = array($context); $this->scopes = array($context);
if (isset($options['safeClass'])) if (isset($options['safeClass']))
$this->safeClass = array_merge($this->safeClass, $options['safeClass']); $this->safeClass = array_merge($this->safeClass, $options['safeClass']);
if (isset($options['autoescape'])) if (isset($options['autoescape']))
$this->autoescape = $options['autoescape']; $this->autoescape = $options['autoescape'];
$this->options = $options; $this->options = $options;
} }
function push($layer = array()){ function push($layer = array()){
return array_unshift($this->scopes, $layer); return array_unshift($this->scopes, $layer);
} }
/** /**
* pop the most recent layer * pop the most recent layer
*/ */
function pop() { function pop() {
if (!isset($this->scopes[1])) if (!isset($this->scopes[1]))
throw new Exception('cannnot pop from empty stack'); throw new Exception('cannnot pop from empty stack');
return array_shift($this->scopes); return array_shift($this->scopes);
} }
function offsetExists($offset) { function offsetExists($offset) {
foreach ($this->scopes as $layer) { foreach ($this->scopes as $layer) {
if (isset($layer[$offset])) return true; if (isset($layer[$offset])) return true;
} }
return false; return false;
} }
function offsetGet($key) { function offsetGet($key) {
foreach ($this->scopes as $layer) { foreach ($this->scopes as $layer) {
if (isset($layer[$key])) if (isset($layer[$key]))
return $layer[$key]; return $layer[$key];
} }
return; return;
} }
function offsetSet($key, $value) { function offsetSet($key, $value) {
if (strpos($key, '.') > -1) if (strpos($key, '.') > -1)
throw new Exception('cannot set non local variable'); throw new Exception('cannot set non local variable');
return $this->scopes[0][$key] = $value; return $this->scopes[0][$key] = $value;
} }
function offsetUnset($key) { function offsetUnset($key) {
foreach ($this->scopes as $layer) { foreach ($this->scopes as $layer) {
if (isset($layer[$key])) unset($layer[$key]); if (isset($layer[$key])) unset($layer[$key]);
} }
} }
function extend($context) { function extend($context) {
$this->scopes[0] = array_merge($this->scopes[0], $context); $this->scopes[0] = array_merge($this->scopes[0], $context);
} }
function set($key, $value) { function set($key, $value) {
return $this->offsetSet($key, $value); return $this->offsetSet($key, $value);
} }
function get($key) { function get($key) {
return $this->offsetGet($key); return $this->offsetGet($key);
} }
function isDefined($key) { function isDefined($key) {
return $this->offsetExists($key); return $this->offsetExists($key);
} }
/** /**
* *
* *
* *
* Variable name * Variable name
* *
* @param $var variable name or array(0 => variable name, 'filters' => filters array) * @param $var variable name or array(0 => variable name, 'filters' => filters array)
* @return unknown_type * @return unknown_type
*/ */
function resolve($var) { function resolve($var) {
# if $var is array - it contains filters to apply # if $var is array - it contains filters to apply
$filters = array(); $filters = array();
if ( is_array($var) ) { if ( is_array($var) ) {
$name = array_shift($var); $name = array_shift($var);
$filters = isset($var['filters'])? $var['filters'] : array(); $filters = isset($var['filters'])? $var['filters'] : array();
} }
else $name = $var; else $name = $var;
$result = null; $result = null;
# Lookup basic types, null, boolean, numeric and string # Lookup basic types, null, boolean, numeric and string
# Variable starts with : (:users.name) to short-circuit lookup # Variable starts with : (:users.name) to short-circuit lookup
if ($name[0] === ':') { if ($name[0] === ':') {
$object = $this->getVariable(substr($name, 1)); $object = $this->getVariable(substr($name, 1));
if (!is_null($object)) $result = $object; if (!is_null($object)) $result = $object;
} else { } else {
if ($name === 'true') { if ($name === 'true') {
$result = true; $result = true;
} }
elseif ($name === 'false') { elseif ($name === 'false') {
$result = false; $result = false;
} }
elseif (preg_match('/^-?\d+(\.\d+)?$/', $name, $matches)) { elseif (preg_match('/^-?\d+(\.\d+)?$/', $name, $matches)) {
$result = isset($matches[1])? floatval($name) : intval($name); $result = isset($matches[1])? floatval($name) : intval($name);
} }
elseif (preg_match('/^"([^"\\\\]*(?:\\.[^"\\\\]*)*)"|' . elseif (preg_match('/^"([^"\\\\]*(?:\\.[^"\\\\]*)*)"|' .
'\'([^\'\\\\]*(?:\\.[^\'\\\\]*)*)\'$/', $name)) { '\'([^\'\\\\]*(?:\\.[^\'\\\\]*)*)\'$/', $name)) {
$result = stripcslashes(substr($name, 1, -1)); $result = stripcslashes(substr($name, 1, -1));
} }
} }
if (!empty(self::$lookupTable) && $result == Null) { if (!empty(self::$lookupTable) && $result == Null) {
$result = $this->externalLookup($name); $result = $this->externalLookup($name);
} }
$result = $this->applyFilters($result,$filters); $result = $this->applyFilters($result,$filters);
return $result; return $result;
} }
function getVariable($name) { function getVariable($name) {
# Local variables. this gives as a bit of performance improvement # Local variables. this gives as a bit of performance improvement
if (!strpos($name, '.')) if (!strpos($name, '.'))
return $this[$name]; return $this[$name];
# Prepare for Big lookup # Prepare for Big lookup
$parts = explode('.', $name); $parts = explode('.', $name);
$object = $this[array_shift($parts)]; $object = $this[array_shift($parts)];
# Lookup context # Lookup context
foreach ($parts as $part) { foreach ($parts as $part) {
if (is_array($object) or $object instanceof ArrayAccess) { if (is_array($object) or $object instanceof ArrayAccess) {
if (isset($object[$part])) { if (isset($object[$part])) {
$object = $object[$part]; $object = $object[$part];
} elseif ($part === 'first') { } elseif ($part === 'first') {
$object = isset($object[0])?$object[0]:null; $object = isset($object[0])?$object[0]:null;
} elseif ($part === 'last') { } elseif ($part === 'last') {
$last = count($object)-1; $last = count($object)-1;
$object = isset($object[$last])?$object[$last]:null; $object = isset($object[$last])?$object[$last]:null;
} elseif ($part === 'size' or $part === 'length') { } elseif ($part === 'size' or $part === 'length') {
return count($object); return count($object);
} else { } else {
return null; return null;
} }
} }
elseif (is_object($object)) { elseif (is_object($object)) {
if (isset($object->$part)) if (isset($object->$part))
$object = $object->$part; $object = $object->$part;
elseif (is_callable(array($object, $part))) { elseif (is_callable(array($object, $part))) {
$methodAllowed = in_array(get_class($object), $this->safeClass) || $methodAllowed = in_array(get_class($object), $this->safeClass) ||
(isset($object->h2o_safe) && ( (isset($object->h2o_safe) && (
$object->h2o_safe === true || in_array($part, $object->h2o_safe) $object->h2o_safe === true || in_array($part, $object->h2o_safe)
) )
); );
$object = $methodAllowed ? $object->$part() : null; $object = $methodAllowed ? $object->$part() : null;
} }
else return null; else return null;
} }
else return null; else return null;
} }
return $object; return $object;
} }
function applyFilters($object, $filters) { function applyFilters($object, $filters) {
foreach ($filters as $filter) { foreach ($filters as $filter) {
$name = substr(array_shift($filter), 1); $name = substr(array_shift($filter), 1);
$args = $filter; $args = $filter;
if (isset(h2o::$filters[$name])) { if (isset(h2o::$filters[$name])) {
foreach ($args as $i => $argument) { foreach ($args as $i => $argument) {
# name args # name args
if (is_array($argument)) { if (is_array($argument)) {
foreach ($argument as $n => $arg) { foreach ($argument as $n => $arg) {
$args[$i][$n] = $this->resolve($arg); $args[$i][$n] = $this->resolve($arg);
} }
} else { } else {
# resolve argument values # resolve argument values
$args[$i] = $this->resolve($argument); $args[$i] = $this->resolve($argument);
} }
} }
array_unshift($args, $object); array_unshift($args, $object);
$object = call_user_func_array(h2o::$filters[$name], $args); $object = call_user_func_array(h2o::$filters[$name], $args);
} }
} }
return $object; return $object;
} }
function escape($value, $var) { function escape($value, $var) {
$safe = false; $safe = false;
$filters = (is_array($var) && isset($var['filters']))? $var['filters'] : array(); $filters = (is_array($var) && isset($var['filters']))? $var['filters'] : array();
foreach ( $filters as $filter ) { foreach ( $filters as $filter ) {
$name = substr(array_shift($filter), 1); $name = substr(array_shift($filter), 1);
$safe = !$safe && ($name === 'safe'); $safe = !$safe && ($name === 'safe');
$escaped = $name === 'escape'; $escaped = $name === 'escape';
} }
$should_escape = $this->autoescape || isset($escaped) && $escaped; $should_escape = $this->autoescape || isset($escaped) && $escaped;
if ( ($should_escape && !$safe)) { if ( ($should_escape && !$safe)) {
$value = htmlspecialchars($value); $value = htmlspecialchars($value);
} }
return $value; return $value;
} }
function externalLookup($name) { function externalLookup($name) {
if (!empty(self::$lookupTable)) { if (!empty(self::$lookupTable)) {
foreach (self::$lookupTable as $lookup) { foreach (self::$lookupTable as $lookup) {
$tmp = call_user_func_array($lookup, array($name, $this)); $tmp = call_user_func_array($lookup, array($name, $this));
if ($tmp !== null) if ($tmp !== null)
return $tmp; return $tmp;
} }
} }
return null; return null;
} }
} }
class BlockContext { class BlockContext {
var $h2o_safe = array('name', 'depth', 'super'); var $h2o_safe = array('name', 'depth', 'super');
var $block, $index; var $block, $index;
private $context; private $context;
function __construct($block, $context, $index) { function __construct($block, $context, $index) {
$this->block =& $block; $this->block =& $block;
$this->context = $context; $this->context = $context;
$this->index = $index; $this->index = $index;
} }
function name() { function name() {
return $this->block->name; return $this->block->name;
} }
function depth() { function depth() {
return $this->index; return $this->index;
} }
function super() { function super() {
$stream = new StreamWriter; $stream = new StreamWriter;
$this->block->parent->render($this->context, $stream, $this->index+1); $this->block->parent->render($this->context, $stream, $this->index+1);
return $stream->close(); return $stream->close();
} }
function __toString() { function __toString() {
return "[BlockContext : {$this->block->name}, {$this->block->filename}]"; return "[BlockContext : {$this->block->name}, {$this->block->filename}]";
} }
} }
?> ?>

View File

@ -1,173 +1,173 @@
<?php <?php
class StreamWriter { class StreamWriter {
var $buffer = array(); var $buffer = array();
var $close; var $close;
function __construct() { function __construct() {
$this->close = false; $this->close = false;
} }
function write($data) { function write($data) {
if ($this->close) if ($this->close)
new Exception('tried to write to closed stream'); new Exception('tried to write to closed stream');
$this->buffer[] = $data; $this->buffer[] = $data;
} }
function close() { function close() {
$this->close = true; $this->close = true;
return implode('', $this->buffer); return implode('', $this->buffer);
} }
} }
class Evaluator { class Evaluator {
static function gt($l, $r) { return $l > $r; } static function gt($l, $r) { return $l > $r; }
static function ge($l, $r) { return $l >= $r; } static function ge($l, $r) { return $l >= $r; }
static function lt($l, $r) { return $l < $r; } static function lt($l, $r) { return $l < $r; }
static function le($l, $r) { return $l <= $r; } static function le($l, $r) { return $l <= $r; }
static function eq($l, $r) { return $l == $r; } static function eq($l, $r) { return $l == $r; }
static function ne($l, $r) { return $l != $r; } static function ne($l, $r) { return $l != $r; }
static function not_($bool) { return !$bool; } static function not_($bool) { return !$bool; }
static function and_($l, $r) { return ($l && $r); } static function and_($l, $r) { return ($l && $r); }
static function or_($l, $r) { return ($l && $r); } static function or_($l, $r) { return ($l && $r); }
# Currently only support single expression with no preceddence ,no boolean expression # Currently only support single expression with no preceddence ,no boolean expression
# [expression] = [optional binary] ? operant [ optional compare operant] # [expression] = [optional binary] ? operant [ optional compare operant]
# [operant] = variable|string|numeric|boolean # [operant] = variable|string|numeric|boolean
# [compare] = > | < | == | >= | <= # [compare] = > | < | == | >= | <=
# [binary] = not | ! # [binary] = not | !
static function exec($args, $context) { static function exec($args, $context) {
$argc = count($args); $argc = count($args);
$first = array_shift($args); $first = array_shift($args);
$first = $context->resolve($first); $first = $context->resolve($first);
switch ($argc) { switch ($argc) {
case 1 : case 1 :
return $first; return $first;
case 2 : case 2 :
if (is_array($first) && isset($first['operator']) && $first['operator'] == 'not') { if (is_array($first) && isset($first['operator']) && $first['operator'] == 'not') {
$operant = array_shift($args); $operant = array_shift($args);
$operant = $context->resolve($operant); $operant = $context->resolve($operant);
return !($operant); return !($operant);
} }
case 3 : case 3 :
list($op, $right) = $args; list($op, $right) = $args;
$right = $context->resolve($right); $right = $context->resolve($right);
return call_user_func(array("Evaluator", $op['operator']), $first, $right); return call_user_func(array("Evaluator", $op['operator']), $first, $right);
default: default:
return false; return false;
} }
} }
} }
/** /**
* $type of token, Block | Variable * $type of token, Block | Variable
*/ */
class H2o_Token { class H2o_Token {
function __construct ($type, $content, $position) { function __construct ($type, $content, $position) {
$this->type = $type; $this->type = $type;
$this->content = $content; $this->content = $content;
$this->result=''; $this->result='';
$this->position = $position; $this->position = $position;
} }
function write($content){ function write($content){
$this->result= $content; $this->result= $content;
} }
} }
/** /**
* a token stream * a token stream
*/ */
class TokenStream { class TokenStream {
var $pushed; var $pushed;
var $stream; var $stream;
var $closed; var $closed;
var $c; var $c;
function __construct() { function __construct() {
$this->pushed = array(); $this->pushed = array();
$this->stream = array(); $this->stream = array();
$this->closed = false; $this->closed = false;
} }
function pop() { function pop() {
if (count($this->pushed)) if (count($this->pushed))
return array_pop($this->pushed); return array_pop($this->pushed);
return array_pop($this->stream); return array_pop($this->stream);
} }
function feed($type, $contents, $position) { function feed($type, $contents, $position) {
if ($this->closed) if ($this->closed)
throw new Exception('cannot feed closed stream'); throw new Exception('cannot feed closed stream');
$this->stream[] = new H2o_Token($type, $contents, $position); $this->stream[] = new H2o_Token($type, $contents, $position);
} }
function push($token) { function push($token) {
if (is_null($token)) if (is_null($token))
throw new Exception('cannot push NULL'); throw new Exception('cannot push NULL');
if ($this->closed) if ($this->closed)
$this->pushed[] = $token; $this->pushed[] = $token;
else else
$this->stream[] = $token; $this->stream[] = $token;
} }
function close() { function close() {
if ($this->closed) if ($this->closed)
new Exception('cannot close already closed stream'); new Exception('cannot close already closed stream');
$this->closed = true; $this->closed = true;
$this->stream = array_reverse($this->stream); $this->stream = array_reverse($this->stream);
} }
function isClosed() { function isClosed() {
return $this->closed; return $this->closed;
} }
function current() { function current() {
return $this->c ; return $this->c ;
} }
function next() { function next() {
return $this->c = $this->pop(); return $this->c = $this->pop();
} }
} }
class H2o_Info { class H2o_Info {
var $h2o_safe = array('filters', 'extensions', 'tags'); var $h2o_safe = array('filters', 'extensions', 'tags');
var $name = 'H2o Template engine'; var $name = 'H2o Template engine';
var $description = "Django inspired template system"; var $description = "Django inspired template system";
var $version = H2O_VERSION; var $version = H2O_VERSION;
function filters() { function filters() {
return array_keys(h2o::$filters); return array_keys(h2o::$filters);
} }
function tags() { function tags() {
return array_keys(h2o::$tags); return array_keys(h2o::$tags);
} }
function extensions() { function extensions() {
return array_keys(h2o::$extensions); return array_keys(h2o::$extensions);
} }
} }
/** /**
* Functions * Functions
*/ */
function sym_to_str($string) { function sym_to_str($string) {
return substr($string, 1); return substr($string, 1);
} }
function is_sym($string) { function is_sym($string) {
return isset($string[0]) && $string[0] === ':'; return isset($string[0]) && $string[0] === ':';
} }
function symbol($string) { function symbol($string) {
return ':'.$string; return ':'.$string;
} }
function strip_regex($regex, $delimiter = '/') { function strip_regex($regex, $delimiter = '/') {
return substr($regex, 1, strrpos($regex, $delimiter)-1); return substr($regex, 1, strrpos($regex, $delimiter)-1);
} }
?> ?>

View File

@ -1,10 +1,10 @@
<?php <?php
# Errors # Errors
class H2o_Error extends Exception {} class H2o_Error extends Exception {}
class ParseError extends H2o_Error {} class ParseError extends H2o_Error {}
class TemplateNotFound extends H2o_Error {} class TemplateNotFound extends H2o_Error {}
class TemplateSyntaxError extends H2o_Error {} class TemplateSyntaxError extends H2o_Error {}
?> ?>

View File

@ -1,369 +1,369 @@
<?php <?php
class FilterCollection {}; class FilterCollection {};
class CoreFilters extends FilterCollection { class CoreFilters extends FilterCollection {
static function first($value) { static function first($value) {
return $value[0]; return $value[0];
} }
static function last($value) { static function last($value) {
return $value[count($value) - 1]; return $value[count($value) - 1];
} }
static function join($value, $delimiter = ', ') { static function join($value, $delimiter = ', ') {
return join($delimiter, $value); return join($delimiter, $value);
} }
static function length($value) { static function length($value) {
return count($value); return count($value);
} }
static function urlencode($data) { static function urlencode($data) {
if (is_array($data)) { if (is_array($data)) {
$result; $result;
foreach ($data as $name => $value) { foreach ($data as $name => $value) {
$result .= $name.'='.urlencode($value).'&'.$querystring; $result .= $name.'='.urlencode($value).'&'.$querystring;
} }
$querystring = substr($result, 0, strlen($result)-1); $querystring = substr($result, 0, strlen($result)-1);
return htmlspecialchars($result); return htmlspecialchars($result);
} else { } else {
return urlencode($data); return urlencode($data);
} }
} }
static function hyphenize ($string) { static function hyphenize ($string) {
$rules = array('/[^\w\s-]+/'=>'','/\s+/'=>'-', '/-{2,}/'=>'-'); $rules = array('/[^\w\s-]+/'=>'','/\s+/'=>'-', '/-{2,}/'=>'-');
$string = preg_replace(array_keys($rules), $rules, trim($string)); $string = preg_replace(array_keys($rules), $rules, trim($string));
return $string = trim(strtolower($string)); return $string = trim(strtolower($string));
} }
static function urlize( $string, $truncate = false ) { static function urlize( $string, $truncate = false ) {
$reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/"; $reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
preg_match_all($reg_exUrl, $string, $matches); preg_match_all($reg_exUrl, $string, $matches);
$usedPatterns = array(); $usedPatterns = array();
foreach($matches[0] as $pattern){ foreach($matches[0] as $pattern){
if(!array_key_exists($pattern, $usedPatterns)){ if(!array_key_exists($pattern, $usedPatterns)){
$usedPatterns[$pattern]=true; $usedPatterns[$pattern]=true;
$string = str_replace($pattern, "<a href=\"{$pattern}\" rel=\"nofollow\">{$pattern}</a>", $string); $string = str_replace($pattern, "<a href=\"{$pattern}\" rel=\"nofollow\">{$pattern}</a>", $string);
} }
} }
$reg_exEmail = "/[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}/"; $reg_exEmail = "/[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}/";
preg_match_all($reg_exEmail, $string, $matches); preg_match_all($reg_exEmail, $string, $matches);
$usedPatterns = array(); $usedPatterns = array();
foreach($matches[0] as $pattern){ foreach($matches[0] as $pattern){
if(!array_key_exists($pattern, $usedPatterns)){ if(!array_key_exists($pattern, $usedPatterns)){
$usedPatterns[$pattern]=true; $usedPatterns[$pattern]=true;
$string = str_replace($pattern, "<a href=\"mailto:{$pattern}\">{$pattern}</a>", $string); $string = str_replace($pattern, "<a href=\"mailto:{$pattern}\">{$pattern}</a>", $string);
} }
} }
return $string; return $string;
} }
static function set_default($object, $default) { static function set_default($object, $default) {
return !$object ? $default : $object; return !$object ? $default : $object;
} }
} }
class StringFilters extends FilterCollection { class StringFilters extends FilterCollection {
static function humanize($string) { static function humanize($string) {
$string = preg_replace('/\s+/', ' ', trim(preg_replace('/[^A-Za-z0-9()!,?$]+/', ' ', $string))); $string = preg_replace('/\s+/', ' ', trim(preg_replace('/[^A-Za-z0-9()!,?$]+/', ' ', $string)));
return capfirst($string); return capfirst($string);
} }
static function capitalize($string) { static function capitalize($string) {
return ucwords(strtolower($string)) ; return ucwords(strtolower($string)) ;
} }
static function titlize($string) { static function titlize($string) {
return self::capitalize($string); return self::capitalize($string);
} }
static function capfirst($string) { static function capfirst($string) {
$string = strtolower($string); $string = strtolower($string);
return strtoupper($string{0}). substr($string, 1, strlen($string)); return strtoupper($string{0}). substr($string, 1, strlen($string));
} }
static function tighten_space($value) { static function tighten_space($value) {
return preg_replace("/\s{2,}/", ' ', $value); return preg_replace("/\s{2,}/", ' ', $value);
} }
static function escape($value, $attribute = false) { static function escape($value, $attribute = false) {
return htmlspecialchars($value, $attribute ? ENT_QUOTES : ENT_NOQUOTES); return htmlspecialchars($value, $attribute ? ENT_QUOTES : ENT_NOQUOTES);
} }
static function escapejson($value) { static function escapejson($value) {
// The standard django escapejs converts all non-ascii characters into hex codes. // The standard django escapejs converts all non-ascii characters into hex codes.
// This function encodes the entire data structure, and strings get quotes around them. // This function encodes the entire data structure, and strings get quotes around them.
return json_encode($value); return json_encode($value);
} }
static function force_escape($value, $attribute = false) { static function force_escape($value, $attribute = false) {
return self::escape($value, $attribute); return self::escape($value, $attribute);
} }
static function e($value, $attribute = false) { static function e($value, $attribute = false) {
return self::escape($value, $attribute); return self::escape($value, $attribute);
} }
static function safe($value) { static function safe($value) {
return $value; return $value;
} }
static function truncate ($string, $max = 50, $ends = '...') { static function truncate ($string, $max = 50, $ends = '...') {
return (strlen($string) > $max ? substr($string, 0, $max).$ends : $string); return (strlen($string) > $max ? substr($string, 0, $max).$ends : $string);
} }
static function limitwords($text, $limit = 50, $ends = '...') { static function limitwords($text, $limit = 50, $ends = '...') {
if (strlen($text) > $limit) { if (strlen($text) > $limit) {
$words = str_word_count($text, 2); $words = str_word_count($text, 2);
$pos = array_keys($words); $pos = array_keys($words);
if (isset($pos[$limit])) { if (isset($pos[$limit])) {
$text = substr($text, 0, $pos[$limit]) . $ends; $text = substr($text, 0, $pos[$limit]) . $ends;
} }
} }
return $text; return $text;
} }
} }
class NumberFilters extends FilterCollection { class NumberFilters extends FilterCollection {
static function filesize ($bytes, $round = 1) { static function filesize ($bytes, $round = 1) {
if ($bytes === 0) if ($bytes === 0)
return '0 bytes'; return '0 bytes';
elseif ($bytes === 1) elseif ($bytes === 1)
return '1 byte'; return '1 byte';
$units = array( $units = array(
'bytes' => pow(2, 0), 'kB' => pow(2, 10), 'bytes' => pow(2, 0), 'kB' => pow(2, 10),
'BM' => pow(2, 20), 'GB' => pow(2, 30), 'BM' => pow(2, 20), 'GB' => pow(2, 30),
'TB' => pow(2, 40), 'PB' => pow(2, 50), 'TB' => pow(2, 40), 'PB' => pow(2, 50),
'EB' => pow(2, 60), 'ZB' => pow(2, 70) 'EB' => pow(2, 60), 'ZB' => pow(2, 70)
); );
$lastUnit = 'bytes'; $lastUnit = 'bytes';
foreach ($units as $unitName => $unitFactor) { foreach ($units as $unitName => $unitFactor) {
if ($bytes >= $unitFactor) { if ($bytes >= $unitFactor) {
$lastUnit = $unitName; $lastUnit = $unitName;
} else { } else {
$number = round( $bytes / $units[$lastUnit], $round ); $number = round( $bytes / $units[$lastUnit], $round );
return number_format($number) . ' ' . $lastUnit; return number_format($number) . ' ' . $lastUnit;
} }
} }
} }
static function currency($amount, $currency = 'USD', $precision = 2, $negateWithParentheses = false) { static function currency($amount, $currency = 'USD', $precision = 2, $negateWithParentheses = false) {
$definition = array( $definition = array(
'EUR' => array('<27>','.',','), 'GBP' => '<27>', 'JPY' => '<27>', 'EUR' => array('<27>','.',','), 'GBP' => '<27>', 'JPY' => '<27>',
'USD'=>'$', 'AU' => '$', 'CAN' => '$' 'USD'=>'$', 'AU' => '$', 'CAN' => '$'
); );
$negative = false; $negative = false;
$separator = ','; $separator = ',';
$decimals = '.'; $decimals = '.';
$currency = strtoupper($currency); $currency = strtoupper($currency);
// Is negative // Is negative
if (strpos('-', $amount) !== false) { if (strpos('-', $amount) !== false) {
$negative = true; $negative = true;
$amount = str_replace("-","",$amount); $amount = str_replace("-","",$amount);
} }
$amount = (float) $amount; $amount = (float) $amount;
if (!$negative) { if (!$negative) {
$negative = $amount < 0; $negative = $amount < 0;
} }
if ($negateWithParentheses) { if ($negateWithParentheses) {
$amount = abs($amount); $amount = abs($amount);
} }
// Get rid of negative zero // Get rid of negative zero
$zero = round(0, $precision); $zero = round(0, $precision);
if (round($amount, $precision) === $zero) { if (round($amount, $precision) === $zero) {
$amount = $zero; $amount = $zero;
} }
if (isset($definition[$currency])) { if (isset($definition[$currency])) {
$symbol = $definition[$currency]; $symbol = $definition[$currency];
if (is_array($symbol)) if (is_array($symbol))
@list($symbol, $separator, $decimals) = $symbol; @list($symbol, $separator, $decimals) = $symbol;
} else { } else {
$symbol = $currency; $symbol = $currency;
} }
$amount = number_format($amount, $precision, $decimals, $separator); $amount = number_format($amount, $precision, $decimals, $separator);
return $negateWithParentheses ? "({$symbol}{$amount})" : "{$symbol}{$amount}"; return $negateWithParentheses ? "({$symbol}{$amount})" : "{$symbol}{$amount}";
} }
} }
class HtmlFilters extends FilterCollection { class HtmlFilters extends FilterCollection {
static function base_url($url, $options = array()) { static function base_url($url, $options = array()) {
return $url; return $url;
} }
static function asset_url($url, $options = array()) { static function asset_url($url, $options = array()) {
return self::base_url($url, $options); return self::base_url($url, $options);
} }
static function image_tag($url, $options = array()) { static function image_tag($url, $options = array()) {
$attr = self::htmlAttribute(array('alt','width','height','border'), $options); $attr = self::htmlAttribute(array('alt','width','height','border'), $options);
return sprintf('<img src="%s" %s/>', $url, $attr); return sprintf('<img src="%s" %s/>', $url, $attr);
} }
static function css_tag($url, $options = array()) { static function css_tag($url, $options = array()) {
$attr = self::htmlAttribute(array('media'), $options); $attr = self::htmlAttribute(array('media'), $options);
return sprintf('<link rel="stylesheet" href="%s" type="text/css" %s />', $url, $attr); return sprintf('<link rel="stylesheet" href="%s" type="text/css" %s />', $url, $attr);
} }
static function script_tag($url, $options = array()) { static function script_tag($url, $options = array()) {
return sprintf('<script src="%s" type="text/javascript"></script>', $url); return sprintf('<script src="%s" type="text/javascript"></script>', $url);
} }
static function links_to($text, $url, $options = array()) { static function links_to($text, $url, $options = array()) {
$attrs = self::htmlAttribute(array('ref'), $options); $attrs = self::htmlAttribute(array('ref'), $options);
$url = self::base_url($url, $options); $url = self::base_url($url, $options);
return sprintf('<a href="%s" %s>%s</a>', $url, $attrs, $text); return sprintf('<a href="%s" %s>%s</a>', $url, $attrs, $text);
} }
static function links_with ($url, $text, $options = array()) { static function links_with ($url, $text, $options = array()) {
return self::links_to($text, $url, $options); return self::links_to($text, $url, $options);
} }
static function strip_tags($text) { static function strip_tags($text) {
$text = preg_replace(array('/</', '/>/'), array(' <', '> '),$text); $text = preg_replace(array('/</', '/>/'), array(' <', '> '),$text);
return strip_tags($text); return strip_tags($text);
} }
static function linebreaks($value, $format = 'p') { static function linebreaks($value, $format = 'p') {
if ($format === 'br') if ($format === 'br')
return HtmlFilters::nl2br($value); return HtmlFilters::nl2br($value);
return HtmlFilters::nl2pbr($value); return HtmlFilters::nl2pbr($value);
} }
static function nl2br($value) { static function nl2br($value) {
return str_replace("\n", "<br />\n", $value); return str_replace("\n", "<br />\n", $value);
} }
static function nl2pbr($value) { static function nl2pbr($value) {
$result = array(); $result = array();
$parts = preg_split('/(\r?\n){2,}/m', $value); $parts = preg_split('/(\r?\n){2,}/m', $value);
foreach ($parts as $part) { foreach ($parts as $part) {
array_push($result, '<p>' . HtmlFilters::nl2br($part) . '</p>'); array_push($result, '<p>' . HtmlFilters::nl2br($part) . '</p>');
} }
return implode("\n", $result); return implode("\n", $result);
} }
protected static function htmlAttribute($attrs = array(), $data = array()) { protected static function htmlAttribute($attrs = array(), $data = array()) {
$attrs = self::extract(array_merge(array('id', 'class', 'title', "style"), $attrs), $data); $attrs = self::extract(array_merge(array('id', 'class', 'title', "style"), $attrs), $data);
$result = array(); $result = array();
foreach ($attrs as $name => $value) { foreach ($attrs as $name => $value) {
$result[] = "{$name}=\"{$value}\""; $result[] = "{$name}=\"{$value}\"";
} }
return join(' ', $result); return join(' ', $result);
} }
protected static function extract($attrs = array(), $data=array()) { protected static function extract($attrs = array(), $data=array()) {
$result = array(); $result = array();
if (empty($data)) return array(); if (empty($data)) return array();
foreach($data as $k => $e) { foreach($data as $k => $e) {
if (in_array($k, $attrs)) $result[$k] = $e; if (in_array($k, $attrs)) $result[$k] = $e;
} }
return $result; return $result;
} }
} }
class DatetimeFilters extends FilterCollection { class DatetimeFilters extends FilterCollection {
static function date($time, $format = 'jS F Y H:i') { static function date($time, $format = 'jS F Y H:i') {
if ($time instanceof DateTime) if ($time instanceof DateTime)
$time = (int) $time->format('U'); $time = (int) $time->format('U');
if (!is_numeric($time)) if (!is_numeric($time))
$time = strtotime($time); $time = strtotime($time);
return date($format, $time); return date($format, $time);
} }
static function relative_time($timestamp, $format = 'g:iA') { static function relative_time($timestamp, $format = 'g:iA') {
if ($timestamp instanceof DateTime) if ($timestamp instanceof DateTime)
$timestamp = (int) $timestamp->format('U'); $timestamp = (int) $timestamp->format('U');
$timestamp = is_numeric($timestamp) ? $timestamp: strtotime($timestamp); $timestamp = is_numeric($timestamp) ? $timestamp: strtotime($timestamp);
$time = mktime(0, 0, 0); $time = mktime(0, 0, 0);
$delta = time() - $timestamp; $delta = time() - $timestamp;
$string = ''; $string = '';
if ($timestamp < $time - 86400) { if ($timestamp < $time - 86400) {
return date("F j, Y, g:i a", $timestamp); return date("F j, Y, g:i a", $timestamp);
} }
if ($delta > 86400 && $timestamp < $time) { if ($delta > 86400 && $timestamp < $time) {
return "Yesterday at " . date("g:i a", $timestamp); return "Yesterday at " . date("g:i a", $timestamp);
} }
if ($delta > 7200) if ($delta > 7200)
$string .= floor($delta / 3600) . " hours, "; $string .= floor($delta / 3600) . " hours, ";
else if ($delta > 3660) else if ($delta > 3660)
$string .= "1 hour, "; $string .= "1 hour, ";
else if ($delta >= 3600) else if ($delta >= 3600)
$string .= "1 hour "; $string .= "1 hour ";
$delta %= 3600; $delta %= 3600;
if ($delta > 60) if ($delta > 60)
$string .= floor($delta / 60) . " minutes "; $string .= floor($delta / 60) . " minutes ";
else else
$string .= $delta . " seconds "; $string .= $delta . " seconds ";
return "$string ago"; return "$string ago";
} }
static function relative_date($time) { static function relative_date($time) {
if ($time instanceof DateTime) if ($time instanceof DateTime)
$time = (int) $time->format('U'); $time = (int) $time->format('U');
$time = is_numeric($time) ? $time: strtotime($time); $time = is_numeric($time) ? $time: strtotime($time);
$today = strtotime(date('M j, Y')); $today = strtotime(date('M j, Y'));
$reldays = ($time - $today)/86400; $reldays = ($time - $today)/86400;
if ($reldays >= 0 && $reldays < 1) if ($reldays >= 0 && $reldays < 1)
return 'today'; return 'today';
else if ($reldays >= 1 && $reldays < 2) else if ($reldays >= 1 && $reldays < 2)
return 'tomorrow'; return 'tomorrow';
else if ($reldays >= -1 && $reldays < 0) else if ($reldays >= -1 && $reldays < 0)
return 'yesterday'; return 'yesterday';
if (abs($reldays) < 7) { if (abs($reldays) < 7) {
if ($reldays > 0) { if ($reldays > 0) {
$reldays = floor($reldays); $reldays = floor($reldays);
return 'in ' . $reldays . ' day' . ($reldays != 1 ? 's' : ''); return 'in ' . $reldays . ' day' . ($reldays != 1 ? 's' : '');
} else { } else {
$reldays = abs(floor($reldays)); $reldays = abs(floor($reldays));
return $reldays . ' day' . ($reldays != 1 ? 's' : '') . ' ago'; return $reldays . ' day' . ($reldays != 1 ? 's' : '') . ' ago';
} }
} }
if (abs($reldays) < 182) if (abs($reldays) < 182)
return date('l, F j',$time ? $time : time()); return date('l, F j',$time ? $time : time());
else else
return date('l, F j, Y',$time ? $time : time()); return date('l, F j, Y',$time ? $time : time());
} }
static function relative_datetime($time) { static function relative_datetime($time) {
$date = self::relative_date($time); $date = self::relative_date($time);
if ($date === 'today') if ($date === 'today')
return self::relative_time($time); return self::relative_time($time);
return $date; return $date;
} }
} }
/* Ultizie php funciton as Filters */ /* Ultizie php funciton as Filters */
h2o::addFilter(array('md5', 'sha1', 'numberformat'=>'number_format', 'wordwrap', 'trim', 'upper' => 'strtoupper', 'lower' => 'strtolower')); h2o::addFilter(array('md5', 'sha1', 'numberformat'=>'number_format', 'wordwrap', 'trim', 'upper' => 'strtoupper', 'lower' => 'strtolower'));
/* Add filter collections */ /* Add filter collections */
h2o::addFilter(array('CoreFilters', 'StringFilters', 'NumberFilters', 'DatetimeFilters', 'HtmlFilters')); h2o::addFilter(array('CoreFilters', 'StringFilters', 'NumberFilters', 'DatetimeFilters', 'HtmlFilters'));
/* Alias default to set_default */ /* Alias default to set_default */
h2o::addFilter('default', array('CoreFilters', 'set_default')); h2o::addFilter('default', array('CoreFilters', 'set_default'));
?> ?>

View File

@ -1,290 +1,290 @@
<?php <?php
/** /**
* *
* @author taylor.luk * @author taylor.luk
* @todo FileLoader need more test coverage * @todo FileLoader need more test coverage
*/ */
class H2o_Loader { class H2o_Loader {
public $parser; public $parser;
public $runtime; public $runtime;
public $cached = false; public $cached = false;
protected $cache = false; protected $cache = false;
public $searchpath = false; public $searchpath = false;
function read($filename) {} function read($filename) {}
function cache_read($file, $object, $ttl = 3600) {} function cache_read($file, $object, $ttl = 3600) {}
} }
class H2o_File_Loader extends H2o_Loader { class H2o_File_Loader extends H2o_Loader {
function __construct($searchpath, $options = array()) { function __construct($searchpath, $options = array()) {
// if (is_file($searchpath)) { // if (is_file($searchpath)) {
// $searthpath = dirname($searchpath).DS; // $searthpath = dirname($searchpath).DS;
// } // }
// if (!is_dir($searchpath)) // if (!is_dir($searchpath))
// throw new TemplateNotFound($filename); // throw new TemplateNotFound($filename);
// //
if (!is_array($searchpath)) if (!is_array($searchpath))
throw new Exception("searchpath must be an array"); throw new Exception("searchpath must be an array");
$this->searchpath = (array) $searchpath; $this->searchpath = (array) $searchpath;
$this->setOptions($options); $this->setOptions($options);
} }
function setOptions($options = array()) { function setOptions($options = array()) {
if (isset($options['cache']) && $options['cache']) { if (isset($options['cache']) && $options['cache']) {
$this->cache = h2o_cache($options); $this->cache = h2o_cache($options);
} }
} }
function read($filename) { function read($filename) {
if (!is_file($filename)) if (!is_file($filename))
$filename = $this->get_template_path($this->searchpath,$filename); $filename = $this->get_template_path($this->searchpath,$filename);
if (is_file($filename)) { if (is_file($filename)) {
$source = file_get_contents($filename); $source = file_get_contents($filename);
return $this->runtime->parse($source); return $this->runtime->parse($source);
} else { } else {
throw new TemplateNotFound($filename); throw new TemplateNotFound($filename);
} }
} }
function get_template_path($search_path, $filename){ function get_template_path($search_path, $filename){
for ($i=0 ; $i < count($search_path) ; $i++) for ($i=0 ; $i < count($search_path) ; $i++)
{ {
if(file_exists($search_path[$i] . $filename)) { if(file_exists($search_path[$i] . $filename)) {
$filename = $search_path[$i] . $filename; $filename = $search_path[$i] . $filename;
return $filename; return $filename;
break; break;
} else { } else {
continue; continue;
} }
} }
throw new Exception('TemplateNotFound - Looked for template: ' . $filename); throw new Exception('TemplateNotFound - Looked for template: ' . $filename);
} }
function read_cache($filename) { function read_cache($filename) {
if (!$this->cache){ if (!$this->cache){
$filename = $this->get_template_path($this->searchpath,$filename); $filename = $this->get_template_path($this->searchpath,$filename);
return $this->read($filename); return $this->read($filename);
} }
if (!is_file($filename)){ if (!is_file($filename)){
$filename = $this->get_template_path($this->searchpath,$filename); $filename = $this->get_template_path($this->searchpath,$filename);
} }
$filename = realpath($filename); $filename = realpath($filename);
$cache = md5($filename); $cache = md5($filename);
$object = $this->cache->read($cache); $object = $this->cache->read($cache);
$this->cached = $object && !$this->expired($object); $this->cached = $object && !$this->expired($object);
if (!$this->cached) { if (!$this->cached) {
$nodelist = $this->read($filename); $nodelist = $this->read($filename);
$object = (object) array( $object = (object) array(
'filename' => $filename, 'filename' => $filename,
'content' => serialize($nodelist), 'content' => serialize($nodelist),
'created' => time(), 'created' => time(),
'templates' => $nodelist->parser->storage['templates'], 'templates' => $nodelist->parser->storage['templates'],
'included' => $nodelist->parser->storage['included'] + array_values(h2o::$extensions) 'included' => $nodelist->parser->storage['included'] + array_values(h2o::$extensions)
); );
$this->cache->write($cache, $object); $this->cache->write($cache, $object);
} else { } else {
foreach($object->included as $ext => $file) { foreach($object->included as $ext => $file) {
include_once (h2o::$extensions[$ext] = $file); include_once (h2o::$extensions[$ext] = $file);
} }
} }
return unserialize($object->content); return unserialize($object->content);
} }
function flush_cache() { function flush_cache() {
$this->cache->flush(); $this->cache->flush();
} }
function expired($object) { function expired($object) {
if (!$object) return false; if (!$object) return false;
$files = array_merge(array($object->filename), $object->templates); $files = array_merge(array($object->filename), $object->templates);
foreach ($files as $file) { foreach ($files as $file) {
if (!is_file($file)) if (!is_file($file))
$file = $this->get_template_path($this->searchpath, $file); $file = $this->get_template_path($this->searchpath, $file);
if ($object->created < filemtime($file)) if ($object->created < filemtime($file))
return true; return true;
} }
return false; return false;
} }
} }
function file_loader($file) { function file_loader($file) {
return new H2o_File_Loader($file); return new H2o_File_Loader($file);
} }
class H2o_Hash_Loader { class H2o_Hash_Loader {
function __construct($scope, $options = array()) { function __construct($scope, $options = array()) {
$this->scope = $scope; $this->scope = $scope;
} }
function setOptions() {} function setOptions() {}
function read($file) { function read($file) {
if (!isset($this->scope[$file])) if (!isset($this->scope[$file]))
throw new TemplateNotFound; throw new TemplateNotFound;
return $this->runtime->parse($this->scope[$file], $file); return $this->runtime->parse($this->scope[$file], $file);
} }
function read_cache($file) { function read_cache($file) {
return $this->read($file); return $this->read($file);
} }
} }
function hash_loader($hash = array()) { function hash_loader($hash = array()) {
return new H2o_Hash_Loader($hash); return new H2o_Hash_Loader($hash);
} }
/** /**
* Cache subsystem * Cache subsystem
* *
*/ */
function h2o_cache($options = array()) { function h2o_cache($options = array()) {
$type = $options['cache']; $type = $options['cache'];
$className = "H2o_".ucwords($type)."_Cache"; $className = "H2o_".ucwords($type)."_Cache";
if (class_exists($className, false)) { if (class_exists($className, false)) {
return new $className($options); return new $className($options);
} }
return false; return false;
} }
class H2o_File_Cache { class H2o_File_Cache {
var $ttl = 3600; var $ttl = 3600;
var $prefix = 'h2o_'; var $prefix = 'h2o_';
function __construct($options = array()) { function __construct($options = array()) {
if (isset($options['cache_dir']) && is_writable($options['cache_dir'])) { if (isset($options['cache_dir']) && is_writable($options['cache_dir'])) {
$path = $options['cache_dir']; $path = $options['cache_dir'];
} else { } else {
$path = dirname($tmp = tempnam(uniqid(rand(), true), '')); $path = dirname($tmp = tempnam(uniqid(rand(), true), ''));
if (file_exists($tmp)) unlink($tmp); if (file_exists($tmp)) unlink($tmp);
} }
if (isset($options['cache_ttl'])) { if (isset($options['cache_ttl'])) {
$this->ttl = $options['cache_ttl']; $this->ttl = $options['cache_ttl'];
} }
if(isset($options['cache_prefix'])) { if(isset($options['cache_prefix'])) {
$this->prefix = $options['cache_prefix']; $this->prefix = $options['cache_prefix'];
} }
$this->path = realpath($path). DS; $this->path = realpath($path). DS;
} }
function read($filename) { function read($filename) {
if (!file_exists($this->path . $this->prefix. $filename)) if (!file_exists($this->path . $this->prefix. $filename))
return false; return false;
$content = file_get_contents($this->path . $this->prefix. $filename); $content = file_get_contents($this->path . $this->prefix. $filename);
$expires = (int)substr($content, 0, 10); $expires = (int)substr($content, 0, 10);
if (time() >= $expires) if (time() >= $expires)
return false; return false;
return unserialize(trim(substr($content, 10))); return unserialize(trim(substr($content, 10)));
} }
function write($filename, &$object) { function write($filename, &$object) {
$expires = time() + $this->ttl; $expires = time() + $this->ttl;
$content = $expires . serialize($object); $content = $expires . serialize($object);
return file_put_contents($this->path . $this->prefix. $filename, $content); return file_put_contents($this->path . $this->prefix. $filename, $content);
} }
function flush() { function flush() {
foreach (glob($this->path. $this->prefix. '*') as $file) { foreach (glob($this->path. $this->prefix. '*') as $file) {
@unlink($file); @unlink($file);
} }
} }
} }
class H2o_Apc_Cache { class H2o_Apc_Cache {
var $ttl = 3600; var $ttl = 3600;
var $prefix = 'h2o_'; var $prefix = 'h2o_';
function __construct($options = array()) { function __construct($options = array()) {
if (!function_exists('apc_add')) if (!function_exists('apc_add'))
throw new Exception('APC extension needs to be loaded to use APC cache'); throw new Exception('APC extension needs to be loaded to use APC cache');
if (isset($options['cache_ttl'])) { if (isset($options['cache_ttl'])) {
$this->ttl = $options['cache_ttl']; $this->ttl = $options['cache_ttl'];
} }
if(isset($options['cache_prefix'])) { if(isset($options['cache_prefix'])) {
$this->prefix = $options['cache_prefix']; $this->prefix = $options['cache_prefix'];
} }
} }
function read($filename) { function read($filename) {
return apc_fetch($this->prefix.$filename); return apc_fetch($this->prefix.$filename);
} }
function write($filename, $object) { function write($filename, $object) {
return apc_store($this->prefix.$filename, $object, $this->ttl); return apc_store($this->prefix.$filename, $object, $this->ttl);
} }
function flush() { function flush() {
return apc_clear_cache('user'); return apc_clear_cache('user');
} }
} }
class H2o_Memcache_Cache { class H2o_Memcache_Cache {
var $ttl = 3600; var $ttl = 3600;
var $prefix = 'h2o_'; var $prefix = 'h2o_';
/** /**
* @var host default is file socket * @var host default is file socket
*/ */
var $host = 'unix:///tmp/memcached.sock'; var $host = 'unix:///tmp/memcached.sock';
var $port = 0; var $port = 0;
var $object; var $object;
function __construct( $scope, $options = array() ) { function __construct( $scope, $options = array() ) {
if ( !function_exists( 'memcache_set' ) ) if ( !function_exists( 'memcache_set' ) )
throw new Exception( 'Memcache extension needs to be loaded to use memcache' ); throw new Exception( 'Memcache extension needs to be loaded to use memcache' );
if ( isset( $options['cache_ttl'] ) ) { if ( isset( $options['cache_ttl'] ) ) {
$this->ttl = $options['cache_ttl']; $this->ttl = $options['cache_ttl'];
} }
if( isset( $options['cache_prefix'] ) ) { if( isset( $options['cache_prefix'] ) ) {
$this->prefix = $options['cache_prefix']; $this->prefix = $options['cache_prefix'];
} }
if( isset( $options['host'] ) ) { if( isset( $options['host'] ) ) {
$this->host = $options['host']; $this->host = $options['host'];
} }
if( isset( $options['port'] ) ) { if( isset( $options['port'] ) ) {
$this->port = $options['port']; $this->port = $options['port'];
} }
$this->object = memcache_connect( $this->host, $this->port ); $this->object = memcache_connect( $this->host, $this->port );
} }
function read( $filename ){ function read( $filename ){
return memcache_get( $this->object, $this->prefix.$filename ); return memcache_get( $this->object, $this->prefix.$filename );
} }
function write( $filename, $content ) { function write( $filename, $content ) {
return memcache_set( $this->object,$this->prefix.$filename,$content , MEMCACHE_COMPRESSED,$this->ttl ); return memcache_set( $this->object,$this->prefix.$filename,$content , MEMCACHE_COMPRESSED,$this->ttl );
} }
function flush(){ function flush(){
return memcache_flush( $this->object ); return memcache_flush( $this->object );
} }
} }

View File

@ -1,84 +1,84 @@
<?php <?php
/* /*
Nodes Nodes
*/ */
class H2o_Node { class H2o_Node {
var $position; var $position;
function __construct($argstring) {} function __construct($argstring) {}
function render($context, $stream) {} function render($context, $stream) {}
} }
class NodeList extends H2o_Node implements IteratorAggregate { class NodeList extends H2o_Node implements IteratorAggregate {
var $parser; var $parser;
var $list; var $list;
function __construct(&$parser, $initial = null, $position = 0) { function __construct(&$parser, $initial = null, $position = 0) {
$this->parser = $parser; $this->parser = $parser;
if (is_null($initial)) if (is_null($initial))
$initial = array(); $initial = array();
$this->list = $initial; $this->list = $initial;
$this->position = $position; $this->position = $position;
} }
function render($context, $stream) { function render($context, $stream) {
foreach($this->list as $node) { foreach($this->list as $node) {
$node->render($context, $stream); $node->render($context, $stream);
} }
} }
function append($node) { function append($node) {
array_push($this->list, $node); array_push($this->list, $node);
} }
function extend($nodes) { function extend($nodes) {
array_merge($this->list, $nodes); array_merge($this->list, $nodes);
} }
function getLength() { function getLength() {
return count($this->list); return count($this->list);
} }
function getIterator() { function getIterator() {
return new ArrayIterator( $this->list ); return new ArrayIterator( $this->list );
} }
} }
class VariableNode extends H2o_Node { class VariableNode extends H2o_Node {
private $filters = array(); private $filters = array();
var $variable; var $variable;
function __construct($variable, $filters, $position = 0) { function __construct($variable, $filters, $position = 0) {
if (!empty($filters)) if (!empty($filters))
$this->filters = $filters; $this->filters = $filters;
$this->variable = $variable; $this->variable = $variable;
} }
function render($context, $stream) { function render($context, $stream) {
$value = $context->resolve($this->variable); $value = $context->resolve($this->variable);
$value = $context->escape($value, $this->variable); $value = $context->escape($value, $this->variable);
$stream->write($value); $stream->write($value);
} }
} }
class CommentNode extends H2o_Node {} class CommentNode extends H2o_Node {}
class TextNode extends H2o_Node { class TextNode extends H2o_Node {
var $content; var $content;
function __construct($content, $position = 0) { function __construct($content, $position = 0) {
$this->content = $content; $this->content = $content;
$this->position = $position; $this->position = $position;
} }
function render($context, $stream) { function render($context, $stream) {
$stream->write($this->content); $stream->write($this->content);
} }
function is_blank() { function is_blank() {
return strlen(trim($this->content)); return strlen(trim($this->content));
} }
} }
?> ?>

View File

@ -1,290 +1,290 @@
<?php <?php
class H2o_Lexer { class H2o_Lexer {
function __construct($options = array()) { function __construct($options = array()) {
$this->options = $options; $this->options = $options;
$trim = ''; $trim = '';
if ($this->options['TRIM_TAGS']) if ($this->options['TRIM_TAGS'])
$trim = '(?:\r?\n)?'; $trim = '(?:\r?\n)?';
$this->pattern = ('/\G(.*?)(?:' . $this->pattern = ('/\G(.*?)(?:' .
preg_quote($this->options['BLOCK_START']). '(.*?)' .preg_quote($this->options['BLOCK_END']) . $trim . '|' . preg_quote($this->options['BLOCK_START']). '(.*?)' .preg_quote($this->options['BLOCK_END']) . $trim . '|' .
preg_quote($this->options['VARIABLE_START']). '(.*?)' .preg_quote($this->options['VARIABLE_END']) . '|' . preg_quote($this->options['VARIABLE_START']). '(.*?)' .preg_quote($this->options['VARIABLE_END']) . '|' .
preg_quote($this->options['COMMENT_START']). '(.*?)' .preg_quote($this->options['COMMENT_END']) . $trim . ')/sm' preg_quote($this->options['COMMENT_START']). '(.*?)' .preg_quote($this->options['COMMENT_END']) . $trim . ')/sm'
); );
} }
function tokenize($source) { function tokenize($source) {
$result = new TokenStream; $result = new TokenStream;
$pos = 0; $pos = 0;
$matches = array(); $matches = array();
preg_match_all($this->pattern, $source, $matches, PREG_SET_ORDER); preg_match_all($this->pattern, $source, $matches, PREG_SET_ORDER);
foreach ($matches as $match) { foreach ($matches as $match) {
if ($match[1]) if ($match[1])
$result->feed('text', $match[1], $pos); $result->feed('text', $match[1], $pos);
$tagpos = $pos + strlen($match[1]); $tagpos = $pos + strlen($match[1]);
if ($match[2]) if ($match[2])
$result->feed('block', trim($match[2]), $tagpos); $result->feed('block', trim($match[2]), $tagpos);
elseif ($match[3]) elseif ($match[3])
$result->feed('variable', trim($match[3]), $tagpos); $result->feed('variable', trim($match[3]), $tagpos);
elseif ($match[4]) elseif ($match[4])
$result->feed('comment', trim($match[4]), $tagpos); $result->feed('comment', trim($match[4]), $tagpos);
$pos += strlen($match[0]); $pos += strlen($match[0]);
} }
if ($pos < strlen($source)){ if ($pos < strlen($source)){
$result->feed('text', substr($source, $pos), $pos); $result->feed('text', substr($source, $pos), $pos);
} }
$result->close(); $result->close();
return $result; return $result;
} }
} }
class H2o_Parser { class H2o_Parser {
var $first; var $first;
var $storage = array(); var $storage = array();
var $filename; var $filename;
var $runtime; var $runtime;
function __construct($source, $filename, $runtime, $options) { function __construct($source, $filename, $runtime, $options) {
$this->options = $options; $this->options = $options;
//$this->source = $source; //$this->source = $source;
$this->runtime = $runtime; $this->runtime = $runtime;
$this->filename = $filename; $this->filename = $filename;
$this->first = true; $this->first = true;
$this->lexer = new H2o_Lexer($options); $this->lexer = new H2o_Lexer($options);
$this->tokenstream = $this->lexer->tokenize($source); $this->tokenstream = $this->lexer->tokenize($source);
$this->storage = array( $this->storage = array(
'blocks' => array(), 'blocks' => array(),
'templates' => array(), 'templates' => array(),
'included' => array() 'included' => array()
); );
} }
function &parse() { function &parse() {
$until = func_get_args(); $until = func_get_args();
$nodelist = new NodeList($this); $nodelist = new NodeList($this);
while($token = $this->tokenstream->next()) { while($token = $this->tokenstream->next()) {
//$token = $this->tokenstream->current(); //$token = $this->tokenstream->current();
switch($token->type) { switch($token->type) {
case 'text' : case 'text' :
$node = new TextNode($token->content, $token->position); $node = new TextNode($token->content, $token->position);
break; break;
case 'variable' : case 'variable' :
$args = H2o_Parser::parseArguments($token->content, $token->position); $args = H2o_Parser::parseArguments($token->content, $token->position);
$variable = array_shift($args); $variable = array_shift($args);
$filters = $args; $filters = $args;
$node = new VariableNode($variable, $filters, $token->position); $node = new VariableNode($variable, $filters, $token->position);
break; break;
case 'comment' : case 'comment' :
$node = new CommentNode($token->content); $node = new CommentNode($token->content);
break; break;
case 'block' : case 'block' :
if (in_array($token->content, $until)) { if (in_array($token->content, $until)) {
$this->token = $token; $this->token = $token;
return $nodelist; return $nodelist;
} }
$temp = preg_split('/\s+/',$token->content, 2); $temp = preg_split('/\s+/',$token->content, 2);
$name = $temp[0]; $name = $temp[0];
$args = (count($temp) > 1 ? $temp[1] : null); $args = (count($temp) > 1 ? $temp[1] : null);
$node = H2o::createTag($name, $args, $this, $token->position); $node = H2o::createTag($name, $args, $this, $token->position);
$this->token = $token; $this->token = $token;
} }
$this->searching = join(',',$until); $this->searching = join(',',$until);
$this->first = false; $this->first = false;
$nodelist->append($node); $nodelist->append($node);
} }
if ($until) { if ($until) {
throw new TemplateSyntaxError('Unclose tag, expecting '. $until[0]); throw new TemplateSyntaxError('Unclose tag, expecting '. $until[0]);
} }
return $nodelist; return $nodelist;
} }
function skipTo($until) { function skipTo($until) {
$this->parse($until); $this->parse($until);
return null; return null;
} }
# Parse arguments # Parse arguments
static function parseArguments($source = null, $fpos = 0){ static function parseArguments($source = null, $fpos = 0){
$parser = new ArgumentLexer($source, $fpos); $parser = new ArgumentLexer($source, $fpos);
$result = array(); $result = array();
$current_buffer = &$result; $current_buffer = &$result;
$filter_buffer = array(); $filter_buffer = array();
$tokens = $parser->parse(); $tokens = $parser->parse();
foreach ($tokens as $token) { foreach ($tokens as $token) {
list($token, $data) = $token; list($token, $data) = $token;
if ($token == 'filter_start') { if ($token == 'filter_start') {
$filter_buffer = array(); $filter_buffer = array();
$current_buffer = &$filter_buffer; $current_buffer = &$filter_buffer;
} }
elseif ($token == 'filter_end') { elseif ($token == 'filter_end') {
if (count($filter_buffer)) { if (count($filter_buffer)) {
$i = count($result)-1; $i = count($result)-1;
if ( is_array($result[$i]) ) $result[$i]['filters'][] = $filter_buffer; if ( is_array($result[$i]) ) $result[$i]['filters'][] = $filter_buffer;
else $result[$i] = array(0 => $result[$i], 'filters' => array($filter_buffer)); else $result[$i] = array(0 => $result[$i], 'filters' => array($filter_buffer));
} }
$current_buffer = &$result; $current_buffer = &$result;
} }
elseif ($token == 'boolean') { elseif ($token == 'boolean') {
$current_buffer[] = ($data === 'true'? true : false); $current_buffer[] = ($data === 'true'? true : false);
} }
elseif ($token == 'name') { elseif ($token == 'name') {
$current_buffer[] = symbol($data); $current_buffer[] = symbol($data);
} }
elseif ($token == 'number' || $token == 'string') { elseif ($token == 'number' || $token == 'string') {
$current_buffer[] = $data; $current_buffer[] = $data;
} }
elseif ($token == 'named_argument') { elseif ($token == 'named_argument') {
$last = $current_buffer[count($current_buffer) - 1]; $last = $current_buffer[count($current_buffer) - 1];
if (!is_array($last)) if (!is_array($last))
$current_buffer[] = array(); $current_buffer[] = array();
$namedArgs =& $current_buffer[count($current_buffer) - 1]; $namedArgs =& $current_buffer[count($current_buffer) - 1];
list($name,$value) = array_map('trim', explode(':', $data, 2)); list($name,$value) = array_map('trim', explode(':', $data, 2));
# if argument value is variable mark it # if argument value is variable mark it
$value = self::parseArguments($value); $value = self::parseArguments($value);
$namedArgs[$name] = $value[0]; $namedArgs[$name] = $value[0];
} }
elseif( $token == 'operator') { elseif( $token == 'operator') {
$current_buffer[] = array('operator'=>$data); $current_buffer[] = array('operator'=>$data);
} }
} }
return $result; return $result;
} }
} }
class H2O_RE { class H2O_RE {
static $whitespace, $seperator, $parentheses, $pipe, $filter_end, $operator, $boolean, $number, $string, $i18n_string, $name, $named_args; static $whitespace, $seperator, $parentheses, $pipe, $filter_end, $operator, $boolean, $number, $string, $i18n_string, $name, $named_args;
static function init() { static function init() {
$r = 'strip_regex'; $r = 'strip_regex';
self::$whitespace = '/\s+/m'; self::$whitespace = '/\s+/m';
self::$parentheses = '/\(|\)/m'; self::$parentheses = '/\(|\)/m';
self::$filter_end = '/;/'; self::$filter_end = '/;/';
self::$boolean = '/true|false/'; self::$boolean = '/true|false/';
self::$seperator = '/,/'; self::$seperator = '/,/';
self::$pipe = '/\|/'; self::$pipe = '/\|/';
self::$operator = '/\s?(>|<|>=|<=|!=|==|!|and |not |or )\s?/i'; self::$operator = '/\s?(>|<|>=|<=|!=|==|!|and |not |or )\s?/i';
self::$number = '/\d+(\.\d*)?/'; self::$number = '/\d+(\.\d*)?/';
self::$name = '/[a-zA-Z][a-zA-Z0-9-_]*(?:\.[a-zA-Z_0-9][a-zA-Z0-9_-]*)*/'; self::$name = '/[a-zA-Z][a-zA-Z0-9-_]*(?:\.[a-zA-Z_0-9][a-zA-Z0-9_-]*)*/';
self::$string = '/(?: self::$string = '/(?:
"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)" | # Double Quote string "([^"\\\\]*(?:\\\\.[^"\\\\]*)*)" | # Double Quote string
\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\' # Single Quote String \'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\' # Single Quote String
)/xsm'; )/xsm';
self::$i18n_string = "/_\({$r(self::$string)}\) | {$r(self::$string)}/xsm"; self::$i18n_string = "/_\({$r(self::$string)}\) | {$r(self::$string)}/xsm";
self::$named_args = "{ self::$named_args = "{
({$r(self::$name)})(?:{$r(self::$whitespace)})? ({$r(self::$name)})(?:{$r(self::$whitespace)})?
: :
(?:{$r(self::$whitespace)})?({$r(self::$i18n_string)}|{$r(self::$number)}|{$r(self::$name)}) (?:{$r(self::$whitespace)})?({$r(self::$i18n_string)}|{$r(self::$number)}|{$r(self::$name)})
}x"; }x";
} }
} }
H2O_RE::init(); H2O_RE::init();
class ArgumentLexer { class ArgumentLexer {
private $source; private $source;
private $match; private $match;
private $pos = 0, $fpos, $eos; private $pos = 0, $fpos, $eos;
private $operator_map = array( private $operator_map = array(
'!' => 'not', '!='=> 'ne', '==' => 'eq', '>' => 'gt', '<' => 'lt', '<=' => 'le', '>=' => 'ge' '!' => 'not', '!='=> 'ne', '==' => 'eq', '>' => 'gt', '<' => 'lt', '<=' => 'le', '>=' => 'ge'
); );
function __construct($source, $fpos = 0){ function __construct($source, $fpos = 0){
if (!is_null($source)) if (!is_null($source))
$this->source = $source; $this->source = $source;
$this->fpos=$fpos; $this->fpos=$fpos;
} }
function parse(){ function parse(){
$result = array(); $result = array();
$filtering = false; $filtering = false;
while (!$this->eos()) { while (!$this->eos()) {
$this->scan(H2O_RE::$whitespace); $this->scan(H2O_RE::$whitespace);
if (!$filtering) { if (!$filtering) {
if ($this->scan(H2O_RE::$operator)){ if ($this->scan(H2O_RE::$operator)){
$operator = trim($this->match); $operator = trim($this->match);
if(isset($this->operator_map[$operator])) if(isset($this->operator_map[$operator]))
$operator = $this->operator_map[$operator]; $operator = $this->operator_map[$operator];
$result[] = array('operator', $operator); $result[] = array('operator', $operator);
} }
elseif ($this->scan(H2O_RE::$boolean)) elseif ($this->scan(H2O_RE::$boolean))
$result[] = array('boolean', $this->match); $result[] = array('boolean', $this->match);
elseif ($this->scan(H2O_RE::$named_args)) elseif ($this->scan(H2O_RE::$named_args))
$result[] = array('named_argument', $this->match); $result[] = array('named_argument', $this->match);
elseif ($this->scan(H2O_RE::$name)) elseif ($this->scan(H2O_RE::$name))
$result[] = array('name', $this->match); $result[] = array('name', $this->match);
elseif ($this->scan(H2O_RE::$pipe)) { elseif ($this->scan(H2O_RE::$pipe)) {
$filtering = true; $filtering = true;
$result[] = array('filter_start', $this->match); $result[] = array('filter_start', $this->match);
} }
elseif ($this->scan(H2O_RE::$seperator)) elseif ($this->scan(H2O_RE::$seperator))
$result[] = array('separator', null); $result[] = array('separator', null);
elseif ($this->scan(H2O_RE::$i18n_string)) elseif ($this->scan(H2O_RE::$i18n_string))
$result[] = array('string', $this->match); $result[] = array('string', $this->match);
elseif ($this->scan(H2O_RE::$number)) elseif ($this->scan(H2O_RE::$number))
$result[] = array('number', $this->match); $result[] = array('number', $this->match);
else else
throw new TemplateSyntaxError('unexpected character in filters : "'. $this->source[$this->pos]. '" at '.$this->getPosition()); throw new TemplateSyntaxError('unexpected character in filters : "'. $this->source[$this->pos]. '" at '.$this->getPosition());
} }
else { else {
// parse filters, with chaining and ";" as filter end character // parse filters, with chaining and ";" as filter end character
if ($this->scan(H2O_RE::$pipe)) { if ($this->scan(H2O_RE::$pipe)) {
$result[] = array('filter_end', null); $result[] = array('filter_end', null);
$result[] = array('filter_start', null); $result[] = array('filter_start', null);
} }
elseif ($this->scan(H2O_RE::$seperator)) elseif ($this->scan(H2O_RE::$seperator))
$result[] = array('separator', null); $result[] = array('separator', null);
elseif ($this->scan(H2O_RE::$filter_end)) { elseif ($this->scan(H2O_RE::$filter_end)) {
$result[] = array('filter_end', null); $result[] = array('filter_end', null);
$filtering = false; $filtering = false;
} }
elseif ($this->scan(H2O_RE::$boolean)) elseif ($this->scan(H2O_RE::$boolean))
$result[] = array('boolean', $this->match); $result[] = array('boolean', $this->match);
elseif ($this->scan(H2O_RE::$named_args)) elseif ($this->scan(H2O_RE::$named_args))
$result[] = array('named_argument', $this->match); $result[] = array('named_argument', $this->match);
elseif ($this->scan(H2O_RE::$name)) elseif ($this->scan(H2O_RE::$name))
$result[] = array('name', $this->match); $result[] = array('name', $this->match);
elseif ($this->scan(H2O_RE::$i18n_string)) elseif ($this->scan(H2O_RE::$i18n_string))
$result[] = array('string', $this->match); $result[] = array('string', $this->match);
elseif ($this->scan(H2O_RE::$number)) elseif ($this->scan(H2O_RE::$number))
$result[] = array('number', $this->match); $result[] = array('number', $this->match);
else else
throw new TemplateSyntaxError('unexpected character in filters : "'. $this->source[$this->pos]. '" at '.$this->getPosition()); throw new TemplateSyntaxError('unexpected character in filters : "'. $this->source[$this->pos]. '" at '.$this->getPosition());
} }
} }
// if we are still in the filter state, we add a filter_end token. // if we are still in the filter state, we add a filter_end token.
if ($filtering) if ($filtering)
$result[] = array('filter_end', null); $result[] = array('filter_end', null);
return $result; return $result;
} }
# String scanner # String scanner
function scan($regexp) { function scan($regexp) {
if (preg_match($regexp . 'A', $this->source, $match, null, $this->pos)) { if (preg_match($regexp . 'A', $this->source, $match, null, $this->pos)) {
$this->match = $match[0]; $this->match = $match[0];
$this->pos += strlen($this->match); $this->pos += strlen($this->match);
return true; return true;
} }
return false; return false;
} }
function eos() { function eos() {
return $this->pos >= strlen($this->source); return $this->pos >= strlen($this->source);
} }
/** /**
* return the position in the template * return the position in the template
*/ */
function getPosition() { function getPosition() {
return $this->fpos + $this->pos; return $this->fpos + $this->pos;
} }
} }
?> ?>

17
system/vendor/is_cli.php vendored Normal file
View File

@ -0,0 +1,17 @@
<?php
function is_cli()
{
if( defined('STDIN') )
{
return true;
}
if( empty($_SERVER['REMOTE_ADDR']) and !isset($_SERVER['HTTP_USER_AGENT']) and count($_SERVER['argv']) > 0)
{
return true;
}
return false;
}

View File

@ -1,6 +1,6 @@
<?php <?php
function isvarset(&$var) function isvarset(&$var)
{ {
return (isset($var) && (!empty($var) || is_numeric($var))) ? true : false; return (isset($var) && (!empty($var) || is_numeric($var))) ? true : false;
} }

19
system/vendor/phpoauthlib2/LICENSE vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2015 Nathan Adams <adamsna@datanethost.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

149
system/vendor/phpoauthlib2/ccurl.php vendored Normal file
View File

@ -0,0 +1,149 @@
<?php
namespace phpoauthlib2;
// Copied from PHP manual comment section:
// http://php.net/manual/en/book.curl.php#90821
// Modified to fit Inefero's/srchub needs
// Now used for oauth lib
class ccurl {
protected $_useragent = 'phpoauthlib2 (http://www.srchub.org); https://srchub.org/p/phpoauthlib2 PHPOAuthLib';
protected $_url;
protected $_followlocation;
protected $_timeout;
protected $_maxRedirects;
protected $_cookieFileLocation = './cookie.txt';
protected $_post;
protected $_postFields;
protected $_referer ="";
// Get around some broken webservers *cough*IIS*cough*?
// http://stackoverflow.com/questions/14459704/does-empty-expect-header-mean-anything
protected $_header = array('Expect:');
protected $_session;
protected $_webpage;
protected $_includeHeader;
protected $_noBody;
protected $_status;
protected $_binaryTransfer;
public $authentication = 0;
public $auth_name = '';
public $auth_pass = '';
public function useAuth($use){
$this->authentication = 0;
if($use == true) $this->authentication = 1;
}
public function setName($name){
$this->auth_name = $name;
}
public function setPass($pass){
$this->auth_pass = $pass;
}
public function addHeader($head)
{
$this->_header[] = $head;
}
public function __construct($url,$followlocation = true,$timeOut = 30,$maxRedirecs = 4,$binaryTransfer = false,$includeHeader = false,$noBody = false)
{
$this->_url = $url;
$this->_followlocation = $followlocation;
$this->_timeout = $timeOut;
$this->_maxRedirects = $maxRedirecs;
$this->_noBody = $noBody;
$this->_includeHeader = $includeHeader;
$this->_binaryTransfer = $binaryTransfer;
$this->_cookieFileLocation = dirname(__FILE__).'/cookie.txt';
}
public function setReferer($referer){
$this->_referer = $referer;
}
public function setCookiFileLocation($path)
{
$this->_cookieFileLocation = $path;
}
public function setPost ($postFields)
{
$this->_post = true;
$this->_postFields = $postFields;
}
public function setUserAgent($userAgent)
{
$this->_useragent = $userAgent;
}
public function createCurl($url = 'nul')
{
if($url != 'nul'){
$this->_url = $url;
}
$s = curl_init();
curl_setopt($s,CURLOPT_URL,$this->_url);
// I understand the implications here - but this isn't a client application
// if my ISP is performing MITM sniffing I have bigger fish to fry
// also the security of a CA signed certificate is questionable at best
// https://www.schneier.com/blog/archives/2012/02/verisign_hacked.html
// Email me if you want to discus this adamsna@datanethost.net
// NA - 12/10/2014
curl_setopt($s, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($s,CURLOPT_HTTPHEADER,$this->_header);
curl_setopt($s,CURLOPT_TIMEOUT,$this->_timeout);
curl_setopt($s,CURLOPT_MAXREDIRS,$this->_maxRedirects);
curl_setopt($s,CURLOPT_RETURNTRANSFER,true);
curl_setopt($s,CURLOPT_FOLLOWLOCATION,$this->_followlocation);
curl_setopt($s,CURLOPT_COOKIEJAR,$this->_cookieFileLocation);
curl_setopt($s,CURLOPT_COOKIEFILE,$this->_cookieFileLocation);
if($this->authentication == 1){
curl_setopt($s, CURLOPT_USERPWD, $this->auth_name.':'.$this->auth_pass);
}
if($this->_post)
{
//curl_setopt($s,CURLOPT_POST,true);
curl_setopt($s, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($s,CURLOPT_POSTFIELDS,$this->_postFields);
}
if($this->_includeHeader)
{
curl_setopt($s,CURLOPT_HEADER,true);
}
if($this->_noBody)
{
curl_setopt($s,CURLOPT_NOBODY,true);
}
curl_setopt($s,CURLOPT_USERAGENT,$this->_useragent);
curl_setopt($s,CURLOPT_REFERER,$this->_referer);
$this->_webpage = curl_exec($s);
$this->_status = curl_getinfo($s,CURLINFO_HTTP_CODE);
curl_close($s);
}
public function getHttpStatus()
{
return $this->_status;
}
public function __tostring(){
return $this->_webpage;
}
}

5
system/vendor/phpoauthlib2/cookie.txt vendored Normal file
View File

@ -0,0 +1,5 @@
# Netscape HTTP Cookie File
# http://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_.google.com TRUE / FALSE 1463331114 NID 73=wOGSMwy8vYCu7qJjpMYLVMQ_gYCNZXru2x8g0p5InvQIpj8X4P2uiXE8QdX50ZcpHvxCXo35XdDS8P5trQSsI0s3UmQ-tmG_01TTIVil6YeJIzFKqoGmKAdWo_0o8MOQ

24
system/vendor/phpoauthlib2/example.php vendored Normal file
View File

@ -0,0 +1,24 @@
<?php
use \phpoauthlib2\providers\GoogleAuthProvider;
use \phpoauthlib2\OAuth;
require 'OAuth.php';
require 'providers/GoogleAuthProvider.php';
$authProvider = new GoogleAuthProvider($_GET, [
"client_id" => "apps.googleusercontent.com",
"client_secret" => "<KEY>",
"redirect_uri" => "http://example.com/phpoauthlib2/example.php"
]);
$oauth = new OAuth($authProvider, $_GET);
$check = $oauth->check();
if ($check === true) {
echo "Hello - " . $authProvider->getFirstName();
echo "<br>Your email is - " . $authProvider->getEmail();
} else {
header("Location: " . $check);
}

26
system/vendor/phpoauthlib2/oauth.php vendored Normal file
View File

@ -0,0 +1,26 @@
<?php
namespace system\vendor\phpoauthlib2;
class OAuth {
protected $oauthProvider = null;
protected $request = null;
public function __construct($provider, $request) {
$this->oauthProvider = $provider;
$this->request = $request;
}
public function check() {
if (isset($this->request["code"]) && !empty($this->request["code"])) {
$this->oauthProvider->getProfile();
return true;
} else {
return $this->oauthProvider->getLoginUrl();
}
}
public function getProfile() {
return $this->oauthProvider->getProfile();
}
}

View File

@ -0,0 +1,113 @@
<?php
namespace system\vendor\phpoauthlib2;
require "ccurl.php";
use phpoauthlib2\ccurl;
class OAUTH_SCOPES {
const EMAIL = "EMAIL";
}
class OAuthDataProvider {
protected $version = "2.0";
protected $name = "undefined";
protected $responseType = "code";
protected $header = "Authorization: Bearer";
protected $profile = "";
protected $dialog = "";
protected $nonce = null;
protected $accessToken = null;
protected $state = "";
protected $redirectURL = "";
protected $scope = "";
protected $clientId = "";
protected $client_secret = "";
protected $request = null;
protected $profileData = [];
public function __construct($profile, $dialog, $accessToken, $request, $header="Authorization: Bearer") {
$this->profile = $profile;
$this->dialog = $dialog;
$this->accessToken = $accessToken;
$this->header = $header;
$this->request = $request;
}
public function getLoginUrl() {
$urlBuilder = [];
$urlBuilder[] = "client_id=" . $this->clientId;
$urlBuilder[] = "response_type=" . $this->responseType;
$urlBuilder[] = "scope=" . $this->scope;
$urlBuilder[] = "state=" . $this->state;
$urlBuilder[] = "redirect_uri=" . urlencode($this->redirectURL);
return $this->dialog . "?" . implode("&", $urlBuilder);
}
protected function getToken() {
$tokenBuilder = [];
$tokenBuilder["client_id"] = $this->clientId;
$tokenBuilder["client_secret"] = $this->client_secret;
$tokenBuilder["grant_type"] = "authorization_code";
$tokenBuilder["redirect_uri"] = htmlspecialchars($this->redirectURL);
$tokenBuilder["code"] = $this->request["code"];
$curl = new ccurl($this->accessToken);
$curl->setPost($tokenBuilder);
$curl->createCurl();
return (string)$curl;
}
protected function parseToken() {
$token = $this->getToken();
$convertedToken = json_decode($token, true);
if (!$convertedToken) {
$realToken = $token;
} else {
$realToken = $convertedToken["access_token"];
}
return $realToken;
}
public function getProfile() {
$token = $this->parseToken();
$profileUrl = $this->profile . "=" . $token;
$curl = new ccurl($profileUrl);
$curl->addHeader($this->header . " " . $token);
$curl->createCurl();
$this->profileData = json_decode((string)$curl, true);
return (string)$curl;
}
public function getEmail() {
return null;
}
public function getFirstName() {
return null;
}
public function getLastName() {
return null;
}
public function getGender() {
return null;
}
public function getId() {
return null;
}
public function getRawProfile() {
return $this->profileData;
}
public function getSource() {
return null;
}
}

View File

@ -0,0 +1,70 @@
<?php
namespace system\vendor\phpoauthlib2\providers;
require "OAuthDataProvider.php";
use phpoauthlib2\ccurl;
use phpoauthlib2\OAUTH_SCOPES;
use phpoauthlib2\OAuthDataProvider;
class FacebookAuthProvider extends OAuthDataProvider {
public function __construct($request, $conf, $scopes=[OAUTH_SCOPES::EMAIL]) {
parent::__construct(
"https://graph.facebook.com/me",
"https://www.facebook.com/dialog/oauth",
"https://graph.facebook.com/oauth/access_token",
$request
);
$this->client_secret = $conf["client_secret"];
$this->redirectURL = $conf["redirect_uri"];
$this->clientId = $conf["client_id"];
$tempScopes = [];
foreach($scopes as $scope) {
switch ($scope) {
case OAUTH_SCOPES::EMAIL:
$tempScopes[] = "email";
}
}
$tempScopes[] = "public_profile";
$this->scope = implode(" ", $tempScopes);
}
public function getEmail() {
return $this->profileData["email"];
}
public function getFirstName() {
return $this->profileData["first_name"];
}
public function getLastName() {
return $this->profileData["last_name"];
}
public function getId() {
return $this->profileData["id"];
}
public function getSource() {
return "FACEBOOK";
}
public function parseToken() {
$token = $this->getToken();
return explode("=", $token)[1];
}
public function getProfile() {
$token = $this->parseToken();
$profileUrl = $this->profile . "?fields=first_name,last_name,name,email,age_range&access_token=" . $token;
$curl = new ccurl($profileUrl);
$curl->createCurl();
$ret = (string)$curl;
$this->profileData = json_decode($ret, true);
return $ret;
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace system\vendor\phpoauthlib2\providers;
use phpoauthlib2\ccurl;
use system\vendor\phpoauthlib2\OAUTH_SCOPES;
use system\vendor\phpoauthlib2\OAuth;
use system\vendor\phpoauthlib2\OAuthDataProvider;
class GoogleAuthProvider extends OAuthDataProvider {
public function __construct($request, $conf, $scopes=[OAUTH_SCOPES::EMAIL]) {
parent::__construct(
"https://www.googleapis.com/oauth2/v1/userinfo?access_token",
"https://accounts.google.com/o/oauth2/auth",
"https://accounts.google.com/o/oauth2/token", $request);
$this->client_secret = $conf["client_secret"];
$this->redirectURL = $conf["redirect_uri"];
$this->clientId = $conf["client_id"];
$tmpScopes = [];
foreach($scopes as $scope) {
switch ($scope) {
case OAUTH_SCOPES::EMAIL:
$tmpScopes[] = "https://www.googleapis.com/auth/userinfo.email";
}
}
$this->scope = implode(" ", $tmpScopes);
}
public function getEmail() {
return $this->profileData["email"];
}
public function getFirstName() {
return $this->profileData["given_name"];
}
public function getLastName() {
return $this->profileData["family_name"];
}
public function getGender() {
return $this->profileData["gender"];
}
public function getId() {
return $this->profileData["id"];
}
public function getSource() {
return "GOOGLE";
}
}

86
system/vendor/phpoauthlib2/readme.md vendored Normal file
View File

@ -0,0 +1,86 @@
# phpoauthlib2
phpoauthlib2 is another OAuth 2.0 library for PHP. The goal of the project is to make it as easy as possible to integrate OAuth into your web application.
You can think of phpoauthlib2 as a combination of ideas from the following projects:
- PHPoAuthLib
- li3_socialauth
- oauth-4-laravel
- PHPoAuthUserData
All wrapped in one simple library.
# Why phpoauthlib2?
Or more specifically why "2"?
For me this is version 2.0. Originally I developed this in private for PHP and it worked but after a refactoring to Django/Python (Python version coming soon to a pip repository near you) then I ported it back to PHP.
# How to use
It's very easy to use this library. Examine the following line -
$authProvider = new GoogleAuthProvider($_GET, [
"client_id" => "apps.googleusercontent.com",
"client_secret" => "<KEY>",
"redirect_uri" => "http://example.com/phpoauthlib2/example.php"
]);
client_id and client_secret are provided by the OAauth provider (in this case Google) and the redirect_uri is where you want to the user to end up on successful login. It should go without saying that client_id and client_secret should be kept private - you should avoid committing them a public place like github (yes - people have services running and monitoring for people who commit credentials. Don't believe me? Commit your Amazon AWS keys and see how fast people will spin up VMs). The library will handle the verification and present you with some simple base methods to extract data you might be interested in or the ability to work with the entire OAuth data.
$oauth = new OAuth($authProvider, $_GET);
OAuth is really a wrapper to do the verification check. In both this line and the previous one we are passing $_GET but phpoauthlib2 can accept any request array from your framework (provided your framework can emit the GET request as an array - which I know at least Symfony can do this).
$check = $oauth->check();
The check method will return true or a string. Not ideal but I couldn't think of any simpler way to do it (obviously not a problem in a lose typed language - but I don't personally like mixing return types). true indicates that the user successfully logged in and you have access to the user's information. A string indicates that you need to redirect them to the OAuth provider to login (the string itself is the redirect URL).
if ($check === true) {
echo "Hello - " . $authProvider->getFirstName();
echo "<br>Your email is - " . $authProvider->getEmail();
} else {
header("Location: " . $check);
}
This library is designed to be very minimal - so you need to decide how to hook into the login subsystem of your web application. In the example file - it's checking to make sure that the login was successful and then can call $authProvider->getXXX (such as getFirstName and getEmail in this example) and the provider class will return those fields from the raw profile data so you don't have to worry about it.
The work flow to integrate to your system is usually:
if ($check === true) {
$mySystem->login($authProvider->getEmail()); // which sets a cookie or session that they logged in with this specific user
header("Location: http://example.com/yoursystem/user.php"); // The line above logs them in to your system - then immediately bounce back to your system and potentially send them straight to their user dashboard
The reasoning behind the getXXX methods is to provide some commonality between providers. That way you can present a OAuth login prompt for different services to the user and you can just call $provider->getEmail() to get their email without having to worry about the actual field that the OAuth provider decided to put it in.
If after you have verified the login was successful you may call
$provider->getRawProfile();
To return the raw return from the OAuth provider (which will be an associative array).
# Google
To get OAuth credentials for Google just go to this URL: https://console.developers.google.com/
And create a project (which is free) and go to APIs & auth -> Credentials.
If you are creating a new project - it may complain that you need to setup the OAuth consent screen. Do this and return to the credentials section and you should be able to setup the project.
Add credentials -> OAuth 2.0 client ID
Then select Web application
It is very important that you input a correct authorized redirect URI. This will be where the user will be sent back on successful login.
# License
I am licensing this under the MIT license. Which essentially grants you the right TDWTFYWWI (to do whatever the f you want with it) - assuming that you acknowledge that I don't provide a warranty.
# What this library is/is not
- This library is a simple interface to use PHP OAuth 2.0 in your web application.
- This library is designed to be as flexible as possible to use in any framework.
- This library is not designed to hold your hand to secure your client_id, client_secret, or other data.
- This library is not designed to be specific to a certain framework.
- This library is not designed to be abstract. The only class you should ever have to extend is OAuthDataProvider - and that is to create a "provider" for different OAuth providers (which merely contains the URLs to send for login, where to query for user data and normalizing data).