3.7.2 unleashed
[claws.git] / src / privacy.c
blob977a83509adc3116dda5859a5758b23035d2c145
1 /*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2009 Hiroyuki Yamamoto & the Claws Mail team
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 3 of the License, or
8 * (at your option) any later version.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <glib.h>
21 #include <glib/gi18n.h>
23 #include "privacy.h"
24 #include "procmime.h"
26 static GSList *systems = NULL;
27 static gchar *privacy_last_error = NULL;
29 void privacy_set_error(const gchar *format, ...)
31 va_list args;
32 gchar buf[BUFSIZ];
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);
41 static gchar tmp_privacy_error[BUFSIZ];
43 void privacy_reset_error(void)
45 g_free(privacy_last_error);
46 privacy_last_error = NULL;
49 gboolean privacy_peek_error(void)
51 return (privacy_last_error != NULL);
54 const gchar *privacy_get_error (void)
56 if (privacy_last_error) {
57 strncpy2(tmp_privacy_error, privacy_last_error, BUFSIZ-1);
58 privacy_reset_error();
59 return tmp_privacy_error;
60 } else {
61 return _("Unknown error");
65 static PrivacySystem *privacy_data_get_system(PrivacyData *data)
67 /* Make sure the cached system is still registered */
68 if (data->system && g_slist_find(systems, data->system))
69 return data->system;
70 else
71 return NULL;
73 /**
74 * Register a new Privacy System
76 * \param system The Privacy System that should be registered
78 void privacy_register_system(PrivacySystem *system)
80 systems = g_slist_append(systems, system);
83 /**
84 * Unregister a new Privacy System. The system must not be in
85 * use anymore when it is unregistered.
87 * \param system The Privacy System that should be unregistered
89 void privacy_unregister_system(PrivacySystem *system)
91 systems = g_slist_remove(systems, system);
94 /**
95 * Free a PrivacyData of a PrivacySystem
97 * \param privacydata The data to free
99 void privacy_free_privacydata(PrivacyData *privacydata)
101 PrivacySystem *system = NULL;
103 cm_return_if_fail(privacydata != NULL);
105 system = privacy_data_get_system(privacydata);
106 if (!system)
107 return;
108 system->free_privacydata(privacydata);
112 * Check if a MimeInfo is signed with one of the available
113 * privacy system. If a privacydata is set in the MimeInfo
114 * it will directory return the return value by the system
115 * set in the privacy data or check all available privacy
116 * systems otherwise.
118 * \return True if the MimeInfo has a signature
120 gboolean privacy_mimeinfo_is_signed(MimeInfo *mimeinfo)
122 GSList *cur;
123 cm_return_val_if_fail(mimeinfo != NULL, FALSE);
125 if (mimeinfo->privacy != NULL) {
126 PrivacySystem *system =
127 privacy_data_get_system(mimeinfo->privacy);
129 if (system == NULL) {
130 mimeinfo->privacy = NULL;
131 goto try_others;
134 if (system->is_signed != NULL)
135 return system->is_signed(mimeinfo);
136 else
137 return FALSE;
139 try_others:
140 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
141 PrivacySystem *system = (PrivacySystem *) cur->data;
143 if(system->is_signed != NULL && system->is_signed(mimeinfo))
144 return TRUE;
147 return FALSE;
150 struct SignedState {
151 MsgInfo *msginfo;
152 gchar **system;
155 static void msginfo_set_signed_flag(GNode *node, gpointer data)
157 struct SignedState *sstate = (struct SignedState *)data;
158 MsgInfo *msginfo = sstate->msginfo;
159 MimeInfo *mimeinfo = node->data;
161 if (privacy_mimeinfo_is_signed(mimeinfo)) {
162 procmsg_msginfo_set_flags(msginfo, 0, MSG_SIGNED);
163 if (sstate->system && !*(sstate->system) && mimeinfo->privacy)
164 *(sstate->system) = g_strdup(mimeinfo->privacy->system->id);
166 if (privacy_mimeinfo_is_encrypted(mimeinfo)) {
167 procmsg_msginfo_set_flags(msginfo, 0, MSG_ENCRYPTED);
168 if (sstate->system && !*(sstate->system) && mimeinfo->privacy)
169 *(sstate->system) = g_strdup(mimeinfo->privacy->system->id);
170 } else {
171 /* searching inside encrypted parts doesn't really make sense */
172 g_node_children_foreach(mimeinfo->node, G_TRAVERSE_ALL, msginfo_set_signed_flag, sstate);
176 void privacy_msginfo_get_signed_state(MsgInfo *msginfo, gchar **system)
178 struct SignedState sstate;
179 MimeInfo *mimeinfo = procmime_scan_message(msginfo);
180 if (!mimeinfo)
181 return;
182 sstate.msginfo = msginfo;
183 sstate.system = system;
184 g_node_children_foreach(mimeinfo->node, G_TRAVERSE_ALL, msginfo_set_signed_flag, &sstate);
188 * Check the signature of a MimeInfo. privacy_mimeinfo_is_signed
189 * should be called before otherwise it is done by this function.
190 * If the MimeInfo is not signed an error code will be returned.
192 * \return Error code indicating the result of the check,
193 * < 0 if an error occured
195 gint privacy_mimeinfo_check_signature(MimeInfo *mimeinfo)
197 PrivacySystem *system;
199 cm_return_val_if_fail(mimeinfo != NULL, -1);
201 if (mimeinfo->privacy == NULL)
202 privacy_mimeinfo_is_signed(mimeinfo);
204 if (mimeinfo->privacy == NULL)
205 return -1;
207 system = privacy_data_get_system(mimeinfo->privacy);
208 if (system == NULL)
209 return -1;
211 if (system->check_signature == NULL)
212 return -1;
214 return system->check_signature(mimeinfo);
217 SignatureStatus privacy_mimeinfo_get_sig_status(MimeInfo *mimeinfo)
219 PrivacySystem *system;
221 cm_return_val_if_fail(mimeinfo != NULL, -1);
223 if (mimeinfo->privacy == NULL)
224 privacy_mimeinfo_is_signed(mimeinfo);
226 if (mimeinfo->privacy == NULL)
227 return SIGNATURE_UNCHECKED;
229 system = privacy_data_get_system(mimeinfo->privacy);
230 if (system == NULL)
231 return SIGNATURE_UNCHECKED;
232 if (system->get_sig_status == NULL)
233 return SIGNATURE_UNCHECKED;
235 return system->get_sig_status(mimeinfo);
238 gchar *privacy_mimeinfo_sig_info_short(MimeInfo *mimeinfo)
240 PrivacySystem *system;
242 cm_return_val_if_fail(mimeinfo != NULL, NULL);
244 if (mimeinfo->privacy == NULL)
245 privacy_mimeinfo_is_signed(mimeinfo);
247 if (mimeinfo->privacy == NULL)
248 return g_strdup(_("No signature found"));
250 system = privacy_data_get_system(mimeinfo->privacy);
251 if (system == NULL)
252 return g_strdup(_("No signature found"));
253 if (system->get_sig_info_short == NULL)
254 return g_strdup(_("No information available"));
256 return system->get_sig_info_short(mimeinfo);
259 gchar *privacy_mimeinfo_sig_info_full(MimeInfo *mimeinfo)
261 PrivacySystem *system;
263 cm_return_val_if_fail(mimeinfo != NULL, NULL);
265 if (mimeinfo->privacy == NULL)
266 privacy_mimeinfo_is_signed(mimeinfo);
268 if (mimeinfo->privacy == NULL)
269 return g_strdup(_("No signature found"));
271 system = privacy_data_get_system(mimeinfo->privacy);
272 if (system == NULL)
273 return g_strdup(_("No signature found"));
274 if (system->get_sig_info_full == NULL)
275 return g_strdup(_("No information available"));
277 return system->get_sig_info_full(mimeinfo);
280 gboolean privacy_mimeinfo_is_encrypted(MimeInfo *mimeinfo)
282 GSList *cur;
283 cm_return_val_if_fail(mimeinfo != NULL, FALSE);
285 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
286 PrivacySystem *system = (PrivacySystem *) cur->data;
288 if(system->is_encrypted != NULL && system->is_encrypted(mimeinfo))
289 return TRUE;
292 return FALSE;
295 static gint decrypt(MimeInfo *mimeinfo, PrivacySystem *system)
297 MimeInfo *decryptedinfo, *parentinfo;
298 gint childnumber;
300 cm_return_val_if_fail(system->decrypt != NULL, -1);
302 decryptedinfo = system->decrypt(mimeinfo);
303 if (decryptedinfo == NULL)
304 return -1;
306 parentinfo = procmime_mimeinfo_parent(mimeinfo);
307 childnumber = g_node_child_index(parentinfo->node, mimeinfo);
309 procmime_mimeinfo_free_all(mimeinfo);
311 g_node_insert(parentinfo->node, childnumber, decryptedinfo->node);
313 return 0;
316 gint privacy_mimeinfo_decrypt(MimeInfo *mimeinfo)
318 GSList *cur;
319 cm_return_val_if_fail(mimeinfo != NULL, FALSE);
321 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
322 PrivacySystem *system = (PrivacySystem *) cur->data;
324 if(system->is_encrypted != NULL && system->is_encrypted(mimeinfo))
325 return decrypt(mimeinfo, system);
328 return -1;
331 GSList *privacy_get_system_ids()
333 GSList *cur;
334 GSList *ret = NULL;
336 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
337 PrivacySystem *system = (PrivacySystem *) cur->data;
339 ret = g_slist_append(ret, g_strdup(system->id));
342 return ret;
345 static PrivacySystem *privacy_get_system(const gchar *id)
347 GSList *cur;
349 cm_return_val_if_fail(id != NULL, NULL);
351 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
352 PrivacySystem *system = (PrivacySystem *) cur->data;
354 if(strcmp(id, system->id) == 0)
355 return system;
358 return NULL;
361 const gchar *privacy_system_get_name(const gchar *id)
363 PrivacySystem *system;
365 cm_return_val_if_fail(id != NULL, NULL);
367 system = privacy_get_system(id);
368 if (system == NULL)
369 return NULL;
371 return system->name;
374 gboolean privacy_system_can_sign(const gchar *id)
376 PrivacySystem *system;
378 cm_return_val_if_fail(id != NULL, FALSE);
380 system = privacy_get_system(id);
381 if (system == NULL)
382 return FALSE;
384 return system->can_sign;
387 gboolean privacy_system_can_encrypt(const gchar *id)
389 PrivacySystem *system;
391 cm_return_val_if_fail(id != NULL, FALSE);
393 system = privacy_get_system(id);
394 if (system == NULL)
395 return FALSE;
397 return system->can_encrypt;
400 gboolean privacy_sign(const gchar *id, MimeInfo *target, PrefsAccount *account, const gchar *from_addr)
402 PrivacySystem *system;
404 cm_return_val_if_fail(id != NULL, FALSE);
405 cm_return_val_if_fail(target != NULL, FALSE);
407 system = privacy_get_system(id);
408 if (system == NULL)
409 return FALSE;
410 if (!system->can_sign)
411 return FALSE;
412 if (system->sign == NULL)
413 return FALSE;
415 return system->sign(target, account, from_addr);
418 gchar *privacy_get_encrypt_data(const gchar *id, GSList *recp_names)
420 PrivacySystem *system;
421 gchar *ret = NULL;
422 GSList *uniq_names = NULL, *cur;
424 cm_return_val_if_fail(id != NULL, NULL);
425 cm_return_val_if_fail(recp_names != NULL, NULL);
427 system = privacy_get_system(id);
428 if (system == NULL)
429 return NULL;
430 if (!system->can_encrypt)
431 return NULL;
432 if (system->get_encrypt_data == NULL)
433 return NULL;
435 for (cur = recp_names; cur; cur = cur->next) {
436 if (!g_slist_find_custom(uniq_names, cur->data, (GCompareFunc)strcmp)) {
437 uniq_names = g_slist_prepend(uniq_names, cur->data);
440 ret = system->get_encrypt_data(uniq_names);
442 g_slist_free(uniq_names);
443 return ret;
446 const gchar *privacy_get_encrypt_warning(const gchar *id)
448 PrivacySystem *system;
450 cm_return_val_if_fail(id != NULL, NULL);
452 system = privacy_get_system(id);
453 if (system == NULL)
454 return NULL;
455 if (!system->can_encrypt)
456 return NULL;
457 if (system->get_encrypt_warning == NULL)
458 return NULL;
460 return system->get_encrypt_warning();
463 void privacy_inhibit_encrypt_warning(const gchar *id, gboolean inhibit)
465 PrivacySystem *system;
467 cm_return_if_fail(id != NULL);
469 system = privacy_get_system(id);
470 if (system == NULL)
471 return;
472 if (!system->can_encrypt)
473 return;
474 if (system->inhibit_encrypt_warning == NULL)
475 return;
477 system->inhibit_encrypt_warning(inhibit);
480 gboolean privacy_encrypt(const gchar *id, MimeInfo *mimeinfo, const gchar *encdata)
482 PrivacySystem *system;
484 cm_return_val_if_fail(id != NULL, FALSE);
485 cm_return_val_if_fail(mimeinfo != NULL, FALSE);
486 if (encdata == NULL) {
487 privacy_set_error(_("No recipient keys defined."));
488 return FALSE;
491 system = privacy_get_system(id);
492 if (system == NULL)
493 return FALSE;
494 if (!system->can_encrypt)
495 return FALSE;
496 if (system->encrypt == NULL)
497 return FALSE;
499 return system->encrypt(mimeinfo, encdata);