不久前,某个朋友的discuz x2.5出现问题,点击某个用户名,应该是进入他的空间,但是有时打不开,有时能打开。
我初步看了一下情况如下:
例如用户“太仓都市网”如果访问链接是:htp://www.tcdushi.com/space-uid-25.html 是这样的话,就能正常访问。而访问链接是:
htp://www.tcdushi.com/space-username-%25CC%25AB%25B2%25D6%25B6%25BC%25CA%25D0%25CD%25F8.html 这种方式,就会显示404错误。
首先,分析rewrite规则,发现实际访问的动态URL应该是 htp://www.tcdushi.com/home.php?mod=space&username=-%25CC%25AB
%25B2%25D6%25B6%25BC%25CA%25D0%25CD%25F8 这样的。直接使用这个地址访问,404错误没有了,出现的是“抱歉,您指定的用户空间不存
在”。看来有眉目!继续!
观察用户名称是“太仓都市网”,感觉这个url编码有些奇怪。写了一个urldecode()看了一下,发现 把“%25CC%25AB
%25B2%25D6%25B6%25BC%25CA%25D0%25CD%25F8”解码以后是“%CC%AB%B2%D6%B6%BC%CA%D0%CD%F8”,要再次urldecode()才变成“太仓都市网
”。问题出在把中文名两次urlencode编码了。首先解决这个问题,进入管理后台——全局——SEO设置 里面的Rewrite兼容性,原来选择的
“是”改为“否”,这样就不会把中文两次编码了。
现在,点击用户“太仓都市网”,通过username访问的地址变成了 htp://www.tcdushi.com/space-username-%CC%AB%B2%D6%B6%BC%CA
%D0%CD%F8.html 可以看到,中文编码正常了。但是访问后页面显示的还是“抱歉,您指定的用户空间不存在”。这时,使用动态URL:
htp://www.tcdushi.com/home.php?mod=space&username=%CC%AB%B2%D6%B6%BC%CA%D0%CD%F8 却已经能正常打开空间了。这就让人觉得很奇
怪,检查了下rewrite规则,也没有错啊!
rewrite的匹配正则表达式为 ^(.*/)*space-(username|uid)-(.+).html\?*(.*)$ 重写规则为:{R:1}/home.php\?mod=space&{R:2}={R:3}&
{R:4},测试了一下,应该是正确的。但是使用静态URL就会提示空间不存在,而使用原动态URL就正常。根据home.php?mod=space 这个信息
,顺藤摸瓜。找到了网站目录下的\source\module\home\home_space.php ,在27行左右,有 if($_GET['username']) 开头的代码,在这个if
里面最前面加上两行。
echo($_GET['username']);
exit();
然后,分别用静态和动态两种URL去访问,终于发现问题了。发现用静态方式打开,中文的编码是UTF-8的,而用动态方式打开,中文编码是
GBK的。记得这个论坛下载的是GBK版本的,因此数据库默认都是GBK的。在静态方式打开空间,获得的用户名是UTF-8的,然后和数据库中的
比对,就会失败。
\source\module\home\home_space.php中相关的代码是 27行起
if($_GET['username']) {
$member = C::t('common_member')->fetch_by_username($_GET['username']);
if(empty($member) && !($member = C::t('common_member_archive')->fetch_by_username($_GET['username']))) {
showmessage('space_does_not_exist');
}
$uid = $member['uid'];
}
问题的根本是urlrewrite以后,中文编码变成了UTF-8,而没有经过rewrite的中文编码还是GBK,具体为什么我也没有深究。先解决这个问题
吧。
把\source\module\home\home_space.php中相关的代码是 27行起 修改为如下:
if($_GET['username']) {
$gbk_username=iconv('UTF-8','GBK',urldecode($_GET['username'])); //add by sunbo
$member = C::t('common_member')->fetch_by_username($gbk_username);
if(empty($member) && !($member = C::t('common_member_archive')->fetch_by_username($gbk_username))) {
showmessage('space_does_not_exist');
}
$uid = $member['uid'];
}
问题解决!