Added call to mailmime_parameter_free to deal with enomem cases which do not originate in the setup of the param data structure. (See trac issue 21)
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);
140 mailmime_parameter_free(param);
145 struct mailmime * get_pgp_encrypted_part(void)
147 struct mailmime * mime = NULL;
148 struct mailmime_fields * mime_fields = NULL;
149 struct mailmime_content * content = NULL;
152 content = mailmime_content_new_with_str("application/pgp-encrypted");
156 mime_fields = mailmime_fields_new_empty();
157 if (mime_fields == NULL)
160 mime = part_new_empty(content, mime_fields, 1);
166 r = mailmime_set_body_text(mime, "Version: 1\n", 10);
174 mailmime_content_free(content);
176 mailmime_fields_free(mime_fields);
183 struct mailmime * get_text_part(
184 const char * filename,
185 const char * mime_type,
191 char * disposition_name = NULL;
192 struct mailmime_fields * mime_fields = NULL;
193 struct mailmime * mime = NULL;
194 struct mailmime_content * content = NULL;
195 struct mailmime_parameter * param = NULL;
196 struct mailmime_disposition * disposition = NULL;
197 struct mailmime_mechanism * encoding = NULL;
200 if (filename != NULL) {
201 disposition_name = strdup(filename);
202 if (disposition_name == NULL)
207 encoding = mailmime_mechanism_new(encoding_type, NULL);
208 if (encoding == NULL)
213 mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_INLINE,
214 disposition_name, NULL, NULL, NULL, (size_t) -1);
215 if (disposition == NULL)
217 disposition_name = NULL;
219 mime_fields = mailmime_fields_new_with_data(encoding, NULL, NULL,
221 if (mime_fields == NULL)
226 content = mailmime_content_new_with_str(mime_type);
230 if (encoding_type != MAILMIME_MECHANISM_7BIT) {
231 param = mailmime_param_new_with_data("charset", "utf-8");
232 r = clist_append(content->ct_parameters, param);
237 mime = part_new_empty(content, mime_fields, 1);
244 r = mailmime_set_body_text(mime, (char *) text, length);
252 free(disposition_name);
254 mailmime_fields_free(mime_fields);
258 mailmime_content_free(content);
260 mailmime_parameter_free(param);
262 mailmime_disposition_free(disposition);
264 mailmime_mechanism_free(encoding);
269 struct mailmime * get_file_part(
270 const char * filename,
271 const char * mime_type,
276 char * disposition_name = NULL;
278 struct mailmime_disposition * disposition = NULL;
279 struct mailmime_mechanism * encoding = NULL;
280 struct mailmime_content * content = NULL;
281 struct mailmime * mime = NULL;
282 struct mailmime_fields * mime_fields = NULL;
285 if (filename != NULL) {
286 disposition_name = strdup(filename);
287 if (disposition_name == NULL)
292 mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
293 disposition_name, NULL, NULL, NULL, (size_t) -1);
294 if (disposition == NULL)
296 disposition_name = NULL;
298 content = mailmime_content_new_with_str(mime_type);
302 encoding_type = MAILMIME_MECHANISM_BASE64;
303 encoding = mailmime_mechanism_new(encoding_type, NULL);
304 if (encoding == NULL)
307 mime_fields = mailmime_fields_new_with_data(encoding, NULL, NULL,
309 if (mime_fields == NULL)
314 mime = part_new_empty(content, mime_fields, 1);
322 r = mailmime_set_body_text(mime, data, length);
330 free(disposition_name);
332 mailmime_disposition_free(disposition);
334 mailmime_mechanism_free(encoding);
336 mailmime_content_free(content);
338 mailmime_fields_free(mime_fields);
345 struct mailmime * part_multiple_new(const char *type)
347 struct mailmime_fields *mime_fields = NULL;
348 struct mailmime_content *content = NULL;
349 struct mailmime *mp = NULL;
351 mime_fields = mailmime_fields_new_empty();
352 if (mime_fields == NULL)
355 content = mailmime_content_new_with_str(type);
359 mp = part_new_empty(content, mime_fields, 0);
367 mailmime_content_free(content);
369 mailmime_fields_free(mime_fields);
374 struct mailimf_field * _new_field(
376 _new_func_t new_func,
380 void *data = new_func(value);
385 struct mailimf_field * result = calloc(1, sizeof(struct mailimf_field));
387 if (result == NULL) {
392 result->fld_type = type;
393 result->fld_data.fld_return_path = data;
398 void _free_field(struct mailimf_field *field)
401 free(field->fld_data.fld_return_path);
408 _new_func_t new_func,
413 struct mailimf_field * field;
419 field = _new_field(type, new_func, value);
423 r = clist_append(list, field);
430 // http://media2.giga.de/2014/02/Image-28.jpg
432 struct mailimf_date_time * timestamp_to_etpantime(const struct tm *ts)
434 struct mailimf_date_time * result = calloc(1,
435 sizeof(struct mailimf_date_time));
442 result->dt_sec = ts->tm_sec;
443 result->dt_min = ts->tm_min;
444 result->dt_hour = ts->tm_hour;
445 result->dt_day = ts->tm_mday;
446 result->dt_month = ts->tm_mon + 1;
447 result->dt_year = ts->tm_year + 1900;
449 result->dt_zone = (int) (ts->tm_gmtoff / 36L);
454 struct tm * etpantime_to_timestamp(const struct mailimf_date_time *et)
456 struct tm * result = calloc(1, sizeof(struct tm));
463 result->tm_sec = et->dt_sec;
464 result->tm_min = et->dt_min;
465 result->tm_hour = et->dt_hour;
466 result->tm_mday = et->dt_day;
467 result->tm_mon = et->dt_month - 1;
468 result->tm_year = et->dt_year - 1900;
470 result->tm_gmtoff = 36L * (long) et->dt_zone;
475 struct mailimf_mailbox * mailbox_from_string(
480 struct mailimf_mailbox *mb = NULL;
482 char *_address = NULL;
486 _name = name ? strdup(name) : strdup("");
490 _address = strdup(address);
491 if (_address == NULL)
494 mb = mailimf_mailbox_new(_name, _address);
508 struct mailimf_field * create_optional_field(
515 struct mailimf_optional_field *optional_field = NULL;
517 _field = strdup(field);
521 _value = mailmime_encode_subject_header("utf-8", value, 0);
525 optional_field = mailimf_optional_field_new(_field, _value);
526 if (optional_field == NULL)
529 struct mailimf_field * result = calloc(1, sizeof(struct mailimf_field));
534 result->fld_type = MAILIMF_FIELD_OPTIONAL_FIELD;
535 result->fld_data.fld_optional_field = optional_field;
540 if (optional_field) {
541 mailimf_optional_field_free(optional_field);
551 int _append_optional_field(
558 struct mailimf_field * optional_field =
559 create_optional_field(field, value);
561 if (optional_field == NULL)
564 r = clist_append(list, optional_field);
566 mailimf_field_free(optional_field);
571 clist * _get_fields(struct mailmime * mime)
573 clist * _fieldlist = NULL;
577 if (mime->mm_data.mm_message.mm_fields &&
578 mime->mm_data.mm_message.mm_fields->fld_list) {
579 _fieldlist = mime->mm_data.mm_message.mm_fields->fld_list;
585 struct mailmime_content * _get_content(struct mailmime * mime)
587 struct mailmime_content * content = NULL;
591 if (mime->mm_data.mm_message.mm_msg_mime)
592 content = mime->mm_data.mm_message.mm_msg_mime->mm_content_type;
597 char * _get_filename(struct mailmime *mime)
599 clist * _fieldlist = NULL;
603 if (mime->mm_mime_fields && mime->mm_mime_fields->fld_list)
604 _fieldlist = mime->mm_mime_fields->fld_list;
609 for (cur = clist_begin(_fieldlist); cur; cur = clist_next(cur)) {
610 struct mailmime_field * _field = clist_content(cur);
611 if (_field && _field->fld_type == MAILMIME_FIELD_DISPOSITION) {
612 if (_field->fld_data.fld_disposition &&
613 _field->fld_data.fld_disposition->dsp_parms) {
615 _field->fld_data.fld_disposition->dsp_parms;
617 for (cur2 = clist_begin(_parmlist); cur2; cur2 =
619 struct mailmime_disposition_parm * param =
621 if (param->pa_type == MAILMIME_DISPOSITION_PARM_FILENAME)
622 return param->pa_data.pa_filename;
631 static bool parameter_has_value(
632 struct mailmime_content *content,
642 clist * list = content->ct_parameters;
646 for (cur = clist_begin(list); cur != NULL ; cur = clist_next(cur)) {
647 struct mailmime_parameter * param = clist_content(cur);
649 param->pa_name && strcasecmp(name, param->pa_name) == 0 &&
650 param->pa_value && strcasecmp(value, param->pa_value) == 0)
657 bool _is_multipart(struct mailmime_content *content, const char *subtype)
661 if (content->ct_type && content->ct_type->tp_type ==
662 MAILMIME_TYPE_COMPOSITE_TYPE &&
663 content->ct_type->tp_data.tp_composite_type &&
664 content->ct_type->tp_data.tp_composite_type->ct_type ==
665 MAILMIME_COMPOSITE_TYPE_MULTIPART) {
667 return content->ct_subtype &&
668 strcasecmp(content->ct_subtype, subtype) == 0;
676 bool _is_PGP_MIME(struct mailmime_content *content)
680 if (_is_multipart(content, "encrypted") &&
681 parameter_has_value(content, "protocol",
682 "application/pgp-encrypted"))
688 bool _is_text_part(struct mailmime_content *content, const char *subtype)
692 if (content->ct_type && content->ct_type->tp_type ==
693 MAILMIME_TYPE_DISCRETE_TYPE &&
694 content->ct_type->tp_data.tp_discrete_type &&
695 content->ct_type->tp_data.tp_discrete_type->dt_type ==
696 MAILMIME_DISCRETE_TYPE_TEXT) {
698 return content->ct_subtype &&
699 strcasecmp(content->ct_subtype, subtype) == 0;
707 int _get_content_type(
708 const struct mailmime_content *content,
714 char *_charset = NULL;
723 if (content->ct_subtype == NULL)
726 if (content->ct_type && content->ct_type->tp_data.tp_discrete_type) {
728 const char *_main_type;
730 switch (content->ct_type->tp_data.tp_discrete_type->dt_type) {
731 case MAILMIME_DISCRETE_TYPE_TEXT:
734 case MAILMIME_DISCRETE_TYPE_IMAGE:
735 _main_type = "image";
737 case MAILMIME_DISCRETE_TYPE_AUDIO:
738 _main_type = "audio";
740 case MAILMIME_DISCRETE_TYPE_VIDEO:
741 _main_type = "video";
743 case MAILMIME_DISCRETE_TYPE_APPLICATION:
744 _main_type = "application";
746 case MAILMIME_DISCRETE_TYPE_EXTENSION:
747 _main_type = "extension";
753 len = strlen(_main_type) + 1 + strlen(content->ct_subtype) + 1;
754 _type = calloc(1, len);
759 strcpy(_type, _main_type);
761 strcat(_type, content->ct_subtype);
763 if (content->ct_parameters) {
765 for (cur = clist_begin(content->ct_parameters); cur; cur =
767 struct mailmime_parameter * param = clist_content(cur);
768 if (param && param->pa_name && strcasecmp(param->pa_name,
770 _charset = param->pa_value;
775 *charset = strdup(_charset);