2006-06-15 [colin] 2.3.0cvs16
[claws.git] / src / privacy.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2006 Hiroyuki Yamamoto & the Sylpheed-Claws team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #include <glib.h>
21 #include <glib/gi18n.h>
22
23 #include "privacy.h"
24 #include "procmime.h"
25
26 static GSList *systems = NULL;
27 static gchar *privacy_last_error = NULL;
28
29 void privacy_set_error(const gchar *format, ...)
30 {
31         va_list args;
32         gchar buf[BUFSIZ];
33
34         va_start(args, format);
35         g_vsnprintf(buf, BUFSIZ, format, args);
36         va_end(args);
37         g_free(privacy_last_error);
38         privacy_last_error = g_strdup(buf);
39 }
40
41 static gchar tmp_privacy_error[BUFSIZ];
42
43 const gchar *privacy_get_error (void)
44 {
45         if (privacy_last_error) {
46                 strncpy2(tmp_privacy_error, privacy_last_error, BUFSIZ-1);
47                 g_free(privacy_last_error);
48                 privacy_last_error = NULL;
49                 return tmp_privacy_error;
50         } else {
51                 return _("Unknown error");
52         }
53 }
54
55 PrivacySystem *privacy_data_get_system(PrivacyData *data)
56 {
57         /* Make sure the cached system is still registered */
58         if (data->system && g_slist_find(systems, data->system))
59                 return data->system;
60         else
61                 return NULL;
62 }
63 /**
64  * Register a new Privacy System
65  *
66  * \param system The Privacy System that should be registered
67  */
68 void privacy_register_system(PrivacySystem *system)
69 {
70         systems = g_slist_append(systems, system);
71 }
72
73 /**
74  * Unregister a new Privacy System. The system must not be in
75  * use anymore when it is unregistered.
76  *
77  * \param system The Privacy System that should be unregistered
78  */
79 void privacy_unregister_system(PrivacySystem *system)
80 {
81         systems = g_slist_remove(systems, system);
82 }
83
84 /**
85  * Free a PrivacyData of a PrivacySystem
86  *
87  * \param privacydata The data to free
88  */
89 void privacy_free_privacydata(PrivacyData *privacydata)
90 {
91         PrivacySystem *system = NULL;
92         
93         g_return_if_fail(privacydata != NULL);
94
95         system = privacy_data_get_system(privacydata);
96         if (!system)
97                 return;
98         system->free_privacydata(privacydata);
99 }
100
101 /**
102  * Check if a MimeInfo is signed with one of the available
103  * privacy system. If a privacydata is set in the MimeInfo
104  * it will directory return the return value by the system
105  * set in the privacy data or check all available privacy
106  * systems otherwise.
107  *
108  * \return True if the MimeInfo has a signature
109  */
110 gboolean privacy_mimeinfo_is_signed(MimeInfo *mimeinfo)
111 {
112         GSList *cur;
113         g_return_val_if_fail(mimeinfo != NULL, FALSE);
114
115         if (mimeinfo->privacy != NULL) {
116                 PrivacySystem *system = 
117                         privacy_data_get_system(mimeinfo->privacy);
118
119                 if (system == NULL) {
120                         mimeinfo->privacy = NULL;
121                         goto try_others;
122                 }
123
124                 if (system->is_signed != NULL)
125                         return system->is_signed(mimeinfo);
126                 else
127                         return FALSE;
128         }
129 try_others:
130         for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
131                 PrivacySystem *system = (PrivacySystem *) cur->data;
132
133                 if(system->is_signed != NULL && system->is_signed(mimeinfo))
134                         return TRUE;
135         }
136
137         return FALSE;
138 }
139
140 /**
141  * Check the signature of a MimeInfo. privacy_mimeinfo_is_signed
142  * should be called before otherwise it is done by this function.
143  * If the MimeInfo is not signed an error code will be returned.
144  *
145  * \return Error code indicating the result of the check,
146  *         < 0 if an error occured
147  */
148 gint privacy_mimeinfo_check_signature(MimeInfo *mimeinfo)
149 {
150         PrivacySystem *system;
151
152         g_return_val_if_fail(mimeinfo != NULL, -1);
153
154         if (mimeinfo->privacy == NULL)
155                 privacy_mimeinfo_is_signed(mimeinfo);
156         
157         if (mimeinfo->privacy == NULL)
158                 return -1;
159         
160         system = privacy_data_get_system(mimeinfo->privacy);
161         if (system == NULL)
162                 return -1;
163
164         if (system->check_signature == NULL)
165                 return -1;
166         
167         return system->check_signature(mimeinfo);
168 }
169
170 SignatureStatus privacy_mimeinfo_get_sig_status(MimeInfo *mimeinfo)
171 {
172         PrivacySystem *system;
173
174         g_return_val_if_fail(mimeinfo != NULL, -1);
175
176         if (mimeinfo->privacy == NULL)
177                 privacy_mimeinfo_is_signed(mimeinfo);
178         
179         if (mimeinfo->privacy == NULL)
180                 return SIGNATURE_UNCHECKED;
181         
182         system = privacy_data_get_system(mimeinfo->privacy);
183         if (system == NULL)
184                 return SIGNATURE_UNCHECKED;
185         if (system->get_sig_status == NULL)
186                 return SIGNATURE_UNCHECKED;
187         
188         return system->get_sig_status(mimeinfo);
189 }
190
191 gchar *privacy_mimeinfo_sig_info_short(MimeInfo *mimeinfo)
192 {
193         PrivacySystem *system;
194
195         g_return_val_if_fail(mimeinfo != NULL, NULL);
196
197         if (mimeinfo->privacy == NULL)
198                 privacy_mimeinfo_is_signed(mimeinfo);
199         
200         if (mimeinfo->privacy == NULL)
201                 return g_strdup(_("No signature found"));
202         
203         system = privacy_data_get_system(mimeinfo->privacy);
204         if (system == NULL)
205                 return g_strdup(_("No signature found"));
206         if (system->get_sig_info_short == NULL)
207                 return g_strdup(_("No information available"));
208         
209         return system->get_sig_info_short(mimeinfo);
210 }
211
212 gchar *privacy_mimeinfo_sig_info_full(MimeInfo *mimeinfo)
213 {
214         PrivacySystem *system;
215
216         g_return_val_if_fail(mimeinfo != NULL, NULL);
217
218         if (mimeinfo->privacy == NULL)
219                 privacy_mimeinfo_is_signed(mimeinfo);
220         
221         if (mimeinfo->privacy == NULL)
222                 return g_strdup(_("No signature found"));
223         
224         system = privacy_data_get_system(mimeinfo->privacy);
225         if (system == NULL)
226                 return g_strdup(_("No signature found"));
227         if (system->get_sig_info_full == NULL)
228                 return g_strdup(_("No information available"));
229         
230         return system->get_sig_info_full(mimeinfo);
231 }
232
233 gboolean privacy_mimeinfo_is_encrypted(MimeInfo *mimeinfo)
234 {
235         GSList *cur;
236         g_return_val_if_fail(mimeinfo != NULL, FALSE);
237
238         for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
239                 PrivacySystem *system = (PrivacySystem *) cur->data;
240
241                 if(system->is_encrypted != NULL && system->is_encrypted(mimeinfo))
242                         return TRUE;
243         }
244
245         return FALSE;
246 }
247
248 static gint decrypt(MimeInfo *mimeinfo, PrivacySystem *system)
249 {
250         MimeInfo *decryptedinfo, *parentinfo;
251         gint childnumber;
252         
253         g_return_val_if_fail(system->decrypt != NULL, -1);
254         
255         decryptedinfo = system->decrypt(mimeinfo);
256         if (decryptedinfo == NULL)
257                 return -1;
258
259         parentinfo = procmime_mimeinfo_parent(mimeinfo);
260         childnumber = g_node_child_index(parentinfo->node, mimeinfo);
261         
262         procmime_mimeinfo_free_all(mimeinfo);
263
264         g_node_insert(parentinfo->node, childnumber, decryptedinfo->node);
265
266         return 0;
267 }
268
269 gint privacy_mimeinfo_decrypt(MimeInfo *mimeinfo)
270 {
271         GSList *cur;
272         g_return_val_if_fail(mimeinfo != NULL, FALSE);
273
274         for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
275                 PrivacySystem *system = (PrivacySystem *) cur->data;
276
277                 if(system->is_encrypted != NULL && system->is_encrypted(mimeinfo))
278                         return decrypt(mimeinfo, system);
279         }
280
281         return -1;
282 }
283
284 GSList *privacy_get_system_ids()
285 {
286         GSList *cur;
287         GSList *ret = NULL;
288
289         for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
290                 PrivacySystem *system = (PrivacySystem *) cur->data;
291
292                 ret = g_slist_append(ret, g_strdup(system->id));
293         }
294
295         return ret;
296 }
297
298 static PrivacySystem *privacy_get_system(const gchar *id)
299 {
300         GSList *cur;
301
302         g_return_val_if_fail(id != NULL, NULL);
303
304         for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
305                 PrivacySystem *system = (PrivacySystem *) cur->data;
306
307                 if(strcmp(id, system->id) == 0)
308                         return system;
309         }
310
311         return NULL;
312 }
313
314 const gchar *privacy_system_get_name(const gchar *id)
315 {
316         PrivacySystem *system;
317
318         g_return_val_if_fail(id != NULL, NULL);
319
320         system = privacy_get_system(id);
321         if (system == NULL)
322                 return NULL;
323
324         return system->name;
325 }
326
327 gboolean privacy_system_can_sign(const gchar *id)
328 {
329         PrivacySystem *system;
330
331         g_return_val_if_fail(id != NULL, FALSE);
332
333         system = privacy_get_system(id);
334         if (system == NULL)
335                 return FALSE;
336
337         return system->can_sign;
338 }
339
340 gboolean privacy_system_can_encrypt(const gchar *id)
341 {
342         PrivacySystem *system;
343
344         g_return_val_if_fail(id != NULL, FALSE);
345
346         system = privacy_get_system(id);
347         if (system == NULL)
348                 return FALSE;
349
350         return system->can_encrypt;
351 }
352
353 gboolean privacy_sign(const gchar *id, MimeInfo *target, PrefsAccount *account)
354 {
355         PrivacySystem *system;
356
357         g_return_val_if_fail(id != NULL, FALSE);
358         g_return_val_if_fail(target != NULL, FALSE);
359
360         system = privacy_get_system(id);
361         if (system == NULL)
362                 return FALSE;
363         if (!system->can_sign)
364                 return FALSE;
365         if (system->sign == NULL)
366                 return FALSE;
367
368         return system->sign(target, account);
369 }
370
371 gchar *privacy_get_encrypt_data(const gchar *id, GSList *recp_names)
372 {
373         PrivacySystem *system;
374
375         g_return_val_if_fail(id != NULL, NULL);
376         g_return_val_if_fail(recp_names != NULL, NULL);
377
378         system = privacy_get_system(id);
379         if (system == NULL)
380                 return NULL;
381         if (!system->can_encrypt)
382                 return NULL;
383         if (system->get_encrypt_data == NULL)
384                 return NULL;
385
386         return system->get_encrypt_data(recp_names);
387 }
388
389 gboolean privacy_encrypt(const gchar *id, MimeInfo *mimeinfo, const gchar *encdata)
390 {
391         PrivacySystem *system;
392
393         g_return_val_if_fail(id != NULL, FALSE);
394         g_return_val_if_fail(mimeinfo != NULL, FALSE);
395         if (encdata == NULL) {
396                 privacy_set_error(_("No recipient keys defined."));
397                 return FALSE;
398         }
399
400         system = privacy_get_system(id);
401         if (system == NULL)
402                 return FALSE;
403         if (!system->can_encrypt)
404                 return FALSE;
405         if (system->encrypt == NULL)
406                 return FALSE;
407
408         return system->encrypt(mimeinfo, encdata);
409 }