Sync Spanish manual
[claws.git] / src / privacy.c
blob87ff87f087e7cc14a18e10d94be488ee79f12e64
1 /*
2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2021 the Claws Mail team and Hiroyuki Yamamoto
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 "config.h"
22 #include <glib.h>
23 #include <glib/gi18n.h>
25 #include "privacy.h"
26 #include "procmime.h"
27 #include "procmsg.h"
29 static GSList *systems = NULL;
30 static gchar *privacy_last_error = NULL;
32 void privacy_set_error(const gchar *format, ...)
34 va_list args;
35 gchar buf[BUFSIZ];
37 va_start(args, format);
38 g_vsnprintf(buf, BUFSIZ, format, args);
39 va_end(args);
40 g_free(privacy_last_error);
41 privacy_last_error = g_strdup(buf);
44 static gchar tmp_privacy_error[BUFSIZ];
46 void privacy_reset_error(void)
48 g_free(privacy_last_error);
49 privacy_last_error = NULL;
52 gboolean privacy_peek_error(void)
54 return (privacy_last_error != NULL);
57 const gchar *privacy_get_error (void)
59 if (privacy_last_error) {
60 strncpy2(tmp_privacy_error, privacy_last_error, BUFSIZ-1);
61 privacy_reset_error();
62 return tmp_privacy_error;
63 } else {
64 return _("Unknown error");
68 static PrivacySystem *privacy_data_get_system(PrivacyData *data)
70 /* Make sure the cached system is still registered */
71 if (data->system && g_slist_find(systems, data->system))
72 return data->system;
73 else
74 return NULL;
76 /**
77 * Register a new Privacy System
79 * \param system The Privacy System that should be registered
81 void privacy_register_system(PrivacySystem *system)
83 systems = g_slist_append(systems, system);
86 /**
87 * Unregister a new Privacy System. The system must not be in
88 * use anymore when it is unregistered.
90 * \param system The Privacy System that should be unregistered
92 void privacy_unregister_system(PrivacySystem *system)
94 systems = g_slist_remove(systems, system);
97 /**
98 * Free a PrivacyData of a PrivacySystem
100 * \param privacydata The data to free
102 void privacy_free_privacydata(PrivacyData *privacydata)
104 PrivacySystem *system = NULL;
106 cm_return_if_fail(privacydata != NULL);
108 system = privacy_data_get_system(privacydata);
109 if (!system)
110 return;
111 system->free_privacydata(privacydata);
114 void privacy_free_signature_data(gpointer data)
116 SignatureData *sig_data = (SignatureData *)data;
118 cm_return_if_fail(sig_data != NULL);
120 g_free(sig_data->info_short);
121 g_free(sig_data->info_full);
122 g_free(sig_data);
125 void privacy_free_sig_check_task_result(gpointer data)
127 SigCheckTaskResult *result = (SigCheckTaskResult *)data;
129 privacy_free_signature_data(result->sig_data);
130 if (result->newinfo)
131 procmime_mimeinfo_free_all(&result->newinfo);
132 g_free(result);
136 * Check if a MimeInfo is signed with one of the available
137 * privacy system. If a privacydata is set in the MimeInfo
138 * it will directory return the return value by the system
139 * set in the privacy data or check all available privacy
140 * systems otherwise.
142 * \return True if the MimeInfo has a signature
144 gboolean privacy_mimeinfo_is_signed(MimeInfo *mimeinfo)
146 GSList *cur;
147 cm_return_val_if_fail(mimeinfo != NULL, FALSE);
149 if (mimeinfo->privacy != NULL) {
150 PrivacySystem *system =
151 privacy_data_get_system(mimeinfo->privacy);
153 if (system == NULL) {
154 mimeinfo->privacy = NULL;
155 goto try_others;
158 if (system->is_signed != NULL)
159 return system->is_signed(mimeinfo);
160 else
161 return FALSE;
163 try_others:
164 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
165 PrivacySystem *system = (PrivacySystem *) cur->data;
167 if(system->is_signed != NULL && system->is_signed(mimeinfo))
168 return TRUE;
171 return FALSE;
174 struct SignedState {
175 MsgInfo *msginfo;
176 gchar **system;
179 static void msginfo_set_signed_flag(GNode *node, gpointer data)
181 struct SignedState *sstate = (struct SignedState *)data;
182 MsgInfo *msginfo = sstate->msginfo;
183 MimeInfo *mimeinfo = node->data;
185 if (privacy_mimeinfo_is_signed(mimeinfo)) {
186 procmsg_msginfo_set_flags(msginfo, 0, MSG_SIGNED);
187 if (sstate->system && !*(sstate->system) && mimeinfo->privacy)
188 *(sstate->system) = g_strdup(mimeinfo->privacy->system->id);
190 if (privacy_mimeinfo_is_encrypted(mimeinfo)) {
191 procmsg_msginfo_set_flags(msginfo, 0, MSG_ENCRYPTED);
192 if (sstate->system && !*(sstate->system) && mimeinfo->privacy)
193 *(sstate->system) = g_strdup(mimeinfo->privacy->system->id);
194 } else {
195 /* searching inside encrypted parts doesn't really make sense */
196 g_node_children_foreach(mimeinfo->node, G_TRAVERSE_ALL, msginfo_set_signed_flag, sstate);
200 void privacy_msginfo_get_signed_state(MsgInfo *msginfo, gchar **system)
202 struct SignedState sstate;
203 MimeInfo *mimeinfo = procmime_scan_message(msginfo);
204 if (!mimeinfo)
205 return;
206 sstate.msginfo = msginfo;
207 sstate.system = system;
208 g_node_children_foreach(mimeinfo->node, G_TRAVERSE_ALL, msginfo_set_signed_flag, &sstate);
212 * Check the signature of a MimeInfo. privacy_mimeinfo_is_signed
213 * should be called before otherwise it is done by this function.
214 * If the MimeInfo is not signed an error code will be returned.
216 * \return Error code indicating the result of the check,
217 * < 0 if an error occurred
219 gint privacy_mimeinfo_check_signature(MimeInfo *mimeinfo,
220 GCancellable *cancellable,
221 GAsyncReadyCallback callback,
222 gpointer user_data)
224 PrivacySystem *system;
226 if (mimeinfo == NULL)
227 g_error("siginfo was NULL");
229 if (mimeinfo->privacy == NULL) {
230 g_warning("mimeinfo->privacy was NULL");
232 privacy_mimeinfo_is_signed(mimeinfo);
233 if (mimeinfo->privacy == NULL) {
234 g_error("failed to set up PrivacyData");
238 system = privacy_data_get_system(mimeinfo->privacy);
239 if (system == NULL)
240 g_error("failed to get privacy system");
241 else if (system->check_signature == NULL)
242 g_error("didn't find check_signature function");
244 return system->check_signature(mimeinfo, cancellable, callback, user_data);
247 SignatureStatus privacy_mimeinfo_get_sig_status(MimeInfo *mimeinfo)
249 PrivacySystem *system;
251 cm_return_val_if_fail(mimeinfo != NULL, -1);
253 if (mimeinfo->privacy == NULL) {
254 privacy_mimeinfo_is_signed(mimeinfo);
256 if (mimeinfo->privacy == NULL)
257 return SIGNATURE_UNCHECKED;
260 system = privacy_data_get_system(mimeinfo->privacy);
261 if (system == NULL)
262 return SIGNATURE_UNCHECKED;
264 if (mimeinfo->sig_data == NULL)
265 return SIGNATURE_UNCHECKED;
266 else
267 return mimeinfo->sig_data->status;
270 gchar *privacy_mimeinfo_get_sig_info(MimeInfo *mimeinfo, gboolean full)
272 PrivacySystem *system;
273 gchar *info;
275 cm_return_val_if_fail(mimeinfo != NULL, NULL);
277 if (mimeinfo->privacy == NULL) {
278 privacy_mimeinfo_is_signed(mimeinfo);
280 if (mimeinfo->privacy == NULL)
281 return _("No signature found");
284 system = privacy_data_get_system(mimeinfo->privacy);
285 if (system == NULL)
286 return _("No signature found");
288 if (mimeinfo->sig_data == NULL)
289 return _("No information available");
291 info = full ? mimeinfo->sig_data->info_full : mimeinfo->sig_data->info_short;
292 if (info == NULL)
293 return _("No information available");
295 return info;
298 gboolean privacy_mimeinfo_is_encrypted(MimeInfo *mimeinfo)
300 GSList *cur;
301 cm_return_val_if_fail(mimeinfo != NULL, FALSE);
303 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
304 PrivacySystem *system = (PrivacySystem *) cur->data;
306 if(system->is_encrypted != NULL && system->is_encrypted(mimeinfo))
307 return TRUE;
310 return FALSE;
313 static gint decrypt(MimeInfo *mimeinfo, PrivacySystem *system)
315 MimeInfo *decryptedinfo, *parentinfo;
316 gint childnumber;
318 cm_return_val_if_fail(system->decrypt != NULL, -1);
320 decryptedinfo = system->decrypt(mimeinfo);
321 if (decryptedinfo == NULL)
322 return -1;
324 parentinfo = procmime_mimeinfo_parent(mimeinfo);
325 childnumber = g_node_child_index(parentinfo->node, mimeinfo);
327 procmime_mimeinfo_free_all(&mimeinfo);
329 g_node_insert(parentinfo->node, childnumber, decryptedinfo->node);
331 return 0;
334 gint privacy_mimeinfo_decrypt(MimeInfo *mimeinfo)
336 GSList *cur;
337 cm_return_val_if_fail(mimeinfo != NULL, FALSE);
339 procmime_decode_content(mimeinfo);
341 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
342 PrivacySystem *system = (PrivacySystem *) cur->data;
344 if(system->is_encrypted != NULL && system->is_encrypted(mimeinfo))
345 return decrypt(mimeinfo, system);
348 return -1;
351 GSList *privacy_get_system_ids()
353 GSList *cur;
354 GSList *ret = NULL;
356 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
357 PrivacySystem *system = (PrivacySystem *) cur->data;
359 ret = g_slist_append(ret, g_strdup(system->id));
362 return ret;
365 static PrivacySystem *privacy_get_system(const gchar *id)
367 GSList *cur;
369 cm_return_val_if_fail(id != NULL, NULL);
371 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
372 PrivacySystem *system = (PrivacySystem *) cur->data;
374 if(strcmp(id, system->id) == 0)
375 return system;
378 return NULL;
381 const gchar *privacy_system_get_name(const gchar *id)
383 PrivacySystem *system;
385 cm_return_val_if_fail(id != NULL, NULL);
387 system = privacy_get_system(id);
388 if (system == NULL)
389 return NULL;
391 return system->name;
394 gboolean privacy_system_can_sign(const gchar *id)
396 PrivacySystem *system;
398 cm_return_val_if_fail(id != NULL, FALSE);
400 system = privacy_get_system(id);
401 if (system == NULL)
402 return FALSE;
404 return system->can_sign;
407 gboolean privacy_system_can_encrypt(const gchar *id)
409 PrivacySystem *system;
411 cm_return_val_if_fail(id != NULL, FALSE);
413 system = privacy_get_system(id);
414 if (system == NULL)
415 return FALSE;
417 return system->can_encrypt;
420 gboolean privacy_sign(const gchar *id, MimeInfo *target, PrefsAccount *account, const gchar *from_addr)
422 PrivacySystem *system;
424 cm_return_val_if_fail(id != NULL, FALSE);
425 cm_return_val_if_fail(target != NULL, FALSE);
427 system = privacy_get_system(id);
428 if (system == NULL)
429 return FALSE;
430 if (!system->can_sign)
431 return FALSE;
432 if (system->sign == NULL)
433 return FALSE;
435 return system->sign(target, account, from_addr);
438 gchar *privacy_get_encrypt_data(const gchar *id, GSList *recp_names)
440 PrivacySystem *system;
441 gchar *ret = NULL;
442 GSList *uniq_names = NULL, *cur;
444 cm_return_val_if_fail(id != NULL, NULL);
445 cm_return_val_if_fail(recp_names != NULL, NULL);
447 system = privacy_get_system(id);
448 if (system == NULL)
449 return NULL;
450 if (!system->can_encrypt)
451 return NULL;
452 if (system->get_encrypt_data == NULL)
453 return NULL;
455 for (cur = recp_names; cur; cur = cur->next) {
456 if (!g_slist_find_custom(uniq_names, cur->data, (GCompareFunc)strcmp)) {
457 uniq_names = g_slist_prepend(uniq_names, cur->data);
460 ret = system->get_encrypt_data(uniq_names);
462 g_slist_free(uniq_names);
463 return ret;
466 const gchar *privacy_get_encrypt_warning(const gchar *id)
468 PrivacySystem *system;
470 cm_return_val_if_fail(id != NULL, NULL);
472 system = privacy_get_system(id);
473 if (system == NULL)
474 return NULL;
475 if (!system->can_encrypt)
476 return NULL;
477 if (system->get_encrypt_warning == NULL)
478 return NULL;
480 return system->get_encrypt_warning();
483 void privacy_inhibit_encrypt_warning(const gchar *id, gboolean inhibit)
485 PrivacySystem *system;
487 cm_return_if_fail(id != NULL);
489 system = privacy_get_system(id);
490 if (system == NULL)
491 return;
492 if (!system->can_encrypt)
493 return;
494 if (system->inhibit_encrypt_warning == NULL)
495 return;
497 system->inhibit_encrypt_warning(inhibit);
500 gboolean privacy_encrypt(const gchar *id, MimeInfo *mimeinfo, const gchar *encdata)
502 PrivacySystem *system;
504 cm_return_val_if_fail(id != NULL, FALSE);
505 cm_return_val_if_fail(mimeinfo != NULL, FALSE);
506 if (encdata == NULL) {
507 privacy_set_error(_("No recipient keys defined."));
508 return FALSE;
511 system = privacy_get_system(id);
512 if (system == NULL)
513 return FALSE;
514 if (!system->can_encrypt)
515 return FALSE;
516 if (system->encrypt == NULL)
517 return FALSE;
519 return system->encrypt(mimeinfo, encdata);
522 gboolean privacy_auto_check_signatures(MimeInfo *mimeinfo)
524 PrivacySystem *system;
526 cm_return_val_if_fail(mimeinfo != NULL, FALSE);
528 if (mimeinfo->privacy == NULL)
529 privacy_mimeinfo_is_signed(mimeinfo);
531 if (mimeinfo->privacy == NULL)
532 return FALSE;
534 system = privacy_data_get_system(mimeinfo->privacy);
535 if (system == NULL)
536 return FALSE;
537 if (system->auto_check_signatures == NULL)
538 return FALSE;
540 return system->auto_check_signatures();