src/etpan_mime.c
author Volker Birk <vb@pep-project.org>
Wed, 16 Mar 2016 11:20:52 +0100
changeset 507 288496838ffb
parent 438 106b9765559d
child 747 d357dceebec6
permissions -rw-r--r--
adding get_binary_path() to Message API
vb@48
     1
#include "etpan_mime.h"
vb@62
     2
#ifndef mailmime_param_new_with_data
vb@62
     3
#include <libetpan/mailprivacy_tools.h>
vb@62
     4
#endif
vb@48
     5
vb@130
     6
#include "platform.h"
vb@130
     7
vb@130
     8
#include <string.h>
vb@130
     9
#include <stdlib.h>
vb@130
    10
#include <assert.h>
vb@157
    11
#include <errno.h>
vb@89
    12
roker@438
    13
#define MAX_MESSAGE_ID 128
vb@48
    14
vb@116
    15
static char * generate_boundary(void)
vb@48
    16
{
vb@48
    17
    char id[MAX_MESSAGE_ID];
vb@54
    18
roker@438
    19
    // no cryptographically strong random needed here
roker@438
    20
    const long value1 = random();
roker@438
    21
    const long value2 = random();
roker@438
    22
    const long value3 = random();
roker@438
    23
    const long value4 = random();
vb@90
    24
vb@116
    25
    snprintf(id, MAX_MESSAGE_ID, "%.4lx%.4lx%.4lx%.4lx", value1, value2,
vb@116
    26
            value3, value4);
vb@48
    27
    
vb@48
    28
    return strdup(id);
vb@48
    29
}
vb@48
    30
vb@48
    31
struct mailmime * part_new_empty(
vb@48
    32
        struct mailmime_content * content,
vb@48
    33
        struct mailmime_fields * mime_fields,
vb@48
    34
        int force_single
vb@48
    35
    )
vb@48
    36
{
vb@48
    37
	struct mailmime * build_info;
vb@115
    38
	clist * list = NULL;
vb@48
    39
	int r;
vb@48
    40
	int mime_type;
vb@115
    41
    char * attr_name = NULL;
vb@115
    42
    char * attr_value = NULL;
vb@115
    43
    struct mailmime_parameter * param = NULL;
vb@115
    44
    clist * parameters = NULL;
vb@116
    45
    char *boundary = NULL;
vb@48
    46
vb@48
    47
	list = NULL;
vb@48
    48
vb@48
    49
	if (force_single) {
vb@48
    50
		mime_type = MAILMIME_SINGLE;
vb@48
    51
	}
vb@48
    52
	else {
vb@48
    53
		switch (content->ct_type->tp_type) {
vb@48
    54
			case MAILMIME_TYPE_DISCRETE_TYPE:
vb@115
    55
                mime_type = MAILMIME_SINGLE;
vb@115
    56
                break;
vb@48
    57
vb@48
    58
			case MAILMIME_TYPE_COMPOSITE_TYPE:
vb@115
    59
                switch (content->ct_type->tp_data.tp_composite_type->ct_type) {
vb@115
    60
                    case MAILMIME_COMPOSITE_TYPE_MULTIPART:
vb@115
    61
                        mime_type = MAILMIME_MULTIPLE;
vb@115
    62
                        break;
vb@48
    63
vb@115
    64
                    case MAILMIME_COMPOSITE_TYPE_MESSAGE:
vb@115
    65
                        if (strcasecmp(content->ct_subtype, "rfc822") == 0)
vb@115
    66
                            mime_type = MAILMIME_MESSAGE;
vb@115
    67
                        else
vb@115
    68
                            mime_type = MAILMIME_SINGLE;
vb@115
    69
                        break;
vb@48
    70
vb@115
    71
                    default:
vb@115
    72
                        goto enomem;
vb@115
    73
                }
vb@115
    74
                break;
vb@48
    75
vb@48
    76
			default:
vb@115
    77
                goto enomem;
vb@48
    78
		}
vb@48
    79
	}
vb@48
    80
vb@48
    81
	if (mime_type == MAILMIME_MULTIPLE) {
vb@48
    82
		list = clist_new();
vb@115
    83
        assert(list);
vb@48
    84
		if (list == NULL)
vb@115
    85
			goto enomem;
vb@48
    86
vb@48
    87
		attr_name = strdup("boundary");
vb@115
    88
        assert(attr_name);
vb@115
    89
        if (attr_name == NULL)
vb@115
    90
            goto enomem;
vb@115
    91
vb@116
    92
		boundary = generate_boundary();
vb@115
    93
        assert(boundary);
vb@48
    94
		attr_value = boundary;
vb@115
    95
		if (attr_value == NULL)
vb@115
    96
			goto enomem;
vb@48
    97
vb@48
    98
		param = mailmime_parameter_new(attr_name, attr_value);
vb@115
    99
        assert(param);
vb@115
   100
		if (param == NULL)
vb@115
   101
			goto enomem;
vb@115
   102
        attr_name = NULL;
vb@115
   103
        attr_value = NULL;
vb@48
   104
vb@48
   105
		if (content->ct_parameters == NULL) {
vb@48
   106
			parameters = clist_new();
vb@115
   107
            assert(parameters);
vb@115
   108
			if (parameters == NULL)
vb@115
   109
				goto enomem;
vb@48
   110
		}
vb@115
   111
		else {
vb@48
   112
			parameters = content->ct_parameters;
vb@115
   113
        }
vb@48
   114
vb@48
   115
		r = clist_append(parameters, param);
vb@115
   116
		if (r)
vb@115
   117
			goto enomem;
vb@115
   118
        param = NULL;
vb@48
   119
vb@48
   120
		if (content->ct_parameters == NULL)
vb@48
   121
			content->ct_parameters = parameters;
vb@48
   122
	}
vb@48
   123
vb@115
   124
    build_info = mailmime_new(mime_type, NULL, 0, mime_fields, content, NULL,
vb@115
   125
            NULL, NULL, list, NULL, NULL);
vb@115
   126
	if (build_info == NULL)
vb@115
   127
		goto enomem;
vb@48
   128
vb@48
   129
	return build_info;
vb@48
   130
vb@115
   131
enomem:
vb@115
   132
    if (list)
vb@115
   133
        clist_free(list);
vb@115
   134
    free(attr_name);
vb@115
   135
    free(attr_value);
vb@115
   136
    if (content->ct_parameters == NULL)
vb@115
   137
        if (parameters)
vb@115
   138
            clist_free(parameters);
vb@115
   139
vb@48
   140
	return NULL;
vb@48
   141
}
vb@48
   142
vb@114
   143
struct mailmime * get_pgp_encrypted_part(void)
vb@114
   144
{
vb@115
   145
	struct mailmime * mime = NULL;
vb@115
   146
	struct mailmime_fields * mime_fields = NULL;
vb@115
   147
	struct mailmime_content * content = NULL;
vb@115
   148
    int r;
vb@114
   149
vb@114
   150
	content = mailmime_content_new_with_str("application/pgp-encrypted");
vb@115
   151
    if (content == NULL)
vb@115
   152
        goto enomem;
vb@115
   153
vb@114
   154
    mime_fields = mailmime_fields_new_empty();
vb@115
   155
    if (mime_fields == NULL)
vb@115
   156
        goto enomem;
vb@115
   157
vb@116
   158
	mime = part_new_empty(content, mime_fields, 1);
vb@115
   159
    if (mime == NULL)
vb@115
   160
        goto enomem;
vb@115
   161
    mime_fields = NULL;
vb@115
   162
    content = NULL;
vb@115
   163
vb@115
   164
    r = mailmime_set_body_text(mime, "Version: 1\n", 10);
vb@115
   165
    if (r != 0)
vb@115
   166
        goto enomem;
vb@114
   167
vb@114
   168
	return mime;
vb@115
   169
vb@115
   170
enomem:
vb@115
   171
    if (content)
vb@115
   172
        mailmime_content_free(content);
vb@115
   173
    if (mime_fields)
vb@115
   174
        mailmime_fields_free(mime_fields);
vb@115
   175
    if (mime)
vb@115
   176
        mailmime_free(mime);
vb@115
   177
vb@115
   178
    return NULL;
vb@114
   179
}
vb@114
   180
vb@48
   181
struct mailmime * get_text_part(
vb@114
   182
        const char * filename,
vb@48
   183
        const char * mime_type,
vb@48
   184
        const char * text,
vb@48
   185
        size_t length,
vb@48
   186
        int encoding_type
vb@48
   187
    )
vb@48
   188
{
vb@114
   189
    char * disposition_name = NULL;
vb@115
   190
	struct mailmime_fields * mime_fields = NULL;
vb@115
   191
	struct mailmime * mime = NULL;
vb@115
   192
	struct mailmime_content * content = NULL;
vb@115
   193
	struct mailmime_parameter * param = NULL;
vb@115
   194
	struct mailmime_disposition * disposition = NULL;
vb@114
   195
	struct mailmime_mechanism * encoding = NULL;
vb@115
   196
    int r;
vb@48
   197
    
vb@115
   198
    if (filename != NULL) {
vb@114
   199
        disposition_name = strdup(filename);
vb@115
   200
        if (disposition_name == NULL)
vb@115
   201
            goto enomem;
vb@115
   202
    }
vb@114
   203
vb@115
   204
    if (encoding_type) {
vb@114
   205
        encoding = mailmime_mechanism_new(encoding_type, NULL);
vb@115
   206
        if (encoding == NULL)
vb@115
   207
            goto enomem;
vb@115
   208
    }
vb@114
   209
vb@115
   210
    disposition =
vb@115
   211
            mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_INLINE,
vb@115
   212
                    disposition_name, NULL, NULL, NULL, (size_t) -1);
vb@115
   213
    if (disposition == NULL)
vb@115
   214
        goto enomem;
vb@115
   215
    disposition_name = NULL;
vb@114
   216
vb@115
   217
    mime_fields = mailmime_fields_new_with_data(encoding, NULL, NULL,
vb@115
   218
            disposition, NULL);
vb@115
   219
    if (mime_fields == NULL)
vb@115
   220
        goto enomem;
vb@115
   221
    encoding = NULL;
vb@115
   222
    disposition = NULL;
vb@48
   223
vb@48
   224
	content = mailmime_content_new_with_str(mime_type);
vb@115
   225
    if (content == NULL)
vb@115
   226
        goto enomem;
vb@114
   227
    
vb@114
   228
    if (encoding_type != MAILMIME_MECHANISM_7BIT) {
vb@114
   229
        param = mailmime_param_new_with_data("charset", "utf-8");
vb@115
   230
        r = clist_append(content->ct_parameters, param);
vb@115
   231
        if (r != 0)
vb@115
   232
            goto enomem;
vb@114
   233
    }
vb@114
   234
vb@116
   235
	mime = part_new_empty(content, mime_fields, 1);
vb@115
   236
    if (mime == NULL)
vb@115
   237
        goto enomem;
vb@115
   238
    content = NULL;
vb@115
   239
    mime_fields = NULL;
vb@114
   240
vb@115
   241
    if (text) {
vb@115
   242
        r = mailmime_set_body_text(mime, (char *) text, length);
vb@115
   243
        if (r != 0)
vb@115
   244
            goto enomem;
vb@115
   245
    }
vb@48
   246
	
vb@48
   247
	return mime;
vb@115
   248
vb@115
   249
enomem:
vb@115
   250
    free(disposition_name);
vb@115
   251
    if (mime_fields)
vb@115
   252
        mailmime_fields_free(mime_fields);
vb@115
   253
    if (mime)
vb@115
   254
        mailmime_free(mime);
vb@115
   255
    if (content)
vb@115
   256
        mailmime_content_free(content);
vb@115
   257
    if (param)
vb@115
   258
        mailmime_parameter_free(param);
vb@115
   259
    if (disposition)
vb@115
   260
        mailmime_disposition_free(disposition);
vb@115
   261
    if (encoding)
vb@115
   262
        mailmime_mechanism_free(encoding);
vb@115
   263
vb@115
   264
    return NULL;
vb@48
   265
}
vb@48
   266
vb@59
   267
struct mailmime * get_file_part(
vb@59
   268
        const char * filename,
vb@59
   269
        const char * mime_type,
vb@59
   270
        char * data,
vb@59
   271
        size_t length
vb@59
   272
    )
vb@59
   273
{
vb@115
   274
    char * disposition_name = NULL;
vb@59
   275
    int encoding_type;
vb@115
   276
    struct mailmime_disposition * disposition = NULL;
vb@115
   277
    struct mailmime_mechanism * encoding = NULL;
vb@115
   278
    struct mailmime_content * content = NULL;
vb@115
   279
    struct mailmime * mime = NULL;
vb@115
   280
    struct mailmime_fields * mime_fields = NULL;
vb@115
   281
    int r;
vb@59
   282
vb@59
   283
    if (filename != NULL) {
vb@59
   284
        disposition_name = strdup(filename);
vb@115
   285
        if (disposition_name == NULL)
vb@115
   286
            goto enomem;
vb@59
   287
    }
vb@115
   288
vb@59
   289
    disposition =
vb@115
   290
            mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
vb@115
   291
                    disposition_name, NULL, NULL, NULL, (size_t) -1);
vb@115
   292
    if (disposition == NULL)
vb@115
   293
        goto enomem;
vb@115
   294
    disposition_name = NULL;
vb@115
   295
vb@59
   296
    content = mailmime_content_new_with_str(mime_type);
vb@115
   297
    if (content == NULL)
vb@115
   298
        goto enomem;
vb@59
   299
vb@59
   300
    encoding_type = MAILMIME_MECHANISM_BASE64;
vb@59
   301
    encoding = mailmime_mechanism_new(encoding_type, NULL);
vb@115
   302
    if (encoding == NULL)
vb@115
   303
        goto enomem;
vb@115
   304
vb@115
   305
    mime_fields = mailmime_fields_new_with_data(encoding, NULL, NULL,
vb@115
   306
            disposition, NULL);
vb@115
   307
    if (mime_fields == NULL)
vb@115
   308
        goto enomem;
vb@115
   309
    encoding = NULL;
vb@115
   310
    disposition = NULL;
vb@115
   311
vb@116
   312
    mime = part_new_empty(content, mime_fields, 1);
vb@115
   313
    if (mime == NULL)
vb@115
   314
        goto enomem;
vb@115
   315
    content = NULL;
vb@115
   316
    mime_fields = NULL;
vb@115
   317
vb@115
   318
    r = mailmime_set_body_text(mime, data, length);
vb@115
   319
    if (r != 0)
vb@115
   320
        goto enomem;
vb@59
   321
vb@59
   322
    return mime;
vb@115
   323
vb@115
   324
enomem:
vb@115
   325
    free(disposition_name);
vb@115
   326
    if (disposition)
vb@115
   327
        mailmime_disposition_free(disposition);
vb@115
   328
    if (encoding)
vb@115
   329
        mailmime_mechanism_free(encoding);
vb@115
   330
    if (content)
vb@115
   331
        mailmime_content_free(content);
vb@115
   332
    if (mime_fields)
vb@115
   333
        mailmime_fields_free(mime_fields);
vb@115
   334
    if (mime)
vb@115
   335
        mailmime_free(mime);
vb@115
   336
vb@115
   337
    return NULL;
vb@59
   338
}
vb@59
   339
vb@116
   340
struct mailmime * part_multiple_new(const char *type)
vb@48
   341
{
vb@115
   342
    struct mailmime_fields *mime_fields = NULL;
vb@115
   343
    struct mailmime_content *content = NULL;
vb@115
   344
    struct mailmime *mp = NULL;
vb@48
   345
    
vb@48
   346
    mime_fields = mailmime_fields_new_empty();
vb@48
   347
    if (mime_fields == NULL)
vb@115
   348
        goto enomem;
vb@48
   349
    
vb@48
   350
    content = mailmime_content_new_with_str(type);
vb@48
   351
    if (content == NULL)
vb@115
   352
        goto enomem;
vb@48
   353
    
vb@116
   354
    mp = part_new_empty(content, mime_fields, 0);
vb@48
   355
    if (mp == NULL)
vb@115
   356
        goto enomem;
vb@48
   357
    
vb@48
   358
    return mp;
vb@48
   359
    
vb@115
   360
enomem:
vb@115
   361
    if (content)
vb@115
   362
        mailmime_content_free(content);
vb@115
   363
    if (mime_fields)
vb@115
   364
        mailmime_fields_free(mime_fields);
vb@115
   365
vb@48
   366
    return NULL;
vb@48
   367
}
vb@48
   368
vb@89
   369
struct mailimf_field * _new_field(
vb@89
   370
        int type,
vb@89
   371
        _new_func_t new_func,
vb@89
   372
        void *value
vb@89
   373
    )
vb@89
   374
{
vb@89
   375
    void *data = new_func(value);
vb@89
   376
    assert(data);
vb@89
   377
    if (data == NULL)
vb@89
   378
        return NULL;
vb@89
   379
vb@89
   380
    struct mailimf_field * result = calloc(1, sizeof(struct mailimf_field));
vb@89
   381
    assert(result);
vb@89
   382
    if (result == NULL) {
vb@89
   383
        free(data);
vb@89
   384
        return NULL;
vb@89
   385
    }
vb@89
   386
vb@89
   387
    result->fld_type = type;
vb@89
   388
    result->fld_data.fld_return_path = data;
vb@89
   389
vb@89
   390
    return result;
vb@89
   391
}
vb@89
   392
vb@89
   393
void _free_field(struct mailimf_field *field)
vb@89
   394
{
vb@89
   395
    if (field)
vb@89
   396
        free(field->fld_data.fld_return_path);
vb@89
   397
    free(field);
vb@89
   398
}
vb@89
   399
vb@89
   400
int _append_field(
vb@89
   401
        clist *list,
vb@89
   402
        int type,
vb@89
   403
        _new_func_t new_func,
vb@89
   404
        void *value
vb@89
   405
    )
vb@89
   406
{
vb@89
   407
    int r;
vb@89
   408
    struct mailimf_field * field;
vb@89
   409
vb@89
   410
    assert(list);
vb@89
   411
    assert(new_func);
vb@89
   412
    assert(value);
vb@89
   413
vb@89
   414
    field = _new_field(type, new_func, value);
vb@89
   415
    if (field == NULL)
vb@89
   416
        return -1;
vb@89
   417
vb@89
   418
    r = clist_append(list, field);
vb@90
   419
    if (r)
vb@89
   420
        _free_field(field);
vb@89
   421
vb@89
   422
    return r;
vb@89
   423
}
vb@89
   424
vb@92
   425
// http://media2.giga.de/2014/02/Image-28.jpg
vb@92
   426
vb@89
   427
struct mailimf_date_time * timestamp_to_etpantime(const struct tm *ts)
vb@89
   428
{
vb@89
   429
    struct mailimf_date_time * result = calloc(1,
vb@89
   430
            sizeof(struct mailimf_date_time));
vb@89
   431
    assert(result);
vb@89
   432
    if (result == NULL)
vb@89
   433
        return NULL;
vb@89
   434
vb@89
   435
    assert(ts);
vb@89
   436
vb@89
   437
    result->dt_sec = ts->tm_sec;
vb@89
   438
    result->dt_min = ts->tm_min;
vb@89
   439
    result->dt_hour = ts->tm_hour;
vb@89
   440
    result->dt_day = ts->tm_mday;
vb@89
   441
    result->dt_month = ts->tm_mon + 1;
vb@89
   442
    result->dt_year = ts->tm_year + 1900;
vb@130
   443
#ifndef WIN32
vb@89
   444
    result->dt_zone = (int) (ts->tm_gmtoff / 36L);
vb@130
   445
#endif
vb@89
   446
    return result;
vb@89
   447
}
vb@89
   448
vb@89
   449
struct tm * etpantime_to_timestamp(const struct mailimf_date_time *et)
vb@89
   450
{
vb@89
   451
    struct tm * result = calloc(1, sizeof(struct tm));
vb@89
   452
    assert(result);
vb@89
   453
    if (result == NULL)
vb@89
   454
        return NULL;
vb@89
   455
vb@89
   456
    assert(et);
vb@89
   457
vb@89
   458
    result->tm_sec = et->dt_sec;
vb@89
   459
    result->tm_min = et->dt_min;
vb@89
   460
    result->tm_hour = et->dt_hour;
vb@89
   461
    result->tm_mday = et->dt_day;
vb@89
   462
    result->tm_mon = et->dt_month - 1;
vb@89
   463
    result->tm_year = et->dt_year - 1900;
vb@130
   464
#ifndef WIN32
vb@89
   465
    result->tm_gmtoff = 36L * (long) et->dt_zone;
vb@130
   466
#endif
vb@89
   467
    return result;
vb@89
   468
}
vb@89
   469
vb@90
   470
struct mailimf_mailbox * mailbox_from_string(
vb@90
   471
        const char *name,
vb@90
   472
        const char *address
vb@90
   473
    )
vb@90
   474
{
vb@90
   475
    struct mailimf_mailbox *mb = NULL;
vb@90
   476
    char *_name = NULL;
vb@90
   477
    char *_address = NULL;
vb@90
   478
vb@90
   479
    assert(address);
vb@90
   480
vb@90
   481
    _name = name ? strdup(name) : strdup("");
vb@90
   482
    if (_name == NULL)
vb@90
   483
        goto enomem;
vb@90
   484
vb@90
   485
    _address = strdup(address);
vb@90
   486
    if (_address == NULL)
vb@90
   487
        goto enomem;
vb@90
   488
vb@90
   489
    mb = mailimf_mailbox_new(_name, _address);
vb@90
   490
    assert(mb);
vb@90
   491
    if (mb == NULL)
vb@90
   492
        goto enomem;
vb@90
   493
vb@90
   494
    return mb;
vb@90
   495
vb@90
   496
enomem:
vb@90
   497
    free(_name);
vb@90
   498
    free(_address);
vb@90
   499
vb@90
   500
    return NULL;
vb@90
   501
}
vb@90
   502
vb@94
   503
struct mailimf_field * create_optional_field(
vb@94
   504
        const char *field,
vb@94
   505
        const char *value
vb@94
   506
    )
vb@94
   507
{
vb@94
   508
    char *_field = NULL;
vb@94
   509
    char *_value = NULL;
vb@94
   510
    struct mailimf_optional_field *optional_field = NULL;
vb@94
   511
vb@94
   512
    _field = strdup(field);
vb@94
   513
    if (_field == NULL)
vb@94
   514
        goto enomem;
vb@94
   515
vb@94
   516
    _value = mailmime_encode_subject_header("utf-8", value, 0);
vb@94
   517
    if (_value == NULL)
vb@94
   518
        goto enomem;
vb@94
   519
vb@94
   520
    optional_field = mailimf_optional_field_new(_field, _value);
vb@94
   521
    if (optional_field == NULL)
vb@94
   522
        goto enomem;
vb@94
   523
vb@94
   524
    struct mailimf_field * result = calloc(1, sizeof(struct mailimf_field));
vb@94
   525
    assert(result);
vb@94
   526
    if (result == NULL)
vb@94
   527
        goto enomem;
vb@94
   528
vb@94
   529
    result->fld_type = MAILIMF_FIELD_OPTIONAL_FIELD;
vb@94
   530
    result->fld_data.fld_optional_field = optional_field;
vb@94
   531
vb@94
   532
    return result;
vb@94
   533
vb@94
   534
enomem:
vb@94
   535
    if (optional_field) {
vb@94
   536
        mailimf_optional_field_free(optional_field);
vb@94
   537
    }
vb@94
   538
    else {
vb@94
   539
        free(_field);
vb@94
   540
        free(_value);
vb@94
   541
    }
vb@94
   542
vb@94
   543
    return NULL;
vb@94
   544
}
vb@94
   545
vb@94
   546
int _append_optional_field(
vb@94
   547
        clist *list,
vb@94
   548
        const char *field,
vb@94
   549
        const char *value
vb@94
   550
    )
vb@94
   551
{
vb@94
   552
    int r;
vb@94
   553
    struct mailimf_field * optional_field =
vb@94
   554
            create_optional_field(field, value);
vb@94
   555
vb@94
   556
    if (optional_field == NULL)
vb@94
   557
        return -1;
vb@94
   558
vb@94
   559
    r = clist_append(list, optional_field);
vb@94
   560
    if (r)
vb@94
   561
        mailimf_field_free(optional_field);
vb@94
   562
vb@94
   563
    return r;
vb@94
   564
}
vb@94
   565
vb@147
   566
clist * _get_fields(struct mailmime * mime)
vb@147
   567
{
vb@147
   568
    clist * _fieldlist = NULL;
vb@147
   569
vb@147
   570
    assert(mime);
vb@147
   571
vb@147
   572
    if (mime->mm_data.mm_message.mm_fields &&
vb@147
   573
            mime->mm_data.mm_message.mm_fields->fld_list) {
vb@147
   574
        _fieldlist = mime->mm_data.mm_message.mm_fields->fld_list;
vb@147
   575
    }
vb@147
   576
vb@147
   577
    return _fieldlist;
vb@147
   578
}
vb@147
   579
vb@147
   580
struct mailmime_content * _get_content(struct mailmime * mime)
vb@147
   581
{
vb@147
   582
    struct mailmime_content * content = NULL;
vb@147
   583
vb@147
   584
    assert(mime);
vb@147
   585
vb@147
   586
    if (mime->mm_data.mm_message.mm_msg_mime)
vb@147
   587
        content = mime->mm_data.mm_message.mm_msg_mime->mm_content_type;
vb@147
   588
vb@147
   589
    return content;
vb@147
   590
}
vb@147
   591
vb@154
   592
char * _get_filename(struct mailmime *mime)
vb@154
   593
{
vb@154
   594
    clist * _fieldlist = NULL;
vb@154
   595
vb@154
   596
    assert(mime);
vb@154
   597
vb@154
   598
    if (mime->mm_mime_fields && mime->mm_mime_fields->fld_list)
vb@154
   599
        _fieldlist = mime->mm_mime_fields->fld_list;
vb@154
   600
    else
vb@154
   601
        return NULL;
vb@154
   602
vb@154
   603
    clistiter *cur;
vb@154
   604
    for (cur = clist_begin(_fieldlist); cur; cur = clist_next(cur)) {
vb@154
   605
        struct mailmime_field * _field = clist_content(cur);
vb@154
   606
        if (_field && _field->fld_type == MAILMIME_FIELD_DISPOSITION) {
vb@154
   607
            if (_field->fld_data.fld_disposition &&
vb@154
   608
                    _field->fld_data.fld_disposition->dsp_parms) {
vb@154
   609
                clist * _parmlist =
vb@154
   610
                        _field->fld_data.fld_disposition->dsp_parms;
vb@154
   611
                clistiter *cur2;
vb@154
   612
                for (cur2 = clist_begin(_parmlist); cur2; cur2 =
vb@154
   613
                        clist_next(cur2)) {
vb@156
   614
                    struct mailmime_disposition_parm * param =
vb@156
   615
                            clist_content(cur2);
vb@156
   616
                    if (param->pa_type == MAILMIME_DISPOSITION_PARM_FILENAME)
vb@156
   617
                        return param->pa_data.pa_filename;
vb@154
   618
                }
vb@154
   619
            }
vb@154
   620
        }
vb@154
   621
    }
vb@154
   622
vb@154
   623
    return NULL;
vb@154
   624
}
vb@154
   625
vb@157
   626
static bool parameter_has_value(
vb@152
   627
        struct mailmime_content *content,       
vb@152
   628
        const char *name,
vb@152
   629
        const char *value
vb@152
   630
    )
vb@152
   631
{
vb@152
   632
    clistiter *cur;
vb@152
   633
vb@152
   634
    assert(name);
vb@152
   635
    assert(value);
vb@152
   636
vb@152
   637
    clist * list = content->ct_parameters;
vb@152
   638
    if (list == NULL)
vb@152
   639
        return false;
vb@152
   640
vb@152
   641
    for (cur = clist_begin(list); cur != NULL ; cur = clist_next(cur)) {
vb@152
   642
        struct mailmime_parameter * param = clist_content(cur);
vb@152
   643
        if (param &&
vb@165
   644
                param->pa_name && strcasecmp(name, param->pa_name) == 0 &&
vb@165
   645
                param->pa_value && strcasecmp(value, param->pa_value) == 0)
vb@152
   646
            return true;
vb@152
   647
    }
vb@152
   648
vb@152
   649
    return false;
vb@152
   650
}
vb@152
   651
vb@151
   652
bool _is_multipart(struct mailmime_content *content, const char *subtype)
vb@147
   653
{
vb@147
   654
    assert(content);
vb@147
   655
vb@147
   656
    if (content->ct_type && content->ct_type->tp_type ==
vb@147
   657
            MAILMIME_TYPE_COMPOSITE_TYPE &&
vb@147
   658
            content->ct_type->tp_data.tp_composite_type &&
vb@147
   659
            content->ct_type->tp_data.tp_composite_type->ct_type ==
vb@151
   660
            MAILMIME_COMPOSITE_TYPE_MULTIPART) {
vb@151
   661
        if (subtype)
vb@151
   662
            return content->ct_subtype &&
vb@165
   663
                    strcasecmp(content->ct_subtype, subtype) == 0;
vb@151
   664
        else
vb@151
   665
            return true;
vb@151
   666
    }
vb@147
   667
vb@151
   668
    return false;
vb@147
   669
}
vb@147
   670
vb@147
   671
bool _is_PGP_MIME(struct mailmime_content *content)
vb@147
   672
{
vb@147
   673
    assert(content);
vb@147
   674
vb@151
   675
    if (_is_multipart(content, "encrypted") &&
vb@152
   676
            parameter_has_value(content, "protocol",
vb@147
   677
                    "application/pgp-encrypted"))
vb@151
   678
        return true;
vb@147
   679
vb@151
   680
    return false;
vb@147
   681
}
vb@147
   682
vb@152
   683
bool _is_text_part(struct mailmime_content *content, const char *subtype)
vb@152
   684
{
vb@152
   685
    assert(content);
vb@152
   686
vb@153
   687
    if (content->ct_type && content->ct_type->tp_type ==
vb@153
   688
            MAILMIME_TYPE_DISCRETE_TYPE &&
vb@153
   689
            content->ct_type->tp_data.tp_discrete_type &&
vb@152
   690
            content->ct_type->tp_data.tp_discrete_type->dt_type ==
vb@152
   691
            MAILMIME_DISCRETE_TYPE_TEXT) {
vb@152
   692
        if (subtype)
vb@152
   693
            return content->ct_subtype &&
vb@165
   694
                    strcasecmp(content->ct_subtype, subtype) == 0;
vb@152
   695
        else
vb@152
   696
            return true;
vb@152
   697
    }
vb@152
   698
vb@152
   699
    return false;
vb@152
   700
}
vb@152
   701
vb@159
   702
int _get_content_type(
vb@159
   703
        const struct mailmime_content *content,
vb@159
   704
        char **type,
vb@159
   705
        char **charset
vb@159
   706
    )
vb@154
   707
{
vb@159
   708
    char *_type = NULL;
vb@159
   709
    char *_charset = NULL;
vb@154
   710
vb@154
   711
    assert(content);
vb@159
   712
    assert(type);
vb@159
   713
    assert(charset);
vb@154
   714
vb@159
   715
    *type = NULL;
vb@159
   716
    *charset = NULL;
vb@159
   717
vb@159
   718
    if (content->ct_subtype == NULL)
vb@159
   719
        return EINVAL;
vb@154
   720
vb@154
   721
    if (content->ct_type && content->ct_type->tp_data.tp_discrete_type) {
vb@154
   722
        size_t len;
vb@159
   723
        const char *_main_type;
vb@154
   724
vb@154
   725
        switch  (content->ct_type->tp_data.tp_discrete_type->dt_type) {
vb@154
   726
            case MAILMIME_DISCRETE_TYPE_TEXT:
vb@159
   727
                _main_type = "text";
vb@154
   728
                break;
vb@154
   729
            case MAILMIME_DISCRETE_TYPE_IMAGE:
vb@159
   730
                _main_type = "image";
vb@154
   731
                break;
vb@154
   732
            case MAILMIME_DISCRETE_TYPE_AUDIO:
vb@159
   733
                _main_type = "audio";
vb@154
   734
                break;
vb@154
   735
            case MAILMIME_DISCRETE_TYPE_VIDEO:
vb@159
   736
                _main_type = "video";
vb@154
   737
                break;
vb@154
   738
            case MAILMIME_DISCRETE_TYPE_APPLICATION:
vb@159
   739
                _main_type = "application";
vb@154
   740
                break;
vb@154
   741
            case MAILMIME_DISCRETE_TYPE_EXTENSION:
vb@159
   742
                _main_type = "extension";
vb@154
   743
                break;
vb@154
   744
            default:
vb@159
   745
                return EINVAL;
vb@154
   746
        }
vb@154
   747
vb@159
   748
        len = strlen(_main_type) + 1 + strlen(content->ct_subtype) + 1;
vb@159
   749
        _type = calloc(1, len);
vb@159
   750
        assert(_type);
vb@159
   751
        if (_type == NULL)
vb@159
   752
            return ENOMEM;
vb@159
   753
vb@159
   754
        strcpy(_type, _main_type);
vb@159
   755
        strcat(_type, "/");
vb@159
   756
        strcat(_type, content->ct_subtype);
vb@159
   757
vb@159
   758
        if (content->ct_parameters) {
vb@159
   759
            clistiter *cur;
vb@159
   760
            for (cur = clist_begin(content->ct_parameters); cur; cur =
vb@159
   761
                    clist_next(cur)) {
vb@159
   762
                struct mailmime_parameter * param = clist_content(cur);
vb@165
   763
                if (param && param->pa_name && strcasecmp(param->pa_name,
vb@159
   764
                            "charset") == 0) {
vb@159
   765
                    _charset = param->pa_value;
vb@159
   766
                    break;
vb@159
   767
                }
vb@159
   768
            }
vb@159
   769
            if (_charset)
vb@159
   770
                *charset = strdup(_charset);
vb@157
   771
        }
vb@154
   772
vb@159
   773
        *type = _type;
vb@159
   774
        return 0;
vb@154
   775
    }
vb@154
   776
vb@159
   777
    return EINVAL;
vb@154
   778
}
vb@154
   779