Evolution 中的 CamelProvider

    Evolution邮件客户端中是使用一种叫“provider”的方式来使用各种不同的邮件协议的。“provider”的使用,使得上层的代码进行邮件的各种操作的时候,底层协议的不同对其是完全透明的。这样的方法使代码具有很强的扩展性,可以很方便地给程序提供新协议的支持。“provider”是一种插件机制。
    Camel是Evolution中是现基本功能的库。Camel中Services被分为两种:Store和Transport,Store用来读取邮件,而Transport则用来发送邮件。在具体使用时,用户只用负责从CamelStore里面读数据和往CamelTransport中发数据就行了,具体的与服务器通信的细节,则是在其派生类中定义的(也就是在provider中所要做的)。Camel中定义了调用provider的时候使用的接口,也就是说,只要实现provider的时候按照这样的接口来实现它,那么它就是一个合法的provider。首先,provider必须提供一个void camel_provider_module_init(void)的函数,在这个函数中必须填充一个CamelProvider的结构体变量,并用camel_provider_register()函数注册之。
结构体定义如下:
  1. typedef struct {
  2.     /* Provider name used in CamelURLs. */
  3.     char *protocol;
  4.     /* Provider name as used by people. (May be the same as protocol) */
  5.     char *name;
  6.     /* Description of the provider. A novice user should be able
  7.      * to read this description, and the information provided by
  8.      * an ISP, IS department, etc, and determine whether or not
  9.      * this provider is relevant to him, and if so, which
  10.      * information goes with it.
  11.      */
  12.     char *description;
  13.     /* The category of message that this provider works with.
  14.      * (evolution-mail will only list a provider in the store/transport
  15.      * config dialogs if its domain is "mail".)
  16.      */
  17.     char *domain;
  18.     /* Flags describing the provider, flags describing its URLs */
  19.     int flags, url_flags;
  20.     /* The ConfEntry and AutoDetect functions will probably be
  21.      * DEPRECATED in a future release */
  22.     /* Extra configuration information */
  23.     CamelProviderConfEntry *extra_conf;
  24.     /* auto-detection function */
  25.     CamelProviderAutoDetectFunc auto_detect;
  26.     /* CamelType(s) of its store and/or transport. If both are
  27.      * set, then they are assumed to be linked together and the
  28.      * transport type can only be used in an account that also
  29.      * uses the store type (eg, Exchange or NNTP).
  30.      */
  31.     CamelType object_types[CAMEL_NUM_PROVIDER_TYPES];
  32.     /* GList of CamelServiceAuthTypes the provider supports */
  33.     GList *authtypes;
  34.     CamelObjectBag *service_cache[CAMEL_NUM_PROVIDER_TYPES];
  35.     GHashFunc url_hash;
  36.     GCompareFunc url_equal;
  37.     /* gettext translation domain (NULL for providers in the
  38.      * evolution source tree).
  39.      */
  40.     char *translation_domain;
  41.     /* This string points to the provider's gconf key value
  42.      */
  43.     const char *license;
  44.     /* This holds the license file name [ ascii text format ] containing
  45.      * the license agreement. This should be the absolute file path. This
  46.      * is read only when the HAS_LICENSE flag is set
  47.      */
  48.     const char *license_file;
  49.     /* Private to the provider */
  50.     void *priv;
  51. } CamelProvider;
以POP3的provider为例,它首先简单的填充了那些固定不变的信息:
  1. static CamelProviderConfEntry pop3_conf_entries[] = {
  2.     { CAMEL_PROVIDER_CONF_SECTION_START, "storage", NULL,
  3.       N_("Message storage") },
  4.     { CAMEL_PROVIDER_CONF_CHECKBOX, "keep_on_server", NULL,
  5.       N_("Leave messages on server"), "0" },
  6.     { CAMEL_PROVIDER_CONF_CHECKSPIN, "delete_after", NULL,
  7.       N_("Delete after %s day(s)"), "0:1:7:365" },
  8.     { CAMEL_PROVIDER_CONF_CHECKBOX, "disable_extensions", NULL,
  9.       N_("Disable support for all POP3 extensions"), "0" },
  10.     { CAMEL_PROVIDER_CONF_SECTION_END },
  11.     { CAMEL_PROVIDER_CONF_END }
  12. };
  13. static CamelProvider pop3_provider = {
  14.     "pop",
  15.     N_("POP"),
  16.     N_("For connecting to and downloading mail from POP servers."),
  17.     "mail",
  18.     CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE |
  19.     CAMEL_PROVIDER_SUPPORTS_SSL,
  20.     CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH,
  21.     pop3_conf_entries,
  22.     /* ... */
  23. };
剩下的部分被放到了 camel_provider_module_init(void)函数中实现:
  1. void
  2. camel_provider_module_init(void)
  3. {
  4.     CamelServiceAuthType *auth;
  5.     pop3_provider.object_types[CAMEL_PROVIDER_STORE] = camel_pop3_store_get_type();
  6.     pop3_provider.url_hash = camel_url_hash;
  7.     pop3_provider.url_equal = camel_url_equal;
  8.     pop3_provider.authtypes = camel_sasl_authtype_list (FALSE);
  9.     auth = camel_sasl_authtype("LOGIN");
  10.     if (auth)
  11.         pop3_provider.authtypes = g_list_prepend(pop3_provider.authtypes, auth);
  12.     pop3_provider.authtypes = g_list_prepend(pop3_provider.authtypes, &camel_pop3_apop_authtype);
  13.     pop3_provider.authtypes = g_list_prepend(pop3_provider.authtypes, &camel_pop3_password_authtype);
  14.     pop3_provider.translation_domain = GETTEXT_PACKAGE;
  15.     camel_provider_register(&pop3_provider);
  16. }
我觉得最值得一提的是这一句: pop3_provider.object_types[CAMEL_PROVIDER_STORE] = camel_pop3_store_get_type();
camel_pop3_store_get_type();能返回一个CamelType类型,而取得这个类型值的代码可以根据这个类型之创建一个CamelPop3Store类型的对象, CamelPop3Store正是CamelStore的派生类。在执行最后一条语句 camel_provider_register(&pop3_provider);以后,就等于说向主程序注册了这个provider了,主程序可以通过一个通用的方法来获得CamelPop3Store提供的服务,而系统只知道它是一个CamelStore。
    CamelPop3Store的定义可以些在另外的源文件里面,其做的最多的一件事就是,默默地实现了基类中定义的大量虚函数,而其自己只增加了少量的几个函数。
    那么,主函数都是怎么知道有那些provider的呢?它只是简单地打开一个默认的路径,搜索里面的所有文件。每个provider包括一个动态库文件和文件名与之对应的*.urls文件,这个文件很简单,只是写了provider提供的协议的名字。主函数可以根据需要,动态地把provider载入盗内存中使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值