diff --git a/var/Typecho/Common.php b/var/Typecho/Common.php index bd454f57..575c59ee 100644 --- a/var/Typecho/Common.php +++ b/var/Typecho/Common.php @@ -9,341 +9,295 @@ * @version $Id$ */ -define('__TYPECHO_MB_SUPPORTED__', function_exists('mb_get_info') && function_exists('mb_regex_encoding')); - -/** - * I18n function - * - * @param string $string 需要翻译的文字 - * @param mixed ...$args 参数 - * - * @return string - */ -function _t(string $string, ...$args): string -{ - if (empty($args)) { - return Typecho_I18n::translate($string); - } else { - return vsprintf(Typecho_I18n::translate($string), $args); - } -} - -/** - * I18n function, translate and echo - * - * @param string $string 需要翻译的文字 - * @param mixed ...$args 参数 - */ -function _e(string $string, ...$args) -{ - array_unshift($args, $string); - echo call_user_func_array('_t', $args); -} - -/** - * 针对复数形式的翻译函数 - * - * @param string $single 单数形式的翻译 - * @param string $plural 复数形式的翻译 - * @param integer $number 数字 - * - * @return string - */ -function _n(string $single, string $plural, int $number): string -{ - return str_replace('%d', $number, Typecho_I18n::ngettext($single, $plural, $number)); -} - -/** - * Typecho公用方法 - * - * @category typecho - * @package Common - * @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org) - * @license GNU General Public License 2.0 - */ -class Typecho_Common -{ - /** 程序版本 */ - const VERSION = '1.2.0'; +namespace { + define('__TYPECHO_MB_SUPPORTED__', function_exists('mb_get_info') && function_exists('mb_regex_encoding')); /** - * 默认编码 + * I18n function * - * @access public - * @var string - */ - public static $charset = 'UTF-8'; - - /** - * 异常处理类 - * - * @access public - * @var string - */ - public static $exceptionHandle; - - /** - * 允许的属性 - * - * @access private - * @var array - */ - private static $_allowableAttributes = []; - - /** - * 将字符串变成大写的回调函数 - * - * @param array $matches - * - * @access public - * @return string - */ - public static function __strToUpper($matches) - { - return strtoupper($matches[0]); - } - - /** - * 将url中的非法xss去掉时的数组回调过滤函数 - * - * @access private - * - * @param string $string 需要过滤的字符串 + * @param string $string 需要翻译的文字 + * @param mixed ...$args 参数 * * @return string */ - public static function __removeUrlXss($string) + function _t(string $string, ...$args): string { - $string = str_replace(['%0d', '%0a'], '', strip_tags($string)); - return preg_replace([ - "/\(\s*(\"|')/i", //函数开头 - "/(\"|')\s*\)/i", //函数结尾 - ], '', $string); + if (empty($args)) { + return Typecho_I18n::translate($string); + } else { + return vsprintf(Typecho_I18n::translate($string), $args); + } } /** - * 检查是否为安全路径 + * I18n function, translate and echo * - * @access public - * - * @param string $path 检查是否为安全路径 - * - * @return boolean + * @param string $string 需要翻译的文字 + * @param mixed ...$args 参数 */ - public static function __safePath($path) + function _e(string $string, ...$args) { - $safePath = rtrim(__TYPECHO_ROOT_DIR__, '/'); - return 0 === strpos($path, $safePath); + array_unshift($args, $string); + echo call_user_func_array('_t', $args); } /** - * __filterAttrs + * 针对复数形式的翻译函数 * - * @param mixed $matches + * @param string $single 单数形式的翻译 + * @param string $plural 复数形式的翻译 + * @param integer $number 数字 * - * @static - * @access public - * @return bool + * @return string */ - public static function __filterAttrs($matches) + function _n(string $single, string $plural, int $number): string { - if (!isset($matches[2])) { - return $matches[0]; - } + return str_replace('%d', $number, Typecho_I18n::ngettext($single, $plural, $number)); + } - $str = trim($matches[2]); + // autoload class + spl_autoload_register(function ($className) { + $path = str_replace(['_', '\\'], '/', $className) . '.php'; + $defaultFile = __TYPECHO_ROOT_DIR__ . '/var/' . $path; - if (empty($str)) { - return $matches[0]; - } + if (file_exists($defaultFile)) { + include_once $defaultFile; + } else { + $pluginFile = __TYPECHO_ROOT_DIR__ . __TYPECHO_PLUGIN_DIR__ . '/' . $path; - $attrs = self::__parseAttrs($str); - $parsedAttrs = []; - $tag = strtolower($matches[1]); - - foreach ($attrs as $key => $val) { - if (in_array($key, self::$_allowableAttributes[$tag])) { - $parsedAttrs[] = " {$key}" . (empty($val) ? '' : "={$val}"); + if (file_exists($pluginFile)) { + include_once $pluginFile; + } else { + return; } } - return '<' . $tag . implode('', $parsedAttrs) . '>'; - } + // hook old class loader + if ( + strpos($className, '_') !== false + && !class_exists($className, false) + && !interface_exists($className, false) + && !trait_exists($className, false) + ) { + $aliasClass = '\\' . str_replace('_', '\\', $className); + class_alias($aliasClass, $className); + } + }); +} + +namespace Typecho { /** - * 解析属性 + * Typecho公用方法 * - * @access public - * - * @param string $attrs 属性字符串 - * - * @return array + * @category typecho + * @package Common + * @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org) + * @license GNU General Public License 2.0 */ - public static function __parseAttrs($attrs) + class Common { - $attrs = trim($attrs); - $len = strlen($attrs); - $pos = - 1; - $result = []; - $quote = ''; - $key = ''; - $value = ''; + /** 程序版本 */ + public const VERSION = '1.2.0'; - for ($i = 0; $i < $len; $i ++) { - if ('=' != $attrs[$i] && !ctype_space($attrs[$i]) && - 1 == $pos) { - $key .= $attrs[$i]; + /** + * 默认编码 + * + * @access public + * @var string + */ + public static $charset = 'UTF-8'; - /** 最后一个 */ - if ($i == $len - 1) { + /** + * 异常处理类 + * + * @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 = ''; + } + + $key = ''; + $value = ''; + $pos = -1; + $key .= $attrs[$i]; + } + } + + return $result; + } + + /** + * 将路径转化为链接 + * + * @access public + * + * @param string $path 路径 + * @param string $prefix 前缀 + * + * @return string + */ + public static function url($path, $prefix) + { + $path = (0 === strpos($path, './')) ? substr($path, 2) : $path; + return rtrim( + rtrim($prefix, '/') . '/' + . str_replace('//', '/', ltrim($path, '/')), + '/' + ); + } + + /** + * 程序初始化方法 + * + * @access public + * @return void + */ + public static function init() + { + /** 设置异常截获函数 */ + set_exception_handler(function (\Throwable $exception) { + if (defined('__TYPECHO_DEBUG__') && __TYPECHO_DEBUG__) { + echo '
';
+ echo '' . htmlspecialchars($exception->getMessage()) . '
';
+ echo htmlspecialchars($exception->__toString());
+ echo '
';
+ } else {
+ @ob_end_clean();
+ if (404 == $exception->getCode() && !empty(self::$exceptionHandle)) {
+ $handleClass = self::$exceptionHandle;
+ new $handleClass($exception);
+ } else {
+ self::error($exception);
}
}
- } 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] = '';
+ exit(1);
+ });
+ }
+
+ /**
+ * 输出错误页面
+ *
+ * @param \Throwable $exception 错误信息
+ */
+ public static function error(\Throwable $exception)
+ {
+ $code = $exception->getCode() ?: 500;
+ $message = $exception->getMessage();
+ $charset = self::$charset;
+
+ if ($exception instanceof \Typecho_Db_Exception) {
+ $code = 500;
+
+ //覆盖原始错误信息
+ $message = 'Database Server Error';
+
+ if ($exception instanceof \Typecho_Db_Adapter_Exception) {
+ $code = 503;
+ $message = 'Error establishing a database connection';
+ } elseif ($exception instanceof \Typecho_Db_Query_Exception) {
+ $message = 'Database Query Error';
}
-
- $key = '';
- $value = '';
- $pos = - 1;
- $key .= $attrs[$i];
}
- }
- return $result;
- }
-
- /**
- * 自动载入类
- *
- * @param $className
- */
- public static function __autoLoad($className)
- {
- $classFile = str_replace(['\\', '_'], '/', $className) . '.php';
- $systemPath = self::url($classFile, __TYPECHO_ROOT_DIR__ . '/var');
-
- if (file_exists($systemPath)) {
- @include_once $systemPath;
- } else {
- $pluginPath = self::url($classFile, __TYPECHO_ROOT_DIR__ . __TYPECHO_PLUGIN_DIR__);
-
- if (file_exists($pluginPath)) {
- @include_once $pluginPath;
+ /** 设置http code */
+ if (is_numeric($code) && $code > 200) {
+ \Typecho_Response::setStatus($code);
}
- }
- }
- /**
- * 将路径转化为链接
- *
- * @access public
- *
- * @param string $path 路径
- * @param string $prefix 前缀
- *
- * @return string
- */
- public static function url($path, $prefix)
- {
- $path = (0 === strpos($path, './')) ? substr($path, 2) : $path;
- return rtrim(
- rtrim($prefix, '/') . '/'
- . str_replace('//', '/', ltrim($path, '/')),
- '/'
- );
- }
+ $message = nl2br($message);
- /**
- * 程序初始化方法
- *
- * @access public
- * @return void
- */
- public static function init()
- {
- /** 设置自动载入函数 */
- spl_autoload_register(['Typecho_Common', '__autoLoad']);
-
- /** 设置异常截获函数 */
- set_exception_handler(function (Throwable $exception) {
- if (defined('__TYPECHO_DEBUG__') && __TYPECHO_DEBUG__) {
- echo '';
- echo '' . htmlspecialchars($exception->getMessage()) . '
';
- echo htmlspecialchars($exception->__toString());
- echo '
';
+ if (defined('__TYPECHO_EXCEPTION_FILE__')) {
+ require_once __TYPECHO_EXCEPTION_FILE__;
} else {
- @ob_end_clean();
- if (404 == $exception->getCode() && !empty(self::$exceptionHandle)) {
- $handleClass = self::$exceptionHandle;
- new $handleClass($exception);
- } else {
- self::error($exception);
- }
- }
-
- exit(1);
- });
- }
-
- /**
- * 输出错误页面
- *
- * @param Throwable $exception 错误信息
- */
- public static function error(Throwable $exception)
- {
- $code = $exception->getCode() ?: 500;
- $message = $exception->getMessage();
- $charset = self::$charset;
-
- if ($exception instanceof Typecho_Db_Exception) {
- $code = 500;
-
- //覆盖原始错误信息
- $message = 'Database Server Error';
-
- if ($exception instanceof Typecho_Db_Adapter_Exception) {
- $code = 503;
- $message = 'Error establishing a database connection';
- } elseif ($exception instanceof Typecho_Db_Query_Exception) {
- $message = 'Database Query Error';
- }
- }
-
- /** 设置http code */
- if (is_numeric($code) && $code > 200) {
- Typecho_Response::setStatus($code);
- }
-
- $message = nl2br($message);
-
- if (defined('__TYPECHO_EXCEPTION_FILE__')) {
- require_once __TYPECHO_EXCEPTION_FILE__;
- } else {
- echo
- <<
+ * echo splitByCount(20, 10, 20, 30, 40, 50);
+ *
+ *
+ * @access public
+ *
+ * @param int $count
+ *
+ * @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 (preg_match("/^(area|base|br|col|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/i", $tag)) {
+ 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", '', $string);
+ }
+
+ /**
+ * 去掉字符串中的html标签
+ * 使用方法:
+ *
+ * $input = 'hello';
+ * $output = Typecho_Common::stripTags($input, );
+ * echo $output;
+ * //display: 'hello'
+ *
+ *
+ * @access public
+ *
+ * @param string $html 需要处理的字符串
+ * @param string|null $allowableTags 需要忽略的html标签
+ *
+ * @return string
+ */
+ public static function stripTags(string $html, ?string $allowableTags = null): string
+ {
+ $normalizeTags = '';
+ $allowableAttributes = [];
+
+ if (!empty($allowableTags) && preg_match_all("/\<([_a-z0-9-]+)([^>]*)\>/is", $allowableTags, $tags)) {
+ $normalizeTags = '<' . implode('><', array_map('strtolower', $tags[1])) . '>';
+ $attributes = array_map('trim', $tags[2]);
+ foreach ($attributes as $key => $val) {
+ $allowableAttributes[strtolower($tags[1][$key])] =
+ array_map('strtolower', array_keys(self::__parseAttrs($val)));
+ }
+ }
+
+ $html = strip_tags($html, $normalizeTags);
+ return preg_replace_callback(
+ "/<([_a-z0-9-]+)(\s+[^>]+)?>/is",
+ function ($matches) use ($allowableAttributes) {
+ if (!isset($matches[2])) {
+ return $matches[0];
+ }
+
+ $str = trim($matches[2]);
+
+ if (empty($str)) {
+ return $matches[0];
+ }
+
+ $attrs = self::__parseAttrs($str);
+ $parsedAttrs = [];
+ $tag = strtolower($matches[1]);
+
+ foreach ($attrs as $key => $val) {
+ if (in_array($key, $allowableAttributes[$tag])) {
+ $parsedAttrs[] = " {$key}" . (empty($val) ? '' : "={$val}");
+ }
+ }
+
+ return '<' . $tag . implode('', $parsedAttrs) . '>';
+ },
+ $html
+ );
+ }
+
+ /**
+ * 过滤用于搜索的字符串
+ *
+ * @access public
+ *
+ * @param string $query 搜索字符串
+ *
+ * @return string
+ */
+ public static function filterSearchQuery($query)
+ {
+ return str_replace('-', ' ', self::slugName($query));
+ }
+
+ /**
+ * 生成缩略名
+ *
+ * @access public
+ *
+ * @param string $str 需要生成缩略名的字符串
+ * @param string $default 默认的缩略名
+ * @param integer $maxLength 缩略名最大长度
+ *
+ * @return string
+ */
+ public static function slugName($str, $default = null, $maxLength = 128)
+ {
+ $str = trim($str);
+
+ if (!strlen($str)) {
+ return $default;
+ }
+
+ if (__TYPECHO_MB_SUPPORTED__) {
+ mb_regex_encoding(self::$charset);
+ mb_ereg_search_init($str, "[\w" . preg_quote('_-') . "]+");
+ $result = mb_ereg_search();
+ $return = '';
+
+ if ($result) {
+ $regs = mb_ereg_search_getregs();
+ $pos = 0;
+ do {
+ $return .= ($pos > 0 ? '-' : '') . $regs[0];
+ $pos++;
+ } while ($regs = mb_ereg_search_regs());
+ }
+
+ $str = $return;
+ } elseif ('UTF-8' == strtoupper(self::$charset)) {
+ if (preg_match_all("/[\w" . preg_quote('_-') . "]+/u", $str, $matches)) {
+ $str = implode('-', $matches[0]);
+ }
} else {
- return false;
+ $str = str_replace(["'", ":", "\\", "/", '"'], "", $str);
+ $str = str_replace(
+ ["+", ",", ' ', ',', ' ', ".", "?", "=", "&", "!", "<", ">", "(", ")", "[", "]", "{", "}"],
+ "-",
+ $str
+ );
+ }
+
+ $str = trim($str, '-_');
+ $str = !strlen($str) ? $default : $str;
+ return substr($str, 0, $maxLength);
+ }
+
+ /**
+ * 将url中的非法字符串
+ *
+ * @param string $url 需要过滤的url
+ *
+ * @return string
+ */
+ public static function safeUrl($url)
+ {
+ //~ 针对location的xss过滤, 因为其特殊性无法使用removeXSS函数
+ //~ fix issue 66
+ $params = parse_url(str_replace(["\r", "\n", "\t", ' '], '', $url));
+
+ /** 禁止非法的协议跳转 */
+ if (isset($params['scheme'])) {
+ if (!in_array($params['scheme'], ['http', 'https'])) {
+ return '/';
+ }
+ }
+
+ /** 过滤解析串 */
+ $params = array_map(['Typecho_Common', '__removeUrlXss'], $params);
+ return self::buildUrl($params);
+ }
+
+ /**
+ * 根据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)
+ . ($params['host'] ?? null)
+ . (isset($params['port']) ? ':' . $params['port'] : null)
+ . ($params['path'] ?? null)
+ . (isset($params['query']) ? '?' . $params['query'] : null)
+ . (isset($params['fragment']) ? '#' . $params['fragment'] : null);
+ }
+
+ /**
+ * 处理XSS跨站攻击的过滤函数
+ *
+ * @param string $val 需要处理的字符串
+ *
+ * @return string
+ * @author kallahar@kallahar.com
+ * @link http://kallahar.com/smallprojects/php_xss_filter_function.php
+ * @access public
+ */
+ 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
+ // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
+ $val = preg_replace('/([\x00-\x08]|[\x0b-\x0c]|[\x0e-\x19])/', '', $val);
+
+ // straight replacements, the user should never need these since they're normal characters
+ // this prevents like
+ $search = 'abcdefghijklmnopqrstuvwxyz';
+ $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ $search .= '1234567890!@#$%^&*()';
+ $search .= '~`";:?+/={}[]-_|\'\\';
+
+ for ($i = 0; $i < strlen($search); $i++) {
+ // ;? matches the ;, which is optional
+ // 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 ;
+ // @ @ 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'];
+ $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'
+ ];
+ $ra = array_merge($ra1, $ra2);
+
+ $found = true; // keep replacing as long as the previous round replaced something
+ while ($found == true) {
+ $val_before = $val;
+ for ($i = 0; $i < sizeof($ra); $i++) {
+ $pattern = '/';
+ for ($j = 0; $j < strlen($ra[$i]); $j++) {
+ if ($j > 0) {
+ $pattern .= '(';
+ $pattern .= '([xX]0{0,8}([9ab]);)';
+ $pattern .= '|';
+ $pattern .= '|({0,8}([9|10|13]);)';
+ $pattern .= ')*';
+ }
+ $pattern .= $ra[$i][$j];
+ }
+ $pattern .= '/i';
+ $replacement = substr($ra[$i], 0, 2) . '' . substr($ra[$i], 2); // add in <> to nerf the tag
+ $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
+
+ if ($val_before == $val) {
+ // no replacements were made, so exit the loop
+ $found = false;
+ }
+ }
+ }
+
+ return $val;
+ }
+
+ /**
+ * 宽字符串截字函数
+ *
+ * @access public
+ *
+ * @param string $str 需要截取的字符串
+ * @param integer $start 开始截取的位置
+ * @param integer $length 需要截取的长度
+ * @param string $trim 截取后的截断标示符
+ *
+ * @return string
+ */
+ public static function subStr($str, $start, $length, $trim = "...")
+ {
+ if (!strlen($str)) {
+ return '';
+ }
+
+ $iLength = self::strLen($str) - $start;
+ $tLength = $length < $iLength ? ($length - self::strLen($trim)) : $length;
+
+ if (__TYPECHO_MB_SUPPORTED__) {
+ $str = mb_substr($str, $start, $tLength, self::$charset);
+ } else {
+ if ('UTF-8' == strtoupper(self::$charset)) {
+ if (preg_match_all("/./u", $str, $matches)) {
+ $str = implode('', array_slice($matches[0], $start, $tLength));
+ }
+ } else {
+ $str = substr($str, $start, $tLength);
+ }
+ }
+
+ return $length < $iLength ? ($str . $trim) : $str;
+ }
+
+ /**
+ * 获取宽字符串长度函数
+ *
+ * @access public
+ *
+ * @param string $str 需要获取长度的字符串
+ *
+ * @return integer
+ */
+ public static function strLen($str)
+ {
+ if (__TYPECHO_MB_SUPPORTED__) {
+ return mb_strlen($str, self::$charset);
+ } else {
+ return 'UTF-8' == strtoupper(self::$charset)
+ ? strlen(utf8_decode($str)) : strlen($str);
}
}
- foreach ($dirs as $dir) {
- if (!empty($dir)) {
- if (file_exists($dir . '/' . $file)) {
+ /**
+ * 判断hash值是否相等
+ *
+ * @access public
+ *
+ * @param string|null $from 源字符串
+ * @param string|null $to 目标字符串
+ *
+ * @return boolean
+ */
+ public static function hashValidate(?string $from, ?string $to): bool
+ {
+ if ($from === null || $to === null) {
+ return false;
+ }
+
+ if ('$T$' == substr($to, 0, 3)) {
+ $salt = substr($to, 3, 9);
+ return self::hash($from, $salt) === $to;
+ } else {
+ return md5($from) === $to;
+ }
+ }
+
+ /**
+ * 对字符串进行hash加密
+ *
+ * @access public
+ *
+ * @param string|null $string 需要hash的字符串
+ * @param string|null $salt 扰码
+ *
+ * @return string
+ */
+ public static function hash(?string $string, ?string $salt = null): string
+ {
+ if ($string === null) {
+ return '';
+ }
+
+ /** 生成随机字符串 */
+ $salt = empty($salt) ? self::randString(9) : $salt;
+ $length = strlen($string);
+
+ if ($length == 0) {
+ return '';
+ }
+
+ $hash = '';
+ $last = ord($string[$length - 1]);
+ $pos = 0;
+
+ /** 判断扰码长度 */
+ if (strlen($salt) != 9) {
+ /** 如果不是9直接返回 */
+ return '';
+ }
+
+ while ($pos < $length) {
+ $asc = ord($string[$pos]);
+ $last = ($last * ord($salt[($last % $asc) % 9]) + $asc) % 95 + 32;
+ $hash .= chr($last);
+ $pos++;
+ }
+
+ return '$T$' . $salt . md5($hash);
+ }
+
+ /**
+ * 生成随机字符串
+ *
+ * @access public
+ *
+ * @param integer $length 字符串长度
+ * @param boolean $specialChars 是否有特殊字符
+ *
+ * @return string
+ */
+ public static function randString($length, $specialChars = false)
+ {
+ $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+ if ($specialChars) {
+ $chars .= '!@#$%^&*()';
+ }
+
+ $result = '';
+ $max = strlen($chars) - 1;
+ for ($i = 0; $i < $length; $i++) {
+ $result .= $chars[rand(0, $max)];
+ }
+ return $result;
+ }
+
+ /**
+ * 创建一个会过期的Token
+ *
+ * @param $secret
+ *
+ * @return string
+ */
+ public static function timeToken($secret)
+ {
+ return sha1($secret . '&' . time());
+ }
+
+ /**
+ * 在时间范围内验证token
+ *
+ * @param $token
+ * @param $secret
+ * @param int $timeout
+ *
+ * @return bool
+ */
+ public static function timeTokenValidate($token, $secret, $timeout = 5)
+ {
+ $now = time();
+ $from = $now - $timeout;
+
+ for ($i = $now; $i >= $from; $i--) {
+ if (sha1($secret . '&' . $i) == $token) {
return true;
}
}
+
+ return false;
}
- return false;
- }
-
- /**
- * @param array $value
- * @param $key
- * @deprecated use array_column instead
- *
- * @return array
- */
- public static function arrayFlatten(array $value, $key): array
- {
- return array_column($value, $key);
- }
-
- /**
- * 根据count数目来输出字符
- *
- * echo splitByCount(20, 10, 20, 30, 40, 50);
- *
- *
- * @access public
- *
- * @param int $count
- *
- * @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 (preg_match("/^(area|base|br|col|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/i", $tag)) {
- 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", '', $string);
- }
-
- /**
- * 去掉字符串中的html标签
- * 使用方法:
- *
- * $input = 'hello';
- * $output = Typecho_Common::stripTags($input, );
- * echo $output;
- * //display: 'hello'
- *
- *
- * @access public
- *
- * @param string $html 需要处理的字符串
- * @param string $allowableTags 需要忽略的html标签
- *
- * @return string
- */
- public static function stripTags($html, $allowableTags = null)
- {
- $normalizeTags = '';
- $allowableAttributes = [];
-
- if (!empty($allowableTags) && preg_match_all("/\<([_a-z0-9-]+)([^>]*)\>/is", $allowableTags, $tags)) {
- $normalizeTags = '<' . implode('><', array_map('strtolower', $tags[1])) . '>';
- $attributes = array_map('trim', $tags[2]);
- foreach ($attributes as $key => $val) {
- $allowableAttributes[strtolower($tags[1][$key])] =
- array_map('strtolower', array_keys(self::__parseAttrs($val)));
- }
- }
-
- self::$_allowableAttributes = $allowableAttributes;
- $html = strip_tags($html, $normalizeTags);
- $html = preg_replace_callback("/<([_a-z0-9-]+)(\s+[^>]+)?>/is",
- ['Typecho_Common', '__filterAttrs'], $html);
-
- return $html;
- }
-
- /**
- * 过滤用于搜索的字符串
- *
- * @access public
- *
- * @param string $query 搜索字符串
- *
- * @return string
- */
- public static function filterSearchQuery($query)
- {
- return str_replace('-', ' ', self::slugName($query));
- }
-
- /**
- * 生成缩略名
- *
- * @access public
- *
- * @param string $str 需要生成缩略名的字符串
- * @param string $default 默认的缩略名
- * @param integer $maxLength 缩略名最大长度
- *
- * @return string
- */
- public static function slugName($str, $default = null, $maxLength = 128)
- {
- $str = trim($str);
-
- if (!strlen($str)) {
- return $default;
- }
-
- if (__TYPECHO_MB_SUPPORTED__) {
- mb_regex_encoding(self::$charset);
- mb_ereg_search_init($str, "[\w" . preg_quote('_-') . "]+");
- $result = mb_ereg_search();
- $return = '';
-
- if ($result) {
- $regs = mb_ereg_search_getregs();
- $pos = 0;
- do {
- $return .= ($pos > 0 ? '-' : '') . $regs[0];
- $pos ++;
- } while ($regs = mb_ereg_search_regs());
- }
-
- $str = $return;
- } elseif ('UTF-8' == strtoupper(self::$charset)) {
- if (preg_match_all("/[\w" . preg_quote('_-') . "]+/u", $str, $matches)) {
- $str = implode('-', $matches[0]);
- }
- } else {
- $str = str_replace(["'", ":", "\\", "/", '"'], "", $str);
- $str = str_replace(["+", ",", ' ', ',', ' ', ".", "?", "=", "&", "!", "<", ">", "(", ")", "[", "]", "{", "}"], "-", $str);
- }
-
- $str = trim($str, '-_');
- $str = !strlen($str) ? $default : $str;
- return substr($str, 0, $maxLength);
- }
-
- /**
- * 将url中的非法字符串
- *
- * @param string $url 需要过滤的url
- *
- * @return string
- */
- public static function safeUrl($url)
- {
- //~ 针对location的xss过滤, 因为其特殊性无法使用removeXSS函数
- //~ fix issue 66
- $params = parse_url(str_replace(["\r", "\n", "\t", ' '], '', $url));
-
- /** 禁止非法的协议跳转 */
- if (isset($params['scheme'])) {
- if (!in_array($params['scheme'], ['http', 'https'])) {
- return '/';
- }
- }
-
- /** 过滤解析串 */
- $params = array_map(['Typecho_Common', '__removeUrlXss'], $params);
- return self::buildUrl($params);
- }
-
- /**
- * 根据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);
- }
-
- /**
- * 处理XSS跨站攻击的过滤函数
- *
- * @param string $val 需要处理的字符串
- *
- * @return string
- * @author kallahar@kallahar.com
- * @link http://kallahar.com/smallprojects/php_xss_filter_function.php
- * @access public
- */
- 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
- // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
- $val = preg_replace('/([\x00-\x08]|[\x0b-\x0c]|[\x0e-\x19])/', '', $val);
-
- // straight replacements, the user should never need these since they're normal characters
- // this prevents like
- $search = 'abcdefghijklmnopqrstuvwxyz';
- $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
- $search .= '1234567890!@#$%^&*()';
- $search .= '~`";:?+/={}[]-_|\'\\';
-
- for ($i = 0; $i < strlen($search); $i ++) {
- // ;? matches the ;, which is optional
- // 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 ;
- // @ @ 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'];
- $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'
- ];
- $ra = array_merge($ra1, $ra2);
-
- $found = true; // keep replacing as long as the previous round replaced something
- while ($found == true) {
- $val_before = $val;
- for ($i = 0; $i < sizeof($ra); $i ++) {
- $pattern = '/';
- for ($j = 0; $j < strlen($ra[$i]); $j ++) {
- if ($j > 0) {
- $pattern .= '(';
- $pattern .= '([xX]0{0,8}([9ab]);)';
- $pattern .= '|';
- $pattern .= '|({0,8}([9|10|13]);)';
- $pattern .= ')*';
- }
- $pattern .= $ra[$i][$j];
- }
- $pattern .= '/i';
- $replacement = substr($ra[$i], 0, 2) . '' . substr($ra[$i], 2); // add in <> to nerf the tag
- $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
-
- if ($val_before == $val) {
- // no replacements were made, so exit the loop
- $found = false;
- }
- }
- }
-
- return $val;
- }
-
- /**
- * 宽字符串截字函数
- *
- * @access public
- *
- * @param string $str 需要截取的字符串
- * @param integer $start 开始截取的位置
- * @param integer $length 需要截取的长度
- * @param string $trim 截取后的截断标示符
- *
- * @return string
- */
- public static function subStr($str, $start, $length, $trim = "...")
- {
- if (!strlen($str)) {
- return '';
- }
-
- $iLength = self::strLen($str) - $start;
- $tLength = $length < $iLength ? ($length - self::strLen($trim)) : $length;
-
- if (__TYPECHO_MB_SUPPORTED__) {
- $str = mb_substr($str, $start, $tLength, self::$charset);
- } else {
- if ('UTF-8' == strtoupper(self::$charset)) {
- if (preg_match_all("/./u", $str, $matches)) {
- $str = implode('', array_slice($matches[0], $start, $tLength));
- }
+ /**
+ * 获取gravatar头像地址
+ *
+ * @param string $mail
+ * @param int $size
+ * @param string $rating
+ * @param string $default
+ * @param bool $isSecure
+ *
+ * @return string
+ */
+ public static function gravatarUrl($mail, $size, $rating, $default, $isSecure = false)
+ {
+ if (defined('__TYPECHO_GRAVATAR_PREFIX__')) {
+ $url = __TYPECHO_GRAVATAR_PREFIX__;
} else {
- $str = substr($str, $start, $tLength);
+ $url = $isSecure ? 'https://secure.gravatar.com' : 'http://www.gravatar.com';
+ $url .= '/avatar/';
}
- }
- return $length < $iLength ? ($str . $trim) : $str;
- }
-
- /**
- * 获取宽字符串长度函数
- *
- * @access public
- *
- * @param string $str 需要获取长度的字符串
- *
- * @return integer
- */
- public static function strLen($str)
- {
- if (__TYPECHO_MB_SUPPORTED__) {
- return mb_strlen($str, self::$charset);
- } else {
- return 'UTF-8' == strtoupper(self::$charset)
- ? strlen(utf8_decode($str)) : strlen($str);
- }
- }
-
- /**
- * 获取大写字符串
- *
- * @param string $str
- *
- * @access public
- * @return string
- */
- public static function strToUpper($str)
- {
- if (__TYPECHO_MB_SUPPORTED__) {
- return mb_strtoupper($str, self::$charset);
- } else {
- return 'UTF-8' == strtoupper(self::$charset)
- ? preg_replace_callback("/[a-z]+/u", ['Typecho_Common', '__strToUpper'], $str) : strtoupper($str);
- }
- }
-
- /**
- * 检查是否为合法的编码数据
- *
- * @param string|array $str
- *
- * @return boolean
- */
- public static function checkStrEncoding($str)
- {
- if (is_array($str)) {
- return array_map(['Typecho_Common', 'checkStrEncoding'], $str);
- }
-
- if (__TYPECHO_MB_SUPPORTED__) {
- return mb_check_encoding($str, self::$charset);
- } else {
- // just support utf-8
- return preg_match('//u', $str);
- }
- }
-
- /**
- * 判断hash值是否相等
- *
- * @access public
- *
- * @param string $from 源字符串
- * @param string $to 目标字符串
- *
- * @return boolean
- */
- public static function hashValidate($from, $to)
- {
- if ('$T$' == substr($to, 0, 3)) {
- $salt = substr($to, 3, 9);
- return self::hash($from, $salt) === $to;
- } else {
- return md5($from) === $to;
- }
- }
-
- /**
- * 对字符串进行hash加密
- *
- * @access public
- *
- * @param string $string 需要hash的字符串
- * @param string $salt 扰码
- *
- * @return string
- */
- public static function hash($string, $salt = null)
- {
- /** 生成随机字符串 */
- $salt = empty($salt) ? self::randString(9) : $salt;
- $length = strlen($string);
- $hash = '';
- $last = ord($string[$length - 1]);
- $pos = 0;
-
- /** 判断扰码长度 */
- if (strlen($salt) != 9) {
- /** 如果不是9直接返回 */
- return;
- }
-
- while ($pos < $length) {
- $asc = ord($string[$pos]);
- $last = ($last * ord($salt[($last % $asc) % 9]) + $asc) % 95 + 32;
- $hash .= chr($last);
- $pos ++;
- }
-
- return '$T$' . $salt . md5($hash);
- }
-
- /**
- * 生成随机字符串
- *
- * @access public
- *
- * @param integer $length 字符串长度
- * @param boolean $specialChars 是否有特殊字符
- *
- * @return string
- */
- public static function randString($length, $specialChars = false)
- {
- $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
- if ($specialChars) {
- $chars .= '!@#$%^&*()';
- }
-
- $result = '';
- $max = strlen($chars) - 1;
- for ($i = 0; $i < $length; $i ++) {
- $result .= $chars[rand(0, $max)];
- }
- return $result;
- }
-
- /**
- * 创建一个会过期的Token
- *
- * @param $secret
- *
- * @return string
- */
- public static function timeToken($secret)
- {
- return sha1($secret . '&' . time());
- }
-
- /**
- * 在时间范围内验证token
- *
- * @param $token
- * @param $secret
- * @param int $timeout
- *
- * @return bool
- */
- public static function timeTokenValidate($token, $secret, $timeout = 5)
- {
- $now = time();
- $from = $now - $timeout;
-
- for ($i = $now; $i >= $from; $i --) {
- if (sha1($secret . '&' . $i) == $token) {
- return true;
+ if (!empty($mail)) {
+ $url .= md5(strtolower(trim($mail)));
}
+
+ $url .= '?s=' . $size;
+ $url .= '&r=' . $rating;
+ $url .= '&d=' . $default;
+
+ return $url;
}
- return false;
- }
+ /**
+ * 给javascript赋值加入扰码设计
+ *
+ * @param string $value
+ *
+ * @return string
+ */
+ public static function shuffleScriptVar($value)
+ {
+ $length = strlen($value);
+ $max = 3;
+ $offset = 0;
+ $result = [];
+ $cut = [];
- /**
- * 获取gravatar头像地址
- *
- * @param string $mail
- * @param int $size
- * @param string $rating
- * @param string $default
- * @param bool $isSecure
- *
- * @return string
- */
- public static function gravatarUrl($mail, $size, $rating, $default, $isSecure = false)
- {
- if (defined('__TYPECHO_GRAVATAR_PREFIX__')) {
- $url = __TYPECHO_GRAVATAR_PREFIX__;
- } else {
- $url = $isSecure ? 'https://secure.gravatar.com' : 'http://www.gravatar.com';
- $url .= '/avatar/';
- }
+ while ($length > 0) {
+ $len = rand(0, min($max, $length));
+ $rand = "'" . self::randString(rand(1, $max)) . "'";
- if (!empty($mail)) {
- $url .= md5(strtolower(trim($mail)));
- }
-
- $url .= '?s=' . $size;
- $url .= '&r=' . $rating;
- $url .= '&d=' . $default;
-
- return $url;
- }
-
- /**
- * 给javascript赋值加入扰码设计
- *
- * @param string $value
- *
- * @return string
- */
- public static function shuffleScriptVar($value)
- {
- $length = strlen($value);
- $max = 3;
- $offset = 0;
- $result = [];
- $cut = [];
-
- while ($length > 0) {
- $len = rand(0, min($max, $length));
- $rand = "'" . self::randString(rand(1, $max)) . "'";
-
- if ($len > 0) {
- $val = "'" . substr($value, $offset, $len) . "'";
- $result[] = rand(0, 1) ? "//{$rand}\n{$val}" : "{$val}//{$rand}\n";
- } else {
- if (rand(0, 1)) {
- $result[] = rand(0, 1) ? "''///*{$rand}*/{$rand}\n" : "/* {$rand}//{$rand} */''";
+ if ($len > 0) {
+ $val = "'" . substr($value, $offset, $len) . "'";
+ $result[] = rand(0, 1) ? "//{$rand}\n{$val}" : "{$val}//{$rand}\n";
} else {
- $result[] = rand(0, 1) ? "//{$rand}\n{$rand}" : "{$rand}//{$rand}\n";
- $cut[] = [$offset, strlen($rand) - 2 + $offset];
+ if (rand(0, 1)) {
+ $result[] = rand(0, 1) ? "''///*{$rand}*/{$rand}\n" : "/* {$rand}//{$rand} */''";
+ } else {
+ $result[] = rand(0, 1) ? "//{$rand}\n{$rand}" : "{$rand}//{$rand}\n";
+ $cut[] = [$offset, strlen($rand) - 2 + $offset];
+ }
}
+
+ $offset += $len;
+ $length -= $len;
}
- $offset += $len;
- $length -= $len;
- }
-
- $name = '_' . self::randString(rand(3, 7));
- $cutName = '_' . self::randString(rand(3, 7));
- $var = implode('+', $result);
- $cutVar = Json::encode($cut);
- return "(function () {
+ $name = '_' . self::randString(rand(3, 7));
+ $cutName = '_' . self::randString(rand(3, 7));
+ $var = implode('+', $result);
+ $cutVar = Json::encode($cut);
+ return "(function () {
var {$name} = {$var}, {$cutName} = {$cutVar};
for (var i = 0; i < {$cutName}.length; i ++) {
@@ -1039,582 +995,586 @@ EOF;
return {$name};
})();";
- }
-
- /**
- * 过滤字段名
- *
- * @access private
- *
- * @param mixed $result
- *
- * @return array
- */
- public static function filterSQLite2ColumnName($result)
- {
- /** 如果结果为空,直接返回 */
- if (empty($result)) {
- return $result;
}
- $tResult = [];
-
- /** 遍历数组 */
- foreach ($result as $key => $val) {
- /** 按点分隔 */
- if (false !== ($pos = strpos($key, '.'))) {
- $key = substr($key, $pos + 1);
+ /**
+ * 过滤字段名
+ *
+ * @access private
+ *
+ * @param mixed $result
+ *
+ * @return array
+ */
+ public static function filterSQLite2ColumnName($result)
+ {
+ /** 如果结果为空,直接返回 */
+ if (empty($result)) {
+ return $result;
}
- $tResult[trim($key, '"')] = $val;
+ $tResult = [];
+
+ /** 遍历数组 */
+ foreach ($result as $key => $val) {
+ /** 按点分隔 */
+ if (false !== ($pos = strpos($key, '.'))) {
+ $key = substr($key, $pos + 1);
+ }
+
+ $tResult[trim($key, '"')] = $val;
+ }
+
+ return $tResult;
}
- return $tResult;
- }
+ /**
+ * 处理sqlite2的distinct count
+ *
+ * @param $sql
+ *
+ * @return string
+ */
+ public static function filterSQLite2CountQuery($sql)
+ {
+ if (preg_match("/SELECT\s+COUNT\(DISTINCT\s+([^\)]+)\)\s+(AS\s+[^\s]+)?\s*FROM\s+(.+)/is", $sql, $matches)) {
+ return 'SELECT COUNT(' . $matches[1] . ') ' . $matches[2] . ' FROM SELECT DISTINCT '
+ . $matches[1] . ' FROM ' . $matches[3];
+ }
- /**
- * 处理sqlite2的distinct count
- *
- * @param $sql
- *
- * @return string
- */
- public static function filterSQLite2CountQuery($sql)
- {
- if (preg_match("/SELECT\s+COUNT\(DISTINCT\s+([^\)]+)\)\s+(AS\s+[^\s]+)?\s*FROM\s+(.+)/is", $sql, $matches)) {
- return 'SELECT COUNT(' . $matches[1] . ') ' . $matches[2] . ' FROM SELECT DISTINCT '
- . $matches[1] . ' FROM ' . $matches[3];
+ return $sql;
}
- return $sql;
- }
+ /**
+ * 创建备份文件缓冲
+ *
+ * @param $type
+ * @param $header
+ * @param $body
+ *
+ * @return string
+ */
+ public static function buildBackupBuffer($type, $header, $body)
+ {
+ $buffer = '';
- /**
- * 创建备份文件缓冲
- *
- * @param $type
- * @param $header
- * @param $body
- *
- * @return string
- */
- public static function buildBackupBuffer($type, $header, $body)
- {
- $buffer = '';
+ $buffer .= pack('vvV', $type, strlen($header), strlen($body));
+ $buffer .= $header . $body;
+ $buffer .= md5($buffer);
- $buffer .= pack('vvV', $type, strlen($header), strlen($body));
- $buffer .= $header . $body;
- $buffer .= md5($buffer);
-
- return $buffer;
- }
-
- /**
- * 从备份文件中解压
- *
- * @param $fp
- * @param bool $offset
- * @param string $version
- *
- * @return array|bool
- */
- public static function extractBackupBuffer($fp, &$offset, $version)
- {
- $realMetaLen = $version == 'FILE' ? 6 : 8;
-
- $meta = fread($fp, $realMetaLen);
- $offset += $realMetaLen;
- $metaLen = strlen($meta);
-
- if (false === $meta || $metaLen != $realMetaLen) {
- return false;
+ return $buffer;
}
- [$type, $headerLen, $bodyLen] = array_values(unpack($version == 'FILE' ? 'v3' : 'v1type/v1headerLen/V1bodyLen', $meta));
+ /**
+ * 从备份文件中解压
+ *
+ * @param $fp
+ * @param bool $offset
+ * @param string $version
+ *
+ * @return array|bool
+ */
+ public static function extractBackupBuffer($fp, &$offset, $version)
+ {
+ $realMetaLen = $version == 'FILE' ? 6 : 8;
- $header = @fread($fp, $headerLen);
- $offset += $headerLen;
+ $meta = fread($fp, $realMetaLen);
+ $offset += $realMetaLen;
+ $metaLen = strlen($meta);
- if (false === $header || strlen($header) != $headerLen) {
- return false;
- }
-
- if ('FILE' == $version) {
- $bodyLen = array_reduce(json_decode($header, true), function ($carry, $len) {
- return null === $len ? $carry : $carry + $len;
- }, 0);
- }
-
- $body = @fread($fp, $bodyLen);
- $offset += $bodyLen;
-
- if (false === $body || strlen($body) != $bodyLen) {
- return false;
- }
-
- $md5 = @fread($fp, 32);
- $offset += 32;
-
- if (false === $md5 || $md5 != md5($meta . $header . $body)) {
- return false;
- }
-
- return [$type, $header, $body];
- }
-
- /**
- * 检查是否是一个安全的主机名
- *
- * @param $host
- *
- * @return bool
- */
- public static function checkSafeHost($host)
- {
- if ('localhost' == $host) {
- return false;
- }
-
- $address = gethostbyname($host);
- $inet = inet_pton($address);
-
- if (false === $inet) {
- // 有可能是ipv6的地址
- $records = dns_get_record($host, DNS_AAAA);
-
- if (empty($records)) {
+ if (false === $meta || $metaLen != $realMetaLen) {
return false;
}
- $address = $records[0]['ipv6'];
- $inet = inet_pton($address);
+ [$type, $headerLen, $bodyLen] = array_values(unpack($version == 'FILE' ? 'v3' : 'v1type/v1headerLen/V1bodyLen', $meta));
+
+ $header = @fread($fp, $headerLen);
+ $offset += $headerLen;
+
+ if (false === $header || strlen($header) != $headerLen) {
+ return false;
+ }
+
+ if ('FILE' == $version) {
+ $bodyLen = array_reduce(json_decode($header, true), function ($carry, $len) {
+ return null === $len ? $carry : $carry + $len;
+ }, 0);
+ }
+
+ $body = @fread($fp, $bodyLen);
+ $offset += $bodyLen;
+
+ if (false === $body || strlen($body) != $bodyLen) {
+ return false;
+ }
+
+ $md5 = @fread($fp, 32);
+ $offset += 32;
+
+ if (false === $md5 || $md5 != md5($meta . $header . $body)) {
+ return false;
+ }
+
+ return [$type, $header, $body];
}
- if (strpos($address, '.')) {
- // ipv4
- // 非公网地址
- $privateNetworks = [
- '10.0.0.0|10.255.255.255',
- '172.16.0.0|172.31.255.255',
- '192.168.0.0|192.168.255.255',
- '169.254.0.0|169.254.255.255',
- '127.0.0.0|127.255.255.255'
- ];
+ /**
+ * 检查是否是一个安全的主机名
+ *
+ * @param $host
+ *
+ * @return bool
+ */
+ public static function checkSafeHost($host)
+ {
+ if ('localhost' == $host) {
+ return false;
+ }
- $long = ip2long($address);
+ $address = gethostbyname($host);
+ $inet = inet_pton($address);
- foreach ($privateNetworks as $network) {
- [$from, $to] = explode('|', $network);
+ if (false === $inet) {
+ // 有可能是ipv6的地址
+ $records = dns_get_record($host, DNS_AAAA);
- if ($long >= ip2long($from) && $long <= ip2long($to)) {
+ if (empty($records)) {
+ return false;
+ }
+
+ $address = $records[0]['ipv6'];
+ $inet = inet_pton($address);
+ }
+
+ if (strpos($address, '.')) {
+ // ipv4
+ // 非公网地址
+ $privateNetworks = [
+ '10.0.0.0|10.255.255.255',
+ '172.16.0.0|172.31.255.255',
+ '192.168.0.0|192.168.255.255',
+ '169.254.0.0|169.254.255.255',
+ '127.0.0.0|127.255.255.255'
+ ];
+
+ $long = ip2long($address);
+
+ foreach ($privateNetworks as $network) {
+ [$from, $to] = explode('|', $network);
+
+ if ($long >= ip2long($from) && $long <= ip2long($to)) {
+ return false;
+ }
+ }
+ } else {
+ // ipv6
+ // https://en.wikipedia.org/wiki/Private_network
+ $from = inet_pton('fd00::');
+ $to = inet_pton('fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff');
+
+ if ($inet >= $from && $inet <= $to) {
return false;
}
}
- } else {
- // ipv6
- // https://en.wikipedia.org/wiki/Private_network
- $from = inet_pton('fd00::');
- $to = inet_pton('fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff');
- if ($inet >= $from && $inet <= $to) {
- return false;
+ return true;
+ }
+
+ /**
+ * 获取图片
+ *
+ * @access public
+ *
+ * @param string $fileName 文件名
+ *
+ * @return string
+ */
+ public static function mimeContentType($fileName)
+ {
+ //改为并列判断
+ if (function_exists('mime_content_type')) {
+ return mime_content_type($fileName);
}
- }
- return true;
- }
+ if (function_exists('finfo_open')) {
+ $fInfo = @finfo_open(FILEINFO_MIME_TYPE);
- /**
- * 获取图片
- *
- * @access public
- *
- * @param string $fileName 文件名
- *
- * @return string
- */
- public static function mimeContentType($fileName)
- {
- //改为并列判断
- if (function_exists('mime_content_type')) {
- return mime_content_type($fileName);
- }
-
- if (function_exists('finfo_open')) {
- $fInfo = @finfo_open(FILEINFO_MIME_TYPE);
-
- if (false !== $fInfo) {
- $mimeType = finfo_file($fInfo, $fileName);
- finfo_close($fInfo);
- return $mimeType;
+ if (false !== $fInfo) {
+ $mimeType = finfo_file($fInfo, $fileName);
+ finfo_close($fInfo);
+ return $mimeType;
+ }
}
- }
- $mimeTypes = [
- 'ez' => 'application/andrew-inset',
- 'csm' => 'application/cu-seeme',
- 'cu' => 'application/cu-seeme',
- 'tsp' => 'application/dsptype',
- 'spl' => 'application/x-futuresplash',
- 'hta' => 'application/hta',
- 'cpt' => 'image/x-corelphotopaint',
- 'hqx' => 'application/mac-binhex40',
- 'nb' => 'application/mathematica',
- 'mdb' => 'application/msaccess',
- 'doc' => 'application/msword',
- 'dot' => 'application/msword',
- 'bin' => 'application/octet-stream',
- 'oda' => 'application/oda',
- 'ogg' => 'application/ogg',
- 'oga' => 'audio/ogg',
- 'ogv' => 'video/ogg',
- 'prf' => 'application/pics-rules',
- 'key' => 'application/pgp-keys',
- 'pdf' => 'application/pdf',
- 'pgp' => 'application/pgp-signature',
- 'ps' => 'application/postscript',
- 'ai' => 'application/postscript',
- 'eps' => 'application/postscript',
- 'rss' => 'application/rss+xml',
- 'rtf' => 'text/rtf',
- 'smi' => 'application/smil',
- 'smil' => 'application/smil',
- 'wp5' => 'application/wordperfect5.1',
- 'xht' => 'application/xhtml+xml',
- 'xhtml' => 'application/xhtml+xml',
- 'zip' => 'application/zip',
- 'cdy' => 'application/vnd.cinderella',
- 'mif' => 'application/x-mif',
- 'xls' => 'application/vnd.ms-excel',
- 'xlb' => 'application/vnd.ms-excel',
- 'cat' => 'application/vnd.ms-pki.seccat',
- 'stl' => 'application/vnd.ms-pki.stl',
- 'ppt' => 'application/vnd.ms-powerpoint',
- 'pps' => 'application/vnd.ms-powerpoint',
- 'pot' => 'application/vnd.ms-powerpoint',
- 'sdc' => 'application/vnd.stardivision.calc',
- 'sda' => 'application/vnd.stardivision.draw',
- 'sdd' => 'application/vnd.stardivision.impress',
- 'sdp' => 'application/vnd.stardivision.impress',
- 'smf' => 'application/vnd.stardivision.math',
- 'sdw' => 'application/vnd.stardivision.writer',
- 'vor' => 'application/vnd.stardivision.writer',
- 'sgl' => 'application/vnd.stardivision.writer-global',
- 'sxc' => 'application/vnd.sun.xml.calc',
- 'stc' => 'application/vnd.sun.xml.calc.template',
- 'sxd' => 'application/vnd.sun.xml.draw',
- 'std' => 'application/vnd.sun.xml.draw.template',
- 'sxi' => 'application/vnd.sun.xml.impress',
- 'sti' => 'application/vnd.sun.xml.impress.template',
- 'sxm' => 'application/vnd.sun.xml.math',
- 'sxw' => 'application/vnd.sun.xml.writer',
- 'sxg' => 'application/vnd.sun.xml.writer.global',
- 'stw' => 'application/vnd.sun.xml.writer.template',
- 'sis' => 'application/vnd.symbian.install',
- 'wbxml' => 'application/vnd.wap.wbxml',
- 'wmlc' => 'application/vnd.wap.wmlc',
- 'wmlsc' => 'application/vnd.wap.wmlscriptc',
- 'wk' => 'application/x-123',
- 'dmg' => 'application/x-apple-diskimage',
- 'bcpio' => 'application/x-bcpio',
- 'torrent' => 'application/x-bittorrent',
- 'cdf' => 'application/x-cdf',
- 'vcd' => 'application/x-cdlink',
- 'pgn' => 'application/x-chess-pgn',
- 'cpio' => 'application/x-cpio',
- 'csh' => 'text/x-csh',
- 'deb' => 'application/x-debian-package',
- 'dcr' => 'application/x-director',
- 'dir' => 'application/x-director',
- 'dxr' => 'application/x-director',
- 'wad' => 'application/x-doom',
- 'dms' => 'application/x-dms',
- 'dvi' => 'application/x-dvi',
- 'pfa' => 'application/x-font',
- 'pfb' => 'application/x-font',
- 'gsf' => 'application/x-font',
- 'pcf' => 'application/x-font',
- 'pcf.Z' => 'application/x-font',
- 'gnumeric' => 'application/x-gnumeric',
- 'sgf' => 'application/x-go-sgf',
- 'gcf' => 'application/x-graphing-calculator',
- 'gtar' => 'application/x-gtar',
- 'tgz' => 'application/x-gtar',
- 'taz' => 'application/x-gtar',
- 'gz' => 'application/x-gtar',
- 'hdf' => 'application/x-hdf',
- 'phtml' => 'application/x-httpd-php',
- 'pht' => 'application/x-httpd-php',
- 'php' => 'application/x-httpd-php',
- 'phps' => 'application/x-httpd-php-source',
- 'php3' => 'application/x-httpd-php3',
- 'php3p' => 'application/x-httpd-php3-preprocessed',
- 'php4' => 'application/x-httpd-php4',
- 'ica' => 'application/x-ica',
- 'ins' => 'application/x-internet-signup',
- 'isp' => 'application/x-internet-signup',
- 'iii' => 'application/x-iphone',
- 'jar' => 'application/x-java-archive',
- 'jnlp' => 'application/x-java-jnlp-file',
- 'ser' => 'application/x-java-serialized-object',
- 'class' => 'application/x-java-vm',
- 'js' => 'application/x-javascript',
- 'chrt' => 'application/x-kchart',
- 'kil' => 'application/x-killustrator',
- 'kpr' => 'application/x-kpresenter',
- 'kpt' => 'application/x-kpresenter',
- 'skp' => 'application/x-koan',
- 'skd' => 'application/x-koan',
- 'skt' => 'application/x-koan',
- 'skm' => 'application/x-koan',
- 'ksp' => 'application/x-kspread',
- 'kwd' => 'application/x-kword',
- 'kwt' => 'application/x-kword',
- 'latex' => 'application/x-latex',
- 'lha' => 'application/x-lha',
- 'lzh' => 'application/x-lzh',
- 'lzx' => 'application/x-lzx',
- 'frm' => 'application/x-maker',
- 'maker' => 'application/x-maker',
- 'frame' => 'application/x-maker',
- 'fm' => 'application/x-maker',
- 'fb' => 'application/x-maker',
- 'book' => 'application/x-maker',
- 'fbdoc' => 'application/x-maker',
- 'wmz' => 'application/x-ms-wmz',
- 'wmd' => 'application/x-ms-wmd',
- 'com' => 'application/x-msdos-program',
- 'exe' => 'application/x-msdos-program',
- 'bat' => 'application/x-msdos-program',
- 'dll' => 'application/x-msdos-program',
- 'msi' => 'application/x-msi',
- 'nc' => 'application/x-netcdf',
- 'pac' => 'application/x-ns-proxy-autoconfig',
- 'nwc' => 'application/x-nwc',
- 'o' => 'application/x-object',
- 'oza' => 'application/x-oz-application',
- 'pl' => 'application/x-perl',
- 'pm' => 'application/x-perl',
- 'p7r' => 'application/x-pkcs7-certreqresp',
- 'crl' => 'application/x-pkcs7-crl',
- 'qtl' => 'application/x-quicktimeplayer',
- 'rpm' => 'audio/x-pn-realaudio-plugin',
- 'shar' => 'application/x-shar',
- 'swf' => 'application/x-shockwave-flash',
- 'swfl' => 'application/x-shockwave-flash',
- 'sh' => 'text/x-sh',
- 'sit' => 'application/x-stuffit',
- 'sv4cpio' => 'application/x-sv4cpio',
- 'sv4crc' => 'application/x-sv4crc',
- 'tar' => 'application/x-tar',
- 'tcl' => 'text/x-tcl',
- 'tex' => 'text/x-tex',
- 'gf' => 'application/x-tex-gf',
- 'pk' => 'application/x-tex-pk',
- 'texinfo' => 'application/x-texinfo',
- 'texi' => 'application/x-texinfo',
- '~' => 'application/x-trash',
- '%' => 'application/x-trash',
- 'bak' => 'application/x-trash',
- 'old' => 'application/x-trash',
- 'sik' => 'application/x-trash',
- 't' => 'application/x-troff',
- 'tr' => 'application/x-troff',
- 'roff' => 'application/x-troff',
- 'man' => 'application/x-troff-man',
- 'me' => 'application/x-troff-me',
- 'ms' => 'application/x-troff-ms',
- 'ustar' => 'application/x-ustar',
- 'src' => 'application/x-wais-source',
- 'wz' => 'application/x-wingz',
- 'crt' => 'application/x-x509-ca-cert',
- 'fig' => 'application/x-xfig',
- 'au' => 'audio/basic',
- 'snd' => 'audio/basic',
- 'mid' => 'audio/midi',
- 'midi' => 'audio/midi',
- 'kar' => 'audio/midi',
- 'mpga' => 'audio/mpeg',
- 'mpega' => 'audio/mpeg',
- 'mp2' => 'audio/mpeg',
- 'mp3' => 'audio/mpeg',
- 'mp4' => 'video/mp4',
- 'm3u' => 'audio/x-mpegurl',
- 'sid' => 'audio/prs.sid',
- 'aif' => 'audio/x-aiff',
- 'aiff' => 'audio/x-aiff',
- 'aifc' => 'audio/x-aiff',
- 'gsm' => 'audio/x-gsm',
- 'wma' => 'audio/x-ms-wma',
- 'wax' => 'audio/x-ms-wax',
- 'ra' => 'audio/x-realaudio',
- 'rm' => 'audio/x-pn-realaudio',
- 'ram' => 'audio/x-pn-realaudio',
- 'pls' => 'audio/x-scpls',
- 'sd2' => 'audio/x-sd2',
- 'wav' => 'audio/x-wav',
- 'pdb' => 'chemical/x-pdb',
- 'xyz' => 'chemical/x-xyz',
- 'bmp' => 'image/x-ms-bmp',
- 'gif' => 'image/gif',
- 'ief' => 'image/ief',
- 'jpeg' => 'image/jpeg',
- 'jpg' => 'image/jpeg',
- 'jpe' => 'image/jpeg',
- 'pcx' => 'image/pcx',
- 'png' => 'image/png',
- 'svg' => 'image/svg+xml',
- 'svgz' => 'image/svg+xml',
- 'tiff' => 'image/tiff',
- 'tif' => 'image/tiff',
- 'wbmp' => 'image/vnd.wap.wbmp',
- 'ras' => 'image/x-cmu-raster',
- 'cdr' => 'image/x-coreldraw',
- 'pat' => 'image/x-coreldrawpattern',
- 'cdt' => 'image/x-coreldrawtemplate',
- 'djvu' => 'image/x-djvu',
- 'djv' => 'image/x-djvu',
- 'ico' => 'image/x-icon',
- 'art' => 'image/x-jg',
- 'jng' => 'image/x-jng',
- 'psd' => 'image/x-photoshop',
- 'pnm' => 'image/x-portable-anymap',
- 'pbm' => 'image/x-portable-bitmap',
- 'pgm' => 'image/x-portable-graymap',
- 'ppm' => 'image/x-portable-pixmap',
- 'rgb' => 'image/x-rgb',
- 'xbm' => 'image/x-xbitmap',
- 'xpm' => 'image/x-xpixmap',
- 'xwd' => 'image/x-xwindowdump',
- 'igs' => 'model/iges',
- 'iges' => 'model/iges',
- 'msh' => 'model/mesh',
- 'mesh' => 'model/mesh',
- 'silo' => 'model/mesh',
- 'wrl' => 'x-world/x-vrml',
- 'vrml' => 'x-world/x-vrml',
- 'csv' => 'text/comma-separated-values',
- 'css' => 'text/css',
- '323' => 'text/h323',
- 'htm' => 'text/html',
- 'html' => 'text/html',
- 'uls' => 'text/iuls',
- 'mml' => 'text/mathml',
- 'asc' => 'text/plain',
- 'txt' => 'text/plain',
- 'text' => 'text/plain',
- 'diff' => 'text/plain',
- 'rtx' => 'text/richtext',
- 'sct' => 'text/scriptlet',
- 'wsc' => 'text/scriptlet',
- 'tm' => 'text/texmacs',
- 'ts' => 'text/texmacs',
- 'tsv' => 'text/tab-separated-values',
- 'jad' => 'text/vnd.sun.j2me.app-descriptor',
- 'wml' => 'text/vnd.wap.wml',
- 'wmls' => 'text/vnd.wap.wmlscript',
- 'xml' => 'text/xml',
- 'xsl' => 'text/xml',
- 'h++' => 'text/x-c++hdr',
- 'hpp' => 'text/x-c++hdr',
- 'hxx' => 'text/x-c++hdr',
- 'hh' => 'text/x-c++hdr',
- 'c++' => 'text/x-c++src',
- 'cpp' => 'text/x-c++src',
- 'cxx' => 'text/x-c++src',
- 'cc' => 'text/x-c++src',
- 'h' => 'text/x-chdr',
- 'c' => 'text/x-csrc',
- 'java' => 'text/x-java',
- 'moc' => 'text/x-moc',
- 'p' => 'text/x-pascal',
- 'pas' => 'text/x-pascal',
- '***' => 'text/x-pcs-***',
- 'shtml' => 'text/x-server-parsed-html',
- 'etx' => 'text/x-setext',
- 'tk' => 'text/x-tcl',
- 'ltx' => 'text/x-tex',
- 'sty' => 'text/x-tex',
- 'cls' => 'text/x-tex',
- 'vcs' => 'text/x-vcalendar',
- 'vcf' => 'text/x-vcard',
- 'dl' => 'video/dl',
- 'fli' => 'video/fli',
- 'gl' => 'video/gl',
- 'mpeg' => 'video/mpeg',
- 'mpg' => 'video/mpeg',
- 'mpe' => 'video/mpeg',
- 'qt' => 'video/quicktime',
- 'mov' => 'video/quicktime',
- 'mxu' => 'video/vnd.mpegurl',
- 'dif' => 'video/x-dv',
- 'dv' => 'video/x-dv',
- 'lsf' => 'video/x-la-asf',
- 'lsx' => 'video/x-la-asf',
- 'mng' => 'video/x-mng',
- 'asf' => 'video/x-ms-asf',
- 'asx' => 'video/x-ms-asf',
- 'wm' => 'video/x-ms-wm',
- 'wmv' => 'video/x-ms-wmv',
- 'wmx' => 'video/x-ms-wmx',
- 'wvx' => 'video/x-ms-wvx',
- 'avi' => 'video/x-msvideo',
- 'movie' => 'video/x-sgi-movie',
- 'ice' => 'x-conference/x-cooltalk',
- 'vrm' => 'x-world/x-vrml',
- 'rar' => 'application/x-rar-compressed',
- 'cab' => 'application/vnd.ms-cab-compressed'
- ];
+ $mimeTypes = [
+ 'ez' => 'application/andrew-inset',
+ 'csm' => 'application/cu-seeme',
+ 'cu' => 'application/cu-seeme',
+ 'tsp' => 'application/dsptype',
+ 'spl' => 'application/x-futuresplash',
+ 'hta' => 'application/hta',
+ 'cpt' => 'image/x-corelphotopaint',
+ 'hqx' => 'application/mac-binhex40',
+ 'nb' => 'application/mathematica',
+ 'mdb' => 'application/msaccess',
+ 'doc' => 'application/msword',
+ 'dot' => 'application/msword',
+ 'bin' => 'application/octet-stream',
+ 'oda' => 'application/oda',
+ 'ogg' => 'application/ogg',
+ 'oga' => 'audio/ogg',
+ 'ogv' => 'video/ogg',
+ 'prf' => 'application/pics-rules',
+ 'key' => 'application/pgp-keys',
+ 'pdf' => 'application/pdf',
+ 'pgp' => 'application/pgp-signature',
+ 'ps' => 'application/postscript',
+ 'ai' => 'application/postscript',
+ 'eps' => 'application/postscript',
+ 'rss' => 'application/rss+xml',
+ 'rtf' => 'text/rtf',
+ 'smi' => 'application/smil',
+ 'smil' => 'application/smil',
+ 'wp5' => 'application/wordperfect5.1',
+ 'xht' => 'application/xhtml+xml',
+ 'xhtml' => 'application/xhtml+xml',
+ 'zip' => 'application/zip',
+ 'cdy' => 'application/vnd.cinderella',
+ 'mif' => 'application/x-mif',
+ 'xls' => 'application/vnd.ms-excel',
+ 'xlb' => 'application/vnd.ms-excel',
+ 'cat' => 'application/vnd.ms-pki.seccat',
+ 'stl' => 'application/vnd.ms-pki.stl',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'pps' => 'application/vnd.ms-powerpoint',
+ 'pot' => 'application/vnd.ms-powerpoint',
+ 'sdc' => 'application/vnd.stardivision.calc',
+ 'sda' => 'application/vnd.stardivision.draw',
+ 'sdd' => 'application/vnd.stardivision.impress',
+ 'sdp' => 'application/vnd.stardivision.impress',
+ 'smf' => 'application/vnd.stardivision.math',
+ 'sdw' => 'application/vnd.stardivision.writer',
+ 'vor' => 'application/vnd.stardivision.writer',
+ 'sgl' => 'application/vnd.stardivision.writer-global',
+ 'sxc' => 'application/vnd.sun.xml.calc',
+ 'stc' => 'application/vnd.sun.xml.calc.template',
+ 'sxd' => 'application/vnd.sun.xml.draw',
+ 'std' => 'application/vnd.sun.xml.draw.template',
+ 'sxi' => 'application/vnd.sun.xml.impress',
+ 'sti' => 'application/vnd.sun.xml.impress.template',
+ 'sxm' => 'application/vnd.sun.xml.math',
+ 'sxw' => 'application/vnd.sun.xml.writer',
+ 'sxg' => 'application/vnd.sun.xml.writer.global',
+ 'stw' => 'application/vnd.sun.xml.writer.template',
+ 'sis' => 'application/vnd.symbian.install',
+ 'wbxml' => 'application/vnd.wap.wbxml',
+ 'wmlc' => 'application/vnd.wap.wmlc',
+ 'wmlsc' => 'application/vnd.wap.wmlscriptc',
+ 'wk' => 'application/x-123',
+ 'dmg' => 'application/x-apple-diskimage',
+ 'bcpio' => 'application/x-bcpio',
+ 'torrent' => 'application/x-bittorrent',
+ 'cdf' => 'application/x-cdf',
+ 'vcd' => 'application/x-cdlink',
+ 'pgn' => 'application/x-chess-pgn',
+ 'cpio' => 'application/x-cpio',
+ 'csh' => 'text/x-csh',
+ 'deb' => 'application/x-debian-package',
+ 'dcr' => 'application/x-director',
+ 'dir' => 'application/x-director',
+ 'dxr' => 'application/x-director',
+ 'wad' => 'application/x-doom',
+ 'dms' => 'application/x-dms',
+ 'dvi' => 'application/x-dvi',
+ 'pfa' => 'application/x-font',
+ 'pfb' => 'application/x-font',
+ 'gsf' => 'application/x-font',
+ 'pcf' => 'application/x-font',
+ 'pcf.Z' => 'application/x-font',
+ 'gnumeric' => 'application/x-gnumeric',
+ 'sgf' => 'application/x-go-sgf',
+ 'gcf' => 'application/x-graphing-calculator',
+ 'gtar' => 'application/x-gtar',
+ 'tgz' => 'application/x-gtar',
+ 'taz' => 'application/x-gtar',
+ 'gz' => 'application/x-gtar',
+ 'hdf' => 'application/x-hdf',
+ 'phtml' => 'application/x-httpd-php',
+ 'pht' => 'application/x-httpd-php',
+ 'php' => 'application/x-httpd-php',
+ 'phps' => 'application/x-httpd-php-source',
+ 'php3' => 'application/x-httpd-php3',
+ 'php3p' => 'application/x-httpd-php3-preprocessed',
+ 'php4' => 'application/x-httpd-php4',
+ 'ica' => 'application/x-ica',
+ 'ins' => 'application/x-internet-signup',
+ 'isp' => 'application/x-internet-signup',
+ 'iii' => 'application/x-iphone',
+ 'jar' => 'application/x-java-archive',
+ 'jnlp' => 'application/x-java-jnlp-file',
+ 'ser' => 'application/x-java-serialized-object',
+ 'class' => 'application/x-java-vm',
+ 'js' => 'application/x-javascript',
+ 'chrt' => 'application/x-kchart',
+ 'kil' => 'application/x-killustrator',
+ 'kpr' => 'application/x-kpresenter',
+ 'kpt' => 'application/x-kpresenter',
+ 'skp' => 'application/x-koan',
+ 'skd' => 'application/x-koan',
+ 'skt' => 'application/x-koan',
+ 'skm' => 'application/x-koan',
+ 'ksp' => 'application/x-kspread',
+ 'kwd' => 'application/x-kword',
+ 'kwt' => 'application/x-kword',
+ 'latex' => 'application/x-latex',
+ 'lha' => 'application/x-lha',
+ 'lzh' => 'application/x-lzh',
+ 'lzx' => 'application/x-lzx',
+ 'frm' => 'application/x-maker',
+ 'maker' => 'application/x-maker',
+ 'frame' => 'application/x-maker',
+ 'fm' => 'application/x-maker',
+ 'fb' => 'application/x-maker',
+ 'book' => 'application/x-maker',
+ 'fbdoc' => 'application/x-maker',
+ 'wmz' => 'application/x-ms-wmz',
+ 'wmd' => 'application/x-ms-wmd',
+ 'com' => 'application/x-msdos-program',
+ 'exe' => 'application/x-msdos-program',
+ 'bat' => 'application/x-msdos-program',
+ 'dll' => 'application/x-msdos-program',
+ 'msi' => 'application/x-msi',
+ 'nc' => 'application/x-netcdf',
+ 'pac' => 'application/x-ns-proxy-autoconfig',
+ 'nwc' => 'application/x-nwc',
+ 'o' => 'application/x-object',
+ 'oza' => 'application/x-oz-application',
+ 'pl' => 'application/x-perl',
+ 'pm' => 'application/x-perl',
+ 'p7r' => 'application/x-pkcs7-certreqresp',
+ 'crl' => 'application/x-pkcs7-crl',
+ 'qtl' => 'application/x-quicktimeplayer',
+ 'rpm' => 'audio/x-pn-realaudio-plugin',
+ 'shar' => 'application/x-shar',
+ 'swf' => 'application/x-shockwave-flash',
+ 'swfl' => 'application/x-shockwave-flash',
+ 'sh' => 'text/x-sh',
+ 'sit' => 'application/x-stuffit',
+ 'sv4cpio' => 'application/x-sv4cpio',
+ 'sv4crc' => 'application/x-sv4crc',
+ 'tar' => 'application/x-tar',
+ 'tcl' => 'text/x-tcl',
+ 'tex' => 'text/x-tex',
+ 'gf' => 'application/x-tex-gf',
+ 'pk' => 'application/x-tex-pk',
+ 'texinfo' => 'application/x-texinfo',
+ 'texi' => 'application/x-texinfo',
+ '~' => 'application/x-trash',
+ '%' => 'application/x-trash',
+ 'bak' => 'application/x-trash',
+ 'old' => 'application/x-trash',
+ 'sik' => 'application/x-trash',
+ 't' => 'application/x-troff',
+ 'tr' => 'application/x-troff',
+ 'roff' => 'application/x-troff',
+ 'man' => 'application/x-troff-man',
+ 'me' => 'application/x-troff-me',
+ 'ms' => 'application/x-troff-ms',
+ 'ustar' => 'application/x-ustar',
+ 'src' => 'application/x-wais-source',
+ 'wz' => 'application/x-wingz',
+ 'crt' => 'application/x-x509-ca-cert',
+ 'fig' => 'application/x-xfig',
+ 'au' => 'audio/basic',
+ 'snd' => 'audio/basic',
+ 'mid' => 'audio/midi',
+ 'midi' => 'audio/midi',
+ 'kar' => 'audio/midi',
+ 'mpga' => 'audio/mpeg',
+ 'mpega' => 'audio/mpeg',
+ 'mp2' => 'audio/mpeg',
+ 'mp3' => 'audio/mpeg',
+ 'mp4' => 'video/mp4',
+ 'm3u' => 'audio/x-mpegurl',
+ 'sid' => 'audio/prs.sid',
+ 'aif' => 'audio/x-aiff',
+ 'aiff' => 'audio/x-aiff',
+ 'aifc' => 'audio/x-aiff',
+ 'gsm' => 'audio/x-gsm',
+ 'wma' => 'audio/x-ms-wma',
+ 'wax' => 'audio/x-ms-wax',
+ 'ra' => 'audio/x-realaudio',
+ 'rm' => 'audio/x-pn-realaudio',
+ 'ram' => 'audio/x-pn-realaudio',
+ 'pls' => 'audio/x-scpls',
+ 'sd2' => 'audio/x-sd2',
+ 'wav' => 'audio/x-wav',
+ 'pdb' => 'chemical/x-pdb',
+ 'xyz' => 'chemical/x-xyz',
+ 'bmp' => 'image/x-ms-bmp',
+ 'gif' => 'image/gif',
+ 'ief' => 'image/ief',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'jpe' => 'image/jpeg',
+ 'pcx' => 'image/pcx',
+ 'png' => 'image/png',
+ 'svg' => 'image/svg+xml',
+ 'svgz' => 'image/svg+xml',
+ 'tiff' => 'image/tiff',
+ 'tif' => 'image/tiff',
+ 'wbmp' => 'image/vnd.wap.wbmp',
+ 'ras' => 'image/x-cmu-raster',
+ 'cdr' => 'image/x-coreldraw',
+ 'pat' => 'image/x-coreldrawpattern',
+ 'cdt' => 'image/x-coreldrawtemplate',
+ 'djvu' => 'image/x-djvu',
+ 'djv' => 'image/x-djvu',
+ 'ico' => 'image/x-icon',
+ 'art' => 'image/x-jg',
+ 'jng' => 'image/x-jng',
+ 'psd' => 'image/x-photoshop',
+ 'pnm' => 'image/x-portable-anymap',
+ 'pbm' => 'image/x-portable-bitmap',
+ 'pgm' => 'image/x-portable-graymap',
+ 'ppm' => 'image/x-portable-pixmap',
+ 'rgb' => 'image/x-rgb',
+ 'xbm' => 'image/x-xbitmap',
+ 'xpm' => 'image/x-xpixmap',
+ 'xwd' => 'image/x-xwindowdump',
+ 'igs' => 'model/iges',
+ 'iges' => 'model/iges',
+ 'msh' => 'model/mesh',
+ 'mesh' => 'model/mesh',
+ 'silo' => 'model/mesh',
+ 'wrl' => 'x-world/x-vrml',
+ 'vrml' => 'x-world/x-vrml',
+ 'csv' => 'text/comma-separated-values',
+ 'css' => 'text/css',
+ '323' => 'text/h323',
+ 'htm' => 'text/html',
+ 'html' => 'text/html',
+ 'uls' => 'text/iuls',
+ 'mml' => 'text/mathml',
+ 'asc' => 'text/plain',
+ 'txt' => 'text/plain',
+ 'text' => 'text/plain',
+ 'diff' => 'text/plain',
+ 'rtx' => 'text/richtext',
+ 'sct' => 'text/scriptlet',
+ 'wsc' => 'text/scriptlet',
+ 'tm' => 'text/texmacs',
+ 'ts' => 'text/texmacs',
+ 'tsv' => 'text/tab-separated-values',
+ 'jad' => 'text/vnd.sun.j2me.app-descriptor',
+ 'wml' => 'text/vnd.wap.wml',
+ 'wmls' => 'text/vnd.wap.wmlscript',
+ 'xml' => 'text/xml',
+ 'xsl' => 'text/xml',
+ 'h++' => 'text/x-c++hdr',
+ 'hpp' => 'text/x-c++hdr',
+ 'hxx' => 'text/x-c++hdr',
+ 'hh' => 'text/x-c++hdr',
+ 'c++' => 'text/x-c++src',
+ 'cpp' => 'text/x-c++src',
+ 'cxx' => 'text/x-c++src',
+ 'cc' => 'text/x-c++src',
+ 'h' => 'text/x-chdr',
+ 'c' => 'text/x-csrc',
+ 'java' => 'text/x-java',
+ 'moc' => 'text/x-moc',
+ 'p' => 'text/x-pascal',
+ 'pas' => 'text/x-pascal',
+ '***' => 'text/x-pcs-***',
+ 'shtml' => 'text/x-server-parsed-html',
+ 'etx' => 'text/x-setext',
+ 'tk' => 'text/x-tcl',
+ 'ltx' => 'text/x-tex',
+ 'sty' => 'text/x-tex',
+ 'cls' => 'text/x-tex',
+ 'vcs' => 'text/x-vcalendar',
+ 'vcf' => 'text/x-vcard',
+ 'dl' => 'video/dl',
+ 'fli' => 'video/fli',
+ 'gl' => 'video/gl',
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'mpe' => 'video/mpeg',
+ 'qt' => 'video/quicktime',
+ 'mov' => 'video/quicktime',
+ 'mxu' => 'video/vnd.mpegurl',
+ 'dif' => 'video/x-dv',
+ 'dv' => 'video/x-dv',
+ 'lsf' => 'video/x-la-asf',
+ 'lsx' => 'video/x-la-asf',
+ 'mng' => 'video/x-mng',
+ 'asf' => 'video/x-ms-asf',
+ 'asx' => 'video/x-ms-asf',
+ 'wm' => 'video/x-ms-wm',
+ 'wmv' => 'video/x-ms-wmv',
+ 'wmx' => 'video/x-ms-wmx',
+ 'wvx' => 'video/x-ms-wvx',
+ 'avi' => 'video/x-msvideo',
+ 'movie' => 'video/x-sgi-movie',
+ 'ice' => 'x-conference/x-cooltalk',
+ 'vrm' => 'x-world/x-vrml',
+ 'rar' => 'application/x-rar-compressed',
+ 'cab' => 'application/vnd.ms-cab-compressed'
+ ];
- $part = explode('.', $fileName);
- $size = count($part);
+ $part = explode('.', $fileName);
+ $size = count($part);
- if ($size > 1) {
- $ext = $part[$size - 1];
- if (isset($mimeTypes[$ext])) {
- return $mimeTypes[$ext];
+ if ($size > 1) {
+ $ext = $part[$size - 1];
+ if (isset($mimeTypes[$ext])) {
+ return $mimeTypes[$ext];
+ }
}
+
+ return 'application/octet-stream';
}
- return 'application/octet-stream';
- }
+ /**
+ * 寻找匹配的mime图标
+ *
+ * @access public
+ *
+ * @param string $mime mime类型
+ *
+ * @return string
+ */
+ public static function mimeIconType($mime)
+ {
+ $parts = explode('/', $mime);
- /**
- * 寻找匹配的mime图标
- *
- * @access public
- *
- * @param string $mime mime类型
- *
- * @return string
- */
- public static function mimeIconType($mime)
- {
- $parts = explode('/', $mime);
-
- if (count($parts) < 2) {
- return 'unknown';
- }
-
- [$type, $stream] = $parts;
-
- if (in_array($type, ['image', 'video', 'audio', 'text', 'application'])) {
- switch (true) {
- case in_array($stream, ['msword', 'msaccess', 'ms-powerpoint', 'ms-powerpoint']):
- case 0 === strpos($stream, 'vnd.'):
- return 'office';
- case false !== strpos($stream, 'html') || false !== strpos($stream, 'xml') || false !== strpos($stream, 'wml'):
- return 'html';
- case false !== strpos($stream, 'compressed') || false !== strpos($stream, 'zip') ||
- in_array($stream, ['application/x-gtar', 'application/x-tar']):
- return 'archive';
- case 'text' == $type && 0 === strpos($stream, 'x-'):
- return 'script';
- default:
- return $type;
+ if (count($parts) < 2) {
+ return 'unknown';
+ }
+
+ [$type, $stream] = $parts;
+
+ if (in_array($type, ['image', 'video', 'audio', 'text', 'application'])) {
+ switch (true) {
+ case in_array($stream, ['msword', 'msaccess', 'ms-powerpoint', 'ms-powerpoint']):
+ case 0 === strpos($stream, 'vnd.'):
+ return 'office';
+ case false !== strpos($stream, 'html')
+ || false !== strpos($stream, 'xml')
+ || false !== strpos($stream, 'wml'):
+ return 'html';
+ case false !== strpos($stream, 'compressed')
+ || false !== strpos($stream, 'zip')
+ || in_array($stream, ['application/x-gtar', 'application/x-tar']):
+ return 'archive';
+ case 'text' == $type && 0 === strpos($stream, 'x-'):
+ return 'script';
+ default:
+ return $type;
+ }
+ } else {
+ return 'unknown';
}
- } else {
- return 'unknown';
}
}
-}
+}
\ No newline at end of file
diff --git a/var/Typecho/Request.php b/var/Typecho/Request.php
index 08d961d5..c1765a5c 100644
--- a/var/Typecho/Request.php
+++ b/var/Typecho/Request.php
@@ -1,21 +1,37 @@
'intval',
+ 'integer' => 'intval',
+ 'search' => ['Typecho_Common', 'filterSearchQuery'],
+ 'xss' => ['Typecho_Common', 'removeXSS'],
+ 'url' => ['Typecho_Common', 'safeUrl'],
+ 'slug' => ['Typecho_Common', 'slugName']
+ ];
+
/**
* 内部参数
*
@@ -32,14 +48,6 @@ class Typecho_Request
*/
private $_pathInfo = null;
- /**
- * 服务端参数
- *
- * @access private
- * @var array
- */
- private $_server = [];
-
/**
* _requestUri
*
@@ -88,22 +96,6 @@ class Typecho_Request
*/
private $_referer = null;
- /**
- * 单例句柄
- *
- * @access private
- * @var Typecho_Request
- */
- private static $_instance;
-
- /**
- * 全部的http数据
- *
- * @var bool|array
- */
- private static $_httpParams = false;
-
-
/**
* 域名前缀
*
@@ -120,99 +112,27 @@ class Typecho_Request
private $_filter = [];
/**
- * 支持的过滤器列表
- *
- * @access private
- * @var string
+ * 初始化变量
*/
- private static $_supportFilters = [
- 'int' => 'intval',
- 'integer' => 'intval',
- 'search' => ['Typecho_Common', 'filterSearchQuery'],
- 'xss' => ['Typecho_Common', 'removeXSS'],
- 'url' => ['Typecho_Common', 'safeUrl'],
- 'slug' => ['Typecho_Common', 'slugName']
- ];
+ public function __construct()
+ {
+ }
/**
* 获取单例句柄
*
* @access public
- * @return Typecho_Request
+ * @return Request
*/
- public static function getInstance(): Typecho_Request
+ public static function getInstance(): Request
{
if (!isset(self::$_instance)) {
- self::$_instance = new Typecho_Request();
+ self::$_instance = new Request();
}
return self::$_instance;
}
- /**
- * 应用过滤器
- *
- * @access private
- *
- * @param mixed $value
- *
- * @return mixed
- */
- private function _applyFilter($value)
- {
- if ($this->_filter) {
- foreach ($this->_filter as $filter) {
- $value = is_array($value) ? array_map($filter, $value) :
- call_user_func($filter, $value);
- }
-
- $this->_filter = [];
- }
-
- return $value;
- }
-
- /**
- * 检查ip地址是否合法
- *
- * @param string $ip ip地址
- *
- * @return boolean
- */
- private function _checkIp(string $ip): bool
- {
- if (__TYPECHO_FILTER_SUPPORTED__) {
- return false !== (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)
- || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
- }
-
- return preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $ip)
- || preg_match("/^[0-9a-f:]+$/i", $ip);
- }
-
- /**
- * 检查ua是否合法
- *
- * @param string $agent ua字符串
- *
- * @return boolean
- */
- private function _checkAgent(string $agent): bool
- {
- return preg_match("/^[_a-z0-9- ,:;=#@\.\(\)\/\+\*\?]+$/i", $agent);
- }
-
- /**
- * 初始化变量
- */
- public function __construct()
- {
- if (false === self::$_httpParams) {
- self::$_httpParams = array_filter(array_merge($_POST, $_GET),
- ['Typecho_Common', 'checkStrEncoding']);
- }
- }
-
/**
* 获取url前缀
*
@@ -224,7 +144,7 @@ class Typecho_Request
if (empty($this->_urlPrefix)) {
if (defined('__TYPECHO_URL_PREFIX__')) {
$this->_urlPrefix = __TYPECHO_URL_PREFIX__;
- } else if (!defined('__TYPECHO_CLI__')) {
+ } elseif (php_sapi_name() != 'cli') {
$this->_urlPrefix = ($this->isSecure() ? 'https' : 'http') . '://'
. ($_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME']);
}
@@ -252,9 +172,9 @@ class Typecho_Request
* 设置过滤器
*
* @access public
- * @return Typecho_Request
+ * @return Request
*/
- public function filter(): Typecho_Request
+ public function filter(): Request
{
$filters = func_get_args();
@@ -291,7 +211,8 @@ class Typecho_Request
*/
public function __isset(string $key)
{
- return isset(self::$_httpParams[$key])
+ return isset($_GET[$key])
+ || isset($_POST[$key])
|| isset($this->_params[$key]);
}
@@ -311,15 +232,18 @@ class Typecho_Request
case isset($this->_params[$key]):
$value = $this->_params[$key];
break;
- case isset(self::$_httpParams[$key]):
- $value = self::$_httpParams[$key];
+ case isset($_GET[$key]):
+ $value = $_GET[$key];
+ break;
+ case isset($_POST[$key]):
+ $value = $_POST[$key];
break;
default:
$value = $default;
break;
}
- $value = !is_array($value) && strlen($value) > 0 ? $value : $default;
+ $value = ((!is_array($value) && strlen($value) > 0) || is_array($default)) ? $value : $default;
return $this->_applyFilter($value);
}
@@ -332,11 +256,10 @@ class Typecho_Request
*/
public function getArray($key): array
{
- $result = $this->_params[$key] ?? (self::$_httpParams[$key] ?? []);
+ $result = $this->get($key, []);
- $result = is_array($result) ? $result
+ return is_array($result) ? $result
: (strlen($result) > 0 ? [$result] : []);
- return $this->_applyFilter($result);
}
/**
@@ -372,9 +295,7 @@ class Typecho_Request
*/
public function setParam(string $name, $value)
{
- if (Typecho_Common::checkStrEncoding($value)) {
- $this->_params[$name] = $value;
- }
+ $this->_params[$name] = $value;
}
/**
@@ -394,8 +315,7 @@ class Typecho_Request
$params = $out;
}
- $this->_params = array_merge($this->_params,
- array_filter($params, ['Typecho_Common', 'checkStrEncoding']));
+ $this->_params = array_merge($this->_params, $params);
}
/**
@@ -524,14 +444,16 @@ class Typecho_Request
if (0 === strpos($requestUri, $baseUrl)) {
// full $baseUrl matches
$finalBaseUrl = $baseUrl;
- } else if (0 === strpos($requestUri, dirname($baseUrl))) {
+ } elseif (0 === strpos($requestUri, dirname($baseUrl))) {
// directory portion of $baseUrl matches
$finalBaseUrl = rtrim(dirname($baseUrl), '/');
- } else if (!strpos($requestUri, basename($baseUrl))) {
+ } elseif (!strpos($requestUri, basename($baseUrl))) {
// no match whatsoever; set it blank
$finalBaseUrl = '';
- } else if ((strlen($requestUri) >= strlen($baseUrl))
- && ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0))) {
+ } elseif (
+ (strlen($requestUri) >= strlen($baseUrl))
+ && ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0))
+ ) {
// If using mod_rewrite or ISAPI_Rewrite strip the script filename
// out of baseUrl. $pos !== 0 makes sure it is not matching a value
// from PATH_INFO or QUERY_STRING
@@ -559,7 +481,7 @@ class Typecho_Request
/** 初始化参数 */
if (is_string($parameter)) {
parse_str($parameter, $args);
- } else if (is_array($parameter)) {
+ } elseif (is_array($parameter)) {
$args = $parameter;
} else {
return $requestUri;
@@ -621,7 +543,7 @@ class Typecho_Request
|| stripos($_SERVER['SERVER_SOFTWARE'], 'ExpressionDevServer') !== false)) {
if (function_exists('mb_convert_encoding')) {
$pathInfo = mb_convert_encoding($pathInfo, $outputEncoding, $inputEncoding);
- } else if (function_exists('iconv')) {
+ } elseif (function_exists('iconv')) {
$pathInfo = iconv($inputEncoding, $outputEncoding, $pathInfo);
}
}
@@ -660,23 +582,11 @@ class Typecho_Request
if (!empty($ip)) {
$this->_ip = $ip;
} else {
- switch (true) {
- case defined('__TYPECHO_IP_SOURCE__')
- && null !== $this->getServer(__TYPECHO_IP_SOURCE__):
- list($this->_ip) = array_map(
- 'trim',
- explode(',',
- $this->getServer(__TYPECHO_IP_SOURCE__))
- );
- break;
- case null !== $this->getServer('REMOTE_ADDR'):
- $this->_ip = $this->getServer('REMOTE_ADDR');
- break;
- case null !== $this->getServer('HTTP_CLIENT_IP'):
- $this->_ip = $this->getServer('HTTP_CLIENT_IP');
- break;
- default:
- break;
+ $header = defined('__TYPECHO_IP_SOURCE__') ? __TYPECHO_IP_SOURCE__ : 'X-Forwarded-For' ;
+ $ips = $this->getHeader($header, $this->getServer('HTTP_CLIENT_IP', $this->getServer('REMOTE_ADDR')));
+
+ if (!empty($ips)) {
+ [$this->_ip] = array_map('trim', explode(',', $ips));
}
}
@@ -700,6 +610,20 @@ class Typecho_Request
return $this->_ip;
}
+ /**
+ * get header value
+ *
+ * @param string $key
+ * @param string|null $default
+ *
+ * @return string|null
+ */
+ public function getHeader(string $key, ?string $default = null): ?string
+ {
+ $key = 'HTTP_' . strtoupper(str_replace('-', '_', $key));
+ return $this->getServer($key, $default);
+ }
+
/**
* 设置客户端
*
@@ -819,7 +743,7 @@ class Typecho_Request
/** 解析串 */
if (is_string($query)) {
parse_str($query, $params);
- } else if (is_array($query)) {
+ } elseif (is_array($query)) {
$params = $query;
}
@@ -837,4 +761,55 @@ class Typecho_Request
return $validated;
}
+
+ /**
+ * 应用过滤器
+ *
+ * @param mixed $value
+ *
+ * @return mixed
+ */
+ private function _applyFilter($value)
+ {
+ if ($this->_filter) {
+ foreach ($this->_filter as $filter) {
+ $value = is_array($value) ? array_map($filter, $value) :
+ call_user_func($filter, $value);
+ }
+
+ $this->_filter = [];
+ }
+
+ return $value;
+ }
+
+ /**
+ * 检查ip地址是否合法
+ *
+ * @param string $ip ip地址
+ *
+ * @return boolean
+ */
+ private function _checkIp(string $ip): bool
+ {
+ if (function_exists('filter_var')) {
+ return false !== (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)
+ || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
+ }
+
+ return preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $ip)
+ || preg_match("/^[0-9a-f:]+$/i", $ip);
+ }
+
+ /**
+ * 检查ua是否合法
+ *
+ * @param string $agent ua字符串
+ *
+ * @return boolean
+ */
+ private function _checkAgent(string $agent): bool
+ {
+ return preg_match("/^[_a-z0-9- ,:;=#@\.\(\)\/\+\*\?]+$/i", $agent);
+ }
}