' => '');
/**
* 允许的标签
*
* @access private
* @var array
*/
private static $_allowableTags = '';
/**
* 允许的属性
*
* @access private
* @var array
*/
private static $_allowableAttributes = array();
/**
* 默认编码
*
* @access public
* @var string
*/
public static $charset = 'UTF-8';
/**
* 异常处理类
*
* @access public
* @var string
*/
public static $exceptionHandle;
/**
* 锁定标签回调函数
*
* @access private
* @param array $matches 匹配的值
* @return string
*/
public static function __lockHTML(array $matches)
{
$guid = ' {$message}' . uniqid(time()) . '';
self::$_lockedBlocks[$guid] = $matches[0];
return $guid;
}
/**
* 将url中的非法xss去掉时的数组回调过滤函数
*
* @access private
* @param string $string 需要过滤的字符串
* @return string
*/
public static function __removeUrlXss($string)
{
$string = str_replace(array('%0d', '%0a'), '', strip_tags($string));
return preg_replace(array(
"/\(\s*(\"|')/i", //函数开头
"/(\"|')\s*\)/i", //函数结尾
), '', $string);
}
/**
* 检查是否为安全路径
*
* @access public
* @param string $path 检查是否为安全路径
* @return boolean
*/
public static function __safePath($path)
{
$safePath = rtrim(__TYPECHO_ROOT_DIR__, '/');
return 0 === strpos($path, $safePath);
}
/**
* html标签过滤
*
* @access public
* @param string $tag 标签
* @param string $attrs 属性
* @return string
*/
public static function __tagFilter($tag, $attrs)
{
$suffix = '';
$tag = strtolower($tag);
if (false === strpos(self::$_allowableTags, "|{$tag}|")) {
return '';
}
if (!empty($attrs)) {
$result = self::__parseAtttrs($attrs);
$attrs = '';
foreach ($result as $name => $val) {
$quote = '';
$lname = strtolower($name);
$lval = self::__attrTrim($val, $quote);
if (in_array($lname, self::$_allowableAttributes[$tag])) {
$attrs .= ' ' . $name . (empty($val) ? '' : '=' . $val);
}
}
}
return "<{$tag}{$attrs}>";
}
/**
* 自闭合标签过滤
*
* @access public
* @param array $matches 匹配值
* @return string
*/
public static function __closeTagFilter($matches)
{
$tag = strtolower($matches[1]);
return false === strpos(self::$_allowableTags, "|{$tag}|") ? '' : "{$tag}>";
}
/**
* 解析属性
*
* @access public
* @param string $attrs 属性字符串
* @return array
*/
public static function __parseAtttrs($attrs)
{
$attrs = trim($attrs);
$len = strlen($attrs);
$pos = -1;
$result = array();
$quote = '';
$key = '';
$value = '';
for ($i = 0; $i < $len; $i ++) {
if ('=' != $attrs[$i] && !ctype_space($attrs[$i]) && -1 == $pos) {
$key .= $attrs[$i];
/** 最后一个 */
if ($i == $len - 1) {
if ('' != ($key = trim($key))) {
$result[$key] = '';
$key = '';
$value = '';
}
}
} else if (ctype_space($attrs[$i]) && -1 == $pos) {
$pos = -2;
} else if ('=' == $attrs[$i] && 0 > $pos) {
$pos = 0;
} else if (('"' == $attrs[$i] || "'" == $attrs[$i]) && 0 == $pos) {
$quote = $attrs[$i];
$value .= $attrs[$i];
$pos = 1;
} else if ($quote != $attrs[$i] && 1 == $pos) {
$value .= $attrs[$i];
} else if ($quote == $attrs[$i] && 1 == $pos) {
$pos = -1;
$value .= $attrs[$i];
$result[trim($key)] = $value;
$key = '';
$value = '';
} else if ('=' != $attrs[$i] && !ctype_space($attrs[$i]) && -2 == $pos) {
if ('' != ($key = trim($key))) {
$result[$key] = '';
}
$key = '';
$value = '';
$pos = -1;
$key .= $attrs[$i];
}
}
return $result;
}
/**
* 清除属性空格
*
* @access public
* @param string $attr 属性
* @param string $quote 引号
* @return string
*/
public static function __attrTrim($attr, &$quote)
{
$attr = trim($attr);
$attr_len = strlen($attr);
$quote = '';
if ($attr_len >= 2 &&
('"' == $attr[0] || "'" == $attr[0])
&& $attr[0] == $attr[$attr_len - 1]) {
$quote = $attr[0];
return trim(substr($attr, 1, -1));
}
return $attr;
}
/**
* 程序初始化方法
*
* @access public
* @return void
*/
public static function init()
{
/** 输出logo */
if (isset($_GET['464D-E63E-9D08-97E2-16DD-6A37-BDEC-6021'])) {
header('content-Type: image/gif', true);
die(base64_decode('R0lGODlhXQAVANUAAP////Pz8+bm5tnZ2c3NzcDAwLOzs5mZmY2NjeR+ANp6A9l5A4CAgM51BsNwCsNwCbhrDXNzc61nEKxmEKFiE6JiE2ZmZpddFpZdFoxZGYtYGoFUHYBUHVlZWXZPIHVPIGtLI2pKI01NTV9GJlRBKVRBKkBAQEk8LT44MD03MDMzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAHAP8ALAAAAABdABUAAAb/QJVwSCwaj8ikUgjxLJ9Gj+JELBSg2OwyodFCSYkKkUDwms3cs5E0GlYSVCFZTX+m60IpSnhKXIZzeEonI21HKIVxQlyIhkaEjkVOQg2TKhIKKggHAgIHCEMmByZEERFCHaAmEQcHp0ckDgmzCxlEKG+zCRAkiw4LtCBEIw26CbZFEIYXD0MeCSQBANMAAUMWABZjZSoHAAzS1AGvQyAJDRwjIRQJDnsoshSFGAsLVLPKIbKGz+jq7A6KjBCjAsweFSgSbJDD7Vq2bUK8ARjwKsIAAORQLHBHREKaCQlKEDmhIYWKdkNSLKCg4sTGg3nuDGm2yJGCPyoCOdQGiJu3/wGkQg0IEJQDtCEjIJwr0QdDEpkqIEBQgQGOkQkLilSIAwFZ1Kk5GwrBxpNhxIdFsDFg0oDPmwUchIxIEKkIVKlRAxrZQJdIBkNdh+ANmxat2W4AkAA4wOQBigyzMJgUEqIvkrtTB0uyLOQvE6+DdY41TBhxUCImFgupqmCXIhInSkC120Xw1Kow3SSYLGTr55kSDu+EiJhxEW8d+CRYEAmMUwgLehERdrI2k6mygxMBw5IIzZOOjgkpIECIieQmAlxBBcDntLVDGABYL8QoBGEoNtSjUqKeBxQneFCMSJgJocEuwpyQgQIN8KbCQEIYJFcC1EXQHiflqSDfAAcYIJ+NexdxeECIpwnxATC6QKBICbLo0kAIi1j31RAcoIiPg1Et890FCcAUgQAACACfChZVY8AA7nVz0URDFpFCCBp8oAgRJWigAYxDSDlMJCl8oAEHIkUxRCVDKABWFoF4I8iaUOgRkyVIdFCWCgKspyabeCLBxphtLVEAAKoYgNadeRZ6BF9wImHCku8NQaihkAqRXxasICACEalEqqkRQQAAOw=='));
}
/** 设置自动载入函数 */
function __autoLoad($className)
{
/**
* 自动载入函数并不判断此类的文件是否存在, 我们认为当你显式的调用它时, 你已经确认它存在了
* 如果真的无法被加载, 那么系统将出现一个严重错误(Fetal Error)
* 如果你需要判断一个类能否被加载, 请使用 Typecho_Common::isAvailableClass 方法
*/
@include_once str_replace('_', '/', $className) . '.php';
}
/** 兼容php6 */
if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
$_GET = self::stripslashesDeep($_GET);
$_POST = self::stripslashesDeep($_POST);
$_COOKIE = self::stripslashesDeep($_COOKIE);
reset($_GET);
reset($_POST);
reset($_COOKIE);
}
/** 设置异常截获函数 */
set_exception_handler(array('Typecho_Common', 'exceptionHandle'));
}
/**
* 异常截获函数
*
* @access public
* @param Exception $exception 截获的异常
* @return void
*/
public static function exceptionHandle(Exception $exception)
{
//$obHandles = ob_list_handlers();
@ob_end_clean();
/*
if (in_array('ob_gzhandler', $obHandles)) {
ob_start('ob_gzhandler');
} else {
ob_start();
}
*/
if (defined('__TYPECHO_DEBUG__')) {
//@ob_clean();
echo nl2br($exception->__toString());
} else {
if (404 == $exception->getCode() && !empty(self::$exceptionHandle)) {
$handleClass = self::$exceptionHandle;
new $handleClass($exception);
} else {
self::error($exception);
}
}
exit;
}
/**
* 输出错误页面
*
* @access public
* @param mixed $exception 错误信息
* @return void
*/
public static function error($exception)
{
$isException = is_object($exception);
if ($isException) {
$code = $exception->getCode();
$message = $exception->getMessage();
} else {
$code = $exception;
}
require_once 'Typecho/Response.php';
$charset = self::$charset;
if ($isException && $exception instanceof Typecho_Db_Exception) {
$code = 500;
@error_log($message);
//覆盖原始错误信息
$message = 'Database Server Error';
if ($exception instanceof Typecho_Db_Adapter_Exception) {
$code = 503;
$message = 'Error establishing a database connection';
} else if ($exception instanceof Typecho_Db_Query_Exception) {
$message = 'Database Query Error';
}
} else {
switch ($code) {
case 500:
$message = 'Server Error';
break;
case 404:
$message = 'Page Not Found';
break;
default:
$code = 'Error';
break;
}
}
/** 设置http code */
if (is_numeric($code) && $code > 200) {
require_once 'Typecho/Response.php';
Typecho_Response::setStatus($code);
}
$message = nl2br($message);
if (defined('__TYPECHO_EXCEPTION_FILE__')) {
require_once __TYPECHO_EXCEPTION_FILE__;
} else {
echo
<<{$code}
* 2, 'banana' => 3), array('apple' => 10, 'banana' => 12));
* $banana = Typecho_Common::arrayFlatten($fruit, 'banana');
* print_r($banana);
* //outputs: array(0 => 3, 1 => 12);
* ?>
*
*
* @access public
* @param array $value 被处理的数组
* @param string $key 需要抽取的键值
* @return array
*/
public static function arrayFlatten(array $value, $key)
{
$result = array();
if ($value) {
foreach ($value as $inval) {
if (is_array($inval) && isset($inval[$key])) {
$result[] = $inval[$key];
} else {
break;
}
}
}
return $result;
}
/**
* 根据parse_url的结果重新组合url
*
* @access public
* @param array $params 解析后的参数
* @return string
*/
public static function buildUrl($params)
{
return (isset($params['scheme']) ? $params['scheme'] . '://' : NULL)
. (isset($params['user']) ? $params['user'] . (isset($params['pass']) ? ':' . $params['pass'] : NULL) . '@' : NULL)
. (isset($params['host']) ? $params['host'] : NULL)
. (isset($params['port']) ? ':' . $params['port'] : NULL)
. (isset($params['path']) ? $params['path'] : NULL)
. (isset($params['query']) ? '?' . $params['query'] : NULL)
. (isset($params['fragment']) ? '#' . $params['fragment'] : NULL);
}
/**
* 根据count数目来输出字符
*
* echo splitByCount(20, 10, 20, 30, 40, 50);
*
*
* @access public
* @return string
*/
public static function splitByCount($count)
{
$sizes = func_get_args();
array_shift($sizes);
foreach ($sizes as $size) {
if ($count < $size) {
return $size;
}
}
return 0;
}
/**
* 自闭合html修复函数
* 使用方法:
*
* $input = '这是一段被截断的html文本
*
* @access public
* @param string $string 需要修复处理的字符串
* @return string
*/
public static function fixHtml($string)
{
//关闭自闭合标签
$startPos = strrpos($string, "<");
if (false == $startPos) {
return $string;
}
$trimString = substr($string, $startPos);
if (false === strpos($trimString, ">")) {
$string = substr($string, 0, $startPos);
}
//非自闭合html标签列表
preg_match_all("/<([_0-9a-zA-Z-\:]+)\s*([^>]*)>/is", $string, $startTags);
preg_match_all("/<\/([_0-9a-zA-Z-\:]+)>/is", $string, $closeTags);
if (!empty($startTags[1]) && is_array($startTags[1])) {
krsort($startTags[1]);
$closeTagsIsArray = is_array($closeTags[1]);
foreach ($startTags[1] as $key => $tag) {
$attrLength = strlen($startTags[2][$key]);
if ($attrLength > 0 && "/" == trim($startTags[2][$key][$attrLength - 1])) {
continue;
}
if (!empty($closeTags[1]) && $closeTagsIsArray) {
if (false !== ($index = array_search($tag, $closeTags[1]))) {
unset($closeTags[1][$index]);
continue;
}
}
$string .= "{$tag}>";
}
}
return preg_replace("/\
\s*\<\/p\>/is", '
* $input = 'hello';
* $output = Typecho_Common::stripTags($input, );
* echo $output;
* //display: 'hello'
*
*
* @access public
* @param string $string 需要处理的字符串
* @param string $allowableTags 需要忽略的html标签
* @return string
*/
public static function stripTags($html, $allowableTags = NULL)
{
if (!empty($allowableTags) && preg_match_all("/\<([a-z]+)([^>]*)\>/is", $allowableTags, $tags)) {
self::$_allowableTags = '|' . implode('|', $tags[1]) . '|';
if (in_array('code', $tags[1])) {
$html = self::lockHTML($html);
}
$normalizeTags = '<' . implode('><', $tags[1]) . '>';
$html = strip_tags($html, $normalizeTags);
$attributes = array_map('trim', $tags[2]);
$allowableAttributes = array();
foreach ($attributes as $key => $val) {
$allowableAttributes[$tags[1][$key]] = array_keys(self::__parseAtttrs($val));
}
self::$_allowableAttributes = $allowableAttributes;
$len = strlen($html);
$tag = '';
$attrs = '';
$pos = -1;
$quote = '';
$start = 0;
for ($i = 0; $i < $len; $i ++) {
if ('<' == $html[$i] && -1 == $pos) {
$start = $i;
$pos = 0;
} else if (0 == $pos && '/' == $html[$i] && empty($tag)) {
$pos = -1;
} else if (0 == $pos && ctype_alpha($html[$i])) {
$tag .= $html[$i];
} else if (0 == $pos && ctype_space($html[$i])) {
$pos = 1;
} else if (1 == $pos && (!empty($quote) || '>' != $html[$i])) {
if (empty($quote) && ('"' == $html[$i] || "'" == $html[$i])) {
$quote = $html[$i];
} else if (!empty($quote) && $quote == $html[$i]) {
$quote = '';
}
$attrs .= $html[$i];
} else if (-1 != $pos && empty($quote) && '>' == $html[$i]) {
$out = self::__tagFilter($tag, $attrs);
$outLen = strlen($out);
$nextStart = $start + $outLen;
$tag = '';
$attrs = '';
$html = substr_replace($html, $out, $start, $i - $start + 1);
$len = strlen($html);
$i = $nextStart - 1;
$pos = -1;
}
}
$html = preg_replace_callback("/<\/([_0-9a-z-]+)>/is", array('Typecho_Common', '__closeTagFilter'), $html);
$html = self::releaseHTML($html);
} else {
$html = strip_tags($html);
}
//去掉注释
return preg_replace("/<\!\-\-[^>]*\-\->/s", '', $html);
}
/**
* 过滤用于搜索的字符串
*
* @access public
* @param string $query 搜索字符串
* @return string
*/
public static function filterSearchQuery($query)
{
return str_replace(array('%', '?', '*', '/', '{', '}'), '', $query);
}
/**
* 将url中的非法字符串
*
* @access private
* @param string $string 需要过滤的url
* @return string
*/
public static function safeUrl($url)
{
//~ 针对location的xss过滤, 因为其特殊性无法使用removeXSS函数
//~ fix issue 66
$params = parse_url(str_replace(array("\r", "\n"), '', $url));
/** 禁止非法的协议跳转 */
if (isset($params['scheme'])) {
if (!in_array($params['scheme'], array('http', 'https'))) {
return;
}
}
/** 过滤解析串 */
$params = array_map(array('Typecho_Common', '__removeUrlXss'), $params);
return self::buildUrl($params);
}
/**
* 处理XSS跨站攻击的过滤函数
*
* @author kallahar@kallahar.com
* @link http://kallahar.com/smallprojects/php_xss_filter_function.php
* @access public
* @param string $val 需要处理的字符串
* @return string
*/
public static function removeXSS($val)
{
// remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
// this prevents some character re-spacing such as (.*?)<\/p>\s*/is", "/\s*
\s*/is",
"/\s*<(div|blockquote|pre|code|script|table|fieldset|ol|ul|dl|h[1-6])([^>]*)>/is",
"/<\/(div|blockquote|pre|code|script|table|fieldset|ol|ul|dl|h[1-6])>\s*/is", "/\s*<\!--more-->\s*/is"),
array("\n\\1\n", "\n", "\n\n<\\1\\2>", "\\1>\n\n", "\n\n\n\n"),
$html));
return trim(self::releaseHTML($html));
}
/**
* 锁定标签
*
* @access public
* @param string $html 输入串
* @return string
*/
public static function lockHTML($html)
{
return preg_replace_callback("/<(code|pre|script)[^>]*>.*?<\/\\1>/is", array('Typecho_Common', '__lockHTML'), $html);
}
/**
* 释放标签
*
* @access public
* @param string $html 输入串
* @return string
*/
public static function releaseHTML($html)
{
$html = trim(str_replace(array_keys(self::$_lockedBlocks), array_values(self::$_lockedBlocks), $html));
self::$_lockedBlocks = array('