* implement saving mime-part by file-name, improve error handling
This commit is contained in:
@ -33,17 +33,21 @@ static gboolean
|
|||||||
save_part (MuMsg *msg, const char *targetdir, guint partidx, gboolean overwrite,
|
save_part (MuMsg *msg, const char *targetdir, guint partidx, gboolean overwrite,
|
||||||
gboolean play)
|
gboolean play)
|
||||||
{
|
{
|
||||||
|
GError *err;
|
||||||
gchar *filepath;
|
gchar *filepath;
|
||||||
|
|
||||||
filepath = mu_msg_part_filepath (msg, targetdir, partidx);
|
filepath = mu_msg_part_filepath (msg, targetdir, partidx);
|
||||||
if (!filepath) {
|
if (!filepath) {
|
||||||
g_warning ("%s: failed to get filepath", __FUNCTION__);
|
g_warning ("failed to get filepath");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mu_msg_part_save (msg, filepath, partidx, overwrite, FALSE)) {
|
err = NULL;
|
||||||
g_warning ("%s: failed to save MIME-part %d at %s",
|
if (!mu_msg_part_save (msg, filepath, partidx, overwrite, FALSE, &err)) {
|
||||||
__FUNCTION__, partidx, filepath);
|
g_warning ("failed to save MIME-part: %s",
|
||||||
|
err&&err->message ? err->message : "error");
|
||||||
|
if (err)
|
||||||
|
g_error_free (err);
|
||||||
g_free (filepath);
|
g_free (filepath);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -51,6 +55,7 @@ save_part (MuMsg *msg, const char *targetdir, guint partidx, gboolean overwrite,
|
|||||||
if (play)
|
if (play)
|
||||||
mu_util_play (filepath, TRUE, FALSE);
|
mu_util_play (filepath, TRUE, FALSE);
|
||||||
|
|
||||||
|
g_free (filepath);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,6 +94,26 @@ save_numbered_parts (MuMsg *msg, MuConfig *opts)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
save_part_with_filename (MuMsg *msg, const char *filename, MuConfig *opts)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
idx = mu_msg_part_find_file (msg, filename);
|
||||||
|
if (idx == -1) {
|
||||||
|
g_warning ("file '%s' not found in this message", filename);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!save_part (msg, opts->targetdir, idx, opts->overwrite,
|
||||||
|
opts->play))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct _SaveData {
|
struct _SaveData {
|
||||||
gboolean attachments_only;
|
gboolean attachments_only;
|
||||||
gboolean result;
|
gboolean result;
|
||||||
@ -126,6 +151,7 @@ save_part_if (MuMsg *msg, MuMsgPart *part, SaveData *sd)
|
|||||||
{
|
{
|
||||||
gchar *filepath;
|
gchar *filepath;
|
||||||
gboolean rv;
|
gboolean rv;
|
||||||
|
GError *err;
|
||||||
|
|
||||||
if (ignore_part (msg, part, sd))
|
if (ignore_part (msg, part, sd))
|
||||||
return;
|
return;
|
||||||
@ -137,9 +163,15 @@ save_part_if (MuMsg *msg, MuMsgPart *part, SaveData *sd)
|
|||||||
if (!filepath)
|
if (!filepath)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
err = NULL;
|
||||||
if (!mu_msg_part_save (msg, filepath, part->index,
|
if (!mu_msg_part_save (msg, filepath, part->index,
|
||||||
sd->overwrite, FALSE))
|
sd->overwrite, FALSE, &err)) {
|
||||||
|
g_warning ("failed to save MIME-part: %s",
|
||||||
|
err&&err->message ? err->message : "error");
|
||||||
|
if (err)
|
||||||
|
g_error_free (err);
|
||||||
goto leave;
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
if (sd->play && !mu_util_play (filepath, TRUE, FALSE))
|
if (sd->play && !mu_util_play (filepath, TRUE, FALSE))
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -183,7 +215,7 @@ save_certain_parts (MuMsg *msg, gboolean attachments_only,
|
|||||||
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
save_parts (const char *path, MuConfig *opts)
|
save_parts (const char *path, const char *filename, MuConfig *opts)
|
||||||
{
|
{
|
||||||
MuMsg* msg;
|
MuMsg* msg;
|
||||||
gboolean rv;
|
gboolean rv;
|
||||||
@ -203,6 +235,8 @@ save_parts (const char *path, MuConfig *opts)
|
|||||||
/* should we save some explicit parts? */
|
/* should we save some explicit parts? */
|
||||||
if (opts->parts)
|
if (opts->parts)
|
||||||
rv = save_numbered_parts (msg, opts);
|
rv = save_numbered_parts (msg, opts);
|
||||||
|
else if (filename)
|
||||||
|
rv = save_part_with_filename (msg, filename, opts);
|
||||||
else if (opts->save_attachments) /* all attachments */
|
else if (opts->save_attachments) /* all attachments */
|
||||||
rv = save_certain_parts (msg, TRUE,
|
rv = save_certain_parts (msg, TRUE,
|
||||||
opts->targetdir, opts->overwrite,
|
opts->targetdir, opts->overwrite,
|
||||||
@ -257,8 +291,14 @@ show_parts (const char* path, MuConfig *opts)
|
|||||||
static gboolean
|
static gboolean
|
||||||
check_params (MuConfig *opts)
|
check_params (MuConfig *opts)
|
||||||
{
|
{
|
||||||
if (!opts->params[1] || opts->params[2]) {
|
if (!opts->params[1] || (opts->params[2] && opts->params[3])) {
|
||||||
g_warning ("usage: mu extract [options] <file>");
|
g_warning ("usage: mu extract [options] <file> [<filename>]");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts->params[2] && (opts->save_attachments || opts->save_all)) {
|
||||||
|
g_warning ("--save-attachments --save-all is allowed don't accept "
|
||||||
|
"a filename");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,7 +329,8 @@ mu_cmd_extract (MuConfig *opts)
|
|||||||
if (!check_params (opts))
|
if (!check_params (opts))
|
||||||
return MU_EXITCODE_ERROR;
|
return MU_EXITCODE_ERROR;
|
||||||
|
|
||||||
if (!opts->parts &&
|
if (!opts->params[2] &&
|
||||||
|
!opts->parts &&
|
||||||
!opts->save_attachments &&
|
!opts->save_attachments &&
|
||||||
!opts->save_all) /* show, don't save */
|
!opts->save_all) /* show, don't save */
|
||||||
rv = show_parts (opts->params[1], opts);
|
rv = show_parts (opts->params[1], opts);
|
||||||
@ -299,7 +340,9 @@ mu_cmd_extract (MuConfig *opts)
|
|||||||
g_warning ("target '%s' is not a writable directory",
|
g_warning ("target '%s' is not a writable directory",
|
||||||
opts->targetdir);
|
opts->targetdir);
|
||||||
else
|
else
|
||||||
rv = save_parts (opts->params[1], opts); /* save */
|
rv = save_parts (opts->params[1],
|
||||||
|
opts->params[2],
|
||||||
|
opts); /* save */
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv ? MU_EXITCODE_OK : MU_EXITCODE_ERROR;
|
return rv ? MU_EXITCODE_OK : MU_EXITCODE_ERROR;
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Copyright (C) 2008-2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
** Copyright (C) 2008-2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
**
|
**
|
||||||
@ -149,7 +151,7 @@ write_to_stream (GMimeObject *part, int fd)
|
|||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
save_part (GMimeObject *part, const char *fullpath,
|
save_part (GMimeObject *part, const char *fullpath,
|
||||||
gboolean overwrite, gboolean use_existing)
|
gboolean overwrite, gboolean use_existing, GError **err)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
gboolean rv;
|
gboolean rv;
|
||||||
@ -161,13 +163,20 @@ save_part (GMimeObject *part, const char *fullpath,
|
|||||||
|
|
||||||
/* ok, try to create the file */
|
/* ok, try to create the file */
|
||||||
fd = mu_util_create_writeable_fd (fullpath, 0600, overwrite);
|
fd = mu_util_create_writeable_fd (fullpath, 0600, overwrite);
|
||||||
if (fd == -1)
|
if (fd == -1) {
|
||||||
|
g_set_error (err, 0, MU_ERROR_FILE,
|
||||||
|
"could not open '%s' for writing: %s",
|
||||||
|
fullpath, errno ? strerror(errno) : "error");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
rv = write_to_stream (part, fd);
|
rv = write_to_stream (part, fd);
|
||||||
if (close (fd) != 0)
|
if (close (fd) != 0) {
|
||||||
g_warning ("%s: failed to close %s: %s", __FUNCTION__,
|
g_set_error (err, 0, MU_ERROR_FILE,
|
||||||
fullpath, strerror(errno));
|
"could not close '%s': %s",
|
||||||
|
fullpath, errno ? strerror(errno) : "error");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -238,7 +247,7 @@ mu_msg_part_filepath_cache (MuMsg *msg, guint partid)
|
|||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
mu_msg_part_save (MuMsg *msg, const char *fullpath, guint partidx,
|
mu_msg_part_save (MuMsg *msg, const char *fullpath, guint partidx,
|
||||||
gboolean overwrite, gboolean use_cached)
|
gboolean overwrite, gboolean use_cached, GError **err)
|
||||||
{
|
{
|
||||||
GMimeObject *part;
|
GMimeObject *part;
|
||||||
|
|
||||||
@ -248,21 +257,17 @@ mu_msg_part_save (MuMsg *msg, const char *fullpath, guint partidx,
|
|||||||
|
|
||||||
part = find_part (msg, partidx);
|
part = find_part (msg, partidx);
|
||||||
if (!GMIME_IS_PART(part)) {
|
if (!GMIME_IS_PART(part)) {
|
||||||
g_warning ("%s: cannot find part %u", __FUNCTION__, partidx);
|
g_set_error (err, 0, MU_ERROR_GMIME,
|
||||||
|
"cannot find part %u", partidx);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!save_part (part, fullpath, overwrite, use_cached)) {
|
if (!save_part (part, fullpath, overwrite, use_cached, err))
|
||||||
g_warning ("%s: failed to save '%s'", __FUNCTION__, fullpath);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef gboolean (*MatchFunc) (GMimeObject *part, gpointer data);
|
typedef gboolean (*MatchFunc) (GMimeObject *part, gpointer data);
|
||||||
|
|
||||||
struct _MatchData {
|
struct _MatchData {
|
||||||
@ -327,6 +332,35 @@ mu_msg_part_find_cid (MuMsg *msg, const char* sought_cid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
match_filename (GMimeObject *part, const char *sought_filename)
|
||||||
|
{
|
||||||
|
const char *fname;
|
||||||
|
|
||||||
|
if (!GMIME_IS_PART(part))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
fname = g_mime_part_get_filename (GMIME_PART(part));
|
||||||
|
if (!fname)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return g_strcmp0 (fname, sought_filename) == 0 ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
mu_msg_part_find_file (MuMsg *msg, const char* sought_filename)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (msg, -1);
|
||||||
|
g_return_val_if_fail (sought_filename, -1);
|
||||||
|
|
||||||
|
return msg_part_find_idx (msg->_file->_mime_msg,
|
||||||
|
(MatchFunc)match_filename,
|
||||||
|
(gpointer)sought_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
mu_msg_part_looks_like_attachment (MuMsgPart *part, gboolean include_inline)
|
mu_msg_part_looks_like_attachment (MuMsgPart *part, gboolean include_inline)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Copyright (C) 2008-2010 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
** Copyright (C) 2008-2010 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
**
|
**
|
||||||
@ -101,11 +103,12 @@ gboolean mu_msg_part_looks_like_attachment (MuMsgPart *part,
|
|||||||
* @param partidx index of the attachment you want to save
|
* @param partidx index of the attachment you want to save
|
||||||
* @param overwrite overwrite existing files?
|
* @param overwrite overwrite existing files?
|
||||||
* @param don't raise error when the file already exists
|
* @param don't raise error when the file already exists
|
||||||
|
* @param err receives error information (when function returns NULL)
|
||||||
*
|
*
|
||||||
* @return full path to the message part saved or NULL in case or error; free with g_free
|
* @return full path to the message part saved or NULL in case or error; free with g_free
|
||||||
*/
|
*/
|
||||||
gboolean mu_msg_part_save (MuMsg *msg, const char *filepath, guint partidx,
|
gboolean mu_msg_part_save (MuMsg *msg, const char *filepath, guint partidx,
|
||||||
gboolean overwrite, gboolean use_cached);
|
gboolean overwrite, gboolean use_cached, GError **err);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -138,7 +141,7 @@ gchar* mu_msg_part_filepath_cache (MuMsg *msg, guint partid)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the part inede for the message part with a certain content-id
|
* get the part index for the message part with a certain content-id
|
||||||
*
|
*
|
||||||
* @param msg a message
|
* @param msg a message
|
||||||
* @param content_id a content-id to search
|
* @param content_id a content-id to search
|
||||||
@ -147,10 +150,19 @@ gchar* mu_msg_part_filepath_cache (MuMsg *msg, guint partid)
|
|||||||
*/
|
*/
|
||||||
int mu_msg_part_find_cid (MuMsg *msg, const char* content_id);
|
int mu_msg_part_find_cid (MuMsg *msg, const char* content_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the (first) part index for the message part with a certain
|
||||||
|
* filename
|
||||||
|
*
|
||||||
|
* @param msg a message
|
||||||
|
* @param sought_filename filename to look for
|
||||||
|
*
|
||||||
|
* @return the part index number of the found part, or -1 if it was not found
|
||||||
|
*/
|
||||||
|
int mu_msg_part_find_file (MuMsg *msg, const char* sought_filename);
|
||||||
|
|
||||||
|
|
||||||
typedef void (*MuMsgPartForeachFunc) (MuMsg *, MuMsgPart *, gpointer);
|
typedef void (*MuMsgPartForeachFunc) (MuMsg*, MuMsgPart*, gpointer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* call a function for each of the mime part in a message
|
* call a function for each of the mime part in a message
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user