October 16, 2007

WP23再次给WPDB BACKUP一个难堪

      wordpress database backup是一款绝好的插件, 几乎是每个wordpress使用者必备的插件之一。 在升级了wordpress 2.3 之后第一件事情就是更新wordpress database backup插件, 这次作者为配合 wordpress 2.3 推出了wpdb backup 2.1.3(花儿开了在作者推出2.1.3版本前就推出了可以兼容 wp2.3 的2.1.2 mod版), 不过想用上这款人人必备的插件却不那么容易, 第一天这款插件就给了我一个难题。

      事情是这样的, 装上wpdb backup, 我一般都会去看看邮箱, 看wpdb backup是否完好工作, 这次wpdb backup工作很认真仔细, 在规定的时间中已经给我的邮箱发送了相应的数据库备份, 可这个数据库备份的主题(subject)竟然是类似这样的乱码。

=?boundary===WPBACKUP-BY-SKIPPY-a8613843682755d784541502833bc47b?B?5YG2?= =?boundary===WPBACKUP-BY-SKIPPY-a8613843682755d784541502833bc47b?B?54ix?= =?boundary===WPBACKUP-BY-SKIPPY-a8613843682755d784541502833bc47b?B?5YG2?= =?boundary===WPBACKUP-BY-SKIPPY-a8613843682755d784541502833bc47b?B?5a62?= =?boundary===WPBACKUP-BY-SKIPPY-a8613843682755d784541502833bc47b?B?IOaV?= =?boundary===WPBACKUP-BY-SKIPPY-a8613843682755d784541502833bc47b?B?sOaN?= =?boundary===WPBACKUP-BY-SKIPPY-a8613843682755d784541502833bc47b?B?ruW6?= =?boundary===WPBACKUP-BY-SKIPPY-a8613843682755d784541502833bc47b?B?k+Wk?= =?boundary===WPBACKUP-BY-SKIPPY-a8613843682755d784541502833bc47b?B?h+S7?= =?boundary===WPBACKUP-BY-SKIPPY-a8613843682755d784541502833bc47b?B?vQ==?=

      而且除了主题乱码外, 邮件内容也是乱码, 这可让人很不爽, 一点意义都没有的主题, 还都是乱七八糟的字符, 一点都不符合审美观点。

      本着有问题就要解决的理念, 我开始辛苦寻找出问题的根源, 将wpdb backup 2.1.2 跟 wpdb backup 2.1.3 进行比对后发现几乎没有什么实质性的改动, 所以曾经的 wpdb backup 2.1.2 在我的wordpress 2.2 上使用的非常好, 那wpdb backup 2.1.3 也应该不会有问题存在的, 那问题只有可能是存在在wordpress 2.3 里面了。

      wordpress database backup 主要用到如下两个 wodpress 文件, pluggable.php 和 class-phpmailer.php。 因为我就比对 wordpress 2.2 和 wordpress 2.3 的这两个文件, 发现class-phpmailer.php这个文件也没有大的变动, 那根源差不多就应该在 pluggable.php 中了。

      wpdb backup 使用了 pluggable.php 文件中的 wp_mail() 函数, 那我直接比对这个函数, 发现从 wordpress 2.2 到 wordpress 2.3 这个函数的改动还真不小。 那就分析分析目前 wordpress 2.3 中的 wp_mail() 函数吧!

      这不分析还不知道, 一分析发现问题还真不少, wpdb bakcup 的整个问题的根源再远Charset的设置错误, 可为什么会出现charset的错误呢? 我们来看这段代码, 整个wp_mail()中这段设计了charset的获取。

    } elseif ( ‘content-type’ == strtolower($name) ) {
     if ( strpos( $content,’;’ ) !== false ) {
      list( $type, $charset ) = explode( ‘;’, $content );
      $content_type = trim( $type );
      $charset = trim( str_replace( array( ‘charset=’, ‘"’ ), ”, $charset ) );
     } else {
      $content_type = trim( $content );

      看这段代码中, wordpress wp_mail() 先获取 content-type, 然后想当然的认为charset是跟content-type是在同一行中的, 然后直接用一个str_replace()函数将‘charset’ 跟 ‘"’替换成空, 然后将剩余的东西直接作为了charset。

      真不知道这个wp 的开发组是咋想的, 这个里面根本就没有仔细判断有没有charset, 而直接采用str_replace()替换来想当然的认为就可以得到charset的值, 作为编程好像不够严谨点吧?

      也正是这个问题, 导致了wpdb backup最后非常严重的错误, 我们反过来看wpdb backup的代码, 它的代码是这样的:

$headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\n";

      看到了没有, 将上面这一行代码套用到wp_mail()的函数中, 你会发现什么? 发现最后得到了 charset=$boundary。 这也正好暗合了上面乱码的格式, 因为wpdb backup 定义的$boundary = "==WPBACKUP-BY-SKIPPY-$randomish"。

     看到了问题, 就应该是修改问题了, 修改起来很简单, 最简单的就是把上面wpdb backup代码中的    ; boundary=\"$boundary\"   删除即可, 应该就可以收到正确编码的邮件了(我这里测试是这样的)。

      不过我想wpdb backup的作者在这里设置一个boundary是有它的道理的, 是为了兼容wordpress的低版本, 我记得在没有使用phpmailer这个class之前, wordpress的邮件都是需要自己设置完全的, 这个boundary也就理所当然的不能少。 那在wordpress使用了phpmailer之后, 由于phpmailer class 会自己创建boundary, 所以这个boundary就已经用不到了。

      我参考了class phpmailer的代码, 最后还是决定不修改这里, 而将代码加入到wpdb backup 的 setup_phpmailer() 中, 最后我将这段代码:

function setup_phpmailer(&$phpmailer) {
  if ( $this->useMailer ) :
   $phpmailer->AddAttachment($this->diskfile, $this->filename);
   $phpmailer->Body = $this->message;
  endif;
  return true;
}

      修改成如下的形式:

function setup_phpmailer(&$phpmailer) {
  if ( $this->useMailer ) :
   $phpmailer->AddAttachment($this->diskfile, $this->filename);
   $phpmailer->Body = $this->message;
   $phpmailer->CharSet = get_bloginfo( ‘charset’ );
   $phpmailer->CustomHeader = array();

  endif;
  return true;
}

      你可能看到这里增加了两行, 其实可以只增加上面这一行, 下面这一行我是看到phpmailer class有了一个变化, 由于wpdb backup中这么一行:

$headers = "MIME-Version: 1.0\n";

      它最后和phpmailer中有重复, 这个重复倒并不是最重要的, 但感觉总是不爽, 所以就加了下面这个$phpmailer->CustomHeader = array(); 语句。

      问题到这里就结束了, 经过这样解决之后我自己测试非常完好, 测试的邮箱是163和gmail, 都没有在出现乱码问题。

*****************************

      上面的这个问题到这里就告一段落了, 不过就在结束的时候发现还有一个问题。 这个问题应该这么描述:

wordpress database backup 是一个多语言用户版本, 中国用户可以使用zh_CN.mo的语言文件来实现wordpress的中文化, 但中文化之后有一个小的问题。 如果你是在Firefox下使用wpdb backup 手动备份数据库, 那你什么也看不到; 但如果你装了中文语言文件之后, 在IE下(我这里是IE6 SP1)下, 你用 WPDB BACKUP 手动备份数据库, 那最底下的进度栏是乱码, 而且可能会进度到一定的程度就出错, 然后进度条就不会再走了, 也就是说无法备份成功。

      这个问题产生的机理我不是很懂, 反正就是Firefox可以备份, IE就不行。 我只知道肯定跟IE在字符传递的过程中的编码有关, 最后经过测试, 产生问题的语句是这句:

var msg = "’ . $msg . ‘";

      可能是在IE将utf-8的编码认成别的编码(我这里认成的编码是ANSI也就是GB2312)的时候, 可能出现了部分字符串的错乱, 而且这个错乱恰好可能被认为了是一个分号(;)从而导致了语句的错误。

      最后我瞎猫碰死耗子的将这段代码:

  echo ‘<script type="text/javascript"><!–//
  var msg = "’ . $msg . ‘";
  window.parent.setProgress(msg);
  window.parent.nextStep();
  //–></script>
  ‘;

      改成了如下的形式, 就可以解决IE中的乱码问题, 并可以成功备份。

  echo ‘<meta http-equiv="Content-Type" content="text/html; charset=’ . get_bloginfo( ‘charset’ ) . ‘" />
  <script type="text/javascript"><!–//
  var msg = "’ . $msg . ‘";
  window.parent.setProgress(msg);
  window.parent.nextStep();
  //–></script>
  ‘;

      具体原理我还是不懂, 你也别问我, 反正这么改我就知道成功了, 一切就归咎于IE的BT。

      好了, 到此为止, 算是彻底的解决了 wordpress database backup 的问题了, 我已经将第一个问题递交给了作者, 作者应该会有自己的更优秀的改进方法, wordpress的追随者有福了。

      我将我的修改版上传到了这里, 点击下载,版本为 2.1.3 mod。

  您喜欢本文吗?即刻订阅"偶爱偶家",精彩文章不再错过!现在就给我们留个话吗?

 

« 我的wordpress不会ping了吗? 开心一刻:07年20条最经典草根名言 »
2 responses to "WP23再次给WPDB BACKUP一个难堪"

[...] 就拿我的wordpress升级来说, 就把我折腾的够呛。 刚解决了在wordpress 2.3 下能够称心的使用wordpress database backup, [...]

UGGboots said:
2009年11月23日

http://www.6inchboot.com/

UGG boots;cheap UGG;UGG classic

[Reply]

Leave a comment