fix random() implementation for Android, so not always the same number is returned. Add comment that random() is predictive and non-secure
1 #include "etpan_mime.h"
2 #ifndef mailmime_param_new_with_data
3 #include <libetpan/mailprivacy_tools.h>
13 #define MAX_MESSAGE_ID 128
15 static char * generate_boundary(void)
17 char id[MAX_MESSAGE_ID];
19 // no cryptographically strong random needed here
20 const long value1 = random();
21 const long value2 = random();
22 const long value3 = random();
23 const long value4 = random();
25 snprintf(id, MAX_MESSAGE_ID, "%.4lx%.4lx%.4lx%.4lx", value1, value2,
31 struct mailmime * part_new_empty(
32 struct mailmime_content * content,
33 struct mailmime_fields * mime_fields,
37 struct mailmime * build_info;
41 char * attr_name = NULL;
42 char * attr_value = NULL;
43 struct mailmime_parameter * param = NULL;
44 clist * parameters = NULL;
45 char *boundary = NULL;
50 mime_type = MAILMIME_SINGLE;
53 switch (content->ct_type->tp_type) {
54 case MAILMIME_TYPE_DISCRETE_TYPE:
55 mime_type = MAILMIME_SINGLE;
58 case MAILMIME_TYPE_COMPOSITE_TYPE:
59 switch (content->ct_type->tp_data.tp_composite_type->ct_type) {
60 case MAILMIME_COMPOSITE_TYPE_MULTIPART:
61 mime_type = MAILMIME_MULTIPLE;
64 case MAILMIME_COMPOSITE_TYPE_MESSAGE:
65 if (strcasecmp(content->ct_subtype, "rfc822") == 0)
66 mime_type = MAILMIME_MESSAGE;
68 mime_type = MAILMIME_SINGLE;
81 if (mime_type == MAILMIME_MULTIPLE) {
87 attr_name = strdup("boundary");
89 if (attr_name == NULL)
92 boundary = generate_boundary();
94 attr_value = boundary;
95 if (attr_value == NULL)
98 param = mailmime_parameter_new(attr_name, attr_value);
105 if (content->ct_parameters == NULL) {
106 parameters = clist_new();
108 if (parameters == NULL)
112 parameters = content->ct_parameters;
115 r = clist_append(parameters, param);
120 if (content->ct_parameters == NULL)
121 content->ct_parameters = parameters;
124 build_info = mailmime_new(mime_type, NULL, 0, mime_fields, content, NULL,
125 NULL, NULL, list, NULL, NULL);
126 if (build_info == NULL)
136 if (content->ct_parameters == NULL)
138 clist_free(parameters);
143 struct mailmime * get_pgp_encrypted_part(void)
145 struct mailmime * mime = NULL;
146 struct mailmime_fields * mime_fields = NULL;
147 struct mailmime_content * content = NULL;
150 content = mailmime_content_new_with_str("application/pgp-encrypted");
154 mime_fields = mailmime_fields_new_empty();
155 if (mime_fields == NULL)
158 mime = part_new_empty(content, mime_fields, 1);
164 r = mailmime_set_body_text(mime, "Version: 1\n", 10);
172 mailmime_content_free(content);
174 mailmime_fields_free(mime_fields);
181 struct mailmime * get_text_part(
182 const char * filename,
183 const char * mime_type,
189 char * disposition_name = NULL;
190 struct mailmime_fields * mime_fields = NULL;
191 struct mailmime * mime = NULL;
192 struct mailmime_content * content = NULL;
193 struct mailmime_parameter * param = NULL;
194 struct mailmime_disposition * disposition = NULL;
195 struct mailmime_mechanism * encoding = NULL;
198 if (filename != NULL) {
199 disposition_name = strdup(filename);
200 if (disposition_name == NULL)
205 encoding = mailmime_mechanism_new(encoding_type, NULL);
206 if (encoding == NULL)
211 mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_INLINE,
212 disposition_name, NULL, NULL, NULL, (size_t) -1);
213 if (disposition == NULL)
215 disposition_name = NULL;
217 mime_fields = mailmime_fields_new_with_data(encoding, NULL, NULL,
219 if (mime_fields == NULL)
224 content = mailmime_content_new_with_str(mime_type);
228 if (encoding_type != MAILMIME_MECHANISM_7BIT) {
229 param = mailmime_param_new_with_data("charset", "utf-8");
230 r = clist_append(content->ct_parameters, param);
235 mime = part_new_empty(content, mime_fields, 1);
242 r = mailmime_set_body_text(mime, (char *) text, length);
250 free(disposition_name);
252 mailmime_fields_free(mime_fields);
256 mailmime_content_free(content);
258 mailmime_parameter_free(param);
260 mailmime_disposition_free(disposition);
262 mailmime_mechanism_free(encoding);
267 struct mailmime * get_file_part(
268 const char * filename,
269 const char * mime_type,
274 char * disposition_name = NULL;
276 struct mailmime_disposition * disposition = NULL;
277 struct mailmime_mechanism * encoding = NULL;
278 struct mailmime_content * content = NULL;
279 struct mailmime * mime = NULL;
280 struct mailmime_fields * mime_fields = NULL;
283 if (filename != NULL) {
284 disposition_name = strdup(filename);
285 if (disposition_name == NULL)
290 mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
291 disposition_name, NULL, NULL, NULL, (size_t) -1);
292 if (disposition == NULL)
294 disposition_name = NULL;
296 content = mailmime_content_new_with_str(mime_type);
300 encoding_type = MAILMIME_MECHANISM_BASE64;
301 encoding = mailmime_mechanism_new(encoding_type, NULL);
302 if (encoding == NULL)
305 mime_fields = mailmime_fields_new_with_data(encoding, NULL, NULL,
307 if (mime_fields == NULL)
312 mime = part_new_empty(content, mime_fields, 1);
318 r = mailmime_set_body_text(mime, data, length);
325 free(disposition_name);
327 mailmime_disposition_free(disposition);
329 mailmime_mechanism_free(encoding);
331 mailmime_content_free(content);
333 mailmime_fields_free(mime_fields);
340 struct mailmime * part_multiple_new(const char *type)
342 struct mailmime_fields *mime_fields = NULL;
343 struct mailmime_content *content = NULL;
344 struct mailmime *mp = NULL;
346 mime_fields = mailmime_fields_new_empty();
347 if (mime_fields == NULL)
350 content = mailmime_content_new_with_str(type);
354 mp = part_new_empty(content, mime_fields, 0);
362 mailmime_content_free(content);
364 mailmime_fields_free(mime_fields);
369 struct mailimf_field * _new_field(
371 _new_func_t new_func,
375 void *data = new_func(value);
380 struct mailimf_field * result = calloc(1, sizeof(struct mailimf_field));
382 if (result == NULL) {
387 result->fld_type = type;
388 result->fld_data.fld_return_path = data;
393 void _free_field(struct mailimf_field *field)
396 free(field->fld_data.fld_return_path);
403 _new_func_t new_func,
408 struct mailimf_field * field;
414 field = _new_field(type, new_func, value);
418 r = clist_append(list, field);
425 // http://media2.giga.de/2014/02/Image-28.jpg
427 struct mailimf_date_time * timestamp_to_etpantime(const struct tm *ts)
429 struct mailimf_date_time * result = calloc(1,
430 sizeof(struct mailimf_date_time));
437 result->dt_sec = ts->tm_sec;
438 result->dt_min = ts->tm_min;
439 result->dt_hour = ts->tm_hour;
440 result->dt_day = ts->tm_mday;
441 result->dt_month = ts->tm_mon + 1;
442 result->dt_year = ts->tm_year + 1900;
444 result->dt_zone = (int) (ts->tm_gmtoff / 36L);
449 struct tm * etpantime_to_timestamp(const struct mailimf_date_time *et)
451 struct tm * result = calloc(1, sizeof(struct tm));
458 result->tm_sec = et->dt_sec;
459 result->tm_min = et->dt_min;
460 result->tm_hour = et->dt_hour;
461 result->tm_mday = et->dt_day;
462 result->tm_mon = et->dt_month - 1;
463 result->tm_year = et->dt_year - 1900;
465 result->tm_gmtoff = 36L * (long) et->dt_zone;
470 struct mailimf_mailbox * mailbox_from_string(
475 struct mailimf_mailbox *mb = NULL;
477 char *_address = NULL;
481 _name = name ? strdup(name) : strdup("");
485 _address = strdup(address);
486 if (_address == NULL)
489 mb = mailimf_mailbox_new(_name, _address);
503 struct mailimf_field * create_optional_field(
510 struct mailimf_optional_field *optional_field = NULL;
512 _field = strdup(field);
516 _value = mailmime_encode_subject_header("utf-8", value, 0);
520 optional_field = mailimf_optional_field_new(_field, _value);
521 if (optional_field == NULL)
524 struct mailimf_field * result = calloc(1, sizeof(struct mailimf_field));
529 result->fld_type = MAILIMF_FIELD_OPTIONAL_FIELD;
530 result->fld_data.fld_optional_field = optional_field;
535 if (optional_field) {
536 mailimf_optional_field_free(optional_field);
546 int _append_optional_field(
553 struct mailimf_field * optional_field =
554 create_optional_field(field, value);
556 if (optional_field == NULL)
559 r = clist_append(list, optional_field);
561 mailimf_field_free(optional_field);
566 clist * _get_fields(struct mailmime * mime)
568 clist * _fieldlist = NULL;
572 if (mime->mm_data.mm_message.mm_fields &&
573 mime->mm_data.mm_message.mm_fields->fld_list) {
574 _fieldlist = mime->mm_data.mm_message.mm_fields->fld_list;
580 struct mailmime_content * _get_content(struct mailmime * mime)
582 struct mailmime_content * content = NULL;
586 if (mime->mm_data.mm_message.mm_msg_mime)
587 content = mime->mm_data.mm_message.mm_msg_mime->mm_content_type;
592 char * _get_filename(struct mailmime *mime)
594 clist * _fieldlist = NULL;
598 if (mime->mm_mime_fields && mime->mm_mime_fields->fld_list)
599 _fieldlist = mime->mm_mime_fields->fld_list;
604 for (cur = clist_begin(_fieldlist); cur; cur = clist_next(cur)) {
605 struct mailmime_field * _field = clist_content(cur);
606 if (_field && _field->fld_type == MAILMIME_FIELD_DISPOSITION) {
607 if (_field->fld_data.fld_disposition &&
608 _field->fld_data.fld_disposition->dsp_parms) {
610 _field->fld_data.fld_disposition->dsp_parms;
612 for (cur2 = clist_begin(_parmlist); cur2; cur2 =
614 struct mailmime_disposition_parm * param =
616 if (param->pa_type == MAILMIME_DISPOSITION_PARM_FILENAME)
617 return param->pa_data.pa_filename;
626 static bool parameter_has_value(
627 struct mailmime_content *content,
637 clist * list = content->ct_parameters;
641 for (cur = clist_begin(list); cur != NULL ; cur = clist_next(cur)) {
642 struct mailmime_parameter * param = clist_content(cur);
644 param->pa_name && strcasecmp(name, param->pa_name) == 0 &&
645 param->pa_value && strcasecmp(value, param->pa_value) == 0)
652 bool _is_multipart(struct mailmime_content *content, const char *subtype)
656 if (content->ct_type && content->ct_type->tp_type ==
657 MAILMIME_TYPE_COMPOSITE_TYPE &&
658 content->ct_type->tp_data.tp_composite_type &&
659 content->ct_type->tp_data.tp_composite_type->ct_type ==
660 MAILMIME_COMPOSITE_TYPE_MULTIPART) {
662 return content->ct_subtype &&
663 strcasecmp(content->ct_subtype, subtype) == 0;
671 bool _is_PGP_MIME(struct mailmime_content *content)
675 if (_is_multipart(content, "encrypted") &&
676 parameter_has_value(content, "protocol",
677 "application/pgp-encrypted"))
683 bool _is_text_part(struct mailmime_content *content, const char *subtype)
687 if (content->ct_type && content->ct_type->tp_type ==
688 MAILMIME_TYPE_DISCRETE_TYPE &&
689 content->ct_type->tp_data.tp_discrete_type &&
690 content->ct_type->tp_data.tp_discrete_type->dt_type ==
691 MAILMIME_DISCRETE_TYPE_TEXT) {
693 return content->ct_subtype &&
694 strcasecmp(content->ct_subtype, subtype) == 0;
702 int _get_content_type(
703 const struct mailmime_content *content,
709 char *_charset = NULL;
718 if (content->ct_subtype == NULL)
721 if (content->ct_type && content->ct_type->tp_data.tp_discrete_type) {
723 const char *_main_type;
725 switch (content->ct_type->tp_data.tp_discrete_type->dt_type) {
726 case MAILMIME_DISCRETE_TYPE_TEXT:
729 case MAILMIME_DISCRETE_TYPE_IMAGE:
730 _main_type = "image";
732 case MAILMIME_DISCRETE_TYPE_AUDIO:
733 _main_type = "audio";
735 case MAILMIME_DISCRETE_TYPE_VIDEO:
736 _main_type = "video";
738 case MAILMIME_DISCRETE_TYPE_APPLICATION:
739 _main_type = "application";
741 case MAILMIME_DISCRETE_TYPE_EXTENSION:
742 _main_type = "extension";
748 len = strlen(_main_type) + 1 + strlen(content->ct_subtype) + 1;
749 _type = calloc(1, len);
754 strcpy(_type, _main_type);
756 strcat(_type, content->ct_subtype);
758 if (content->ct_parameters) {
760 for (cur = clist_begin(content->ct_parameters); cur; cur =
762 struct mailmime_parameter * param = clist_content(cur);
763 if (param && param->pa_name && strcasecmp(param->pa_name,
765 _charset = param->pa_value;
770 *charset = strdup(_charset);