45分钟!给gmailfs添加中文文件名支持 ::-- ZoomQuiet [2007-03-24 08:41:01]

CPUG联盟::

CPUG::门户plone

BPUG

SPUG

ZPUG

SpreadPython Python宣传

1. vcc.给gmailfs添加中文文件名支持

最近把工作基本都转到了Ubuntu下面,程序员还是用*nix最方便啊,支持多多。想 用gmailfs把一些东西备份到gmail里去,反正google这么慷慨的提供了这么好的服 务,不用白不用;-)

ubuntu安装软件那个是爽,sudo apt-get instal gmailfs就搞定了,看了一下说 明,配了gmailfs.conf,开始mount,cp....,ls,直接出错,中文文件名不支 持!怎么办?马上去gmailfs作者的主页看看。有一个0.7.3版本发布,有一个 bugfix “The failure to handle some text encoding for non-English languages“。OK, 下载下来换上一试,还是不行。怎么办?没办法了,只好打开 编辑器,看看代码了。

先在出错代码处加上log.debug:

   1  def getdir(self, path):
   2            #  .....
   3            for thread in folder:
   4               assert len(thread) == 1
   5               for msg in thread:
   6                 log.debug("thread.summary is " + thread.snippet)
   7                 m = re.search(FileNameTag+'='+FileStartDelim+'(.*)'+
   8                               FileEndDelim, thread.snippet)
   9                 if (m):
  10                     # Match succeeded, we got the whole filename.
  11                     log.debug("Used summary for filename")
  12                     filename = m.group(1)
  13                 else:
  14                     # Filename was too long, have to fetch message.
  15                     log.debug("Long filename, had to fetch message")
  16                     body = fixQuotedPrintable(msg.source)
  17                     log.debug('body='+body+'  '+ FileNameTag+'='+FileStartDelim+'(.*)'+FileEndDelim) #这里加上
  18                     m = re.search(FileNameTag+'='+FileStartDelim+'(.*)'+ FileEndDelim, body)
  19                     filename = m.group(1)
  20                #.....

然后把gmailfs.conf的[logs]的level设为debug。

1.1. 原来body是base64编码的

再试,哦,原来body是base64编码的,OK,我们来看看fixQuotedPrintable都干了 些什么活:

   1 #ubuntu带的0.7.2版的:
   2 def fixQuotedPrintable(body):
   3    fixed = body
   4    if re.search("Content-Transfer-Encoding: quoted",body):
   5        fixed = quopri.decodestring(body)
   6    # Map unicode
   7    return fixed.replace('\u003d','=')
   8 #新版0.7.3的:
   9 def fixQuotedPrintable(body):
  10    # first remove headers
  11    newline = body.find("\r\n\r\n")
  12    if newline >= 0:
  13        body = body[newline:]
  14    fixed = body
  15    if re.search("Content-Transfer-Encoding: quoted",body):
  16        fixed = quopri.decodestring(body)
  17    # Map unicode
  18    return fixed.replace('\u003d','=')
  19 ##注意到没,加了newline。先把base64的decodestring加上,
  20 def fixQuotedPrintable(body):
  21    # first remove headers
  22    newline = body.find("\r\n\r\n")
  23    if newline >= 0:
  24        body = body[newline:]
  25    fixed = body
  26    if re.search("Content-Transfer-Encoding: quoted",body):
  27        fixed = quopri.decodestring(body)
  28    if re.search("Content-Transfer-Encoding: base64",body):
  29        fixed = base64.decodestring(body)
  30    # Map unicode
  31    return fixed.replace('\u003d','=')

加上import base64, 试一下,不行,再仔细看一下代码,哦,看出问题出来了没?

原来他已经先把header去掉了,所以 re.search("Content-Transfer-Encoding: base64",body)做的是无用功啊。怎么 改?先保留他的代码,不要动他,加上:

   1 def fixQuotedPrintable(body):
   2    # first remove headers
   3    newline = body.find("\r\n\r\n")
   4    body_orig = body加一个变量保存有header的body
   5    if newline >= 0:
   6        body = body[newline:]
   7    fixed = body
   8    if re.search("Content-Transfer-Encoding: quoted",body_orig):
   9        fixed = quopri.decodestring(body)
  10    if re.search("Content-Transfer-Encoding: base64",body_orig):
  11        fixed = base64.decodestring(body)
  12    # Map unicode
  13    return fixed.replace('\u003d','=')

OK,这下ls不会出错了,大功....,等等,ls出来中文名是乱码啊,哥们,别高兴 得太早;-)

1.2. 把charset加上吧

没办法,那就把charset加上吧:

   1 def fixQuotedPrintable(body):
   2    # first remove headers
   3    newline = body.find("\r\n\r\n")
   4    body_orig = body
   5    # check encoding
   6    charset_match = re.search("charset=([^;]+)",body_orig) # 这里解析
   7 encoding charset
   8    if newline >= 0:
   9        body = body[newline:]
  10    fixed = body
  11    if re.search("Content-Transfer-Encoding: quoted",body_orig):
  12        fixed = quopri.decodestring(body)
  13    if re.search("Content-Transfer-Encoding: base64",body_orig):
  14        fixed = base64.decodestring(body)
  15    if charset_match:
  16        fixed = unicode(fixed,charset_match.group(1)).encode('utf-8')
  17    # Map unicode
  18    return fixed.replace('\u003d','=')

OK,ls出来正确的文件名,再试试把它cp回来看看,

1.3. 找不到inode为XXXXXXXX的数据邮件

糟糕,出错,似乎找不到inode为XXXXXXXX的数据邮件,看了一下gmail邮箱,有啊。再仔细看一下他的代 码,没有发现什么问题,难道是“灵异”事件?不会这么好彩吧;-) 多年的编程经验 告诉我,不会有什么邪门的事,一定是事出有因,多半是我自己的问题。我是相信 gmailfs代码的质量,不至于最基本的问题都搞不定,google我也相信不会乱来, 那一定是我的问题了。那我的问题在哪里呢?

仔细看看我的邮箱,search一下,1个2个3个4个,等等,别的英文名文件都是3个,这个为什么是4个,而且有一个内 容里s=0 (s是sizeTag),难怪,干掉这个邮件,再试,终于OK了。

1.4. 附上修改给gmailfs的作者

开始cp...., 另发一封简短的邮件附上修改给gmailfs的作者,顺道感谢感谢他_

虽然这是我第一次接触gmailfs,不过读懂代码并不是什么难事,python的代码的 可读性又是特别的好。还在害怕读代码的人们,不要站在岸边看风景,跳进源码的 海洋里游泳吧!

附注:查看发件箱,这是22号晚上的事,今天把它补记下来,也作一点点些微的贡 献吧。另多出一个邮件的无头公案,就交给在座的各位看官,再世的包青天包大 人.....-

vcc
_
都是我的错,让你多一个,不该乱把Ctrl-C拼命的按;-)

1.5. 反馈

MicroProj/2007-03-24 (last edited 2009-12-25 07:14:50 by localhost)