2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2012 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/>.
21 #include <glib/gi18n.h>
27 static GSList
*systems
= NULL
;
28 static gchar
*privacy_last_error
= NULL
;
30 void privacy_set_error(const gchar
*format
, ...)
35 va_start(args
, format
);
36 g_vsnprintf(buf
, BUFSIZ
, format
, args
);
38 g_free(privacy_last_error
);
39 privacy_last_error
= g_strdup(buf
);
42 static gchar tmp_privacy_error
[BUFSIZ
];
44 void privacy_reset_error(void)
46 g_free(privacy_last_error
);
47 privacy_last_error
= NULL
;
50 gboolean
privacy_peek_error(void)
52 return (privacy_last_error
!= NULL
);
55 const gchar
*privacy_get_error (void)
57 if (privacy_last_error
) {
58 strncpy2(tmp_privacy_error
, privacy_last_error
, BUFSIZ
-1);
59 privacy_reset_error();
60 return tmp_privacy_error
;
62 return _("Unknown error");
66 static PrivacySystem
*privacy_data_get_system(PrivacyData
*data
)
68 /* Make sure the cached system is still registered */
69 if (data
->system
&& g_slist_find(systems
, data
->system
))
75 * Register a new Privacy System
77 * \param system The Privacy System that should be registered
79 void privacy_register_system(PrivacySystem
*system
)
81 systems
= g_slist_append(systems
, system
);
85 * Unregister a new Privacy System. The system must not be in
86 * use anymore when it is unregistered.
88 * \param system The Privacy System that should be unregistered
90 void privacy_unregister_system(PrivacySystem
*system
)
92 systems
= g_slist_remove(systems
, system
);
96 * Free a PrivacyData of a PrivacySystem
98 * \param privacydata The data to free
100 void privacy_free_privacydata(PrivacyData
*privacydata
)
102 PrivacySystem
*system
= NULL
;
104 cm_return_if_fail(privacydata
!= NULL
);
106 system
= privacy_data_get_system(privacydata
);
109 system
->free_privacydata(privacydata
);
113 * Check if a MimeInfo is signed with one of the available
114 * privacy system. If a privacydata is set in the MimeInfo
115 * it will directory return the return value by the system
116 * set in the privacy data or check all available privacy
119 * \return True if the MimeInfo has a signature
121 gboolean
privacy_mimeinfo_is_signed(MimeInfo
*mimeinfo
)
124 cm_return_val_if_fail(mimeinfo
!= NULL
, FALSE
);
126 if (mimeinfo
->privacy
!= NULL
) {
127 PrivacySystem
*system
=
128 privacy_data_get_system(mimeinfo
->privacy
);
130 if (system
== NULL
) {
131 mimeinfo
->privacy
= NULL
;
135 if (system
->is_signed
!= NULL
)
136 return system
->is_signed(mimeinfo
);
141 for(cur
= systems
; cur
!= NULL
; cur
= g_slist_next(cur
)) {
142 PrivacySystem
*system
= (PrivacySystem
*) cur
->data
;
144 if(system
->is_signed
!= NULL
&& system
->is_signed(mimeinfo
))
156 static void msginfo_set_signed_flag(GNode
*node
, gpointer data
)
158 struct SignedState
*sstate
= (struct SignedState
*)data
;
159 MsgInfo
*msginfo
= sstate
->msginfo
;
160 MimeInfo
*mimeinfo
= node
->data
;
162 if (privacy_mimeinfo_is_signed(mimeinfo
)) {
163 procmsg_msginfo_set_flags(msginfo
, 0, MSG_SIGNED
);
164 if (sstate
->system
&& !*(sstate
->system
) && mimeinfo
->privacy
)
165 *(sstate
->system
) = g_strdup(mimeinfo
->privacy
->system
->id
);
167 if (privacy_mimeinfo_is_encrypted(mimeinfo
)) {
168 procmsg_msginfo_set_flags(msginfo
, 0, MSG_ENCRYPTED
);
169 if (sstate
->system
&& !*(sstate
->system
) && mimeinfo
->privacy
)
170 *(sstate
->system
) = g_strdup(mimeinfo
->privacy
->system
->id
);
172 /* searching inside encrypted parts doesn't really make sense */
173 g_node_children_foreach(mimeinfo
->node
, G_TRAVERSE_ALL
, msginfo_set_signed_flag
, sstate
);
177 void privacy_msginfo_get_signed_state(MsgInfo
*msginfo
, gchar
**system
)
179 struct SignedState sstate
;
180 MimeInfo
*mimeinfo
= procmime_scan_message(msginfo
);
183 sstate
.msginfo
= msginfo
;
184 sstate
.system
= system
;
185 g_node_children_foreach(mimeinfo
->node
, G_TRAVERSE_ALL
, msginfo_set_signed_flag
, &sstate
);
189 * Check the signature of a MimeInfo. privacy_mimeinfo_is_signed
190 * should be called before otherwise it is done by this function.
191 * If the MimeInfo is not signed an error code will be returned.
193 * \return Error code indicating the result of the check,
194 * < 0 if an error occurred
196 gint
privacy_mimeinfo_check_signature(MimeInfo
*mimeinfo
)
198 PrivacySystem
*system
;
200 cm_return_val_if_fail(mimeinfo
!= NULL
, -1);
202 if (mimeinfo
->privacy
== NULL
)
203 privacy_mimeinfo_is_signed(mimeinfo
);
205 if (mimeinfo
->privacy
== NULL
)
208 system
= privacy_data_get_system(mimeinfo
->privacy
);
212 if (system
->check_signature
== NULL
)
215 return system
->check_signature(mimeinfo
);
218 SignatureStatus
privacy_mimeinfo_get_sig_status(MimeInfo
*mimeinfo
)
220 PrivacySystem
*system
;
222 cm_return_val_if_fail(mimeinfo
!= NULL
, -1);
224 if (mimeinfo
->privacy
== NULL
)
225 privacy_mimeinfo_is_signed(mimeinfo
);
227 if (mimeinfo
->privacy
== NULL
)
228 return SIGNATURE_UNCHECKED
;
230 system
= privacy_data_get_system(mimeinfo
->privacy
);
232 return SIGNATURE_UNCHECKED
;
233 if (system
->get_sig_status
== NULL
)
234 return SIGNATURE_UNCHECKED
;
236 return system
->get_sig_status(mimeinfo
);
239 gchar
*privacy_mimeinfo_sig_info_short(MimeInfo
*mimeinfo
)
241 PrivacySystem
*system
;
243 cm_return_val_if_fail(mimeinfo
!= NULL
, NULL
);
245 if (mimeinfo
->privacy
== NULL
)
246 privacy_mimeinfo_is_signed(mimeinfo
);
248 if (mimeinfo
->privacy
== NULL
)
249 return g_strdup(_("No signature found"));
251 system
= privacy_data_get_system(mimeinfo
->privacy
);
253 return g_strdup(_("No signature found"));
254 if (system
->get_sig_info_short
== NULL
)
255 return g_strdup(_("No information available"));
257 return system
->get_sig_info_short(mimeinfo
);
260 gchar
*privacy_mimeinfo_sig_info_full(MimeInfo
*mimeinfo
)
262 PrivacySystem
*system
;
264 cm_return_val_if_fail(mimeinfo
!= NULL
, NULL
);
266 if (mimeinfo
->privacy
== NULL
)
267 privacy_mimeinfo_is_signed(mimeinfo
);
269 if (mimeinfo
->privacy
== NULL
)
270 return g_strdup(_("No signature found"));
272 system
= privacy_data_get_system(mimeinfo
->privacy
);
274 return g_strdup(_("No signature found"));
275 if (system
->get_sig_info_full
== NULL
)
276 return g_strdup(_("No information available"));
278 return system
->get_sig_info_full(mimeinfo
);
281 gboolean
privacy_mimeinfo_is_encrypted(MimeInfo
*mimeinfo
)
284 cm_return_val_if_fail(mimeinfo
!= NULL
, FALSE
);
286 for(cur
= systems
; cur
!= NULL
; cur
= g_slist_next(cur
)) {
287 PrivacySystem
*system
= (PrivacySystem
*) cur
->data
;
289 if(system
->is_encrypted
!= NULL
&& system
->is_encrypted(mimeinfo
))
296 static gint
decrypt(MimeInfo
*mimeinfo
, PrivacySystem
*system
)
298 MimeInfo
*decryptedinfo
, *parentinfo
;
301 cm_return_val_if_fail(system
->decrypt
!= NULL
, -1);
303 decryptedinfo
= system
->decrypt(mimeinfo
);
304 if (decryptedinfo
== NULL
)
307 parentinfo
= procmime_mimeinfo_parent(mimeinfo
);
308 childnumber
= g_node_child_index(parentinfo
->node
, mimeinfo
);
310 procmime_mimeinfo_free_all(&mimeinfo
);
312 g_node_insert(parentinfo
->node
, childnumber
, decryptedinfo
->node
);
317 gint
privacy_mimeinfo_decrypt(MimeInfo
*mimeinfo
)
320 cm_return_val_if_fail(mimeinfo
!= NULL
, FALSE
);
322 procmime_decode_content(mimeinfo
);
324 for(cur
= systems
; cur
!= NULL
; cur
= g_slist_next(cur
)) {
325 PrivacySystem
*system
= (PrivacySystem
*) cur
->data
;
327 if(system
->is_encrypted
!= NULL
&& system
->is_encrypted(mimeinfo
))
328 return decrypt(mimeinfo
, system
);
334 GSList
*privacy_get_system_ids()
339 for(cur
= systems
; cur
!= NULL
; cur
= g_slist_next(cur
)) {
340 PrivacySystem
*system
= (PrivacySystem
*) cur
->data
;
342 ret
= g_slist_append(ret
, g_strdup(system
->id
));
348 static PrivacySystem
*privacy_get_system(const gchar
*id
)
352 cm_return_val_if_fail(id
!= NULL
, NULL
);
354 for(cur
= systems
; cur
!= NULL
; cur
= g_slist_next(cur
)) {
355 PrivacySystem
*system
= (PrivacySystem
*) cur
->data
;
357 if(strcmp(id
, system
->id
) == 0)
364 const gchar
*privacy_system_get_name(const gchar
*id
)
366 PrivacySystem
*system
;
368 cm_return_val_if_fail(id
!= NULL
, NULL
);
370 system
= privacy_get_system(id
);
377 gboolean
privacy_system_can_sign(const gchar
*id
)
379 PrivacySystem
*system
;
381 cm_return_val_if_fail(id
!= NULL
, FALSE
);
383 system
= privacy_get_system(id
);
387 return system
->can_sign
;
390 gboolean
privacy_system_can_encrypt(const gchar
*id
)
392 PrivacySystem
*system
;
394 cm_return_val_if_fail(id
!= NULL
, FALSE
);
396 system
= privacy_get_system(id
);
400 return system
->can_encrypt
;
403 gboolean
privacy_sign(const gchar
*id
, MimeInfo
*target
, PrefsAccount
*account
, const gchar
*from_addr
)
405 PrivacySystem
*system
;
407 cm_return_val_if_fail(id
!= NULL
, FALSE
);
408 cm_return_val_if_fail(target
!= NULL
, FALSE
);
410 system
= privacy_get_system(id
);
413 if (!system
->can_sign
)
415 if (system
->sign
== NULL
)
418 return system
->sign(target
, account
, from_addr
);
421 gchar
*privacy_get_encrypt_data(const gchar
*id
, GSList
*recp_names
)
423 PrivacySystem
*system
;
425 GSList
*uniq_names
= NULL
, *cur
;
427 cm_return_val_if_fail(id
!= NULL
, NULL
);
428 cm_return_val_if_fail(recp_names
!= NULL
, NULL
);
430 system
= privacy_get_system(id
);
433 if (!system
->can_encrypt
)
435 if (system
->get_encrypt_data
== NULL
)
438 for (cur
= recp_names
; cur
; cur
= cur
->next
) {
439 if (!g_slist_find_custom(uniq_names
, cur
->data
, (GCompareFunc
)strcmp
)) {
440 uniq_names
= g_slist_prepend(uniq_names
, cur
->data
);
443 ret
= system
->get_encrypt_data(uniq_names
);
445 g_slist_free(uniq_names
);
449 const gchar
*privacy_get_encrypt_warning(const gchar
*id
)
451 PrivacySystem
*system
;
453 cm_return_val_if_fail(id
!= NULL
, NULL
);
455 system
= privacy_get_system(id
);
458 if (!system
->can_encrypt
)
460 if (system
->get_encrypt_warning
== NULL
)
463 return system
->get_encrypt_warning();
466 void privacy_inhibit_encrypt_warning(const gchar
*id
, gboolean inhibit
)
468 PrivacySystem
*system
;
470 cm_return_if_fail(id
!= NULL
);
472 system
= privacy_get_system(id
);
475 if (!system
->can_encrypt
)
477 if (system
->inhibit_encrypt_warning
== NULL
)
480 system
->inhibit_encrypt_warning(inhibit
);
483 gboolean
privacy_encrypt(const gchar
*id
, MimeInfo
*mimeinfo
, const gchar
*encdata
)
485 PrivacySystem
*system
;
487 cm_return_val_if_fail(id
!= NULL
, FALSE
);
488 cm_return_val_if_fail(mimeinfo
!= NULL
, FALSE
);
489 if (encdata
== NULL
) {
490 privacy_set_error(_("No recipient keys defined."));
494 system
= privacy_get_system(id
);
497 if (!system
->can_encrypt
)
499 if (system
->encrypt
== NULL
)
502 return system
->encrypt(mimeinfo
, encdata
);
505 gboolean
privacy_auto_check_signatures(MimeInfo
*mimeinfo
)
507 PrivacySystem
*system
;
509 cm_return_val_if_fail(mimeinfo
!= NULL
, FALSE
);
511 if (mimeinfo
->privacy
== NULL
)
512 privacy_mimeinfo_is_signed(mimeinfo
);
514 if (mimeinfo
->privacy
== NULL
)
517 system
= privacy_data_get_system(mimeinfo
->privacy
);
520 if (system
->auto_check_signatures
== NULL
)
523 return system
->auto_check_signatures();