You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

180 lines
3.7 KiB

#include "mime.h"
#include <libetpan/libetpan.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include "etpan_mime.h"
DYNAMIC_API PEP_STATUS mime_encode_text(
const char *plaintext,
const char *htmltext,
char **resulttext
)
{
struct mailmime * msg_mime = NULL;
struct mailimf_fields * fields = NULL;
struct mailmime * mime = NULL;
struct mailmime * submime = NULL;
int col;
int r;
int fd;
FILE *file = NULL;
size_t size;
char *buf = NULL;
PEP_STATUS error = PEP_OUT_OF_MEMORY;
assert(plaintext);
assert(resulttext);
*resulttext = NULL;
msg_mime = mailmime_new_message_data(NULL);
assert(msg_mime);
if (msg_mime == NULL)
goto enomem;
fields = mailimf_fields_new_empty();
assert(fields);
if (fields == NULL)
goto enomem;
mailmime_set_imf_fields(msg_mime, fields);
mime = part_multiple_new("multipart/mixed", NULL);
assert(mime);
if (mime == NULL)
goto enomem;
submime = get_text_part("text/plain", plaintext, strlen(plaintext),
MAILMIME_MECHANISM_QUOTED_PRINTABLE);
assert(submime);
if (submime == NULL) {
mailmime_free(msg_mime);
goto enomem;
}
r = mailmime_smart_add_part(mime, submime);
assert(r == MAILIMF_NO_ERROR);
if (r == MAILIMF_ERROR_MEMORY) {
mailmime_free(msg_mime);
goto enomem;
}
else {
// mailmime_smart_add_part() takes ownership of submime
submime = NULL;
}
r = mailmime_add_part(msg_mime, mime);
assert(r == MAILIMF_NO_ERROR);
if (r == MAILIMF_ERROR_MEMORY) {
goto enomem;
}
// mailmime_add_part() takes ownership of mime
char *template = strdup("/tmp/temp.XXXXXXXXXXXXXXXXXXXX");
assert(template);
if (template == NULL)
goto enomem;
do {
fd = mkstemp(template);
} while (fd == -1 && errno == EINTR);
assert(fd != -1);
if (fd == -1)
goto err_file;
r = unlink(template);
assert(r == 0);
if (r == -1)
goto err_file;
free(template);
template = NULL;
do {
file = fdopen(fd, "w+");
} while (file == NULL && errno == EINTR);
assert(file);
if (file == NULL) {
switch (errno) {
case ENOMEM:
goto enomem;
default:
goto err_file;
}
}
fd = -1;
col = 0;
r = mailmime_write_file(file, &col, mime);
assert(r == MAILIMF_NO_ERROR);
if (r == MAILIMF_ERROR_MEMORY)
goto enomem;
else if (r != MAILIMF_NO_ERROR)
goto err_file;
off_t len = ftello(file);
assert(len != -1);
if (len == -1 && errno == EOVERFLOW)
goto err_file;
if (len + 1 > SIZE_T_MAX)
goto err_buffer;
size = (size_t) len;
rewind(file);
buf = calloc(1, size + 1);
assert(buf);
if (buf == NULL)
goto enomem;
char *_buf = buf;
size_t rest = size;
for (size_t bytes_read = 0; rest > 0; rest -= bytes_read, _buf += rest) {
assert(feof(file) == 0);
if (feof(file))
goto err_file;
bytes_read = fread(_buf, rest, 1, file);
if (ferror(file))
goto err_file;
}
fclose(file);
mailmime_free(msg_mime);
*resulttext = buf;
return PEP_STATUS_OK;
err_buffer:
error = PEP_BUFFER_TOO_SMALL;
goto enomem;
err_file:
error = PEP_CANNOT_CREATE_TEMP_FILE;
enomem:
free(buf);
free(template);
if (file)
fclose(file);
else if (fd != -1)
close(fd);
if (msg_mime)
mailmime_free(msg_mime);
if (fields)
mailimf_fields_free(fields);
if (submime)
mailmime_free(submime);
return error;
}