日志分类:Web与互联网

开发插件解决 Claws Mail 看不到 Extmail 发来邮件内容的问题

2012/04/25 | 21:30 | 分类:Web与互联网 | 标签: | 1,804次阅读

  前文所说的这个问题,理应在 Extmail 服务端解决,然而我向 Extmail 开发者发信,尚未得到回复。尔后委托 Jeoygin 同学修改代码,却得知 Extmail 在这块的设计逻辑有些混乱,并不是改一两行代码就能搞掂的,有一些纠结的逻辑必须重构。考虑到这是实验室的生产环境,加之受影响的只有我等另类用户,就不在服务器上折腾了。
  退而求其次,在客户端解决吧。要么让 Claws Mail 在解析邮件时忽略非标准的头部,要么在收到邮件之后将其修改正确再解析。Claws Mail 的功能丰富,但遍历各个功能,没有发现能够直接解决这类问题的选项。虽然可以通过 Action 或 Run command 机制调用外部脚本修改邮件文件,但实验发现总有一些小问题:或是需要额外的鼠标操作,或是不能及时刷新。于是决定发挥主观能动性,自己写个 Claws Mail 插件。我仿照官方提供的插件示例,实现了一个 ExtMailHeaderFixer。思路很简单,添加一个处理接收到的邮件的钩子函数,当收到 Extmail 发来的带有 multipart 和 base64 头的邮件时,将 Content-Transfer-Encoding: base64 修改为 X-ExtMail-Header-Encoding: base64 即可。之所以不在解析时处理,而要修改邮件,是因为实验发现 Claws Mail 确实可以解析符合 Content-Transfer-Encoding: base64 语义的 multipart 邮件(即将 multipart 整体进行 base64 编码),不仅如此,Claws Mail 还能解析不同格式多级内联的邮件,我不想失去这个挺酷的特性。之所以不删除 Content-Transfer-Encoding: base64 这一行,或者把 base64 修改成合法的 8bit,而把这一行修改成对客户端无影响的 MIME 扩展字段,是便于必要时快速恢复邮件原样。这个方案也有缺点,即相关的钩子函数只对 POP3 邮件有效,对 IMAP 邮件无效,Claws Mail 这样设计可能与两个协议的语义差别(接收或同步)有关。在我目前的使用场景中,这个问题不大。
  在 32 位 Ubuntu 12.04+Claws Mail 3.8.0 和 64 位 Debian wheezy+Claws Mail 3.8.0 下测试通过。把代码释放出来,放在 sf.net(万古不化……),按传染性要求以 GPLv3 授权,方便遇到相同问题的朋友使用:http://sourceforge.net/projects/extmailhf/

Extmail 未严格遵守 RFC 导致 Claws Mail 看不到邮件内容的问题

2012/04/21 | 21:06 | 分类:Web与互联网 | 标签: | 1,419次阅读

  实验室的邮件系统最近改用了国产开源邮件服务器——Extmail。我在使用过程中发现一个问题:Claws Mail 客户端收到来自 Extmail web 界面发来的带有附件的邮件,内容均为空白,既无正文也无附件。而使用 Foxmail 等其他客户端接收邮件,则正常。经测试,发现问题出在 Extmail web 界面生成的邮件头中的这一行:

  1. Content-Transfer-Encoding: base64

  如果将这一行删除,则 Claws Mail 可以正确显示邮件正文与附件。那么,这是 Extmail 的问题还是 Claws Mail 的问题呢?既然这一问题只出现含有附件的邮件中,就从实现邮件附件的规范——MIME 的 Multipart Content-Type 入手分析。查阅 RFC 1341 相关章节,其中明确说明了 multipart 类型的 Content-Transfer-Encoding 只允许是 7bit、8bit 或 binary,而具体内容(正文和附件)的 Content-Transfer-Encoding 应在各个 part 的头部声明。因此,Extmail 在邮件头部指定“Content-Transfer-Encoding: base64”是不符合 RFC 的。而 Claws Mail 可能对标准的执行过于严格,容错能力不足,因此不能显示不符合规范的 multipart 邮件的正文和附件。
  我又查看了 Foxmail、Coremail 等 X-Mailer 发来的 multipart 邮件,发现多数 X-Mailer 构造的 multipart 邮件在头部都不指定 Content-Transfer-Encoding,只在下面的各个 part 中分别指定 Content-Transfer-Encoding。作为具有缺省值、可以省略的字段,multipart 邮件头部不指定 Content-Transfer-Encoding 应该是符合 RFC 的,这些邮件在 Claws Mail 中解析正确。
  因此,这个问题的根源在于 Extmail 未严格遵守 RFC。简单查了一下,构造 multipart 邮件的相关代码位于 libs/Ext/App/Compose.pm 文件,应该比较好修改。不过 Claws Mail 的“死板”也算一个原因,应对中国制造就要学会超强纠错(还记得这个例子吗)。


  Update 2012-04-24: Jeoygin 同学提醒,有关 MIME multipart 的更新标准是 RFC 2046。该 RFC 仍限制 Content-Transfer-Encoding 只能是 7bit、8bit 或 binary。另外,Extmail 修改这个 bug 并不是一行代码就能搞掂的,Compose.pm 里面有一些纠结的逻辑有待重构。

解决 nginx 反向代理网页首尾出现神秘字符的问题

2011/07/15 | 14:06 | 分类:Web与互联网 | 标签: | 3,056次阅读

  一台内网 LAMP 服务器上运行 MediaWiki,另一台具有外网 IP 的服务器上运行 nginx,为内网服务器提供反向代理,允许从外部访问 MediaWiki。测试发现,通过反向代理访问一般页面没有问题,但对于返回 HTTP/1.1 404 的页面,HTML 头部和尾部分别出现了额外的字符。头部多出的是 2-4 位 16 进制数,如“355b”,尾部多出的总是“0”。而且这个现象只出现在 nginx 反向代理之后的页面,不出现在 Apache 原始页面。
  使用 Wireshark 对比 nginx 和 Apache 的 respone,发现凡是出问题的页面,其传输方式均为 chunked(“Transfer-Encoding: chunked”)。查阅资料得知头部的 16 进制数(chunk 长度)、尾部的 0(chunk 终结)正是 chunked 传输方式的消息标识。Apache 的 respone 只有一个 chunk,而 nginx 的 respone 则分为 4 个 chunks,其中第 1 个 chunk 的头部、第 4 个 chunk 的尾部出现的额外字节正是 Apache 的 respone 中原始的 chunk 标识。看来,出现额外的字符是因为 nginx 对已经做过 chunked 的消息重复执行了 chunked 操作。
  解决这个问题,只需要禁止 nginx 进行多余的 chunked 过程。经查,可以在 nginx 配置文件中相应网站的 location 段中加一行“chunked_transfer_encoding off;”。

  1. location / {
  2.         proxy_pass              http://10.0.0.10/;
  3.         proxy_redirect          off;
  4.         proxy_set_header        Host            $http_host;
  5.         proxy_set_header        X-Real-IP       $remote_addr;
  6.         proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
  7.         chunked_transfer_encoding       off;
  8. }

  另外,也有人提供了 patch,更加智能地解决这个问题。

使用 rsync 或 unison 备份或同步支持 ssh 的 web 主机

2010/01/07 | 15:11 | 分类:Web与互联网 | 标签: | 4,831次阅读

  使用 web 主机而非 VPS 的站长,站点的备份或同步常常是一个问题。很多站点只能使用 ftp 做单向备份,基于较弱的元信息来判定文件是否需要重新下载,缺乏校验、压缩、增量传输等高级特性。有的服务商在 web 控制面板中提供备份功能,或允许上传简单的 cron 脚本,但这些途径通常只适合备份整站或指定目录,而不方便以增量方式传输更新过的内容。Linux 下成熟的镜像同步工具是 rsync,如果你的 web 主机允许 ssh 登录,则可以考虑使用 rsync 或其它类似工具。
  网上有很多说法认为 web 主机不允许跑 daemon、不允许开自定义端口,故而无法使用 rsync。其实不然,rsync 可以仅通过 ssh 连接而不需要开放额外的端口,服务端也可以借助 sshd 来启动而不需要作为 daemon 运行。我们需要的只是 ssh 登录以及运行自己上传的程序的权限。我使用的 Godaddy Economy Plan Hosting (Linux) 即属于这种情况。
  Godaddy 的 web 主机不提供 rsync 程序,我们可以从本地上传一个。需要注意上传的 rsync 二进制文件应该与你的 web 主机的平台一致,连接 libc、libpopt 等库的版本一致。对于使用 x86 版 CentOS 5.2 的 Godaddy 主机,我也直接在相同版本的 CentOS 中提取了一个 rsync 上传。这时,在客户端使用“-e”参数指定连接方式为 ssh,用“--rsync-path”参数指定服务端 rsync 所在的位置,即可借助 ssh 连接传输数据了。

  1. rsync -vzrtopgl --progress --delete -e ssh --rsync-path=/[remote_home_dir]/bin/rsync [username]@[hostname]:/[remote_home_dir]/html/ /[local_home_dir]/

  如果客户端为 Windows,则可以使用 Win32 下移植的 cwRsync,这个工具基于 cygwin 库但不需要安装整个 cygwin 环境,它同时包含了 Win32 版的 OpenSSH 客户端。上述命令无须修改即可在 Windows 下运行。
  rsync 解决了文件的单向的备份或镜像功能,但如果需要双向同步,更适合的工具是 unison。unison 使用 OCaml 语言开发,基于 rsync 算法对两端文件进行比较,将它们更新到一致的状态(最新的、不冲突的版本)。unison 可借助 socket、ssh 等连接方式,并支持多种操作系统。与 rsync 类似,我们需要向 web 主机上传一个 unison 二进制文件。官方只提供了最新版的源代码,需要自行下载到本地编译(事先安装 OCaml 编译器及 etags 工具)。服务端部署之后,客户端配置文件([config_name].prf)为:

  1. root = /[local_home_dir]/html/
  2. root = ssh://[username]@[hostname]//[remote_home_dir]/html/
  3. servercmd = /[remote_home_dir]/bin/unison

  在客户端执行 ./unison [config_name] 即可完成双向同步。注意 unison 要求服务端和客户端的主次版本号一致。
  如果客户端为 Windows,同样可以使用来自 cwRsync 的 ssh 命令。如果嫌这个 ssh 外加 cygwin 库的体积太大(~5M),另一种替代的方案是使用 Putty 提供的 Plink 工具。这是一个小巧的 Win32 ssh 客户端(276K),由于运行参数与 OpenSSH 不同,因此需要写一个批处理文件(ssh.bat)来封装:

  1. @Plink.exe [hostname] -l [username] -pw [password] "/[remote_home_dir]/bin/unison -server"

  并在 unicon 配置文件中指定 ssh 命令:

  1. sshcmd = ssh.bat

  此时运行 unicon,即可使用 Plink 进行 ssh 连接。
  无论使用 OpenSSH 的 ssh 还是 Putty 的 Plink,都可以借助公钥认证方式避免密码的输入。这样有利于定时备份和同步的自动化执行。具体方法不再赘述。

浏览器中安全执行本地代码——Google NaCl 与 Microsoft Xax

2009/07/16 | 22:20 | 分类:Web与互联网 | 标签: | 6,497次阅读

  Native Client(简称 NaCl)和 Xax 分别是 Google 和 Microsoft 近一年来开展的有关在 web 浏览器中安全执行本地代码的研究性工作。它们都已有实验原型,其功能类似于现在的 ActiveX,但相比只能在 IE 中运行的 ActiveX,二者都支持跨操作系统、跨浏览器运行(Xax 还声称可以跨体系结构),同时具备比 ActiveX 更完善的安全模型。这类在本地系统直接运行的代码相比 Flash、Silverlight、Java Applet 等虚拟机、JIT 机制,在性能、功能灵活性方面有优势,也便于移植遗留应用。
  NaCl 是开源的,其项目主页提供了大量的文档和示例程序,并开放了讨论区。加之 Google IO 大会的宣传,它得到了行业和媒体相对较多的关注,不少人认为它会成为“ActiveX 杀手”。而 Xax 在网上只有一个简单的论文页面,官方没有提供实验产品和更详细的资料下载,因此网络上关注它的文章很少,可能只在学术界为人知晓。
  NaCl 和 Xax 已发表的论文分别是:
  ● Native Client: A Sandbox for Portable, Untrusted x86 Native Code
  ● Leveraging Legacy Code to Deploy Desktop Applications on the Web
  从论文可以看出两项工作的侧重点有所不同。NaCl 的论文发表在 S&P/Oakland 2009,主要在论证其模型的安全性,欲打造一个安全且跨平台的 ActiveX 替代品;而 Xax 的论文发表在 OSDI 2008,更强调其软件结构的特性利于遗留应用快速移植到与操作系统、浏览器无关的 web 平台。
  NaCl 的结构比 Xax 简单,更类似于 ActiveX。它通过浏览器插件加载应用代码,创建一个沙盒进程来执行不可信的代码,直接在浏览器窗口中输出结果。不可信的代码不能直接访问本地文件系统和网络接口,而可以通过 IMC(Inter-Module Communications)间接调用一些可信的服务模块来访问本地资源。这些模块也是一些浏览器插件,可以通过它们实施安全策略。因此,NaCl 客户端安装和运行过程不需要特殊权限。Xax 的结构相对复杂,它的浏览器插件称为 Xax Monitor。Xax Monitor 包含一个 web proxy,浏览器的 HTTP 流量均要经过它。当 Xax Monitor 发现有 Xax 应用的链接时,它会从远程下载 Xax 应用。Xax Monitor 将下载来的应用代码与 PAL(Platform Abstraction Layer)模块连接,作为本地进程(称为“picoprocess”)运行。picoprocess 通过共享内存与 Xax Monitor 交互,由 Xax Monitor 为其执行封装过的、有限的、安全的系统调用(称为“xaxcalls”)。Xax Monitor 同时作为本地的 web server,通过 HTTP 消息与浏览器通信,处理浏览器到 picoprocess 的输入输出。Xax 使用系统特定的机制(Linux 的 ptrace 或 Windows 的虚拟设备驱动)来保证安全,在 Windows 下安装时需要超级用户的权限。
  NaCl 修改了一套 C/C++ 工具链,开发人员下了大量工夫让这套工具链生成的二进制代码安全可靠。其中包括严格的指令对齐、禁用系统调用和中断(只能通过 IMC 间接调用系统服务)、安全的跳转指令等。使用自己的加载器,使得不含系统调用的二进制代码可以跨操作系统加载执行(限于 x86 平台)。Xax 完成的工作类似,生成代码安全方面没有像 NaCl 那样严格控制,而是通过在运行时使用 Linux 的 ptrace 或 Windows 的虚拟设备驱动来阻止恶意添加的系统调用,同时接管内存分配工作,安全地管理堆上数据分配。
  Xax 所谓的跨体系结构,目前是在 x86 和 PowerPC 平台上分别做了 ABI(Application Binary Interface)各异的实现,因此运行在不同体系结构上的应用的二进制代码并不能互相兼容,只是说 Xax 机制已能在不同的体系结构上成功实现。作者提出可以用 Binary rewriting 的方法使得 x86 代码在其它平台上翻译执行,做到真正的跨体系结构,不知道现在实现没有。
  NaCl 的图形输出与本地程序渲染基本无异,用户体验较好,官方给出的 Quake 示例运行得很流畅(下图是在我的 Ubuntu 9.04 / Firefox 3.5 上运行的截图)。而对于 Xax,浏览器只能通过 HTTP 与连接到 Xax Monitor 的 picoprocess 通信,浏览器中的应用界面目前只能使用 HTML、Javascript 等已有技术渲染。论文中给出的 OpenGL 3D 示例使用 PNG 贴图的方式模拟动画输出,达到了 8.8 fps,用户体验比 NaCl、ActiveX 差一些。但相信加强浏览器插件的能力可以改善效果。
浏览器中安全执行本地代码——Google NaCl 与 Microsoft Xax
  由于 Xax 没有提供下载试用,所以不方便对比二者实际的编程难度和用户体验。个人感觉从用户角度而言,NaCl 似乎是一项更有吸引力的技术,简单地说它就是安全的、跨操作系统和浏览器的 ActiveX。而 Xax 在部署方式(权限)和界面交互效果方面还有欠缺。从开发人员角度来说,使用 NaCl 或 Xax 开发新应用或移植遗留应用都需要把原来使用系统调用的地方修改成调用 NaCl 可信服务模块或 xaxcalls,同时需要重写界面和 I/O 相关代码。NaCl 对代码有更严格的要求,比如不能使用部分不安全的标准库函数、不能滥用不安全的内嵌汇编指令等。而 Xax 的论文认为向 Xax 移植遗留应用是一件程序化的事,只要按照几个步骤去做,很多修改的代码可以复用。估计类似的步骤也可以应用于 NaCl,从 Quake 的成功移植可以看出 NaCl 在这方面应该不差。

页面: 上页(较新) 1 2 3 4 5 下页(较旧)