diff --git a/mms-engine/Makefile b/mms-engine/Makefile index 9d7cbe0..daa9fff 100644 --- a/mms-engine/Makefile +++ b/mms-engine/Makefile @@ -17,7 +17,7 @@ include ../mms-lib/Config.mak # PKGS = gio-unix-2.0 gio-2.0 -LIB_PKGS = libwspcodec libsoup-2.4 dconf $(RESIZE_PKG) $(PKGS) +LIB_PKGS = libwspcodec gmime-2.6 libsoup-2.4 dconf $(RESIZE_PKG) $(PKGS) # # Default target diff --git a/mms-engine/mms-engine.pro b/mms-engine/mms-engine.pro index 564bc04..f36e22c 100644 --- a/mms-engine/mms-engine.pro +++ b/mms-engine/mms-engine.pro @@ -1,6 +1,6 @@ TEMPLATE = app CONFIG += link_pkgconfig -PKGCONFIG += gio-unix-2.0 gio-2.0 glib-2.0 libsoup-2.4 dconf libwspcodec ImageMagick +PKGCONFIG += gmime-2.6 gio-unix-2.0 gio-2.0 glib-2.0 libsoup-2.4 dconf libwspcodec ImageMagick DBUS_INTERFACE_DIR = $$_PRO_FILE_PWD_ MMS_LIB_DIR = $$_PRO_FILE_PWD_/../mms-lib MMS_OFONO_DIR = $$_PRO_FILE_PWD_/../mms-ofono diff --git a/mms-lib/Makefile b/mms-lib/Makefile index d7f7d7b..745c4a2 100644 --- a/mms-lib/Makefile +++ b/mms-lib/Makefile @@ -12,7 +12,7 @@ include Config.mak # Required packages # -PKGS = glib-2.0 libsoup-2.4 libwspcodec +PKGS = gmime-2.6 glib-2.0 libsoup-2.4 libwspcodec # # Default target diff --git a/mms-lib/include/mms_message.h b/mms-lib/include/mms_message.h index 92d4696..7441b01 100644 --- a/mms-lib/include/mms_message.h +++ b/mms-lib/include/mms_message.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2015 Jolla Ltd. + * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -48,6 +49,7 @@ typedef struct _mms_message_part { char* content_type; /* Content-Type */ char* content_id; /* Content-ID */ char* file; /* File name */ + char* orig; /* File prior to decoding */ } MMSMessagePart; MMSMessage* diff --git a/mms-lib/mms-lib.pro b/mms-lib/mms-lib.pro index d611627..4de9c55 100644 --- a/mms-lib/mms-lib.pro +++ b/mms-lib/mms-lib.pro @@ -1,7 +1,7 @@ TEMPLATE = lib CONFIG += staticlib CONFIG += link_pkgconfig -PKGCONFIG += glib-2.0 libsoup-2.4 libwspcodec +PKGCONFIG += gmime-2.6 glib-2.0 libsoup-2.4 libwspcodec INCLUDEPATH += include QMAKE_CFLAGS += -Wno-unused diff --git a/mms-lib/src/mms_codec.c b/mms-lib/src/mms_codec.c index a7234ac..4a3bf14 100644 --- a/mms-lib/src/mms_codec.c +++ b/mms-lib/src/mms_codec.c @@ -3,7 +3,7 @@ * Multimedia Messaging Service * * Copyright (C) 2010-2011 Intel Corporation. All rights reserved. - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2015 Jolla Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -501,6 +501,7 @@ static gboolean extract_text(struct wsp_header_iter *iter, void *user) if (text == NULL) return FALSE; + g_free(*out); *out = g_strdup(text); return TRUE; @@ -1261,24 +1262,29 @@ static gboolean attachment_parse_headers(struct wsp_header_iter *iter, { while (wsp_header_iter_next(iter)) { const unsigned char *hdr = wsp_header_iter_get_hdr(iter); - unsigned char h; - - /* Skip application headers */ - if (wsp_header_iter_get_hdr_type(iter) != - WSP_HEADER_TYPE_WELL_KNOWN) - continue; - - h = hdr[0] & 0x7f; - switch (h) { - case MMS_PART_HEADER_CONTENT_ID: - if (!extract_quoted_string(iter, &part->content_id)) - return FALSE; - break; - case MMS_PART_HEADER_CONTENT_LOCATION: - if (!extract_text(iter, &part->content_location)) - return FALSE; - break; + if (wsp_header_iter_get_hdr_type(iter) == + WSP_HEADER_TYPE_WELL_KNOWN) { + switch (hdr[0] & 0x7f) { + case MMS_PART_HEADER_CONTENT_ID: + if (!extract_quoted_string(iter, + &part->content_id)) + return FALSE; + break; + case MMS_PART_HEADER_CONTENT_LOCATION: + if (!extract_text(iter, + &part->content_location)) + return FALSE; + break; + } + } else { + /* Application (textual) header */ + if (g_ascii_strcasecmp((char*)hdr, + "content-transfer-encoding") == 0) { + if (!extract_text(iter, + &part->transfer_encoding)) + return FALSE; + } } } @@ -1292,6 +1298,7 @@ static void free_attachment(gpointer data, gpointer user_data) g_free(attach->content_type); g_free(attach->content_id); g_free(attach->content_location); + g_free(attach->transfer_encoding); g_free(attach); } diff --git a/mms-lib/src/mms_codec.h b/mms-lib/src/mms_codec.h index 5f9c757..8d00684 100644 --- a/mms-lib/src/mms_codec.h +++ b/mms-lib/src/mms_codec.h @@ -3,6 +3,7 @@ * Multimedia Messaging Service * * Copyright (C) 2010-2011 Intel Corporation. All rights reserved. + * Copyright (C) 2013-2015 Jolla Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -185,6 +186,7 @@ struct mms_attachment { char *content_type; char *content_id; char *content_location; + char *transfer_encoding; }; struct mms_message { diff --git a/mms-lib/src/mms_file_util.c b/mms-lib/src/mms_file_util.c index f508928..41f8f16 100644 --- a/mms-lib/src/mms_file_util.c +++ b/mms-lib/src/mms_file_util.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2015 Jolla Ltd. + * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -222,6 +223,123 @@ mms_file_copy( return ok; } +/* + * MIME decoding + */ +typedef struct mms_mime_decode { + int out; + const char* dest; + size_t outbytes; + size_t outbuflen; + void* outbuf; + GMimeEncoding state; +} MMSMimeDecode; + +static +gboolean +mms_file_decode_init( + MMSMimeDecode* dec, + const char* dest, + GMimeContentEncoding enc, + GError** error) +{ + memset(dec, 0, sizeof(*dec)); + dec->out = open(dest, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, MMS_FILE_PERM); + if (dec->out >= 0) { + dec->dest = dest; + g_mime_encoding_init_decode(&dec->state, enc); + return TRUE; + } else { + MMS_ERROR(error, MMS_LIB_ERROR_IO, "Failed to create file %s: %s", + dest, strerror(errno)); + return FALSE; + } +} + +static +void +mms_file_decode_deinit( + MMSMimeDecode* dec) +{ + g_free(dec->outbuf); + close(dec->out); +} + +gboolean +mms_file_decode_step( + MMSMimeDecode* dec, + const void* inbuf, + size_t inlen, + size_t (*step)(GMimeEncoding*, const char*, size_t, char*), + GError** error) +{ + ssize_t nbytes; + size_t need = g_mime_encoding_outlen(&dec->state, inlen); + if (need > dec->outbuflen) { + g_free(dec->outbuf); + dec->outbuf = g_malloc(need); + dec->outbuflen = need; + } + nbytes = step(&dec->state, inbuf, inlen, dec->outbuf); + if (write(dec->out, dec->outbuf, nbytes) == nbytes) { + dec->outbytes += nbytes; + return TRUE; + } else { + MMS_ERROR(error, MMS_LIB_ERROR_IO, "Failed to write %s: %s", + dec->dest, strerror(errno)); + return FALSE; + } +} + +gboolean +mms_file_decode( + const char* src, + const char* dest, + GMimeContentEncoding enc, + GError** error) +{ + gboolean ok = FALSE; + int in = open(src, O_RDONLY | O_BINARY); + if (in >= 0) { + MMSMimeDecode dec; + if (mms_file_decode_init(&dec, dest, enc, error)) { + int nbytes; + size_t inbytes = 0; + const size_t buflen = 1024; + void* inbuf = g_malloc(buflen); + ok = TRUE; + while ((nbytes = read(in, inbuf, buflen)) > 0) { + inbytes += nbytes; + if (!mms_file_decode_step(&dec, inbuf, nbytes, + g_mime_encoding_step, error)) { + ok = FALSE; + break; + } + } + if (nbytes < 0) { + ok = FALSE; + MMS_ERROR(error, MMS_LIB_ERROR_IO, + "Failed to read %s: %s", src, strerror(errno)); + } else if (ok) { + if (mms_file_decode_step(&dec, NULL, 0, + g_mime_encoding_flush, error)) { + MMS_DEBUG("Decoded %s (%d bytes) -> %s (%d bytes)", + src, (int)inbytes, dest, (int)dec.outbytes); + } else { + ok = FALSE; + } + } + mms_file_decode_deinit(&dec); + g_free(inbuf); + } + close(in); + } else { + MMS_ERROR(error, MMS_LIB_ERROR_IO, + "Failed to open file %s: %s", src, strerror(errno)); + } + return ok; +} + /* * Local Variables: * mode: C diff --git a/mms-lib/src/mms_file_util.h b/mms-lib/src/mms_file_util.h index 45dccd9..d5d2d77 100644 --- a/mms-lib/src/mms_file_util.h +++ b/mms-lib/src/mms_file_util.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2015 Jolla Ltd. + * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -17,6 +18,8 @@ #include "mms_lib_types.h" +#include + /* Permissions for MMS files and directories */ #define MMS_DIR_PERM (0755) #define MMS_FILE_PERM (0644) @@ -75,6 +78,13 @@ mms_file_copy( const char* dest, GError** error); +gboolean +mms_file_decode( + const char* src, + const char* dest, + GMimeContentEncoding enc, + GError** error); + #define mms_message_dir(config,id) \ (g_strconcat((config)->root_dir, "/" MMS_MESSAGE_DIR "/" , id, NULL)) #define mms_task_dir(task) \ diff --git a/mms-lib/src/mms_message.c b/mms-lib/src/mms_message.c index 6ec8836..b6628eb 100644 --- a/mms-lib/src/mms_message.c +++ b/mms-lib/src/mms_message.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2015 Jolla Ltd. + * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -33,6 +34,10 @@ mms_message_part_free( if (!(msg->flags & MMS_MESSAGE_FLAG_KEEP_FILES)) remove(part->file); g_free(part->file); } + if (part->orig) { + if (!(msg->flags & MMS_MESSAGE_FLAG_KEEP_FILES)) remove(part->orig); + g_free(part->orig); + } g_free(part); } diff --git a/mms-lib/src/mms_task_decode.c b/mms-lib/src/mms_task_decode.c index b556edd..96ac2bd 100644 --- a/mms-lib/src/mms_task_decode.c +++ b/mms-lib/src/mms_task_decode.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2015 Jolla Ltd. + * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -54,7 +55,7 @@ mms_task_decode_array_contains_string( } static -char* +const char* mms_task_decode_add_file_name( GPtrArray* names, const char* proposed) @@ -100,6 +101,42 @@ mms_task_decode_make_content_id( return id; } +static +void +mms_task_decode_part( + MMSMessagePart* part, + GMimeContentEncoding enc, + const char* dir, + GPtrArray* part_files) +{ + char* default_name; + const char* orig_file; + const char* part_file; + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + part_file = g_basename(part->file); + G_GNUC_END_IGNORE_DEPRECATIONS; + + default_name = g_strconcat(part_file, ".orig", NULL); + orig_file = mms_task_decode_add_file_name(part_files, default_name); + g_free(default_name); + + part->orig = g_strconcat(dir, "/", orig_file, NULL); + if (rename(part->file, part->orig) == 0) { + GError* error = NULL; + if (!mms_file_decode(part->orig, part->file, enc, &error)) { + unlink(part->file); + rename(part->orig, part->file); + g_free(part->orig); + part->orig = NULL; + MMS_ERR("%s", MMS_ERRMSG(error)); + g_error_free(error); + } + } else { + MMS_ERR("Failed to rename %s to %s: %s", part->file, part->orig, + strerror(errno)); + } +} + static MMSMessage* mms_task_decode_retrieve_conf( @@ -169,7 +206,7 @@ mms_task_decode_retrieve_conf( const char* name = attach->content_location ? attach->content_location : attach->content_id; char* path = NULL; - char* file; + const char* file; if (name && name[0]) { file = mms_task_decode_add_file_name(part_files, name); } else { @@ -188,6 +225,16 @@ mms_task_decode_retrieve_conf( part->content_type = g_strdup(attach->content_type); part->content_id = mms_task_decode_make_content_id(part_ids, id); part->file = path; + if (attach->transfer_encoding) { + GMimeContentEncoding enc = + g_mime_content_encoding_from_string( + attach->transfer_encoding); + if (enc > GMIME_CONTENT_ENCODING_BINARY) { + /* The part actually needs some decoding */ + MMS_DEBUG("Decoding %s", attach->transfer_encoding); + mms_task_decode_part(part,enc,msg->parts_dir,part_files); + } + } msg->parts = g_slist_append(msg->parts, part); if (tmp && tmp != part->content_id) g_free(tmp); } diff --git a/mms-lib/test/common/Makefile b/mms-lib/test/common/Makefile index abdfbbb..9389faf 100644 --- a/mms-lib/test/common/Makefile +++ b/mms-lib/test/common/Makefile @@ -25,7 +25,7 @@ include ../../Config.mak # Required packages # -PKGS += glib-2.0 libsoup-2.4 +PKGS += gmime-2.6 glib-2.0 libsoup-2.4 LIB_PKGS += $(PKGS) libwspcodec $(RESIZE_PKG) # diff --git a/mms-lib/test/test_retrieve/data/Base64/m-acknowledge.ind b/mms-lib/test/test_retrieve/data/Base64/m-acknowledge.ind new file mode 100644 index 0000000..1ae3721 Binary files /dev/null and b/mms-lib/test/test_retrieve/data/Base64/m-acknowledge.ind differ diff --git a/mms-lib/test/test_retrieve/data/Base64/m-notification.ind b/mms-lib/test/test_retrieve/data/Base64/m-notification.ind new file mode 100644 index 0000000..02ffdcc Binary files /dev/null and b/mms-lib/test/test_retrieve/data/Base64/m-notification.ind differ diff --git a/mms-lib/test/test_retrieve/data/Base64/m-retrieve.conf b/mms-lib/test/test_retrieve/data/Base64/m-retrieve.conf new file mode 100644 index 0000000..467d762 Binary files /dev/null and b/mms-lib/test/test_retrieve/data/Base64/m-retrieve.conf differ diff --git a/mms-lib/test/test_retrieve/data/Base64/parts/1.jpg b/mms-lib/test/test_retrieve/data/Base64/parts/1.jpg new file mode 100644 index 0000000..be62e83 Binary files /dev/null and b/mms-lib/test/test_retrieve/data/Base64/parts/1.jpg differ diff --git a/mms-lib/test/test_retrieve/data/Base64/parts/2.txt b/mms-lib/test/test_retrieve/data/Base64/parts/2.txt new file mode 100644 index 0000000..7764f42 --- /dev/null +++ b/mms-lib/test/test_retrieve/data/Base64/parts/2.txt @@ -0,0 +1 @@ +Tämmönen 😈 tää lähtee huomenna. \ No newline at end of file diff --git a/mms-lib/test/test_retrieve/data/Base64/parts/2.txt.orig b/mms-lib/test/test_retrieve/data/Base64/parts/2.txt.orig new file mode 100644 index 0000000..ee68d01 --- /dev/null +++ b/mms-lib/test/test_retrieve/data/Base64/parts/2.txt.orig @@ -0,0 +1 @@ +VMOkbW3Dtm5lbiDwn5iIIHTDpMOkIGzDpGh0ZWUgaHVvbWVubmEuT \ No newline at end of file diff --git a/mms-lib/test/test_retrieve/data/Base64/parts/smil b/mms-lib/test/test_retrieve/data/Base64/parts/smil new file mode 100644 index 0000000..e84f43f --- /dev/null +++ b/mms-lib/test/test_retrieve/data/Base64/parts/smil @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/mms-lib/test/test_retrieve/data/InvalidSubject/parts/1 b/mms-lib/test/test_retrieve/data/InvalidSubject/parts/1 new file mode 100644 index 0000000..9aa5520 Binary files /dev/null and b/mms-lib/test/test_retrieve/data/InvalidSubject/parts/1 differ diff --git a/mms-lib/test/test_retrieve/data/InvalidSubject/parts/smil.smi b/mms-lib/test/test_retrieve/data/InvalidSubject/parts/smil.smi new file mode 100644 index 0000000..eeb4b57 --- /dev/null +++ b/mms-lib/test/test_retrieve/data/InvalidSubject/parts/smil.smi @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/mms-lib/test/test_retrieve/data/QuotedPrintable/m-acknowledge.ind b/mms-lib/test/test_retrieve/data/QuotedPrintable/m-acknowledge.ind new file mode 100644 index 0000000..1ae3721 Binary files /dev/null and b/mms-lib/test/test_retrieve/data/QuotedPrintable/m-acknowledge.ind differ diff --git a/mms-lib/test/test_retrieve/data/QuotedPrintable/m-notification.ind b/mms-lib/test/test_retrieve/data/QuotedPrintable/m-notification.ind new file mode 100644 index 0000000..02ffdcc Binary files /dev/null and b/mms-lib/test/test_retrieve/data/QuotedPrintable/m-notification.ind differ diff --git a/mms-lib/test/test_retrieve/data/QuotedPrintable/m-retrieve.conf b/mms-lib/test/test_retrieve/data/QuotedPrintable/m-retrieve.conf new file mode 100644 index 0000000..b8c5cb9 Binary files /dev/null and b/mms-lib/test/test_retrieve/data/QuotedPrintable/m-retrieve.conf differ diff --git a/mms-lib/test/test_retrieve/data/QuotedPrintable/parts/1.jpg b/mms-lib/test/test_retrieve/data/QuotedPrintable/parts/1.jpg new file mode 100644 index 0000000..be62e83 Binary files /dev/null and b/mms-lib/test/test_retrieve/data/QuotedPrintable/parts/1.jpg differ diff --git a/mms-lib/test/test_retrieve/data/QuotedPrintable/parts/2.txt b/mms-lib/test/test_retrieve/data/QuotedPrintable/parts/2.txt new file mode 100644 index 0000000..7764f42 --- /dev/null +++ b/mms-lib/test/test_retrieve/data/QuotedPrintable/parts/2.txt @@ -0,0 +1 @@ +Tämmönen 😈 tää lähtee huomenna. \ No newline at end of file diff --git a/mms-lib/test/test_retrieve/data/QuotedPrintable/parts/2.txt.orig b/mms-lib/test/test_retrieve/data/QuotedPrintable/parts/2.txt.orig new file mode 100644 index 0000000..5c51878 --- /dev/null +++ b/mms-lib/test/test_retrieve/data/QuotedPrintable/parts/2.txt.orig @@ -0,0 +1 @@ +T=C3=A4mm=C3=B6nen =F0=9F=98=88 t=C3=A4=C3=A4 l=C3=A4htee huomenna. \ No newline at end of file diff --git a/mms-lib/test/test_retrieve/data/QuotedPrintable/parts/smil b/mms-lib/test/test_retrieve/data/QuotedPrintable/parts/smil new file mode 100644 index 0000000..e84f43f --- /dev/null +++ b/mms-lib/test/test_retrieve/data/QuotedPrintable/parts/smil @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/mms-lib/test/test_retrieve/data/Success1/parts/0 b/mms-lib/test/test_retrieve/data/Success1/parts/0.smil similarity index 100% rename from mms-lib/test/test_retrieve/data/Success1/parts/0 rename to mms-lib/test/test_retrieve/data/Success1/parts/0.smil diff --git a/mms-lib/test/test_retrieve/data/Success2/parts/2014_03_.jpg b/mms-lib/test/test_retrieve/data/Success2/parts/2014_03_.jpg new file mode 100644 index 0000000..7c82150 Binary files /dev/null and b/mms-lib/test/test_retrieve/data/Success2/parts/2014_03_.jpg differ diff --git a/mms-lib/test/test_retrieve/data/Success2/parts/332047400 b/mms-lib/test/test_retrieve/data/Success2/parts/332047400 new file mode 100644 index 0000000..1fc57eb --- /dev/null +++ b/mms-lib/test/test_retrieve/data/Success2/parts/332047400 @@ -0,0 +1 @@ + diff --git a/mms-lib/test/test_retrieve/data/Success2/parts/Test_mms.txt b/mms-lib/test/test_retrieve/data/Success2/parts/Test_mms.txt new file mode 100644 index 0000000..76e4db8 --- /dev/null +++ b/mms-lib/test/test_retrieve/data/Success2/parts/Test_mms.txt @@ -0,0 +1 @@ +Test mms msg \ No newline at end of file diff --git a/mms-lib/test/test_retrieve/test_retrieve.c b/mms-lib/test/test_retrieve/test_retrieve.c index 5f4a1d1..57415c6 100644 --- a/mms-lib/test/test_retrieve/test_retrieve.c +++ b/mms-lib/test/test_retrieve/test_retrieve.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2015 Jolla Ltd. + * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -97,6 +98,12 @@ static const TestPartDesc retrieve_success3_parts [] = { { "text/plain;charset=utf-8", "<2>", "text_001.txt" } }; +static const TestPartDesc retrieve_transfer_encoding_parts [] = { + { "application/smil;charset=utf-8", "", "smil" }, + { "image/jpeg", "<1.jpg>", "1.jpg" }, + { "text/plain;charset=utf-8", "<2.txt>", "2.txt" } +}; + static const TestPartDesc retrieve_invalid_subject [] = { { "application/smil;charset=us-ascii", "", "smil.smi" }, { "image/jpeg", "<1>", "1" } @@ -142,6 +149,30 @@ static const TestDesc retrieve_tests[] = { MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND, TEST_PARTS(retrieve_success3_parts), 0 + },{ + "QuotedPrintable", /* quoted-printable transfer encoding for text */ + NULL, + "m-notification.ind", + "m-retrieve.conf", + SOUP_STATUS_OK, + MMS_CONTENT_TYPE, + NULL, + MMS_RECEIVE_STATE_DECODING, + MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND, + TEST_PARTS(retrieve_transfer_encoding_parts), + 0 + },{ + "Base64", /* Base64 transfer encoding for text */ + NULL, + "m-notification.ind", + "m-retrieve.conf", + SOUP_STATUS_OK, + MMS_CONTENT_TYPE, + NULL, + MMS_RECEIVE_STATE_DECODING, + MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND, + TEST_PARTS(retrieve_transfer_encoding_parts), + 0 },{ "InvalidSubject", NULL, @@ -313,6 +344,36 @@ static const TestDesc retrieve_tests[] = { } }; +static +gboolean +test_files_equal( + const char* path1, + const char* path2) +{ + gboolean equal = FALSE; + if (path1 && path2) { + GError* error = NULL; + GMappedFile* f1 = g_mapped_file_new(path1, FALSE, &error); + if (f1) { + GMappedFile* f2 = g_mapped_file_new(path2, FALSE, &error); + if (f2) { + const gsize size = g_mapped_file_get_length(f1); + if (g_mapped_file_get_length(f2) == size) { + const void* data1 = g_mapped_file_get_contents(f1); + const void* data2 = g_mapped_file_get_contents(f2); + equal = !memcmp(data1, data2, size); + } + g_mapped_file_unref(f2); + } + g_mapped_file_unref(f1); + } + } + if (!equal) { + MMS_ERR("%s is not identical to %s", path1, path2); + } + return equal; +} + static int test_validate_parts( @@ -323,16 +384,28 @@ test_validate_parts( if (!desc->nparts && (!msg || !g_slist_length(msg->parts))) { return RET_OK; } else { + const char* dir = desc->dir ? desc->dir : desc->name; const unsigned int nparts = g_slist_length(msg->parts); if (desc->nparts == nparts) { const TestPartDesc* expect = test->desc->parts; GSList* list = msg->parts; while (list) { const MMSMessagePart* part = list->data; + char* sample = g_strconcat(DATA_DIR, dir, "/parts/", + expect->file_name, NULL); + const gboolean match = test_files_equal(part->file, sample); const char* fname; + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; fname = g_basename(part->file); G_GNUC_END_IGNORE_DEPRECATIONS; + + g_free(sample); + if (!match) { + /* Message message is printed by test_files_equal */ + return RET_ERR; + } + if (strcmp(expect->content_type, part->content_type)) { MMS_ERR("Content type mismatch: expected %s, got %s", expect->content_type, part->content_type); @@ -352,7 +425,7 @@ test_validate_parts( expect->content_id, part->content_id); return RET_ERR; } - list = list->next; + list = list->next; expect++; } return RET_OK; @@ -408,33 +481,17 @@ test_finish( } } if (test->ret == RET_OK && desc->attic_file) { - gboolean ok = FALSE; const char* dir = desc->dir ? desc->dir : desc->name; char* f1 = g_strconcat(DATA_DIR, dir, "/", desc->ni_file, NULL); char* f2 = g_strconcat(test->config->root_dir, "/" MMS_ATTIC_DIR "/", desc->attic_file, NULL); - GMappedFile* m1 = g_mapped_file_new(f1, FALSE, NULL); - if (m1) { - GMappedFile* m2 = g_mapped_file_new(f2, FALSE, NULL); - if (m2) { - const gsize len = g_mapped_file_get_length(m1); - if (len == g_mapped_file_get_length(m2)) { - const void* ptr1 = g_mapped_file_get_contents(m1); - const void* ptr2 = g_mapped_file_get_contents(m2); - ok = !memcmp(ptr1, ptr2, len); - } - g_mapped_file_unref(m2); - } - g_mapped_file_unref(m1); - } - if (ok) { + if (test_files_equal(f1, f2)) { char* dir = g_path_get_dirname(f2); remove(f2); rmdir(dir); g_free(dir); } else { test->ret = RET_ERR; - MMS_ERR("%s is not identical to %s", f2, f1); } g_free(f1); g_free(f2); @@ -691,6 +748,7 @@ int main(int argc, char* argv[]) MMSConfig config; const char* test_name = (argc == 2) ? argv[1] : NULL; char* tmpd = g_mkdtemp(g_strdup("/tmp/test_retrieve_XXXXXX")); + char* msgdir = g_strconcat(tmpd, "/msg", NULL); MMS_VERBOSE("Temporary directory %s", tmpd); mms_lib_default_config(&config); @@ -721,7 +779,9 @@ int main(int argc, char* argv[]) } } - remove(tmpd); + rmdir(msgdir); + rmdir(tmpd); + g_free(msgdir); g_free(tmpd); } else { fprintf(stderr, "%s\n", MMS_ERRMSG(error)); diff --git a/rpm/mms-engine.spec b/rpm/mms-engine.spec index 9cc319d..a04d62f 100644 --- a/rpm/mms-engine.spec +++ b/rpm/mms-engine.spec @@ -16,6 +16,7 @@ BuildRequires: libjpeg-turbo-devel BuildRequires: pkgconfig(dconf) BuildRequires: pkgconfig(libpng) BuildRequires: pkgconfig(libexif) +BuildRequires: pkgconfig(gmime-2.6) BuildRequires: pkgconfig(glib-2.0) >= 2.32 BuildRequires: pkgconfig(libsoup-2.4) >= 2.38 BuildRequires: pkgconfig(libwspcodec) >= 2.2