2006-08-01

pkblogs,救星

最近借助pkblogs看了不少blogspot上的文章,真是广大受压迫人民的救星呀。托pkblogs的福,这个blog也能再利用一下了:

http://www.pkblogs.com/xieyanbo

2006-03-02

好的心态比啥都强

偶尔读到一段话,有点共鸣:
有句俗语说:“满怀希望的旅途要比到达目的地更快乐。”与之相对的是英国吉普赛诗人W•H•戴维斯(W. H. Davies)的诗句:“终日营营的生活会是怎样,无暇驻足停留凝神欣赏?”

2006-02-12

还是关于python的web开发

Peter Hunt在“How Python wins on the Web”里说道:“In fact, what I would love more than anything would be a portable mod_wsgi across Apache, LightTPD, and IIS: a module that would let me drop a .egg file into a directory and have it automatically pick up and install the WSGI application from the archive. Once we've got this, a standard, portable way of easily installing ANY Python web app, we'll be getting somewhere.”心有戚戚焉。

一个大一统的Python Web Framework可能对企业用户更有吸引力,但它肯定不能适用于所有应用。对一个语言来说,拥有众多杀手级的应用才是证明它的存在价值的最好方法。最近工作不太顺心,不过倒正好是个机会,有闲暇的功夫补习这两年Web开发的发展。Zope3Django的发展都不能忽视;但是要建一个好的网站,需要特别开发和优化的东西大多无法依靠这些框架,可能还反受框架之累;比起完整的解决方案,我更喜欢WSGI/Template/ORM这些部分都能各自独立,随心选择不同实现。高内聚,低耦合,这是硬道理呀。

2006-02-11

ColorQuiz




ColorQuiz.comxyb took the free ColorQuiz.com personality test!

"Wants interesting and exciting things to happen. A..."


Click here to read the rest of the results.


Free personality analysis from ColorQuiz.com.
Generated on Fri Feb 10 21:38:41 2006.

Your Existing Situation

    Active, but feels that insufficient progress or reward is being made for the effort exerted.

Your Stress Sources

    Wishes to be independent, unhampered, and free from any limitation or restriction, other than those which he imposes of himself or by his own choice and decision.

Your Restrained Characteristics

    Willing to participate and to allow himself to become involved, but tries to fend off conflict and disturbance in order to reduce tension.

    Remains emotionally unattached even when involved in a close relationship.

    Feels that he cannot do much about his existing problems and difficulties and that he must make the best of things as they are. Able to achieve satisfaction through sexual activity.


Your Desired Objective

    Wants interesting and exciting things to happen. Able to make himself well-liked by his obvious interest and by the very openness of his charm. Over-imaginative and given to fantasy or day-dreaming.

Your Actual Problem

    Seeks to avoid criticism and to prevent restriction of his freedom to act, and to decide for himself by the exercise of great personal charm in his dealings with others.

2006-02-06

脚本语言的胜利

Ruby VS. Java Books碰巧看到“
Ruby on Rails将程式设计化繁为简
”,里面的一张照片很吸引眼球。文章还提到,脚本语言“兼具脚本(scripting)程式语言PHP的速度与易用性,以及Java结构式作法的‘干净和清爽’”,“Ruby on Rails备受瞩目,反映程式设计界兴起一股以脚本程式语言(scripting language)取代Java或微软C#的风潮”。相比于Ruby on RailsPython语言正在开发的Web framework Django也吸引了Python界众多领军人物的眼光,第一个正式版的发布已进入倒计时;而Guido为自己在新公司Google的项目公开征集基于Python的Web framework,更是激起了空前热情的大讨论,网上的妙文不断。有理由相信,2006年将是Python的Web framwrok大发展的一年。而商业公司也在过去的两年里与脚本语言关系越来越密切,微软发布了IronPython,旨在把UNIX开发商吸引到.Net框架中;CNET的文章称,“过去曾经被正统的编程人员认为是玩具的脚本语言正在成为企业软件开发世界的一等公民”。

在这里,我学到的是,在这个竞争激烈、一寸光阴一寸金的年代,开发框架的“易用性”正在成为压倒一切的重要特征;因为易用性给开发、部署、维护方面带来的时间与金钱的节约,是任何投资者都无法忽视的——包括公司的投资者和免费软件程序员。

不过,企业应用一贯是期望使用的语言提供更成熟和繁复的架构,这本身和脚本语言的哲学有些相背;希望今后的几年脚本语言能给这个领域带来一些清新的风,而不是被“企业级应用”带到沟里去,忘了自己的本分。

闲话一句,似乎Perl6的开发进度还是不太乐观,拭目以待吧。

2006-01-19

《小王子》的测试

fox.
You are the fox.


Saint Exupery's 'The Little Prince' Quiz.
brought to you by Quizilla

用.netrc来自动登录

linux里面的好多程序都靠$HOME/.netrc来获取密码,进行认证。自己常用的lftp就是这样,也不知道为什么,它就是不用我已经配置好的ssh public key来,非得配置.netrc才能实现自动登录。
machine 202.108.35.239
login xyb
password mask

machine 202.106.182.247
login yanbo
password mask

这样配置好了,lftp就能自己查询相应的用户名和密码登录了。

Mass Transit - How Python wins on the Web

由于Ruby on Rails带来的压力和展示出的美好前景,Python圈子里一时Web Framework流行。SubwayTurbogearsDjango,一个一个新的框架蓬勃发展。看起来生机勃勃,不过……Mass Transit回顾了python的“重量级”应用,反思了最近的Framework的热潮,Python的魅力到底在那里呢?在“How Python wins on the Web”这篇文章里,他提出了自己的一些观点。说实话,从使用者的角度来看,开发语言是Python还是Perl还是Ruby,都不重要,重要的是产品的功能是我用得着的,同样重要的是产品是好维护的:一个egg就可以部署的WSGI应用确实要更方便一些。

Read more at www.aminus.org/blogs/in...

2006-01-10

基于postfix实现邮件用户的分布式处理

基于一些特殊的考虑,现在邮件系统经常面临把用户分散在几个不同服务器上的需求。这里谈一下我在使用postfix完成该功能时的一点认识和实践,需求所限,没有涉及到用户通过SMTP或者POP3登录收发邮件的部分。请各位朋友谅解并指正。

一般分布情况下,MX和用户所在的服务器是分离的;本文所描述的即是这种设计。下面把用户所在的服务器简称为单元(UNIT)。

MX

MX是接受邮件的关键,可以由一台或一组服务器组成。它对外开放SMTP端口,负责接受邮件并转投到收件人所在单元服务器。

简单的说,一封信投递到我们的系统中,首先会进入MX,MX检查收件人是否存在,然后根据用户的信息把信通过smtp协议转发到他所在的UNIT上。

由于用户分散在不同主机中,所以MX对用户进行查证的工作必须进行特殊的处理;这里大家可以集思广益,设计一两百种方案我看是没什么问题。不过,我们的任务是说明postfix如何处理用户分布的情况,所以我们假定已经有一个写好了的函数,调用它就可以查证用户了。我们利用它,就可以实现dict_unit这个map。利用选项 local_recipient_maps,使外部发信到我们的用户时,调用我们指定的接口对用户查证;输入为收件人的邮件地址。
local_recipient_maps = unit:smtpcheck

这里dict_unit的实现在后面详细解释。

用户查证是在访问者发出“RCPT ”指令时,如果postfix确认了该用户存在,就开始准备接收“DATA”指令发过来的邮件正文了。成功收到邮件后,通过配置好的 transport_maps,postfix可以询问我们的dict_unit,获得下一步处理的指令。比如,输入收件人邮件地址“user@my.com”,输出“smtp:unit12.my.com”,这就会让postfix通过smtp把信转投到unit12.my.com域名的这台机器上。
transport_maps = unit:transportmx


UNIT

邮件系统中的用户通过注册、转移等方式,被存放在不同的单元服务器中。他们负责接收从MX转投过来的信件,并最终放入存储系统中。

在这里,一样会使用local_recipient_maps检查收件人是否真实存在。但与MX不同的是,这是信件的最终目的地,transport_maps查询的结果就不能再是“smtp:unit12.my.com”,要设置成合适的本地处理程序,比如local或者指定mda的名称(在etc/master.cf中设置)等。

local_recipient_maps = unit:smtpcheck
transport_maps = unit:transportunit


自定义的map

这里是dict_unit的实现示意。通过这个map,我们可以把前面提到的用户查证、转发邮件、处理邮件的所有指引工作在一起完成;实际上,它相当于一个多向的阀门,可以让邮件流向不同的方向。

注意,这仅仅是示意的代码。有需要做开发的朋友请自行参考dict_pam[1]的实现,那是真正可执行的代码。请不要写信询问我如何编写并调试可用的dict,google[2]postfix官方网站[3]上都可以查到。

这个函数负责处理用户查证的工作。
static int dict_unit_smtpcheck(const char *name, char *result)
{
char userhost[128] = {0};

if (msg_verbose)
msg_info("dict_unit: lookup smtp user: %s", name);
ret = getuser(name, &userhost);
if (ret != 0){
if (msg_verbose)
msg_warn("dict_unit: lookup smtp failed, name: %s", name);
return 1;
}
if (msg_verbose)
msg_info("dict_unit: lookup transport successed, name: %s, host: %s, path: %s",
name,
userhost);

strncpy(result, userhost, sizeof(userhost));
return 0;
}


这个函数负责控制MX服务中邮件的流向。

static int dict_unit_transportmx(const char *name, char *result)
{
char userhost[128] = {0};

if (msg_verbose)
msg_info("dict_unit: lookup transport user: %s", name);

ret = getuser(name, &userhost);
if (ret != 0){
if (msg_verbose)
msg_warn("dict_unit: lookup transport failed, name: %s", name);
return 1;
}
if (msg_verbose)
msg_info("dict_unit: lookup transport successed, name: %s, host: %s,",
name,
userhost);

/* result formal like: "smtp:unit12.my.com" */
strncpy(result, "smtp:", sizeof(userhost));
strncat(result, userhost, sizeof(userhost)-strlen("smtp:"));
return 0;
}


这个函数负责控制UNIT中的邮件的流向。值得一提的是,这里我们使用了var_myhostname来鉴别该用户是不是本机的(很简陋,演示嘛),要正确编译的话,在src/global/dict_unit.c中,必须加入这一行:
#include "mail_params.h"

要正确运行的话,则必须再在etc/main.cf中配置好正确的本机域名:
myhostname = unit12.my.com

最后,我们这里的是调用了一个定制的MDA程序“mymda”来完成最终信件的投递。要让它能正确运行,得配置etc/master.cf,请自行查阅手册。

static int dict_unit_transportunit(const char *name, char *result)
{
char userhost[128] = {0};

if (msg_verbose)
msg_info("dict_unit: lookup transport user: %s", name);

ret = getuser(name, &userhost);
if (ret != 0){
if (msg_verbose)
msg_warn("dict_unit: lookup transport failed, name: %s", name);
return 1;
}
if (msg_verbose)
msg_info("dict_unit: lookup transport successed, name: %s, host: %s",
name,
userhost);

/* for local user, result is: "mymda:"
* for remote user, result is: "smtp:mx.my.com"
*/
if (0==strnstr(userhost, var_myhostname, sizeof(userhost)))
/* MX can delivery it */
strncpy(result, "smtp:mx.my.com", sizeof(userhost));
else
/* local MDA is ok */
strncpy(result, "mymda:", sizeof(userhost));

return 0;
}


最后,为了让上面的三个lookup能真正工作起来,要在dict对外提供的接口处调用他们。这个分流是通过lookup时传入的dict->service来辨认的,也就是在main.cf中的配置“unit:smtpcheck”冒号后面的部分。

static const char *dict_unit_lookup(DICT *dict, const char *name)
{
DICT_unit *dp = (DICT_unit *) dict;
char result[128] = {0};
int ret;

if (0 == strcmp(vstring_str(dp->service), "smtpcheck"))
ret = dict_unit_smtpcheck(name, result);
else if (0 == strcmp(vstring_str(dp->service), "transportmx"))
ret = dict_unit_transportmx(name, result);
else if (0 == strcmp(vstring_str(dp->service), "transportunit"))
ret = dict_unit_transportunit(name, result);
else
{
if (msg_verbose)
msg_error("dict_unit: lookup unknown service %s, name %s.",
vstring_str(dp->service), name);
return (0);
}
if ((0 != ret) || (0 == result[0]))
return (0);

succ:
if (msg_verbose)
msg_info("dict_unit: service %s, name: %s, result: %s.",
vstring_str(dp->service), name, result);
vstring_strncpy(dp->result, result, sizeof(result));
return vstring_str(dp->result);
}


组装在一起,这个控制邮件流向的大阀门就算是完工了。

以上是利用postfix实现用户分布的一次实践。当然,方案并非只有一种,大家各有不同。请大家多多讨论,共同进步。

本文基于创作共用协议[4]之“署名-保持一致”[5]许可证发表,使用前请阅读该协议。-- xyb

参考
[1] http://d.scn.ru/proj/postfix/dict_pam/
[2] http://www.google.com/
[3] http://www.postfix.org/
[4] http://www.creativecommons.cn/
[5] http://creativecommons.cn/licenses/by-sa/1.0/

2006-01-07

txt2pdbdoc

经常用palm看些电子书,所以用txt2pdbdoc自己做.pdb文件是免不了的。可是要命的是,中文文本用它制作时,常常发生core dump。今天没事,分析了一下,发现问题处在compress这个函数上。这是个非常简单的压缩算法;但该算法效率最差时,压缩之后的数据要比之前的还要大。看来这个算法对英文等字符集较小的文字效率不错,但对中文就有点水土不服啦。因为压缩后的数据超出了预期大小,造成了缓冲区溢出,引发莫名其妙的问题就在所难免了。

找到问题所在,解决就很简单了:对中文文档,指定参数“-c”,不进行压缩。不过,这样其实是指标不治本,还是修改一下代码来的实在。把缓冲区增大到压缩算法效率最差时需要的空间。这里是修改之后的patch,把缓冲区增加到原来的两倍,问题解决。

2006-01-06

How Do People See You?

Slow and Steady

Your friends see you as painstaking and fussy.

They see you as very cautious, extremely careful, a slow and steady plodder.

It'd really surprise them if you ever did something impulsively or on the spur of the moment.

They expect you to examine everything carefully from every angle and then usually decide against it.

厄,这是评测男生的吗?

2006-01-03

2006的第一场爱国卫生运动

昨天晚上睡觉,觉得背上有点痒。突然想到,住进来一直没有好好收拾过屋子和床铺,可能最近穿衣服、睡觉总是有点痒跟床上不干净有关系。今天起来大动干戈,把能洗的都拿去洗了,好好清扫了一下屋里的卫生。好多土呀。幸亏还有前两年非典剩下的口罩,劳动生产正好用上,哈哈。

最近事稍微少了一点,刚刚上网正好看见有个Grsync,翻译量很少,拿来即兴翻译了一下,提交给了作者。希望今年上半年能多些自主的时间,可以参与些开源项目。

注:刚发完信一刻钟,Grsync的作者就回信了,反应倒是真快。算起来那边的时间该吃中午饭了,我也吃晚饭去啦 :)