src/etpan_mime.c
author vb
Sun, 08 Mar 2015 00:35:18 +0100
changeset 90 42b5eb9d5af2
parent 89 aef5a4bc78f3
child 92 c9be62386ffb
permissions -rw-r--r--
...
     1 #include <string.h>
     2 #include <stdlib.h>
     3 #include <unistd.h>
     4 #include <assert.h>
     5 
     6 #include "etpan_mime.h"
     7 #ifndef mailmime_param_new_with_data
     8 #include <libetpan/mailprivacy_tools.h>
     9 #endif
    10 
    11 time_t mail_mkgmtime(struct tm * tmp);
    12 
    13 #define MAX_MESSAGE_ID 512
    14 
    15 static char * generate_boundary(const char * boundary_prefix)
    16 {
    17     char id[MAX_MESSAGE_ID];
    18     time_t now;
    19     char name[MAX_MESSAGE_ID];
    20     long value;
    21  
    22     id[MAX_MESSAGE_ID - 1] = 0;
    23     name[MAX_MESSAGE_ID - 1] = 0;
    24 
    25     now = time(NULL);
    26 
    27     value = random();
    28     gethostname(name, MAX_MESSAGE_ID - 1);
    29     
    30     if (boundary_prefix == NULL)
    31         boundary_prefix = "";
    32     
    33     snprintf(id, MAX_MESSAGE_ID, "%s%lx_%lx_%x", boundary_prefix, now, value,
    34             getpid());
    35     
    36     return strdup(id);
    37 }
    38 
    39 struct mailmime * part_new_empty(
    40         struct mailmime_content * content,
    41         struct mailmime_fields * mime_fields,
    42         const char * boundary_prefix,
    43         int force_single
    44     )
    45 {
    46 	struct mailmime * build_info;
    47 	clist * list;
    48 	int r;
    49 	int mime_type;
    50 
    51 	list = NULL;
    52 
    53 	if (force_single) {
    54 		mime_type = MAILMIME_SINGLE;
    55 	}
    56 	else {
    57 		switch (content->ct_type->tp_type) {
    58 			case MAILMIME_TYPE_DISCRETE_TYPE:
    59 			mime_type = MAILMIME_SINGLE;
    60 			break;
    61 
    62 			case MAILMIME_TYPE_COMPOSITE_TYPE:
    63 			switch (content->ct_type->tp_data.tp_composite_type->ct_type) {
    64 				case MAILMIME_COMPOSITE_TYPE_MULTIPART:
    65 				mime_type = MAILMIME_MULTIPLE;
    66 				break;
    67 
    68 				case MAILMIME_COMPOSITE_TYPE_MESSAGE:
    69 				if (strcasecmp(content->ct_subtype, "rfc822") == 0)
    70 					mime_type = MAILMIME_MESSAGE;
    71 				else
    72 					mime_type = MAILMIME_SINGLE;
    73 				break;
    74 
    75 				default:
    76 				goto err;
    77 			}
    78 			break;
    79 
    80 			default:
    81 			goto err;
    82 		}
    83 	}
    84 
    85 	if (mime_type == MAILMIME_MULTIPLE) {
    86 		char * attr_name;
    87 		char * attr_value;
    88 		struct mailmime_parameter * param;
    89 		clist * parameters;
    90 		char * boundary;
    91 
    92 		list = clist_new();
    93 		if (list == NULL)
    94 			goto err;
    95 
    96 		attr_name = strdup("boundary");
    97 		boundary = generate_boundary(boundary_prefix);
    98 		attr_value = boundary;
    99 		if (attr_name == NULL) {
   100 			free(attr_name);
   101 			goto free_list;
   102 		}
   103 
   104 		param = mailmime_parameter_new(attr_name, attr_value);
   105 		if (param == NULL) {
   106 			free(attr_value);
   107 			free(attr_name);
   108 			goto free_list;
   109 		}
   110 
   111 		if (content->ct_parameters == NULL) {
   112 			parameters = clist_new();
   113 			if (parameters == NULL) {
   114 				mailmime_parameter_free(param);
   115 				goto free_list;
   116 			}
   117 		}
   118 		else
   119 			parameters = content->ct_parameters;
   120 
   121 		r = clist_append(parameters, param);
   122 		if (r) {
   123 			clist_free(parameters);
   124 			mailmime_parameter_free(param);
   125 			goto free_list;
   126 		}
   127 
   128 		if (content->ct_parameters == NULL)
   129 			content->ct_parameters = parameters;
   130 	}
   131 
   132 	build_info = mailmime_new(mime_type,
   133 		NULL, 0, mime_fields, content,
   134 		NULL, NULL, NULL, list,
   135 		NULL, NULL);
   136 	if (build_info == NULL) {
   137 		clist_free(list);
   138 		return NULL;
   139 	}
   140 
   141 	return build_info;
   142 
   143 	free_list:
   144 	clist_free(list);
   145 	err:
   146 	return NULL;
   147 }
   148 
   149 struct mailmime * get_text_part(
   150         const char * mime_type,
   151         const char * text,
   152         size_t length,
   153         int encoding_type
   154     )
   155 {
   156 	struct mailmime_fields * mime_fields;
   157 	struct mailmime * mime;
   158 	struct mailmime_content * content;
   159 	struct mailmime_parameter * param;
   160 	struct mailmime_disposition * disposition;
   161 	struct mailmime_mechanism * encoding;
   162     
   163 	encoding = mailmime_mechanism_new(encoding_type, NULL);
   164 	disposition = mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_INLINE,
   165 		NULL, NULL, NULL, NULL, (size_t) -1);
   166 	mime_fields = mailmime_fields_new_with_data(encoding,
   167 		NULL, NULL, disposition, NULL);
   168 
   169 	content = mailmime_content_new_with_str(mime_type);
   170 	param = mailmime_param_new_with_data("charset", "utf-8");
   171 	clist_append(content->ct_parameters, param);
   172 	mime = part_new_empty(content, mime_fields, NULL, 1);
   173 	mailmime_set_body_text(mime, (char *) text, length);
   174 	
   175 	return mime;
   176 }
   177 
   178 struct mailmime * get_file_part(
   179         const char * filename,
   180         const char * mime_type,
   181         char * data,
   182         size_t length
   183     )
   184 {
   185     char * disposition_name;
   186     int encoding_type;
   187     struct mailmime_disposition * disposition;
   188     struct mailmime_mechanism * encoding;
   189     struct mailmime_content * content;
   190     struct mailmime * mime;
   191     struct mailmime_fields * mime_fields;
   192 
   193     disposition_name = NULL;
   194     if (filename != NULL) {
   195         disposition_name = strdup(filename);
   196     }
   197     disposition =
   198         mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
   199                 disposition_name, NULL, NULL, NULL, (size_t) -1);
   200     content = mailmime_content_new_with_str(mime_type);
   201 
   202     encoding_type = MAILMIME_MECHANISM_BASE64;
   203     encoding = mailmime_mechanism_new(encoding_type, NULL);
   204     mime_fields = mailmime_fields_new_with_data(encoding,
   205         NULL, NULL, disposition, NULL);
   206     mime = part_new_empty(content, mime_fields, NULL, 1);
   207     mailmime_set_body_text(mime, data, length);
   208 
   209     return mime;
   210 }
   211 
   212 struct mailmime * part_multiple_new(
   213         const char * type,
   214         const char * boundary_prefix
   215     )
   216 {
   217     struct mailmime_fields * mime_fields;
   218     struct mailmime_content * content;
   219     struct mailmime * mp;
   220     
   221     mime_fields = mailmime_fields_new_empty();
   222     if (mime_fields == NULL)
   223         goto err;
   224     
   225     content = mailmime_content_new_with_str(type);
   226     if (content == NULL)
   227         goto free_fields;
   228     
   229     mp = part_new_empty(content, mime_fields, boundary_prefix, 0);
   230     if (mp == NULL)
   231         goto free_content;
   232     
   233     return mp;
   234     
   235 free_content:
   236     mailmime_content_free(content);
   237 free_fields:
   238     mailmime_fields_free(mime_fields);
   239 err:
   240     return NULL;
   241 }
   242 
   243 struct mailimf_field * _new_field(
   244         int type,
   245         _new_func_t new_func,
   246         void *value
   247     )
   248 {
   249     void *data = new_func(value);
   250     assert(data);
   251     if (data == NULL)
   252         return NULL;
   253 
   254     struct mailimf_field * result = calloc(1, sizeof(struct mailimf_field));
   255     assert(result);
   256     if (result == NULL) {
   257         free(data);
   258         return NULL;
   259     }
   260 
   261     result->fld_type = type;
   262     result->fld_data.fld_return_path = data;
   263 
   264     return result;
   265 }
   266 
   267 void _free_field(struct mailimf_field *field)
   268 {
   269     if (field)
   270         free(field->fld_data.fld_return_path);
   271     free(field);
   272 }
   273 
   274 int _append_field(
   275         clist *list,
   276         int type,
   277         _new_func_t new_func,
   278         void *value
   279     )
   280 {
   281     int r;
   282     struct mailimf_field * field;
   283 
   284     assert(list);
   285     assert(new_func);
   286     assert(value);
   287 
   288     field = _new_field(type, new_func, value);
   289     if (field == NULL)
   290         return -1;
   291 
   292     r = clist_append(list, field);
   293     if (r)
   294         _free_field(field);
   295 
   296     return r;
   297 }
   298 
   299 struct mailimf_date_time * timestamp_to_etpantime(const struct tm *ts)
   300 {
   301     struct mailimf_date_time * result = calloc(1,
   302             sizeof(struct mailimf_date_time));
   303     assert(result);
   304     if (result == NULL)
   305         return NULL;
   306 
   307     assert(ts);
   308 
   309     result->dt_sec = ts->tm_sec;
   310     result->dt_min = ts->tm_min;
   311     result->dt_hour = ts->tm_hour;
   312     result->dt_day = ts->tm_mday;
   313     result->dt_month = ts->tm_mon + 1;
   314     result->dt_year = ts->tm_year + 1900;
   315     result->dt_zone = (int) (ts->tm_gmtoff / 36L);
   316 
   317     return result;
   318 }
   319 
   320 struct tm * etpantime_to_timestamp(const struct mailimf_date_time *et)
   321 {
   322     struct tm * result = calloc(1, sizeof(struct tm));
   323     assert(result);
   324     if (result == NULL)
   325         return NULL;
   326 
   327     assert(et);
   328 
   329     result->tm_sec = et->dt_sec;
   330     result->tm_min = et->dt_min;
   331     result->tm_hour = et->dt_hour;
   332     result->tm_mday = et->dt_day;
   333     result->tm_mon = et->dt_month - 1;
   334     result->tm_year = et->dt_year - 1900;
   335     result->tm_gmtoff = 36L * (long) et->dt_zone;
   336 
   337     return result;
   338 }
   339 
   340 struct mailimf_mailbox * mailbox_from_string(
   341         const char *name,
   342         const char *address
   343     )
   344 {
   345     struct mailimf_mailbox *mb = NULL;
   346     char *_name = NULL;
   347     char *_address = NULL;
   348 
   349     assert(address);
   350 
   351     _name = name ? strdup(name) : strdup("");
   352     if (_name == NULL)
   353         goto enomem;
   354 
   355     _address = strdup(address);
   356     if (_address == NULL)
   357         goto enomem;
   358 
   359     mb = mailimf_mailbox_new(_name, _address);
   360     assert(mb);
   361     if (mb == NULL)
   362         goto enomem;
   363 
   364     return mb;
   365 
   366 enomem:
   367     free(_name);
   368     free(_address);
   369 
   370     return NULL;
   371 }
   372