diff --git a/install.php b/install.php index c46bcd73..2b593116 100644 --- a/install.php +++ b/install.php @@ -1229,7 +1229,7 @@ function install_dispatch() } if (install_is_cli()) { - install_step_2_perform(); + install_step_1_perform(); } else { $request = \Typecho\Request::getInstance(); $step = $request->get('step'); diff --git a/var/Markdown.php b/var/Markdown.php index ee10bbf3..73bd82dc 100644 --- a/var/Markdown.php +++ b/var/Markdown.php @@ -32,34 +32,5 @@ class Markdown return str_replace('

', '', $parser->makeHtml($text)); } - - /** - * transerCodeClass - * - * @param string $html - * @return string - */ - public static function transerCodeClass($html) - { - return preg_replace("//i", "", $html); - } - - /** - * @param $html - * @return mixed - */ - public static function transerComment($html) - { - return preg_replace_callback("//s", ['Markdown', 'transerCommentCallback'], $html); - } - - /** - * @param $matches - * @return string - */ - public static function transerCommentCallback($matches) - { - return self::$parser->makeHolder($matches[0]); - } } diff --git a/var/Typecho/Common.php b/var/Typecho/Common.php index fe3fb508..1e06aa1e 100644 --- a/var/Typecho/Common.php +++ b/var/Typecho/Common.php @@ -1,16 +1,6 @@ '\Typecho\Plugin\PluginInterface', @@ -140,118 +129,6 @@ namespace Typecho /** 程序版本 */ public const VERSION = '1.2.0'; - /** - * 默认编码 - * - * @access public - * @var string - */ - public static $charset = 'UTF-8'; - - /** - * 异常处理类 - * - * @access public - * @var string - */ - public static $exceptionHandle; - - /** - * 将url中的非法xss去掉时的数组回调过滤函数 - * - * @access private - * - * @param string $string 需要过滤的字符串 - * - * @return string - */ - public static function __removeUrlXss($string) - { - $string = str_replace(['%0d', '%0a'], '', strip_tags($string)); - return preg_replace([ - "/\(\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); - } - - /** - * 解析属性 - * - * @access public - * - * @param string $attrs 属性字符串 - * - * @return array - */ - public static function __parseAttrs($attrs) - { - $attrs = trim($attrs); - $len = strlen($attrs); - $pos = -1; - $result = []; - $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 = ''; - } - } - - } elseif (ctype_space($attrs[$i]) && -1 == $pos) { - $pos = -2; - } elseif ('=' == $attrs[$i] && 0 > $pos) { - $pos = 0; - } elseif (('"' == $attrs[$i] || "'" == $attrs[$i]) && 0 == $pos) { - $quote = $attrs[$i]; - $value .= $attrs[$i]; - $pos = 1; - } elseif ($quote != $attrs[$i] && 1 == $pos) { - $value .= $attrs[$i]; - } elseif ($quote == $attrs[$i] && 1 == $pos) { - $pos = -1; - $value .= $attrs[$i]; - $result[trim($key)] = $value; - $key = ''; - $value = ''; - } elseif ('=' != $attrs[$i] && !ctype_space($attrs[$i]) && -2 == $pos) { - if ('' != ($key = trim($key))) { - $result[$key] = ''; - } - - $key = ''; - $value = ''; - $pos = -1; - $key .= $attrs[$i]; - } - } - - return $result; - } - /** * 将路径转化为链接 * @@ -290,29 +167,11 @@ namespace Typecho /** 设置异常截获函数 */ set_exception_handler(function (\Throwable $exception) { - if (defined('__TYPECHO_DEBUG__') && __TYPECHO_DEBUG__) { - echo '
';
-                    echo '

' . htmlspecialchars($exception->getMessage()) . '

'; - echo htmlspecialchars($exception->__toString()); - echo '
'; - } else { - Response::getInstance()->clean(); - ob_end_clean(); - - ob_start(function ($content) { - Response::getInstance()->sendHeaders(); - return $content; - }); - - if (404 == $exception->getCode() && !empty(self::$exceptionHandle)) { - $handleClass = self::$exceptionHandle; - new $handleClass($exception); - } else { - self::error($exception); - } - } - - exit(1); + echo '
';
+                echo '

' . htmlspecialchars($exception->getMessage()) . '

'; + echo htmlspecialchars($exception->__toString()); + echo '
'; + exit; }); } @@ -400,47 +259,13 @@ EOF; } /** - * 判断类是否能被加载 - * 此函数会遍历所有的include目录, 所以会有一定的性能消耗, 但是不会很大 - * 可是我们依然建议你在必须检测一个类能否被加载时使用它, 它通常表现为以下两种情况 - * 1. 当需要被加载的类不存在时, 系统不会停止运行 (如果你不判断, 系统会因抛出严重错误而停止) - * 2. 你需要知道哪些类无法被加载, 以提示使用者 - * 除了以上情况, 你无需关注那些类无法被加载, 因为当它们不存在时系统会自动停止并报错 - * - * @access public - * * @param string $className 类名 - * @param string $path 指定的路径名称 - * * @return boolean + * @deprecated */ - public static function isAvailableClass($className, $path = null) + public static function isAvailableClass(string $className): bool { - /** 获取所有include目录 */ - //增加安全目录检测 fix issue 106 - $dirs = array_map('realpath', array_filter(explode(PATH_SEPARATOR, get_include_path()), - ['Typecho_Common', '__safePath'])); - - $file = str_replace('_', '/', $className) . '.php'; - - if (!empty($path)) { - $path = realpath($path); - if (in_array($path, $dirs)) { - $dirs = [$path]; - } else { - return false; - } - } - - foreach ($dirs as $dir) { - if (!empty($dir)) { - if (file_exists($dir . '/' . $file)) { - return true; - } - } - } - - return false; + return class_exists($className); } /** @@ -570,7 +395,7 @@ EOF; $attributes = array_map('trim', $tags[2]); foreach ($attributes as $key => $val) { $allowableAttributes[strtolower($tags[1][$key])] = - array_map('strtolower', array_keys(self::__parseAttrs($val))); + array_map('strtolower', array_keys(self::parseAttrs($val))); } } @@ -588,7 +413,7 @@ EOF; return $matches[0]; } - $attrs = self::__parseAttrs($str); + $attrs = self::parseAttrs($str); $parsedAttrs = []; $tag = strtolower($matches[1]); @@ -676,8 +501,14 @@ EOF; } } - /** 过滤解析串 */ - $params = array_map(['Typecho_Common', '__removeUrlXss'], $params); + $params = array_map(function ($string) { + $string = str_replace(['%0d', '%0a'], '', strip_tags($string)); + return preg_replace([ + "/\(\s*(\"|')/i", //函数开头 + "/(\"|')\s*\)/i", //函数结尾 + ], '', $string); + }, $params); + return self::buildUrl($params); } @@ -729,15 +560,28 @@ EOF; // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars // @ @ search for the hex values - $val = preg_replace('/(&#[xX]0{0,8}' . dechex(ord($search[$i])) . ';?)/i', $search[$i], $val); // with a ; + $val = preg_replace('/(&#[xX]0{0,8}' . dechex(ord($search[$i])) . ';?)/i', $search[$i], $val); // @ @ 0{0,7} matches '0' zero to seven times $val = preg_replace('/(�{0,8}' . ord($search[$i]) . ';?)/', $search[$i], $val); // with a ; } // now the only remaining whitespace attacks are \t, \n, and \r - $ra1 = ['javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base']; + $ra1 = ['javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', + 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base']; $ra2 = [ - 'onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload' + 'onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', + 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', + 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', + 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', + 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', + 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', + 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', + 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', + 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', + 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', + 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', + 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', + 'onsubmit', 'onunload' ]; $ra = array_merge($ra1, $ra2); @@ -1124,15 +968,15 @@ EOF; } return filter_var( - $address, - FILTER_VALIDATE_IP, - FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE - ) !== false; + $address, + FILTER_VALIDATE_IP, + FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE + ) !== false; } /** - * @deprecated after 1.2.0 * @return bool + * @deprecated after 1.2.0 */ public static function isAppEngine(): bool { @@ -1535,5 +1379,65 @@ EOF; return 'unknown'; } } + + /** + * 解析属性 + * + * @param string $attrs 属性字符串 + * @return array + */ + private static function parseAttrs(string $attrs): array + { + $attrs = trim($attrs); + $len = strlen($attrs); + $pos = -1; + $result = []; + $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 = ''; + } + } + + } elseif (ctype_space($attrs[$i]) && -1 == $pos) { + $pos = -2; + } elseif ('=' == $attrs[$i] && 0 > $pos) { + $pos = 0; + } elseif (('"' == $attrs[$i] || "'" == $attrs[$i]) && 0 == $pos) { + $quote = $attrs[$i]; + $value .= $attrs[$i]; + $pos = 1; + } elseif ($quote != $attrs[$i] && 1 == $pos) { + $value .= $attrs[$i]; + } elseif ($quote == $attrs[$i] && 1 == $pos) { + $pos = -1; + $value .= $attrs[$i]; + $result[trim($key)] = $value; + $key = ''; + $value = ''; + } elseif ('=' != $attrs[$i] && !ctype_space($attrs[$i]) && -2 == $pos) { + if ('' != ($key = trim($key))) { + $result[$key] = ''; + } + + $key = ''; + $value = ''; + $pos = -1; + $key .= $attrs[$i]; + } + } + + return $result; + } } -} \ No newline at end of file +} diff --git a/var/Typecho/Router.php b/var/Typecho/Router.php index e1b56a79..49053e0b 100644 --- a/var/Typecho/Router.php +++ b/var/Typecho/Router.php @@ -28,14 +28,6 @@ class Router */ private static $routingTable = []; - /** - * 全路径 - * - * @access private - * @var string - */ - private static $pathInfo = null; - /** * 解析路径 * @@ -86,7 +78,7 @@ class Router public static function dispatch() { /** 获取PATHINFO */ - $pathInfo = self::getPathInfo(); + $pathInfo = Request::getInstance()->getPathInfo(); foreach (self::$routingTable as $key => $route) { if (preg_match($route['regx'], $pathInfo, $matches)) { @@ -125,35 +117,6 @@ class Router throw new RouterException("Path '{$pathInfo}' not found", 404); } - /** - * 获取全路径 - * - * @access public - * @return string - */ - public static function getPathInfo(): ?string - { - if (null === self::$pathInfo) { - self::setPathInfo(); - } - - return self::$pathInfo; - } - - /** - * 设置全路径 - * - * @access public - * - * @param string $pathInfo - * - * @return void - */ - public static function setPathInfo(string $pathInfo = '/') - { - self::$pathInfo = $pathInfo; - } - /** * 路由反解析函数 * diff --git a/var/Widget/Do.php b/var/Widget/Do.php index 92106b6c..04b73e3d 100644 --- a/var/Widget/Do.php +++ b/var/Widget/Do.php @@ -53,21 +53,11 @@ class Widget_Do extends Typecho_Widget /** 验证路由地址 **/ $action = $this->request->action; - //兼容老版本 - if (empty($action)) { - $widget = trim($this->request->widget, '/'); - $objectName = 'Widget_' . str_replace('/', '_', $widget); + /** 判断是否为plugin */ + $actionTable = array_merge($this->map, unserialize($this->widget('Widget_Options')->actionTable)); - if (preg_match("/^[_a-z0-9]$/i", $objectName) && Typecho_Common::isAvailableClass($objectName)) { - $widgetName = $objectName; - } - } else { - /** 判断是否为plugin */ - $actionTable = array_merge($this->map, unserialize($this->widget('Widget_Options')->actionTable)); - - if (isset($actionTable[$action])) { - $widgetName = $actionTable[$action]; - } + if (isset($actionTable[$action])) { + $widgetName = $actionTable[$action]; } if (isset($widgetName) && class_exists($widgetName)) { diff --git a/var/Widget/ExceptionHandle.php b/var/Widget/ExceptionHandle.php index d2f2fc8b..5a50c088 100644 --- a/var/Widget/ExceptionHandle.php +++ b/var/Widget/ExceptionHandle.php @@ -1,12 +1,10 @@ installed) { - $options->update(['value' => 1], Typecho_Db::get()->sql()->where('name = ?', 'installed')); + $options->update(['value' => 1], Db::get()->sql()->where('name = ?', 'installed')); } /** 语言包初始化 */ if ($options->lang && $options->lang != 'zh_CN') { $dir = defined('__TYPECHO_LANG_DIR__') ? __TYPECHO_LANG_DIR__ : __TYPECHO_ROOT_DIR__ . '/usr/langs'; - Typecho_I18n::setLang($dir . '/' . $options->lang . '.mo'); + I18n::setLang($dir . '/' . $options->lang . '.mo'); } /** 备份文件目录初始化 */ @@ -43,32 +52,41 @@ class Widget_Init extends Typecho_Widget } /** cookie初始化 */ - Typecho_Cookie::setPrefix($options->rootUrl); + Cookie::setPrefix($options->rootUrl); /** 初始化exception */ - Typecho_Common::$exceptionHandle = 'Widget_ExceptionHandle'; + if (!defined('__TYPECHO_DEBUG__') || !__TYPECHO_DEBUG__) { + set_exception_handler(function (\Throwable $exception) { + Response::getInstance()->clean(); + ob_end_clean(); - /** 设置路径 */ - if (defined('__TYPECHO_PATHINFO_ENCODING__')) { - $pathInfo = $this->request->getPathInfo(__TYPECHO_PATHINFO_ENCODING__, $options->charset); - } else { - $pathInfo = $this->request->getPathInfo(); + ob_start(function ($content) { + Response::getInstance()->sendHeaders(); + return $content; + }); + + if (404 == $exception->getCode()) { + new ExceptionHandle($exception); + } else { + Common::error($exception); + } + + exit; + }); } - Typecho_Router::setPathInfo($pathInfo); - /** 初始化路由器 */ - Typecho_Router::setRoutes($options->routingTable); + Router::setRoutes($options->routingTable); /** 初始化插件 */ - Typecho_Plugin::init($options->plugins); + Plugin::init($options->plugins); /** 初始化回执 */ $this->response->setCharset($options->charset); $this->response->setContentType($options->contentType); /** 初始化时区 */ - Typecho_Date::setTimezoneOffset($options->timezone); + Date::setTimezoneOffset($options->timezone); /** 开始会话, 减小负载只针对后台打开session支持 */ if (!defined('__TYPECHO_INSTALL__') && $this->widget('Widget_User')->hasLogin()) {