diff --git a/configure.ac b/configure.ac index 0ad62615..ab1fca7a 100644 --- a/configure.ac +++ b/configure.ac @@ -122,6 +122,16 @@ AC_SUBST(WEBKIT_CFLAGS) AC_SUBST(WEBKIT_LIBS) AM_CONDITIONAL(HAVE_WEBKIT, [test "x$have_webkit" = "xyes"]) +# gio is needed for some widget/ things +PKG_CHECK_MODULES(GIO,gio-2.0,[have_gio=yes],[have_gio=no]) +AS_IF([test "x$have_gio" = "xyes"],[ + gio_version="`pkg-config --modversion gio-2.0`"]) +AC_SUBST(GIO_CFLAGS) +AC_SUBST(GIO_LIBS) +AM_CONDITIONAL(HAVE_WEBKIT, [test "x$have_webkit" = "xyes"]) + +# should we build the widgets/ dir? +AM_CONDITIONAL(BUILD_WIDGETS, [test "x$have_webkit" = "xyes" -a "x$have_gio" = "xyes"]) # xapian? AC_CHECK_PROG(XAPIAN,xapian-config,xapian-config,no) @@ -183,6 +193,13 @@ if test "x$have_gtk2" = "xyes" -o "x$have_gtk3" = "xyes"; then else have_gtk="no" fi + +# check for xdg-open +AC_PATH_PROG(XDGOPEN, [xdg-open], [], [$PATH]) +AS_IF([test "x$XDGOPEN" != "x"],[ + AC_DEFINE_UNQUOTED([XDGOPEN], ["$XDGOPEN"],[Path to xdg-open])],[ + AC_MSG_WARN([xdg-open not found, mu cannot open attachments])]) + # check for pmccabe AC_PATH_PROG([PMCCABE],[pmccabe],[pmccabe],[no]) @@ -228,7 +245,11 @@ if test "x$have_gtk" != "xno"; then echo "GTK+ version : $gtk_version" fi -if test "x$have_webkit" != "xno"; then +if test "x$have_gio" = "xyes"; then +echo "GIO version : $gio_version" +fi + +if test "x$have_webkit" = "xyes"; then echo "Webkit version : $webkit_version" fi @@ -236,6 +257,7 @@ echo echo "Build unit tests (glib >= 2.22) : $have_gtest" echo "Build 'mug' (requires GTK+) : $have_gtk" echo "McCabe's Cyclomatic Complexity tool : $have_pmccabe" +echo "xdg-open : $XDGOPEN" echo echo "Have direntry->d_ino : $use_dirent_d_ino" diff --git a/man/mu-extract.1 b/man/mu-extract.1 index fa5b96c9..814e7dec 100644 --- a/man/mu-extract.1 +++ b/man/mu-extract.1 @@ -1,4 +1,4 @@ -.TH MU EXTRACT 1 "October 2010" "User Manuals" +.TH MU EXTRACT 1 "January 2011" "User Manuals" .SH NAME @@ -41,7 +41,14 @@ the current working directory. .TP \fB\-\-overwrite\fR -overwrite existing files with the same name. +overwrite existing files with the same name; by default overwriting is not +allowed. + +.TP +\fB\-\-play\fR +Try to 'play' (open) the attachment with the corresponding +application. Depends on the \fBxdg-open\fR utility. + .SH BUGS Please report bugs if you find them: @@ -54,4 +61,4 @@ Dirk-Jan C. Binnema .SH "SEE ALSO" -.BR mu(1) +.BR mu(1) xdg-open(1) diff --git a/src/mu-cmd.c b/src/mu-cmd.c index ee93144d..67c7417f 100644 --- a/src/mu-cmd.c +++ b/src/mu-cmd.c @@ -52,7 +52,7 @@ save_numbered_parts (MuMsg *msg, MuConfig *opts) } if (!mu_msg_mime_part_save - (msg, idx, opts->targetdir, opts->overwrite)) { + (msg, idx, opts->targetdir, opts->overwrite, opts->play)) { g_warning ("failed to save MIME-part %d", idx); rv = FALSE; break; @@ -71,6 +71,7 @@ struct _SaveData { guint saved_num; const gchar* targetdir; gboolean overwrite; + gboolean play; }; typedef struct _SaveData SaveData; @@ -97,7 +98,7 @@ save_part_if (MuMsgPart *part, SaveData *sd) return; sd->result = mu_msg_mime_part_save (sd->msg, part->index, - sd->targetdir, sd->overwrite); + sd->targetdir, sd->overwrite, sd->play); if (!sd->result) g_warning ("failed to save MIME-part %u", part->index); else @@ -107,7 +108,7 @@ save_part_if (MuMsgPart *part, SaveData *sd) static gboolean save_certain_parts (MuMsg *msg, gboolean attachments_only, - const gchar *targetdir, gboolean overwrite) + const gchar *targetdir, gboolean overwrite, gboolean play) { SaveData sd; @@ -117,6 +118,7 @@ save_certain_parts (MuMsg *msg, gboolean attachments_only, sd.attachments_only = attachments_only; sd.overwrite = overwrite; sd.targetdir = targetdir; + sd.play = play; mu_msg_msg_part_foreach (msg, (MuMsgPartForeachFunc)save_part_if, @@ -155,10 +157,12 @@ save_parts (const char *path, MuConfig *opts) rv = save_numbered_parts (msg, opts); else if (opts->save_attachments) /* all attachments */ rv = save_certain_parts (msg, TRUE, - opts->targetdir, opts->overwrite); + opts->targetdir, opts->overwrite, + opts->play); else if (opts->save_all) /* all parts */ rv = save_certain_parts (msg, FALSE, - opts->targetdir, opts->overwrite); + opts->targetdir, opts->overwrite, + opts->play); else g_assert_not_reached (); @@ -196,7 +200,6 @@ show_parts (const char* path, MuConfig *opts) g_print ("MIME-parts in this message:\n"); mu_msg_msg_part_foreach (msg, each_part_show, NULL); - mu_msg_destroy (msg); return TRUE; @@ -206,7 +209,7 @@ show_parts (const char* path, MuConfig *opts) static gboolean check_params (MuConfig *opts) { - if (!opts->params[1]) { + if (!opts->params[1] || opts->params[2]) { g_warning ("usage: mu extract [options] "); return FALSE; } diff --git a/src/mu-config.c b/src/mu-config.c index 37f19345..a6b0c985 100644 --- a/src/mu-config.c +++ b/src/mu-config.c @@ -219,6 +219,8 @@ config_options_group_extract(MuConfig *opts) "target directory for saving", NULL}, {"overwrite", 0, 0, G_OPTION_ARG_NONE, &opts->overwrite, "overwrite existing files (false)", NULL}, + {"play", 0, 0, G_OPTION_ARG_NONE, &opts->play, + "try to 'play' (open) the extracted parts", NULL}, {NULL, 0, 0, 0, NULL, NULL, NULL} }; diff --git a/src/mu-config.h b/src/mu-config.h index 2cef1b26..3d6c1cff 100644 --- a/src/mu-config.h +++ b/src/mu-config.h @@ -98,9 +98,10 @@ struct _MuConfig { gboolean *save_all; /* extract all parts */ gboolean *save_attachments; /* extract all attachment parts */ gchar *parts; /* comma-sep'd list of parts - * to save */ + * to save / open */ char *targetdir; /* where to save the attachments */ gboolean overwrite; /* should we overwrite same-named files */ + gboolean play; /* after saving, try to play (open) the attmnt */ }; typedef struct _MuConfig MuConfig; diff --git a/src/mu-msg-part.c b/src/mu-msg-part.c index ba57f5fb..b841e4d6 100644 --- a/src/mu-msg-part.c +++ b/src/mu-msg-part.c @@ -1,5 +1,5 @@ /* -** Copyright (C) 2008-2010 Dirk-Jan C. Binnema +** Copyright (C) 2008-2011 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify it ** under the terms of the GNU General Public License as published by the @@ -17,7 +17,7 @@ ** */ -#ifdef HAVE_CONFIG_H +#if HAVE_CONFIG_H #include "config.h" #endif /*HAVE_CONFIG_H*/ @@ -29,169 +29,201 @@ #include "mu-msg-part.h" struct _PartData { - unsigned _idx; - MuMsgPartForeachFunc _func; - gpointer _user_data; + unsigned _idx; + MuMsgPartForeachFunc _func; + gpointer _user_data; }; -typedef struct _PartData PartData; +typedef struct _PartData PartData; static void part_foreach_cb (GMimeObject *parent, GMimeObject *part, PartData *pdata) { - GMimeContentType *ct; - MuMsgPart pi; + GMimeContentType *ct; + MuMsgPart pi; - memset (&pi, 0, sizeof pi); - pi.index = pdata->_idx++; - pi.content_id = (char*)g_mime_object_get_content_id (part); + memset (&pi, 0, sizeof pi); + pi.index = pdata->_idx++; + pi.content_id = (char*)g_mime_object_get_content_id (part); - ct = g_mime_object_get_content_type (part); - if (GMIME_IS_CONTENT_TYPE(ct)) { - pi.type = (char*)g_mime_content_type_get_media_type (ct); - pi.subtype = (char*)g_mime_content_type_get_media_subtype (ct); - } + ct = g_mime_object_get_content_type (part); + if (GMIME_IS_CONTENT_TYPE(ct)) { + pi.type = (char*)g_mime_content_type_get_media_type (ct); + pi.subtype = (char*)g_mime_content_type_get_media_subtype (ct); + } - if (GMIME_IS_PART(part)) { - pi.disposition = (char*)g_mime_object_get_disposition (part); - pi.file_name = (char*)g_mime_part_get_filename (GMIME_PART(part)); - } + if (GMIME_IS_PART(part)) { + pi.disposition = (char*)g_mime_object_get_disposition (part); + pi.file_name = (char*)g_mime_part_get_filename (GMIME_PART(part)); + } - pdata->_func(&pi, pdata->_user_data); + pdata->_func(&pi, pdata->_user_data); } void mu_msg_msg_part_foreach (MuMsg *msg, - MuMsgPartForeachFunc func, - gpointer user_data) + MuMsgPartForeachFunc func, + gpointer user_data) { - PartData pdata; + PartData pdata; - g_return_if_fail (msg); - g_return_if_fail (GMIME_IS_OBJECT(msg->_mime_msg)); + g_return_if_fail (msg); + g_return_if_fail (GMIME_IS_OBJECT(msg->_mime_msg)); - pdata._idx = 0; - pdata._func = func; - pdata._user_data = user_data; + pdata._idx = 0; + pdata._func = func; + pdata._user_data = user_data; - g_mime_message_foreach (msg->_mime_msg, - (GMimeObjectForeachFunc)part_foreach_cb, - &pdata); + g_mime_message_foreach (msg->_mime_msg, + (GMimeObjectForeachFunc)part_foreach_cb, + &pdata); } struct _SavePartData { - guint idx, wanted_idx; - const gchar* targetdir; - gboolean overwrite; - gboolean stream; - guint cookie; - gboolean result; + guint idx, wanted_idx; + const gchar* targetdir; + gboolean overwrite; + gboolean stream; + guint cookie; + gboolean result; + gboolean play; }; typedef struct _SavePartData SavePartData; static gboolean -save_part (GMimeObject *part, const char *filename, - const char *targetdir, gboolean overwrite) +write_to_stream (GMimeObject *part, int fd) { - int fd, rv; - GMimeDataWrapper *wrapper; - GMimeStream *stream; - - rv = TRUE; - fd = mu_util_create_writeable_fd (filename, targetdir, - overwrite); - if (fd == -1) { - g_warning ("error saving file %s%s %s", - filename, errno != 0 ? ":" : "", - errno != 0 ? strerror(errno) : ""); - return FALSE; - } - - stream = g_mime_stream_fs_new (fd); - if (!stream) { - g_critical ("%s: failed to create stream", __FUNCTION__); - close (fd); - return FALSE; - } + GMimeStream *stream; + GMimeDataWrapper *wrapper; + gboolean rv; + + stream = g_mime_stream_fs_new (fd); + if (!stream) { + g_critical ("%s: failed to create stream",__FUNCTION__); + return FALSE; + } + g_mime_stream_fs_set_owner (GMIME_STREAM_FS(stream), FALSE); + + wrapper = g_mime_part_get_content_object (GMIME_PART(part)); + if (!wrapper) { + g_critical ("%s: failed to create wrapper", __FUNCTION__); + g_object_unref (stream); + return FALSE; + } + g_object_ref (part); /* FIXME: otherwise, the unrefs below + * give errors...*/ + + rv = g_mime_data_wrapper_write_to_stream (wrapper, stream); + if (!rv) + g_critical ("%s: failed to write to stream", __FUNCTION__); + + g_object_unref (wrapper); + g_object_unref (stream); + + return rv; +} - /* GMimeStream will close the fd */ - g_mime_stream_fs_set_owner (GMIME_STREAM_FS(stream), TRUE); - - if (!(wrapper = g_mime_part_get_content_object (GMIME_PART(part)))) { - g_object_unref (G_OBJECT(stream)); - g_critical ("%s: failed to create wrapper", __FUNCTION__); - return FALSE; - } - - rv = g_mime_data_wrapper_write_to_stream (wrapper, stream); - g_object_unref (G_OBJECT(stream)); - return rv == -1 ? FALSE : TRUE; +static gboolean +save_part (GMimeObject *part, const char *filename, + const char *targetdir, gboolean overwrite, gboolean tryplay) +{ + int fd; + char *fullpath; + gboolean rv; + + fullpath = g_strdup_printf ("%s%s%s", + targetdir ? targetdir : "", + targetdir ? G_DIR_SEPARATOR_S : "", + filename); + + fd = mu_util_create_writeable_fd (fullpath, 0600, overwrite); + if (fd == -1) { + g_free (fullpath); + return FALSE; + } + + rv = write_to_stream (part, fd); + if (close (fd) != 0) + g_warning ("%s: failed to close %s: %s", __FUNCTION__, + fullpath, strerror(errno)); + + if (rv && tryplay) { + rv = mu_util_play (fullpath); + if (!rv) + g_warning ("%s: failed to play %s", __FUNCTION__, + fullpath); + } + + return rv; } static void part_foreach_save_cb (GMimeObject *parent, GMimeObject *part, - SavePartData *spd) + SavePartData *spd) { - const gchar* filename; + const gchar* filename; - /* did we find the right part yet? */ - if (spd->result || spd->wanted_idx != spd->idx++) - return; + /* did we find the right part yet? */ + if (spd->result || spd->wanted_idx != spd->idx++) + return; - if (!GMIME_IS_PART(part)) /* ie., multiparts are ignored */ - return; + if (!GMIME_IS_PART(part)) /* ie., multiparts are ignored */ + return; - filename = g_mime_part_get_filename (GMIME_PART(part)); - if (filename) { - spd->result = save_part (part, filename, - spd->targetdir, - spd->overwrite); - } else { /* make up a filename */ - gchar *my_filename; - my_filename = g_strdup_printf ("%x-part-%u", - spd->cookie, - spd->wanted_idx); - spd->result = save_part (part, my_filename, - spd->targetdir, - spd->overwrite); - g_free (my_filename); - } + filename = g_mime_part_get_filename (GMIME_PART(part)); + if (filename) { + spd->result = save_part (part, filename, + spd->targetdir, + spd->overwrite, + spd->play); + } else { /* make up a filename */ + gchar *my_filename; + my_filename = g_strdup_printf ("%x-part-%u", + spd->cookie, + spd->wanted_idx); + spd->result = save_part (part, my_filename, + spd->targetdir, + spd->overwrite, + spd->play); + g_free (my_filename); + } } gboolean mu_msg_mime_part_save (MuMsg *msg, unsigned wanted_idx, - const char *targetdir, gboolean overwrite) + const char *targetdir, gboolean overwrite, gboolean play) { - SavePartData spd; - const char *msgid; + SavePartData spd; + const char *msgid; - g_return_val_if_fail (msg, FALSE); + g_return_val_if_fail (msg, FALSE); - spd.idx = 0; - spd.wanted_idx = wanted_idx; - spd.targetdir = targetdir; - spd.overwrite = overwrite; - spd.stream = FALSE; /* not used yet */ - spd.result = FALSE; + spd.idx = 0; + spd.wanted_idx = wanted_idx; + spd.targetdir = targetdir; + spd.overwrite = overwrite; + spd.stream = FALSE; /* not used yet */ + spd.result = FALSE; + spd.play = play; - /* get something fairly unique for building a filename; - * normally based on the message id, but if that is not - * available, a random number. basing it on the message id - * gives makes it easy to distinguish the parts of different - * messages */ - msgid = mu_msg_get_msgid (msg); - spd.cookie = (guint)(msgid ? g_str_hash (msgid) : (guint)random()); + /* get something fairly unique for building a filename; + * normally based on the message id, but if that is not + * available, a random number. basing it on the message id + * gives makes it easy to distinguish the parts of different + * messages */ + msgid = mu_msg_get_msgid (msg); + spd.cookie = (guint)(msgid ? g_str_hash (msgid) : (guint)random()); - g_mime_message_foreach (msg->_mime_msg, - (GMimeObjectForeachFunc)part_foreach_save_cb, - &spd); - return spd.result; + g_mime_message_foreach (msg->_mime_msg, + (GMimeObjectForeachFunc)part_foreach_save_cb, + &spd); + return spd.result; } diff --git a/src/mu-msg.h b/src/mu-msg.h index 2e5cea59..dafb31ca 100644 --- a/src/mu-msg.h +++ b/src/mu-msg.h @@ -27,18 +27,6 @@ G_BEGIN_DECLS -/* what kind of message is this; use by the indexer */ -enum _MuMsgStatus { - MU_MSG_STATUS_NEW, /* message is new */ - MU_MSG_STATUS_UPDATE, /* message is to be updated */ - MU_MSG_STATUS_CLEANUP, /* message is to be cleaned up from db */ - MU_MSG_STATUS_CLEANED_UP, /* message has been cleaned up from db */ - MU_MSG_STATUS_EXISTS, /* message exists (will not be cleaned up) */ - MU_MSG_STATUS_UPTODATE /* message is up-to-date */ -}; -typedef enum _MuMsgStatus MuMsgStatus; - - struct _MuMsg; typedef struct _MuMsg MuMsg; @@ -131,11 +119,13 @@ const char* mu_msg_get_summary (MuMsg *msg, size_t max_lines); * @param wanted_idx index of the attachment you want to save * @param targetdir filesystem directory to save the attachment * @param overwrite existing files? + * @param try to 'play' (open) the saved mime-part after saving * * @return TRUE if saving succeeded, FALSE otherwise */ gboolean mu_msg_mime_part_save (MuMsg *msg, unsigned wanted_idx, - const char *targetdir, gboolean overwrite); + const char *targetdir, gboolean overwrite, + gboolean tryplay); /** * get the sender (From:) of this message diff --git a/src/mu-util.c b/src/mu-util.c index 11698224..c2d3ac3f 100644 --- a/src/mu-util.c +++ b/src/mu-util.c @@ -1,6 +1,6 @@ /* ** -** Copyright (C) 2008-2010 Dirk-Jan C. Binnema +** Copyright (C) 2008-2011 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -18,7 +18,7 @@ ** */ -#ifdef HAVE_CONFIG_H +#if HAVE_CONFIG_H #include #endif /*HAVE_CONFIG_H*/ @@ -248,33 +248,59 @@ mu_util_str_from_strv (const gchar **params) } int -mu_util_create_writeable_fd (const char* filename, const char* dir, +mu_util_create_writeable_fd (const char* path, mode_t mode, gboolean overwrite) { int fd; - char *fullpath; errno = 0; /* clear! */ - g_return_val_if_fail (filename, -1); - - fullpath = g_strdup_printf ("%s%s%s", - dir ? dir : "", - dir ? G_DIR_SEPARATOR_S : "", - filename); - + g_return_val_if_fail (path, -1); + if (overwrite) - fd = open (fullpath, O_WRONLY|O_CREAT|O_TRUNC, 0644); + fd = open (path, O_WRONLY|O_CREAT|O_TRUNC, mode); else - fd = open (fullpath, O_WRONLY|O_CREAT, 0644); + fd = open (path, O_WRONLY|O_CREAT|O_EXCL, mode); if (fd < 0) - g_debug ("%s: cannot open %s for writing: %s", - __FUNCTION__, fullpath, strerror(errno)); - - g_free (fullpath); + g_warning ("%s: cannot open %s for writing: %s", + __FUNCTION__, path, strerror(errno)); + return fd; } +gboolean +mu_util_play (const char *path) +{ +#ifndef XDGOPEN + g_warning ("opening files not supported (xdg-open missing)"); + return FALSE; +#else + gboolean rv; + GError *err; + const gchar *argv[3]; + + g_return_val_if_fail (path, FALSE); + g_return_val_if_fail (access (path, R_OK) == 0, FALSE); + + argv[0] = XDGOPEN; + argv[1] = path; + argv[2] = NULL; + + err = NULL; + rv = g_spawn_async (NULL, (gchar**)&argv, NULL, 0, + NULL, NULL, NULL, &err); + + if (!rv) { + g_warning ("failed to spawn xdg-open: %s", + err->message ? err->message : "error"); + g_error_free (err); + } + + return rv; +#endif /*XDGOPEN*/ +} + + unsigned char mu_util_get_dtype_with_lstat (const char *path) { diff --git a/src/mu-util.h b/src/mu-util.h index 60a9f4e8..3ab0711d 100644 --- a/src/mu-util.h +++ b/src/mu-util.h @@ -22,6 +22,7 @@ #include #include +#include /* for mode_t */ G_BEGIN_DECLS @@ -100,19 +101,30 @@ gboolean mu_util_check_dir (const gchar* path, gboolean readable, * create a writeable file and return its file descriptor (which * you'll need to close(2) when done with it.) * - * @param filename the filename - * @param dir the target directory, or NULL for the current + * @param path the full path of the file to create + * @param the mode to open (ie. 0644 or 0600 etc., see chmod(3) * @param overwrite should we allow for overwriting existing files? * - * @return a file descriptor, or -1 in case of error. If it's a fily - * system error, 'errno' may have more info. use 'close()' when done + * @return a file descriptor, or -1 in case of error. If it's a file + * system error, 'errno' may contain more info. use 'close()' when done * with the file descriptor */ -int mu_util_create_writeable_fd (const char* filename, const char* dir, +int mu_util_create_writeable_fd (const char* path, mode_t mode, gboolean overwrite) G_GNUC_WARN_UNUSED_RESULT; +/** + * try to 'play' (ie., open with it's associated program) a + * file. depends on xdg-open to do the actual opening + * + * @param path full path of the file to open + * + * @return TRUE if it succeeded, FALSE otherwise + */ +gboolean mu_util_play (const char *path); + + /** * get the version of the xapian database (ie., the version of the * 'schema' we are using). If this version != MU_XAPIAN_DB_VERSION, diff --git a/src/tests/test-mu-cmd.c b/src/tests/test-mu-cmd.c index 8ddb4345..29650cc7 100644 --- a/src/tests/test-mu-cmd.c +++ b/src/tests/test-mu-cmd.c @@ -307,6 +307,51 @@ test_mu_extract_03 (void) } +static void +test_mu_extract_04 (void) +{ + gchar *cmdline, *output, *erroutput, *tmpdir; + + tmpdir = test_mu_common_get_random_tmpdir(); + + g_assert (g_mkdir_with_parents (tmpdir, 0700) == 0); + + cmdline = g_strdup_printf ("%s extract -a --target-dir=%s %s%cFoo%ccur%cmail5", + MU_PROGRAM, tmpdir, + MU_TESTMAILDIR2, G_DIR_SEPARATOR, + G_DIR_SEPARATOR, G_DIR_SEPARATOR); + + g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, NULL, NULL)); + g_assert_cmpstr (output, ==, ""); + g_assert_cmpstr (erroutput, ==, ""); + g_free (erroutput); + g_free (output); + + /* now, it should fail, because we don't allow overwrites without --overwrite */ + g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, NULL, NULL)); + g_assert_cmpstr (output, ==, ""); + g_assert_cmpstr (erroutput, !=, ""); + g_free (erroutput); + g_free (output); + + g_free (cmdline); + /* this should work now, because we have specified --overwrite */ + cmdline = g_strdup_printf ("%s extract -a --overwrite " + "--target-dir=%s %s%cFoo%ccur%cmail5", + MU_PROGRAM, tmpdir, MU_TESTMAILDIR2, G_DIR_SEPARATOR, + G_DIR_SEPARATOR, G_DIR_SEPARATOR); + g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, NULL, NULL)); + g_assert_cmpstr (output, ==, ""); + g_assert_cmpstr (erroutput, ==, ""); + g_free (erroutput); + g_free (output); + + g_free (tmpdir); + g_free (cmdline); +} + + + static void test_mu_view_01 (void) { @@ -384,11 +429,13 @@ main (int argc, char *argv[]) g_test_add_func ("/mu-cmd/test-mu-extract-01", test_mu_extract_01); g_test_add_func ("/mu-cmd/test-mu-extract-02", test_mu_extract_02); g_test_add_func ("/mu-cmd/test-mu-extract-03", test_mu_extract_03); + g_test_add_func ("/mu-cmd/test-mu-extract-04", test_mu_extract_04); g_test_add_func ("/mu-cmd/test-mu-view-01", test_mu_view_01); g_test_add_func ("/mu-cmd/test-mu-mkdir-01", test_mu_mkdir_01); g_log_set_handler (NULL, - G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION, + G_LOG_LEVEL_MASK | G_LOG_LEVEL_WARNING| + G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION, (GLogFunc)black_hole, NULL); mu_msg_gmime_init ();