summaryrefslogtreecommitdiffabout
path: root/libetpan/src/engine/mailprivacy.c
Unidiff
Diffstat (limited to 'libetpan/src/engine/mailprivacy.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/engine/mailprivacy.c949
1 files changed, 949 insertions, 0 deletions
diff --git a/libetpan/src/engine/mailprivacy.c b/libetpan/src/engine/mailprivacy.c
new file mode 100644
index 0000000..99cc50f
--- a/dev/null
+++ b/libetpan/src/engine/mailprivacy.c
@@ -0,0 +1,949 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailprivacy.h"
37
38#include <libetpan/libetpan.h>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <fcntl.h>
42#include <unistd.h>
43#include <sys/mman.h>
44#include <stdlib.h>
45#include <string.h>
46#include "mailprivacy_tools.h"
47
48carray * mailprivacy_get_protocols(struct mailprivacy * privacy)
49{
50 return privacy->protocols;
51}
52
53static int recursive_check_privacy(struct mailprivacy * privacy,
54 mailmessage * msg,
55 struct mailmime * mime);
56
57static int check_tmp_dir(char * tmp_dir)
58{
59 struct stat stat_info;
60 int r;
61
62 r = stat(tmp_dir, &stat_info);
63 if (r < 0)
64 return MAIL_ERROR_FILE;
65
66 /* check if the directory belongs to the user */
67 if (stat_info.st_uid != getuid())
68 return MAIL_ERROR_INVAL;
69
70 if ((stat_info.st_mode & 00777) != 0700) {
71 r = chmod(tmp_dir, 0700);
72 if (r < 0)
73 return MAIL_ERROR_FILE;
74 }
75
76 return MAIL_NO_ERROR;
77}
78
79struct mailprivacy * mailprivacy_new(char * tmp_dir, int make_alternative)
80{
81 struct mailprivacy * privacy;
82 int r;
83
84#if 0
85 r = check_tmp_dir(tmp_dir);
86 if (r != MAIL_NO_ERROR)
87 goto err;
88#endif
89
90 privacy = malloc(sizeof(* privacy));
91 if (privacy == NULL)
92 goto err;
93
94 privacy->tmp_dir = strdup(tmp_dir);
95 if (privacy->tmp_dir == NULL)
96 goto free;
97
98 privacy->msg_ref = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
99 if (privacy->msg_ref == NULL)
100 goto free_tmp_dir;
101
102 privacy->mmapstr = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
103 if (privacy->mmapstr == NULL)
104 goto free_msg_ref;
105
106 privacy->mime_ref = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
107 if (privacy->mime_ref == NULL)
108 goto free_mmapstr;
109
110 privacy->protocols = carray_new(16);
111 if (privacy->protocols == NULL)
112 goto free_mime_ref;
113
114 privacy->make_alternative = make_alternative;
115
116 return privacy;
117
118 free_mime_ref:
119 chash_free(privacy->mime_ref);
120 free_mmapstr:
121 chash_free(privacy->mmapstr);
122 free_msg_ref:
123 chash_free(privacy->msg_ref);
124 free_tmp_dir:
125 free(privacy->tmp_dir);
126 free:
127 free(privacy);
128 err:
129 return NULL;
130}
131
132void mailprivacy_free(struct mailprivacy * privacy)
133{
134 carray_free(privacy->protocols);
135 chash_free(privacy->mime_ref);
136 chash_free(privacy->mmapstr);
137 chash_free(privacy->msg_ref);
138 free(privacy->tmp_dir);
139 free(privacy);
140}
141
142static int msg_is_modified(struct mailprivacy * privacy,
143 mailmessage * msg)
144{
145 chashdatum key;
146 chashdatum data;
147 int r;
148
149 if (privacy == NULL)
150 return 0;
151
152 key.data = &msg;
153 key.len = sizeof(msg);
154
155 r = chash_get(privacy->msg_ref, &key, &data);
156 if (r < 0)
157 return 0;
158 else
159 return 1;
160}
161
162static int register_msg(struct mailprivacy * privacy,
163 mailmessage * msg)
164{
165 chashdatum key;
166 chashdatum data;
167 int r;
168
169 if (privacy == NULL)
170 return MAIL_NO_ERROR;
171
172 key.data = &msg;
173 key.len = sizeof(msg);
174 data.data = msg;
175 data.len = 0;
176
177 r = chash_set(privacy->msg_ref, &key, &data, NULL);
178 if (r < 0)
179 return MAIL_ERROR_MEMORY;
180 else
181 return MAIL_NO_ERROR;
182}
183
184static void unregister_message(struct mailprivacy * privacy,
185 mailmessage * msg)
186{
187 chashdatum key;
188
189 key.data = &msg;
190 key.len = sizeof(msg);
191
192 chash_delete(privacy->msg_ref, &key, NULL);
193}
194
195static int result_is_mmapstr(struct mailprivacy * privacy, char * str)
196{
197 chashdatum key;
198 chashdatum data;
199 int r;
200
201 key.data = &str;
202 key.len = sizeof(str);
203
204 r = chash_get(privacy->mmapstr, &key, &data);
205 if (r < 0)
206 return 0;
207 else
208 return 1;
209}
210
211static int register_result_mmapstr(struct mailprivacy * privacy,
212 char * content)
213{
214 chashdatum key;
215 chashdatum data;
216 int r;
217
218 key.data = &content;
219 key.len = sizeof(content);
220 data.data = content;
221 data.len = 0;
222
223 r = chash_set(privacy->mmapstr, &key, &data, NULL);
224 if (r < 0)
225 return MAIL_ERROR_MEMORY;
226
227 return 0;
228}
229
230static void unregister_result_mmapstr(struct mailprivacy * privacy,
231 char * str)
232{
233 chashdatum key;
234
235 mmap_string_unref(str);
236
237 key.data = &str;
238 key.len = sizeof(str);
239
240 chash_delete(privacy->mmapstr, &key, NULL);
241}
242
243static int register_mime(struct mailprivacy * privacy,
244 struct mailmime * mime)
245{
246 chashdatum key;
247 chashdatum data;
248 int r;
249
250 key.data = &mime;
251 key.len = sizeof(mime);
252 data.data = mime;
253 data.len = 0;
254
255 r = chash_set(privacy->mime_ref, &key, &data, NULL);
256 if (r < 0)
257 return MAIL_ERROR_MEMORY;
258 else
259 return MAIL_NO_ERROR;
260}
261
262static void unregister_mime(struct mailprivacy * privacy,
263 struct mailmime * mime)
264{
265 chashdatum key;
266
267 key.data = &mime;
268 key.len = sizeof(mime);
269
270 chash_delete(privacy->mime_ref, &key, NULL);
271}
272
273static int mime_is_registered(struct mailprivacy * privacy,
274 struct mailmime * mime)
275{
276 chashdatum key;
277 chashdatum data;
278 int r;
279
280 key.data = &mime;
281 key.len = sizeof(mime);
282
283 r = chash_get(privacy->mime_ref, &key, &data);
284 if (r < 0)
285 return 0;
286 else
287 return 1;
288}
289
290static int recursive_register_mime(struct mailprivacy * privacy,
291 struct mailmime * mime)
292{
293 clistiter * cur;
294 int r;
295
296 r = register_mime(privacy, mime);
297 if (r != MAIL_NO_ERROR)
298 return r;
299
300 switch (mime->mm_type) {
301 case MAILMIME_SINGLE:
302 break;
303
304 case MAILMIME_MULTIPLE:
305 for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
306 cur != NULL ; cur = clist_next(cur)) {
307 struct mailmime * child;
308
309 child = clist_content(cur);
310
311 r = recursive_register_mime(privacy, child);
312 if (r != MAIL_NO_ERROR)
313 return r;
314 }
315 break;
316
317 case MAILMIME_MESSAGE:
318 if (mime->mm_data.mm_message.mm_msg_mime) {
319 r = recursive_register_mime(privacy,
320 mime->mm_data.mm_message.mm_msg_mime);
321 if (r != MAIL_NO_ERROR)
322 return r;
323 }
324 break;
325 }
326
327 return MAIL_NO_ERROR;
328}
329
330void mailprivacy_recursive_unregister_mime(struct mailprivacy * privacy,
331 struct mailmime * mime)
332{
333 clistiter * cur;
334
335 unregister_mime(privacy, mime);
336
337 switch (mime->mm_type) {
338 case MAILMIME_SINGLE:
339 break;
340
341 case MAILMIME_MULTIPLE:
342 for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
343 cur != NULL ; cur = clist_next(cur)) {
344 struct mailmime * child;
345
346 child = clist_content(cur);
347
348 mailprivacy_recursive_unregister_mime(privacy, child);
349 }
350 break;
351
352 case MAILMIME_MESSAGE:
353 if (mime->mm_data.mm_message.mm_msg_mime)
354 mailprivacy_recursive_unregister_mime(privacy,
355 mime->mm_data.mm_message.mm_msg_mime);
356 break;
357 }
358}
359
360static void recursive_clear_registered_mime(struct mailprivacy * privacy,
361 struct mailmime * mime)
362{
363 clistiter * cur;
364 struct mailmime_data * data;
365
366 switch (mime->mm_type) {
367 case MAILMIME_SINGLE:
368 if (mime_is_registered(privacy, mime)) {
369 data = mime->mm_data.mm_single;
370 if (data != NULL) {
371 if (data->dt_type == MAILMIME_DATA_FILE)
372 unlink(data->dt_data.dt_filename);
373 }
374 }
375 break;
376
377 case MAILMIME_MULTIPLE:
378 if (mime_is_registered(privacy, mime)) {
379 data = mime->mm_data.mm_multipart.mm_preamble;
380 if (data != NULL) {
381 if (data->dt_type == MAILMIME_DATA_FILE)
382 unlink(data->dt_data.dt_filename);
383 }
384 data = mime->mm_data.mm_multipart.mm_epilogue;
385 if (data != NULL) {
386 if (data->dt_type == MAILMIME_DATA_FILE)
387 unlink(data->dt_data.dt_filename);
388 }
389 }
390 for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
391 cur != NULL ; cur = clist_next(cur)) {
392 struct mailmime * child;
393
394 child = clist_content(cur);
395
396 recursive_clear_registered_mime(privacy, child);
397 }
398 break;
399
400 case MAILMIME_MESSAGE:
401 if (mime->mm_data.mm_message.mm_msg_mime)
402 recursive_clear_registered_mime(privacy,
403 mime->mm_data.mm_message.mm_msg_mime);
404 break;
405 }
406 unregister_mime(privacy, mime);
407}
408
409
410/* **************************************************** */
411/* fetch operations start here */
412
413
414static void recursive_clear_registered_mime(struct mailprivacy * privacy,
415 struct mailmime * mime);
416
417#if 0
418static void display_recursive_part(struct mailmime * mime)
419{
420 clistiter * cur;
421
422 fprintf(stderr, "part %p\n", mime->mm_body);
423 switch (mime->mm_type) {
424 case MAILMIME_SINGLE:
425 fprintf(stderr, "single %p - %i\n", mime->mm_data.mm_single,
426 mime->mm_data.mm_single->dt_type);
427 if (mime->mm_data.mm_single->dt_type == MAILMIME_DATA_TEXT) {
428 fprintf(stderr, "data : %p %i\n",
429 mime->mm_data.mm_single->dt_data.dt_text.dt_data,
430 mime->mm_data.mm_single->dt_data.dt_text.dt_length);
431 }
432 break;
433 case MAILMIME_MESSAGE:
434 fprintf(stderr, "message %p\n", mime->mm_data.mm_message.mm_msg_mime);
435 display_recursive_part(mime->mm_data.mm_message.mm_msg_mime);
436 break;
437 case MAILMIME_MULTIPLE:
438 for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; cur != NULL ;
439 cur = clist_next(cur)) {
440
441 fprintf(stderr, "multipart\n");
442 display_recursive_part(clist_content(cur));
443 }
444 break;
445 }
446}
447#endif
448
449int mailprivacy_msg_get_bodystructure(struct mailprivacy * privacy,
450 mailmessage * msg_info,
451 struct mailmime ** result)
452{
453 int r;
454 struct mailmime * mime;
455
456 if (msg_info->msg_mime != NULL)
457 return MAIL_NO_ERROR;
458
459 if (msg_is_modified(privacy, msg_info))
460 return MAIL_NO_ERROR;
461
462 r = mailmessage_get_bodystructure(msg_info, &mime);
463 if (r != MAIL_NO_ERROR)
464 return r;
465
466 /* modification on message if necessary */
467 r = recursive_check_privacy(privacy, msg_info, msg_info->msg_mime);
468 if (r != MAIL_NO_ERROR) {
469 * result = msg_info->msg_mime;
470 return MAIL_NO_ERROR;
471 }
472
473 r = register_msg(privacy, msg_info);
474 if (r != MAIL_NO_ERROR) {
475 recursive_clear_registered_mime(privacy, mime);
476 mailmessage_flush(msg_info);
477 return MAIL_ERROR_MEMORY;
478 }
479
480 * result = msg_info->msg_mime;
481
482 return MAIL_NO_ERROR;
483}
484
485void mailprivacy_msg_flush(struct mailprivacy * privacy,
486 mailmessage * msg_info)
487{
488 if (msg_is_modified(privacy, msg_info)) {
489 /* remove all modified parts */
490 if (msg_info->msg_mime != NULL)
491 recursive_clear_registered_mime(privacy, msg_info->msg_mime);
492 unregister_message(privacy, msg_info);
493 }
494
495 mailmessage_flush(msg_info);
496}
497
498static int fetch_registered_part(struct mailprivacy * privacy,
499 int (* fetch_section)(mailmessage *, struct mailmime *,
500 char **, size_t *),
501 struct mailmime * mime,
502 char ** result, size_t * result_len)
503{
504 mailmessage * dummy_msg;
505 int res;
506 char * content;
507 size_t content_len;
508 int r;
509
510 dummy_msg = mime_message_init(NULL);
511 if (dummy_msg == NULL) {
512 res = MAIL_ERROR_MEMORY;
513 goto err;
514 }
515
516 r = mime_message_set_tmpdir(dummy_msg, privacy->tmp_dir);
517 if (r != MAIL_NO_ERROR) {
518 res = MAIL_ERROR_MEMORY;
519 goto free_msg;
520 }
521
522 r = fetch_section(dummy_msg, mime, &content, &content_len);
523 if (r != MAIL_NO_ERROR) {
524 res = r;
525 goto free_msg;
526 }
527
528 r = register_result_mmapstr(privacy, content);
529 if (r != MAIL_NO_ERROR) {
530 res = r;
531 goto free_fetch;
532 }
533
534 mailmessage_free(dummy_msg);
535
536 * result = content;
537 * result_len = content_len;
538
539 return MAIL_NO_ERROR;
540
541 free_fetch:
542 mailmessage_fetch_result_free(dummy_msg, content);
543 free_msg:
544 mailmessage_free(dummy_msg);
545 err:
546 return res;
547}
548
549int mailprivacy_msg_fetch_section(struct mailprivacy * privacy,
550 mailmessage * msg_info,
551 struct mailmime * mime,
552 char ** result, size_t * result_len)
553{
554 if (msg_is_modified(privacy, msg_info) &&
555 mime_is_registered(privacy, mime)) {
556 return fetch_registered_part(privacy, mailmessage_fetch_section,
557 mime, result, result_len);
558 }
559
560 return mailmessage_fetch_section(msg_info, mime, result, result_len);
561}
562
563int mailprivacy_msg_fetch_section_header(struct mailprivacy * privacy,
564 mailmessage * msg_info,
565 struct mailmime * mime,
566 char ** result,
567 size_t * result_len)
568{
569 if (msg_is_modified(privacy, msg_info) &&
570 mime_is_registered(privacy, mime)) {
571 return fetch_registered_part(privacy, mailmessage_fetch_section_header,
572 mime, result, result_len);
573 }
574
575 return mailmessage_fetch_section_header(msg_info, mime, result, result_len);
576}
577
578int mailprivacy_msg_fetch_section_mime(struct mailprivacy * privacy,
579 mailmessage * msg_info,
580 struct mailmime * mime,
581 char ** result,
582 size_t * result_len)
583{
584 if (msg_is_modified(privacy, msg_info) &&
585 mime_is_registered(privacy, mime)) {
586 return fetch_registered_part(privacy, mailmessage_fetch_section_mime,
587 mime, result, result_len);
588 }
589
590 return mailmessage_fetch_section_mime(msg_info, mime, result, result_len);
591}
592
593int mailprivacy_msg_fetch_section_body(struct mailprivacy * privacy,
594 mailmessage * msg_info,
595 struct mailmime * mime,
596 char ** result,
597 size_t * result_len)
598{
599 if (msg_is_modified(privacy, msg_info) &&
600 mime_is_registered(privacy, mime)) {
601 return fetch_registered_part(privacy, mailmessage_fetch_section_body,
602 mime, result, result_len);
603 }
604
605 return mailmessage_fetch_section_body(msg_info, mime, result, result_len);
606}
607
608void mailprivacy_msg_fetch_result_free(struct mailprivacy * privacy,
609 mailmessage * msg_info,
610 char * msg)
611{
612 if (msg == NULL)
613 return;
614
615 if (msg_is_modified(privacy, msg_info)) {
616 if (result_is_mmapstr(privacy, msg)) {
617 unregister_result_mmapstr(privacy, msg);
618 return;
619 }
620 }
621
622 mailmessage_fetch_result_free(msg_info, msg);
623}
624
625int mailprivacy_msg_fetch(struct mailprivacy * privacy,
626 mailmessage * msg_info,
627 char ** result,
628 size_t * result_len)
629{
630 return mailmessage_fetch(msg_info, result, result_len);
631}
632
633int mailprivacy_msg_fetch_header(struct mailprivacy * privacy,
634 mailmessage * msg_info,
635 char ** result,
636 size_t * result_len)
637{
638 return mailmessage_fetch_header(msg_info, result, result_len);
639}
640
641/* end of fetch operations */
642/* **************************************************** */
643
644static int privacy_handler(struct mailprivacy * privacy,
645 mailmessage * msg,
646 struct mailmime * mime, struct mailmime ** result);
647
648
649
650static struct mailmime *
651mime_add_alternative(struct mailprivacy * privacy,
652 mailmessage * msg,
653 struct mailmime * mime,
654 struct mailmime * alternative)
655{
656 struct mailmime * multipart;
657 int r;
658 struct mailmime * mime_copy;
659 char original_filename[PATH_MAX];
660
661 if (mime->mm_parent == NULL)
662 goto err;
663
664 r = mailmime_new_with_content("multipart/alternative", NULL, &multipart);
665 if (r != MAILIMF_NO_ERROR)
666 goto err;
667
668 r = mailmime_smart_add_part(multipart, alternative);
669 if (r != MAILIMF_NO_ERROR) {
670 goto free_multipart;
671 }
672
673 /* get copy of mime part "mime" and set parts */
674
675 r = mailprivacy_fetch_mime_body_to_file(privacy,
676 original_filename, sizeof(original_filename),
677 msg, mime);
678 if (r != MAIL_NO_ERROR)
679 goto detach_alternative;
680
681 r = mailprivacy_get_part_from_file(privacy, 0,
682 original_filename, &mime_copy);
683 unlink(original_filename);
684 if (r != MAIL_NO_ERROR) {
685 goto detach_alternative;
686 }
687
688 r = mailmime_smart_add_part(multipart, mime_copy);
689 if (r != MAILIMF_NO_ERROR) {
690 goto free_mime_copy;
691 }
692
693 r = recursive_register_mime(privacy, multipart);
694 if (r != MAIL_NO_ERROR)
695 goto detach_mime_copy;
696
697 mailmime_substitute(mime, multipart);
698
699 mailmime_free(mime);
700
701 return multipart;
702
703 detach_mime_copy:
704 mailprivacy_recursive_unregister_mime(privacy, multipart);
705 mailmime_remove_part(alternative);
706 free_mime_copy:
707 mailprivacy_mime_clear(mime_copy);
708 mailmime_free(mime_copy);
709 detach_alternative:
710 mailmime_remove_part(alternative);
711 free_multipart:
712 mailmime_free(multipart);
713 err:
714 return NULL;
715}
716
717/*
718 recursive_check_privacy returns MAIL_NO_ERROR if at least one
719 part is using a privacy protocol.
720*/
721
722static int recursive_check_privacy(struct mailprivacy * privacy,
723 mailmessage * msg,
724 struct mailmime * mime)
725{
726 int r;
727 clistiter * cur;
728 struct mailmime * alternative;
729 int res;
730 struct mailmime * multipart;
731
732 if (privacy == NULL)
733 return MAIL_NO_ERROR;
734
735 if (mime_is_registered(privacy, mime))
736 return MAIL_ERROR_INVAL;
737
738 r = privacy_handler(privacy, msg, mime, &alternative);
739 if (r == MAIL_NO_ERROR) {
740 if (privacy->make_alternative) {
741 multipart = mime_add_alternative(privacy, msg, mime, alternative);
742 if (multipart == NULL) {
743 mailprivacy_mime_clear(alternative);
744 mailmime_free(alternative);
745 return MAIL_ERROR_MEMORY;
746 }
747 }
748 else {
749 mailmime_substitute(mime, alternative);
750 mailmime_free(mime);
751 mime = NULL;
752 }
753
754 return MAIL_NO_ERROR;
755 }
756 else {
757 switch (mime->mm_type) {
758 case MAILMIME_SINGLE:
759 return MAIL_ERROR_INVAL;
760
761 case MAILMIME_MULTIPLE:
762 res = MAIL_ERROR_INVAL;
763
764 for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
765 cur != NULL ; cur = clist_next(cur)) {
766 struct mailmime * child;
767
768 child = clist_content(cur);
769
770 r = recursive_check_privacy(privacy, msg, child);
771 if (r == MAIL_NO_ERROR)
772 res = MAIL_NO_ERROR;
773 }
774
775 return res;
776
777 case MAILMIME_MESSAGE:
778 if (mime->mm_data.mm_message.mm_msg_mime != NULL)
779 return recursive_check_privacy(privacy, msg,
780 mime->mm_data.mm_message.mm_msg_mime);
781 return MAIL_ERROR_INVAL;
782
783 default:
784 return MAIL_ERROR_INVAL;
785 }
786 }
787}
788
789static int privacy_handler(struct mailprivacy * privacy,
790 mailmessage * msg,
791 struct mailmime * mime, struct mailmime ** result)
792{
793 int r;
794 struct mailmime * alternative_mime;
795 unsigned int i;
796
797 alternative_mime = NULL;
798 for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) {
799 struct mailprivacy_protocol * protocol;
800
801 protocol = carray_get(privacy->protocols, i);
802
803 if (protocol->decrypt != NULL) {
804 r = protocol->decrypt(privacy, msg, mime, &alternative_mime);
805 if (r == MAIL_NO_ERROR) {
806
807 * result = alternative_mime;
808
809 return MAIL_NO_ERROR;
810 }
811 }
812 }
813
814 return MAIL_ERROR_INVAL;
815}
816
817int mailprivacy_register(struct mailprivacy * privacy,
818 struct mailprivacy_protocol * protocol)
819{
820 int r;
821
822 r = carray_add(privacy->protocols, protocol, NULL);
823 if (r < 0)
824 return MAIL_ERROR_MEMORY;
825
826 return MAIL_NO_ERROR;
827}
828
829void mailprivacy_unregister(struct mailprivacy * privacy,
830 struct mailprivacy_protocol * protocol)
831{
832 unsigned int i;
833
834 for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) {
835 if (carray_get(privacy->protocols, i) == protocol) {
836 carray_delete(privacy->protocols, i);
837 return;
838 }
839 }
840}
841
842static struct mailprivacy_protocol *
843get_protocol(struct mailprivacy * privacy, char * privacy_driver)
844{
845 unsigned int i;
846
847 for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) {
848 struct mailprivacy_protocol * protocol;
849
850 protocol = carray_get(privacy->protocols, i);
851 if (strcasecmp(protocol->name, privacy_driver) == 0)
852 return protocol;
853 }
854
855 return NULL;
856}
857
858static struct mailprivacy_encryption *
859get_encryption(struct mailprivacy_protocol * protocol,
860 char * privacy_encryption)
861{
862 int i;
863
864 for(i = 0 ; i < protocol->encryption_count ; i ++) {
865 struct mailprivacy_encryption * encryption;
866
867 encryption = &protocol->encryption_tab[i];
868 if (strcasecmp(encryption->name, privacy_encryption) == 0)
869 return encryption;
870 }
871
872 return NULL;
873}
874
875int mailprivacy_encrypt(struct mailprivacy * privacy,
876 char * privacy_driver, char * privacy_encryption,
877 struct mailmime * mime,
878 struct mailmime ** result)
879{
880 struct mailprivacy_protocol * protocol;
881 struct mailprivacy_encryption * encryption;
882 int r;
883
884 protocol = get_protocol(privacy, privacy_driver);
885 if (protocol == NULL)
886 return MAIL_ERROR_INVAL;
887
888 encryption = get_encryption(protocol, privacy_encryption);
889 if (encryption == NULL)
890 return MAIL_ERROR_INVAL;
891
892 if (encryption->encrypt == NULL)
893 return MAIL_ERROR_NOT_IMPLEMENTED;
894
895 r = encryption->encrypt(privacy, mime, result);
896 if (r != MAIL_NO_ERROR)
897 return r;
898
899 return MAIL_NO_ERROR;
900}
901
902char * mailprivacy_get_encryption_name(struct mailprivacy * privacy,
903 char * privacy_driver, char * privacy_encryption)
904{
905 struct mailprivacy_protocol * protocol;
906 struct mailprivacy_encryption * encryption;
907
908 protocol = get_protocol(privacy, privacy_driver);
909 if (protocol == NULL)
910 return NULL;
911
912 encryption = get_encryption(protocol, privacy_encryption);
913 if (encryption == NULL)
914 return NULL;
915
916 return encryption->description;
917}
918
919int mailprivacy_is_encrypted(struct mailprivacy * privacy,
920 mailmessage * msg,
921 struct mailmime * mime)
922{
923 unsigned int i;
924
925 if (mime_is_registered(privacy, mime))
926 return 0;
927
928 for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) {
929 struct mailprivacy_protocol * protocol;
930
931 protocol = carray_get(privacy->protocols, i);
932
933 if (protocol->is_encrypted != NULL) {
934 if (protocol->is_encrypted(privacy, msg, mime))
935 return 1;
936 }
937 }
938
939 return 0;
940}
941
942void mailprivacy_debug(struct mailprivacy * privacy, FILE * f)
943{
944 fprintf(f, "privacy debug -- begin\n");
945 fprintf(f, "registered message: %i\n", chash_count(privacy->msg_ref));
946 fprintf(f, "registered MMAPStr: %i\n", chash_count(privacy->mmapstr));
947 fprintf(f, "registered mailmime: %i\n", chash_count(privacy->mime_ref));
948 fprintf(f, "privacy debug -- end\n");
949}