某日在老外一个博客上逛,发现它上面的东东下载方式有点不同,于是查看了下它页面的HTML源代码,发现疑似物:wp-downloadmanager 。GOOGLE了下,还真找到这个东东了。用过一段时间后,发现它有一个BUG,就是没有考虑中文这样的非拉丁字符,导致上传的纯中文名称的附件名称只剩下从“.”开始后面的东东了,比如我通过它上传“ 中文.test ” 这个文件,最终的结果是这个文件在服务器上的名称变成了“ .test “ 。这样就会出问题,因为只要是全中文名的文件一上传上去后名称全部变成一个模样啦。
于是我从它的源代码入手,看它是怎么处理上传的。它处理上传的文件是:download-add.php ,从这个文件可以看到它处理从本地上传文件的代码块为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | case 1: if($_FILES['file_upload']['size'] > get_max_upload_size()) { $text = '<font color="red">'.sprintf(__('File Size Too Large. Maximum Size Is %s', 'wp-downloadmanager'), format_filesize(get_max_upload_size())).'</font>'; 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 = '<font color="red">'.__('Error In Uploading File', 'wp-downloadmanager').'</font>'; break; } } else { $text = '<font color="red">'.__('Error In Uploading File', 'wp-downloadmanager').'</font>'; break; } } break; |
首先引起我怀疑的是download_rename_file这个函数,这个函数的定义是在wp-downloadmanager.php文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ### 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; } } |
从上可看出这个函数先是把文件名中的空格换成了下划线,这不要紧,关键是下面这一句:
1 |
它把文件名中除去大小写字母、数字、连接符号、点号、下划线和斜杠之外的所有字符都通通毫不留情地给替换为空了,这样中文文件名的中的中文字符就这样消失啦。
于是修改了一这个函数中的正则,让它对中文手下留情:
1 |
本以为这样以后就完事啦,谁知这样以后问题依旧存在。我想问题肯定不是单单出在这,肯定还有别的函数对中文字符“先下杀手”了。于是继续看代码,在上面给出的download-add.php 中代码块的
1 | $file = download_rename_file($file_path, $file); |
这一行上面dump :
1 2 3 4 5 |
再在
1 | $file = download_rename_file($file_path, $file); |
这行下面下“断点”:
1 |
这样保存后,再去后台通过wp-downloadmanager上传一个中文名的文件,发现中文名是被basename这个php内置函数给扼杀了。
为了进一步证实我观点的正确性,于是写了个测试文件: zw.php
内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?php 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; } //eg: $_GET['a']='/dd/ww/cc/中文.test'; $a=preg_replace("/[^A-Za-z0-9\-._\/\x7f-\xff]/", '', $_GET['a']); echo $a.'<br>'; $b=basename($_GET['a']); echo $b.'<br>'; // will print '.test' $c=getFileBaseName($_GET['a']); echo $c; // 中文.test ?> |
提交zw.php?a=/dd/ww/cc/中文.test时,输出:
1 2 3 | /dd/ww/cc/中文.test .test 中文.test |
上述测试证实了我的观点的正确性,于是在wp-downloadmanager.php中增加自定义函数 getFileBaseName用来取代basename :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 。这样以后再测试,发现问题得到解决了。
喜欢这篇文章吗?
请订阅本站 RSS feed 或




9:17 下午, 2011年02月24日何苦呢 /
如何外国的主机支持中文名称的文件 还不乱码才好呢
7:16 下午, 2010年07月3日香肠Ⅰ号 /
12:38 上午, 2010年05月27日③秋之流☆ /
刚才看来访信息,发现有人搜这个插件去到我的博客,心血来潮,我也搜了一下,来到了你这里.
以前我也装过这个插件,不过后来发现在后台的时候IE会有报错(前台不记得有没有了),貌似还会影响编辑器的一些按钮,我不懂怎么解决,就停用了..
11:34 上午, 2010年05月27日荒野无灯 /
其实不会的,如果报错的话,基本上可以确定你是用古老的IE6浏览器,经我测试,在目前主流浏览器下都没有问题。
我这里折腾出了一个升级版: 《wordpress下载管理插件Hacklog-downloadmanager》
目前我在用这个。
11:38 上午, 2010年05月27日③秋之流☆ /
我用的是IE7(傲游)
改天我再去测试一下…
12:06 下午, 2009年12月18日嘉林 /
好,支持,辛苦了。
我现在不会用这个插件,文件上传了,插件设置里也添加了,就是不知道怎么在日志里插入下载。
12:31 下午, 2009年12月19日荒野无灯 /
@嘉林, 在代码编辑器里,点那个 download按钮,然后会弹出框来,你填入一个id,这个id就是你上传后文件的id,在后台可以看到文件ID的