##language:zh
#pragma section-numbers on
'''
45分钟!给gmailfs添加中文文件名支持
'''
::-- ZoomQuiet [<<DateTime(2007-03-24T08:41:01Z)>>]
<<TableOfContents>>
## 默许导航,请保留
<<Include(CPUGnav)>>

= 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:{{{#!python
 def getdir(self, path):
           #  .....
           for thread in folder:
              assert len(thread) == 1
              for msg in thread:
                log.debug("thread.summary is " + thread.snippet)
                m = re.search(FileNameTag+'='+FileStartDelim+'(.*)'+
                              FileEndDelim, thread.snippet)
                if (m):
                    # Match succeeded, we got the whole filename.
                    log.debug("Used summary for filename")
                    filename = m.group(1)
                else:
                    # Filename was too long, have to fetch message.
                    log.debug("Long filename, had to fetch message")
                    body = fixQuotedPrintable(msg.source)
                    log.debug('body='+body+'  '+ FileNameTag+'='+FileStartDelim+'(.*)'+FileEndDelim) #这里加上
                    m = re.search(FileNameTag+'='+FileStartDelim+'(.*)'+ FileEndDelim, body)
                    filename = m.group(1)
               #.....
}}}
然后把gmailfs.conf的[logs]的level设为debug。
== 原来body是base64编码的 ==
再试,哦,原来body是base64编码的,OK,我们来看看fixQuotedPrintable都干了
些什么活:{{{#!python
#ubuntu带的0.7.2版的:
def fixQuotedPrintable(body):
   fixed = body
   if re.search("Content-Transfer-Encoding: quoted",body):
       fixed = quopri.decodestring(body)
   # Map unicode
   return fixed.replace('\u003d','=')
#新版0.7.3的:
def fixQuotedPrintable(body):
   # first remove headers
   newline = body.find("\r\n\r\n")
   if newline >= 0:
       body = body[newline:]
   fixed = body
   if re.search("Content-Transfer-Encoding: quoted",body):
       fixed = quopri.decodestring(body)
   # Map unicode
   return fixed.replace('\u003d','=')
##注意到没,加了newline。先把base64的decodestring加上,
def fixQuotedPrintable(body):
   # first remove headers
   newline = body.find("\r\n\r\n")
   if newline >= 0:
       body = body[newline:]
   fixed = body
   if re.search("Content-Transfer-Encoding: quoted",body):
       fixed = quopri.decodestring(body)
   if re.search("Content-Transfer-Encoding: base64",body):
       fixed = base64.decodestring(body)
   # Map unicode
   return fixed.replace('\u003d','=')
}}}
加上import base64, 试一下,不行,再仔细看一下代码,哦,看出问题出来了没?

原来他已经先把header去掉了,所以
`re.search("Content-Transfer-Encoding: base64",body)`做的是无用功啊。怎么
改?先保留他的代码,不要动他,加上:
{{{#!python
def fixQuotedPrintable(body):
   # first remove headers
   newline = body.find("\r\n\r\n")
   body_orig = body # 加一个变量保存有header的body
   if newline >= 0:
       body = body[newline:]
   fixed = body
   if re.search("Content-Transfer-Encoding: quoted",body_orig):
       fixed = quopri.decodestring(body)
   if re.search("Content-Transfer-Encoding: base64",body_orig):
       fixed = base64.decodestring(body)
   # Map unicode
   return fixed.replace('\u003d','=')
}}}
OK,这下ls不会出错了,大功....,等等,ls出来中文名是乱码啊,哥们,别高兴
得太早;-)
== 把charset加上吧 ==
没办法,那就把charset加上吧:
{{{#!python
def fixQuotedPrintable(body):
   # first remove headers
   newline = body.find("\r\n\r\n")
   body_orig = body
   # check encoding
   charset_match = re.search("charset=([^;]+)",body_orig) # 这里解析
encoding charset
   if newline >= 0:
       body = body[newline:]
   fixed = body
   if re.search("Content-Transfer-Encoding: quoted",body_orig):
       fixed = quopri.decodestring(body)
   if re.search("Content-Transfer-Encoding: base64",body_orig):
       fixed = base64.decodestring(body)
   if charset_match:
       fixed = unicode(fixed,charset_match.group(1)).encode('utf-8')
   # Map unicode
   return fixed.replace('\u003d','=')
}}}
OK,ls出来正确的文件名,再试试把它cp回来看看,

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

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


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

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

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

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

== 反馈 ==