From ad0b5301a41727b68fac8568041f23256eb5af5e Mon Sep 17 00:00:00 2001 From: Zhai Yiming Date: Fri, 14 Jul 2017 10:27:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8B=86=E5=88=86htmlEncode=E4=B8=8EurlDecode?= =?UTF-8?q?=E5=87=BD=E6=95=B0=20=E4=BD=BF=E5=8A=9F=E8=83=BD=E6=9B=B4?= =?UTF-8?q?=E4=B8=93=E4=B8=80=E9=80=BB=E8=BE=91=E6=9B=B4=E6=B8=85=E6=99=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Access_Core.php | 67 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/Access_Core.php b/Access_Core.php index 8d16e2e..e9f590e 100644 --- a/Access_Core.php +++ b/Access_Core.php @@ -83,8 +83,8 @@ class Access_Core default: break; } - $this->logs['list'] = $this->db->fetchAll($query); - foreach ($this->logs['list'] as &$row) { + $list = $this->db->fetchAll($query); + foreach ($list as &$row) { $ua = new Access_UA($row['ua']); if ($ua->isRobot()) { $name = $ua->getRobotID(); @@ -101,8 +101,7 @@ class Access_Core $row['display_name'] = $name . ' / ' . $version; } } - - $this->htmlEncode($this->logs['list']); + $this->logs['list'] = $this->htmlEncode($this->urlDecode($list)); $this->logs['rows'] = $this->db->fetchAll($qcount)[0]['count']; @@ -128,7 +127,7 @@ class Access_Core $this->referer['domain'] = $this->db->fetchAll($this->db->select('DISTINCT entrypoint_domain AS value, COUNT(1) as count') ->from('table.access_log')->where("entrypoint_domain <> ''")->group('entrypoint_domain') ->order('count', Typecho_Db::SORT_DESC)->limit($this->config->pageSize)); - $this->htmlEncode($this->referer); + $this->referer = $this->htmlEncode($this->urlDecode($this->referer)); } /** @@ -191,20 +190,58 @@ class Access_Core } /** - * 转义特殊字符,防止XSS等攻击 - * - * @access public - * @return void + * 编码数组中的字符串为 HTML 实体 + * 默认只有数组的值被编码,下标不被编码 + * 如果数据类型是数组,那么它的所有子元素都将被递归编码 + * 只有字符串类型才会被编码 + * @param array $data 将要被编码的数据 + * @param bool $valuesOnly 是否只编码数组数值,如果为 false 那么所有下标和值都将被编码 + * @param string $charset 字符串编码方式,默认为 UTF-8 + * @return array 编码后的数据 + * @see http://www.php.net/manual/en/function.htmlspecialchars.php */ - protected function htmlEncode(&$variable) + protected function htmlEncode($data, $valuesOnly = true, $charset = 'UTF-8') { - if (is_array($variable)) { - foreach ($variable as &$value) { - $this->htmlEncode($value); + if (is_array($data)) { + $d = []; + foreach ($data as $key => $value) { + if (!$valuesOnly) { + $key = $this->htmlEncode($key, $valuesOnly, $charset); + } + $d[$key] = $this->htmlEncode($value, $valuesOnly, $charset); } - } elseif (is_string($variable)) { - $variable = htmlspecialchars(urldecode($variable)); + $data = $d; + } elseif (is_string($data)) { + $data = htmlspecialchars($data, ENT_QUOTES | ENT_SUBSTITUTE, $charset); } + return $data; + } + + /** + * 解析所有 URL 编码过的字符 + * 默认只有数组的值被解码,下标不被解码 + * 如果数据类型是数组,那么它的所有子元素都将被递归解码 + * 只有字符串类型才会被解码 + * @param array $data 将要被解码的数据 + * @param bool $valuesOnly 是否只解码数组数值,如果为 false 那么所有下标和值都将被解码 + * @return array 解码后的数据 + * @see http://www.php.net/manual/en/function.urldecode.php + */ + protected function urlDecode($data, $valuesOnly = true) + { + if (is_array($data)) { + $d = []; + foreach ($data as $key => $value) { + if (!$valuesOnly) { + $key = $this->urlDecode($key, $valuesOnly); + } + $d[$key] = $this->urlDecode($value, $valuesOnly); + } + $data = $d; + } elseif (is_string($data)) { + $data = urldecode($data); + } + return $data; } /**