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/>.
21 #include <glib/gi18n.h>
26 static GSList
*systems
= NULL
;
27 static gchar
*privacy_last_error
= NULL
;
29 void privacy_set_error(const gchar
*format
, ...)
34 va_start(args
, format
);
35 g_vsnprintf(buf
, BUFSIZ
, format
, 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
;
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
))
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
);
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
);
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
);
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
118 * \return True if the MimeInfo has a signature
120 gboolean
privacy_mimeinfo_is_signed(MimeInfo
*mimeinfo
)
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
;
134 if (system
->is_signed
!= NULL
)
135 return system
->is_signed(mimeinfo
);
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
))
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
);
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
);
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
)
207 system
= privacy_data_get_system(mimeinfo
->privacy
);
211 if (system
->check_signature
== NULL
)
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
);
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
);
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
);
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
)
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
))
295 static gint
decrypt(MimeInfo
*mimeinfo
, PrivacySystem
*system
)
297 MimeInfo
*decryptedinfo
, *parentinfo
;
300 cm_return_val_if_fail(system
->decrypt
!= NULL
, -1);
302 decryptedinfo
= system
->decrypt(mimeinfo
);
303 if (decryptedinfo
== NULL
)
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
);
316 gint
privacy_mimeinfo_decrypt(MimeInfo
*mimeinfo
)
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
);
331 GSList
*privacy_get_system_ids()
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
));
345 static PrivacySystem
*privacy_get_system(const gchar
*id
)
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)
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
);
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
);
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
);
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
);
410 if (!system
->can_sign
)
412 if (system
->sign
== NULL
)
415 return system
->sign(target
, account
, from_addr
);
418 gchar
*privacy_get_encrypt_data(const gchar
*id
, GSList
*recp_names
)
420 PrivacySystem
*system
;
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
);
430 if (!system
->can_encrypt
)
432 if (system
->get_encrypt_data
== 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
);
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
);
455 if (!system
->can_encrypt
)
457 if (system
->get_encrypt_warning
== 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
);
472 if (!system
->can_encrypt
)
474 if (system
->inhibit_encrypt_warning
== NULL
)
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."));
491 system
= privacy_get_system(id
);
494 if (!system
->can_encrypt
)
496 if (system
->encrypt
== NULL
)
499 return system
->encrypt(mimeinfo
, encdata
);