0d096a9f33ed4248e94233c800c3e24d0748fbe6
[platform/upstream/evolution-data-server.git] / camel / camel-provider.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* camel-provider.c: provider framework */
3
4 /*
5  *
6  * Authors:
7  *  Bertrand Guiheneuf <bertrand@helixcode.com>
8  *  Dan Winship <danw@ximian.com>
9  *  Jeffrey Stedfast <fejj@ximian.com>
10  *
11  * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of version 2 of the GNU General Public
15  * License as published by the Free Software Foundation.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25  * USA
26  */
27
28
29 /* FIXME: Shouldn't we add a version number to providers ? */
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include <sys/types.h>
36 #include <dirent.h>
37 #include <errno.h>
38 #include <stdio.h>
39 #include <string.h>
40
41 #include <gmodule.h>
42
43 #include "camel-provider.h"
44 #include "camel-exception.h"
45 #include "string-utils.h"
46
47
48 /**
49  * camel_provider_init:
50  *
51  * Initialize the Camel provider system by reading in the .urls
52  * files in the provider directory and creating a hash table mapping
53  * URLs to module names.
54  *
55  * A .urls file has the same initial prefix as the shared library it
56  * correspond to, and consists of a series of lines containing the URL
57  * protocols that that library handles.
58  *
59  * Return value: a hash table mapping URLs to module names
60  **/
61 GHashTable *
62 camel_provider_init (void)
63 {
64         GHashTable *providers;
65         DIR *dir;
66         struct dirent *d;
67         char *p, *name, buf[80];
68         
69         providers = g_hash_table_new (g_strcase_hash, g_strcase_equal);
70         
71         dir = opendir (CAMEL_PROVIDERDIR);
72         if (!dir) {
73                 g_error ("Could not open camel provider directory: %s",
74                          strerror (errno));
75                 return NULL;
76         }
77         
78         while ((d = readdir (dir))) {
79                 FILE *fp;
80                 
81                 p = strchr (d->d_name, '.');
82                 if (!p || strcmp (p, ".urls") != 0)
83                         continue;
84                 
85                 name = g_strdup_printf ("%s/%s", CAMEL_PROVIDERDIR, d->d_name);
86                 fp = fopen (name, "r");
87                 if (!fp) {
88                         g_warning ("Could not read provider info file %s: %s",
89                                    name, strerror (errno));
90                         g_free (name);
91                         continue;
92                 }
93                 
94                 p = strrchr (name, '.');
95                 strcpy (p, ".so");
96                 while ((fgets (buf, sizeof (buf), fp))) {
97                         buf[sizeof (buf) - 1] = '\0';
98                         p = strchr (buf, '\n');
99                         if (p)
100                                 *p = '\0';
101                         
102                         if (*buf)
103                                 g_hash_table_insert (providers, g_strdup (buf), g_strdup (name));
104                 }
105                 
106                 g_free (name);
107                 fclose (fp);
108         }
109
110         closedir (dir);
111         return providers;
112 }
113
114 /**
115  * camel_provider_load:
116  * @session: the current session
117  * @path: the path to a shared library
118  * @ex: a CamelException
119  *
120  * Loads the provider at @path, and calls its initialization function,
121  * passing @session as an argument. The provider should then register
122  * itself with @session.
123  **/ 
124 void
125 camel_provider_load (CamelSession *session, const char *path, CamelException *ex)
126 {
127         GModule *module;
128         CamelProvider *(*camel_provider_module_init) ();
129
130         if (!g_module_supported ()) {
131                 camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
132                                       _("Could not load %s: Module loading "
133                                       "not supported on this system."),
134                                       path);
135                 return;
136         }
137
138         module = g_module_open (path, 0);
139         if (!module) {
140                 camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
141                                       _("Could not load %s: %s"),
142                                       path, g_module_error ());
143                 return;
144         }
145
146         if (!g_module_symbol (module, "camel_provider_module_init",
147                               (gpointer *)&camel_provider_module_init)) {
148                 camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
149                                       _("Could not load %s: No initialization "
150                                         "code in module."), path);
151                 g_module_close (module);
152                 return;
153         }
154
155         camel_provider_module_init (session);
156 }
157
158
159 /**
160  * camel_provider_auto_detect:
161  * @provider: camel provider
162  * @settings: currently set settings
163  * @auto_detected: output hash table of auto-detected values
164  * @ex: exception
165  *
166  * After filling in the standard Username/Hostname/Port/Path settings
167  * (which must be set in @settings), if the provider supports it, you
168  * may wish to have the provider auto-detect further settings based on
169  * the aformentioned settings.
170  *
171  * If the provider does not support auto-detection, @auto_detected
172  * will be set to %NULL. Otherwise the provider will attempt to
173  * auto-detect whatever it can and file them into @auto_detected. If
174  * for some reason it cannot auto-detect anything (not enough
175  * information provided in @settings?) then @auto_deetected will be
176  * set to %NULL and an exception may be set to explain why it failed.
177  *
178  * Returns 0 on success or -1 on fail.
179  **/
180 int
181 camel_provider_auto_detect (CamelProvider *provider, CamelURL *url,
182                             GHashTable **auto_detected, CamelException *ex)
183 {
184         g_return_val_if_fail (provider != NULL, -1);
185         
186         if (provider->auto_detect) {
187                 return provider->auto_detect (url, auto_detected, ex);
188         } else {
189                 *auto_detected = NULL;
190                 return 0;
191         }
192 }