Sametime 协议现在有一个开源的协议实现叫做 [Meanwhile],原来它自己维护了一个 Gaim 的插件,叫做 gaim-meanwhile,后来进入官方,又改回了原来的 sametime,底下的实现仍然是调用了 Meanwhile,要把这个关系搞清楚。
然后再说我碰到的问题,很早以前就发现了,不过一直没空改,今天仔细看了看给解决了。在 Gaim 中给 Sametime 帐号加一个联系人的时候,跟其他一样,要选择名字,要加入的组等信息,把这个对话框加 A。对于 Sametime 来说,后台通常是一个 LDAP 服务器,用于存储用户信息,所以这里填的名字只是整个 ID 的一部分,通常叫 UID,是唯一的,其他部分绝大多数情况下都是一样的,但不可省略。然后会调用 Meanwhile 的函数进行查找,它可能会找出好多个类似的名字,让后选择一个添加,这时候弹出的另外一个对话框 B 和 A 是一样的,不过里面的数据不同,用户名已经是整个 ID,别名也帮你自动填好了,但是对于用户来讲,在 A 中选择了一个组,要把加的这个联系人添加进去,而在 B 中的这个组和 A 中的并不相同,所以用户还得再选择一遍,非常地不方便。然后再进行相同的一次添加过程,不过这时候用户名已经是绝对唯一并且完整的了,可以直接添加。那么就要把用户组这个信息保留下来,就不需要再选择一次。
调用过程如下:
-
01 gtkblist.c:1048:create_group_menu() 找到 "Add a Buddy" 的回调函数
-
02 tbblist.c:826:gaim_gtk_blist_add_buddy_cb() 根据现在的选择状态,调整参数(帐号和用户组等)
-
03 blist.c:2388:gaim_blist_request_add_buddy() 调用真正的界面显示函数
-
在 gtkmain.c:234:gaim_gtk_ui_init() 中调用 gtkblist.c:5101:gaim_gtk_blist_get_ui_ops() 进行设置
-
而 gtkblist.c:5085:blist_ui_ops 就静态定义了 GTK+ 的一些回调函数。
-
04 gtkblist.c:4542:gaim_gtk_blist_request_add_buddy() 显示对话框,就是我们前面说到的 A
-
05 gtkblist.c:4489:add_buddy_cb()
-
06 account.c:1960:gaim_account_add_buddy() 调用帐号所属的协议中定义的添加联系人函数
-
07 sametime.c:4398:mw_prpl_add_buddy() Sametime 需要添加联系人
-
08 sametime.c:4314:add_buddy_resolved() 找出了匹配的联系人,可能不唯一
-
09 sametime.c:4262:multi_resolved_query() 显示给用户进行选择
-
10 sametime.c:4242:notify_add() 用户选择了一个,进行添加,又调用了第(4)步的函数,补充了一些数据
-
重复 4-8 步,这一次用户 ID 完整且唯一,可以直接进行添加。
-
11 sametime.c:793:buddy_add() 真正地添加一个联系人
问题就在于第 4 步和第 10 步的两次对话框中的用户组信息不一致,需要在其中的 Sametime 的回调函数中把相关的信息添加进去。这个解决起来就很容易了。一个注意的地方是在第 7 步中申请了一个结构保存了 buddy 和 group 信息,那么就需要释放掉,现在是有两个分支,一个是在第 8 步中找到了唯一的联系人并且 ID 是完整的,也就是说是第二次运行过来,应该释放一次;另外就是第 9 步用户列表显示完,在关闭的时候需要释放。
BTW,修 bug 用了 10 分钟,写这篇文章用了大半个小时,呵呵。
说句题外话,Gaim 里面大部分的协议都是自己实现的,如果能把这些协议的实现都拿出来,就像 Meanwhile 那样,就可以供另外的程序调用,这样各个 IM 客户端的实现也会减少很多的工作量,也可以集中力量针对协议本身进行开发。也就是说,协议库本身只提供功能,界面以及其他的处理由上层来做。不过这样带来的问题也很多的,比如 socket 啦,回调啦,会比较麻烦一些,设计接口的时候要考虑独立性,很多东西不能写死了,这样才能更方便地让上层来调用。




终于提交进去了
SVN r17685 by Christopher 'siege' O'Brien (taliesein),真是不容易啊。
Post new comment