author | zautrix <zautrix> | 2005-03-18 20:17:03 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2005-03-18 20:17:03 (UTC) |
commit | 9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf (patch) (unidiff) | |
tree | 2528e6cc740225ca0f47d5ac8ff70f7d3bb10621 /libetpan/src/engine/mailprivacy.c | |
parent | 9319998f20f03dcc217fbb39656755dc65226276 (diff) | |
download | kdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.zip kdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.tar.gz kdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.tar.bz2 |
Initial revision
Diffstat (limited to 'libetpan/src/engine/mailprivacy.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libetpan/src/engine/mailprivacy.c | 949 |
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 | |||
48 | carray * mailprivacy_get_protocols(struct mailprivacy * privacy) | ||
49 | { | ||
50 | return privacy->protocols; | ||
51 | } | ||
52 | |||
53 | static int recursive_check_privacy(struct mailprivacy * privacy, | ||
54 | mailmessage * msg, | ||
55 | struct mailmime * mime); | ||
56 | |||
57 | static 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 | |||
79 | struct 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 | |||
132 | void 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 | |||
142 | static 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 | |||
162 | static 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 | |||
184 | static 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 | |||
195 | static 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 | |||
211 | static 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 | |||
230 | static 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 | |||
243 | static 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 | |||
262 | static 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 | |||
273 | static 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 | |||
290 | static 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 | |||
330 | void 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 | |||
360 | static 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 | |||
414 | static void recursive_clear_registered_mime(struct mailprivacy * privacy, | ||
415 | struct mailmime * mime); | ||
416 | |||
417 | #if 0 | ||
418 | static 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 | |||
449 | int 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 | |||
485 | void 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 | |||
498 | static 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 | |||
549 | int 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 | |||
563 | int 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 | |||
578 | int 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 | |||
593 | int 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 | |||
608 | void 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 | |||
625 | int 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 | |||
633 | int 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 | |||
644 | static int privacy_handler(struct mailprivacy * privacy, | ||
645 | mailmessage * msg, | ||
646 | struct mailmime * mime, struct mailmime ** result); | ||
647 | |||
648 | |||
649 | |||
650 | static struct mailmime * | ||
651 | mime_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 | |||
722 | static 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 | |||
789 | static 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 | |||
817 | int 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 | |||
829 | void 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 | |||
842 | static struct mailprivacy_protocol * | ||
843 | get_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 | |||
858 | static struct mailprivacy_encryption * | ||
859 | get_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 | |||
875 | int 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 | |||
902 | char * 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 | |||
919 | int 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 | |||
942 | void 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 | } | ||