Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@ngyuki
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ngyuki/c55edaaab45d75a43d7d to your computer and use it in GitHub Desktop.
Save ngyuki/c55edaaab45d75a43d7d to your computer and use it in GitHub Desktop.
PhpRenderer sample
PhpRenderer sample.
<?php
/**
* @var string $name user name
* @var string $html html string
*/
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
Hello <?= $name ?>.
<br>
None Escape <?php echo $html ?>
</body>
</html>
<?php
require __DIR__ . '/Renderer.php';
require __DIR__ . '/StreamWrapper.php';
use PhpRenderer\Renderer;
$data = [
'name' => "<script>alert('!')</script>",
'html' => "<strong>safe string</strong>",
];
echo (new Renderer)->render(__DIR__ . '/index.html.php', $data);
<?php
namespace PhpRenderer;
class Renderer
{
public function render($filename, $values = [])
{
return self::render2($filename, $values);
}
private static function render2()
{
StreamWrapper::register();
extract(func_get_arg(1));
ob_start();
try {
/** @noinspection PhpIncludeInspection */
include StreamWrapper::SCHEME . '://' . func_get_arg(0);
} finally {
return ob_get_clean();
}
}
}
<?php
namespace PhpRenderer;
class StreamWrapper
{
private $pos;
private $stat;
private $data;
private static $registered = false;
const SCHEME = 'php.renderer';
public static function register()
{
if (self::$registered == false) {
self::$registered = true;
stream_wrapper_register(self::SCHEME, __CLASS__);
}
}
public static function html($str)
{
return htmlspecialchars($str, ENT_NOQUOTES);
}
public function stream_open($path)
{
$path = substr($path, strlen(self::SCHEME) + 3);
$this->pos = 0;
$this->stat = stat($path);
$this->data = file_get_contents($path);
if ($this->data === false) {
return false;
}
$this->data = $this->rewrite($this->data);
return true;
}
public function stream_stat()
{
return $this->stat;
}
public function stream_read($count)
{
$ret = substr($this->data, $this->pos, $count);
$this->pos += strlen($ret);
return $ret;
}
public function stream_eof()
{
return $this->pos >= strlen($this->data);
}
private function rewrite($source)
{
$tokens = token_get_all($source);
$flag = false;
$output = "";
foreach ($tokens as $token) {
if (is_array($token)) {
list ($id, $code) = $token;
if ($id === T_OPEN_TAG_WITH_ECHO) {
$flag = true;
$code = $code . __CLASS__ . '::html(';
} else {
if ($flag && $id === T_CLOSE_TAG) {
$flag = false;
$code = ')' . $code;
}
}
$output .= $code;
} else {
$output .= $token;
}
}
return $output;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment