让wp-downloadmanager支持中文文件名 » 荒野无灯weblog

Keep It Simple, Stupid.

荒野无灯weblog

让wp-downloadmanager支持中文文件名

某日在老外一个博客上逛,发现它上面的东东下载方式有点不同,于是查看了下它页面的HTML源代码,发现疑似物:wp-downloadmanager 。GOOGLE了下,还真找到这个东东了。用过一段时间后,发现它有一个BUG,就是没有考虑中文这样的非拉丁字符,导致上传的纯中文名称的附件名称只剩下从“.”开始后面的东东了,比如我通过它上传“ 中文.test ” 这个文件,最终的结果是这个文件在服务器上的名称变成了“ .test “ 。这样就会出问题,因为只要是全中文名的文件一上传上去后名称全部变成一个模样啦。

于是我从它的源代码入手,看它是怎么处理上传的。它处理上传的文件是:download-add.php ,从这个文件可以看到它处理从本地上传文件的代码块为:

case 1:

                    if($_FILES['file_upload']['size'] > get_max_upload_size()) {

                        $text = ''.sprintf(__('File Size Too Large. Maximum Size Is %s', 'wp-downloadmanager'), format_filesize(get_max_upload_size())).'';

                        break;

                    } else {

                        if(is_uploaded_file($_FILES['file_upload']['tmp_name'])) {

                            if($_POST['file_upload_to'] == '/') {

                                $file_upload_to = '/';

                            } else {

                                $file_upload_to = $_POST['file_upload_to'].'/';

                            }

                            if(move_uploaded_file($_FILES['file_upload']['tmp_name'], $file_path.$file_upload_to.basename($_FILES['file_upload']['name']))) {

                                $file = $file_upload_to.basename($_FILES['file_upload']['name']);

                                $file = download_rename_file($file_path, $file);

                                $file_size = filesize($file_path.$file);    

                            } else {

                                $text = ''.__('Error In Uploading File', 'wp-downloadmanager').'';

                                break;

                            }

                        } else {

                            $text = ''.__('Error In Uploading File', 'wp-downloadmanager').'';

                            break;

                        }

                    }

                    break;

首先引起我怀疑的是download_rename_file这个函数,这个函数的定义是在wp-downloadmanager.php文件中:

### Function: Rename File To Ensure (Credits: imvain2)
function download_rename_file($file_path, $file) {
    $rename = false;
    $file_old = $file;
    $file = str_replace(' ', '_', $file);
    $file = preg_replace('/[^A-Za-z0-9\-._\/]/', '', $file);
    if($file != $file_old) {
        $rename = rename($file_path.$file_old, $file_path.$file);
    }
    if($rename) {
        return $file;
    } else {
        return $file_old;
    }
}

从上可看出这个函数先是把文件名中的空格换成了下划线,这不要紧,关键是下面这一句:

$file = preg_replace('/[^A-Za-z0-9\-._\/]/', '', $file);

它把文件名中除去大小写字母、数字、连接符号、点号、下划线和斜杠之外的所有字符都通通毫不留情地给替换为空了,这样中文文件名的中的中文字符就这样消失啦。
于是修改了一这个函数中的正则,让它对中文手下留情:

$file = preg_replace("/[^A-Za-z0-9\-._\/\x7f-\xff]/", '', $file);

本以为这样以后就完事啦,谁知这样以后问题依旧存在。我想问题肯定不是单单出在这,肯定还有别的函数对中文字符“先下杀手”了。于是继续看代码,在上面给出的download-add.php 中代码块的

$file = download_rename_file($file_path, $file);

这一行上面dump :

var_dump($file);
echo '
'; var_dump($_FILES['file_upload']['name']); echo '
'; var_dump(basename($_FILES['file_upload']['name']));

再在

$file = download_rename_file($file_path, $file);

这行下面下“断点”:

die($file);

这样保存后,再去后台通过wp-downloadmanager上传一个中文名的文件,发现中文名是被basename这个php内置函数给扼杀了。
为了进一步证实我观点的正确性,于是写了个测试文件: zw.php
内容如下:

';
$b=basename($_GET['a']);    
echo $b.'
'; // will print '.test' $c=getFileBaseName($_GET['a']); echo $c; // 中文.test ?>

提交zw.php?a=/dd/ww/cc/中文.test时,输出:

/dd/ww/cc/中文.test
.test
中文.test

上述测试证实了我的观点的正确性,于是在wp-downloadmanager.php中增加自定义函数 getFileBaseName用来取代basename :

function getFileBaseName($file_name)

{
if(eregi('/',$file_name)){
$baseDir=dirname($file_name);
$basename=str_replace($baseDir,'',$file_name);
$basename=str_replace('/','',$basename);
}
else {
$basename=$file_name;

}

return $basename;

} 

再把插件中凡是用到basename函数的地方全部换成getFileBaseName 。这样以后再测试,发现问题得到解决了。

Tagged in : wp问题

All Comments (0)
Gravatar image
No Comments