PHP Safe Mode and Upload Problem

时间:12-04-08 栏目:站长の天地 作者:wukong 评论:0 点击: 1,834 次

当我在Wordpress(版本:3.0.0)中开始一个新帖子,打算上传一张图片的时候,在点击了Upload按钮之后,出现的却是下面的这条消息:

The uploaded file could not be moved to .

奇怪,明明上传目录的权限都没问题,为什么会无法上传呢?查找了一下上面消息的来源,发现wp-admin/admin-functions.php的大概位于1776行处有如下代码:

  1. // Move the file to the uploads dir
  2. $new_file = $uploads[‘path’] . "/$filename";
  3. if ( false === @ move_uploaded_file($file[‘tmp_name’], $new_file) )
  4.     die(printf(__(‘The uploaded file could not be moved to %s.’), $file[‘path’]));

复制代码


可见,问题的原因是move_uploaded_file函数无法正常将文件拷贝所致。在允许显示错误信息后,可看到类似下面的错误信息:

Warning: move_uploaded_file(): SAFE MODE Restriction in effect. The script whose uid is 1525 is not allowed to access /somefolder/wp-content/uploads/2007/05 owned by uid48 in /somefolder/wp-admin/admin-functions.php on line 1778

可见,这是因为SAFE MODE功能阻止了uid为1525的脚本访问uid为48的用户所拥有的上传目录(uploads/2007/05)。那么,什么是SAFE MODE呢?

SAFE MODE(安全模式)是为了解决共用服务器(例如一台服务器划分成多台虚拟主机的服务商)中的安全问题而被添加到PHP中的一种功能。该功能通过一些强制性的限制而提高安全性,但是反之这些限制使得程序受到约束,甚至产生问题。

SAFE MODE中很重要的一个功能就是,在PHP脚本进行文件系统操作时,对uid/gid进行比较、核查。当一个用户的脚本试图访问另一个用户的目录时,系统就会拒绝访问并给出上面那样的错误信息。

那么,为什么目录“uploads/2007/05”会是“另一个”用户的目录呢?这“另一个”用户,到底是谁呢?

继续调查,找到了创建这个目录的代码。该代码位于/wp-includes/functions-post.php的约867行开始的wp_mkdir_p()函数中:

  1. [backcolor=rgb(229, 231, 231)]if (@ mkdir($target)) {[/backcolor]
  2.         $stat = @ stat(dirname($target));
  3.         $dir_perms = $stat[‘mode’] & 0007777;  // Get the permission bits.
  4.         @ chmod($target, $dir_perms);
  5.         return true;
  6. } else {
  7.         if ( is_dir(dirname($target)) )
  8.                 return false;
  9. }

复制代码


问题就出在mkdir函数上面。在SAFE MODE模式下,PHP的mkdir()函数所创建的目录,owner并不是script,而是Apache。因此,上面消息中“uploads/2007/05”的owner ID 48,就是Apache进程的uid了。

由此可见,在不改变服务器端设置的前提下(跟服务商打交道比较麻烦,而且让他们更改SAFE MODE不大现实),要想解决这个问题,只能想办法不使用mkdir()了。幸好Wordpress里面,需要创建目录的也就是上传的时候,因此作为workaround,手动用ftp事先创建好每个月的上传目录就是了。因为ftp所使用的帐号是和自己的www服务挂钩的,因此不存在uid不同的问题。

那么,对于必须使用mkdir的程序,有什么办法呢?据说,PHP6里面就会取消SAFE MODE——不过,等PHP6大功告成,再等保守的服务提供商们更新换代,估计都到了Web 4.0时代了。目前的解决方案来说,既不改变服务器设置、也不对应用程序本身进行大规模的重新设计的workaround,就是以ftp_mkdir()替换mkdir()。原理就是因为ftp是以和script相同的用户操作文件系统的。当然,这个替换并不是简单的把mkdir换成ftp_mkdir,而是需要ftp服务器的IP地址,用户名和密码,很有局限性,使用前需要仔细权衡。

声明: 本文由( wukong )原创编译,转载请保留链接: PHP Safe Mode and Upload Problem

PHP Safe Mode and Upload Problem:等您坐沙发呢!

发表评论

您必须 [ 登录 ] 才能发表留言!

------====== 本站公告 ======------
大家有任何疑问和建议,请到这里留言:点击留言板

读者排行