* mu-cmd-server, m-msg-part.c: add support opening, extracting attachments
This commit is contained in:
@ -48,6 +48,7 @@
|
|||||||
#include "mu-maildir.h"
|
#include "mu-maildir.h"
|
||||||
#include "mu-query.h"
|
#include "mu-query.h"
|
||||||
#include "mu-index.h"
|
#include "mu-index.h"
|
||||||
|
#include "mu-msg-part.h"
|
||||||
|
|
||||||
|
|
||||||
/* we include \376 (0xfe) and \377, (0xff) because it cannot occur as
|
/* we include \376 (0xfe) and \377, (0xff) because it cannot occur as
|
||||||
@ -125,8 +126,10 @@ enum _Cmd {
|
|||||||
CMD_INDEX,
|
CMD_INDEX,
|
||||||
CMD_MKDIR,
|
CMD_MKDIR,
|
||||||
CMD_MOVE,
|
CMD_MOVE,
|
||||||
|
CMD_OPEN,
|
||||||
CMD_QUIT,
|
CMD_QUIT,
|
||||||
CMD_REMOVE,
|
CMD_REMOVE,
|
||||||
|
CMD_SAVE,
|
||||||
CMD_VERSION,
|
CMD_VERSION,
|
||||||
CMD_VIEW,
|
CMD_VIEW,
|
||||||
|
|
||||||
@ -150,8 +153,10 @@ cmd_from_string (const char *str)
|
|||||||
{ CMD_INDEX, "index"},
|
{ CMD_INDEX, "index"},
|
||||||
{ CMD_MKDIR, "mkdir"},
|
{ CMD_MKDIR, "mkdir"},
|
||||||
{ CMD_MOVE, "move"},
|
{ CMD_MOVE, "move"},
|
||||||
|
{ CMD_OPEN, "open" },
|
||||||
{ CMD_QUIT, "quit"},
|
{ CMD_QUIT, "quit"},
|
||||||
{ CMD_REMOVE, "remove" },
|
{ CMD_REMOVE, "remove" },
|
||||||
|
{ CMD_SAVE, "save"},
|
||||||
{ CMD_VERSION, "version"},
|
{ CMD_VERSION, "version"},
|
||||||
{ CMD_VIEW, "view"}
|
{ CMD_VIEW, "view"}
|
||||||
};
|
};
|
||||||
@ -420,10 +425,7 @@ cmd_move (MuStore *store, GSList *lst, GError **err)
|
|||||||
(NULL, MU_ERROR_IN_PARAMETERS,
|
(NULL, MU_ERROR_IN_PARAMETERS,
|
||||||
"usage: move <docid> <maildir> [<flags>]");
|
"usage: move <docid> <maildir> [<flags>]");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return move_or_flag (store, lst, TRUE, err);
|
return move_or_flag (store, lst, TRUE, err);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static MuError
|
static MuError
|
||||||
@ -477,6 +479,90 @@ cmd_remove (MuStore *store, GSList *lst, GError **err)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static MuError
|
||||||
|
save_or_open (MuStore *store, GSList *args, gboolean is_save, GError **err)
|
||||||
|
{
|
||||||
|
MuMsg *msg;
|
||||||
|
unsigned docid, partindex;
|
||||||
|
char* targetpath;
|
||||||
|
gboolean rv;
|
||||||
|
|
||||||
|
docid = get_docid ((const char*)args->data);
|
||||||
|
msg = mu_store_get_msg (store, docid, err);
|
||||||
|
if (!msg)
|
||||||
|
return server_error (err, MU_ERROR, "failed to get message");
|
||||||
|
|
||||||
|
partindex = atoi((const char*)g_slist_nth (args, 1)->data);
|
||||||
|
|
||||||
|
if (is_save)
|
||||||
|
targetpath = g_strdup ((const char*)g_slist_nth (args, 2)->data);
|
||||||
|
else
|
||||||
|
targetpath = mu_msg_part_filepath_cache (msg, partindex);
|
||||||
|
|
||||||
|
if (!targetpath) {
|
||||||
|
mu_msg_unref (msg);
|
||||||
|
return server_error (err, MU_ERROR_FILE,
|
||||||
|
"failed to determine target path");
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = mu_msg_part_save (msg, targetpath, partindex,
|
||||||
|
is_save ? TRUE : FALSE,
|
||||||
|
is_save ? FALSE : TRUE, err);
|
||||||
|
mu_msg_unref (msg);
|
||||||
|
|
||||||
|
if (rv && !is_save)
|
||||||
|
mu_util_play (targetpath, TRUE, FALSE);
|
||||||
|
|
||||||
|
if (rv) {
|
||||||
|
gchar *info, *path;
|
||||||
|
path = mu_str_escape_c_literal (targetpath, FALSE);
|
||||||
|
info = g_strdup_printf ("(:info %s :message \"%s %s\")",
|
||||||
|
is_save ? "save" : "open",
|
||||||
|
is_save ? "Saved" : "Opened",
|
||||||
|
path);
|
||||||
|
send_expr (info);
|
||||||
|
g_free (path);
|
||||||
|
g_free (info);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (targetpath);
|
||||||
|
|
||||||
|
if (!rv)
|
||||||
|
return server_error (err, MU_ERROR_FILE,
|
||||||
|
"failed to save attachment");
|
||||||
|
|
||||||
|
return MU_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static MuError
|
||||||
|
cmd_save (MuStore *store, GSList *args, GError **err)
|
||||||
|
{
|
||||||
|
if (!check_param_num (args, 3, 3))
|
||||||
|
return server_error
|
||||||
|
(NULL, MU_ERROR_IN_PARAMETERS,
|
||||||
|
"save <docid> <partindex> <targetpath>");
|
||||||
|
|
||||||
|
return save_or_open (store, args, TRUE, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static MuError
|
||||||
|
cmd_open (MuStore *store, GSList *args, GError **err)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!check_param_num (args, 2, 2))
|
||||||
|
return server_error
|
||||||
|
(NULL, MU_ERROR_IN_PARAMETERS,
|
||||||
|
"open <docid> <partindex>");
|
||||||
|
|
||||||
|
return save_or_open (store, args, FALSE, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static MuError
|
static MuError
|
||||||
cmd_view (MuStore *store, GSList *args, GError **err)
|
cmd_view (MuStore *store, GSList *args, GError **err)
|
||||||
{
|
{
|
||||||
@ -571,16 +657,17 @@ static MuError
|
|||||||
cmd_add (MuStore *store, GSList *lst, GError **err)
|
cmd_add (MuStore *store, GSList *lst, GError **err)
|
||||||
{
|
{
|
||||||
unsigned docid;
|
unsigned docid;
|
||||||
const char *path;
|
const char *path, *maildir;
|
||||||
gchar *str, *escpath;
|
gchar *str, *escpath;
|
||||||
|
|
||||||
if (!check_param_num (lst, 1, 1))
|
if (!check_param_num (lst, 2, 2))
|
||||||
return server_error (NULL, MU_ERROR_IN_PARAMETERS,
|
return server_error (NULL, MU_ERROR_IN_PARAMETERS,
|
||||||
"usage: add <path>");
|
"usage: add <path> <maildir>");
|
||||||
|
|
||||||
path = (const char*)lst->data;
|
path = (const char*)lst->data;
|
||||||
|
maildir = (const char*)g_slist_nth (lst, 1)->data;
|
||||||
|
|
||||||
docid = mu_store_add_path (store, path, err);
|
docid = mu_store_add_path (store, path, maildir, err);
|
||||||
if (docid == MU_STORE_INVALID_DOCID)
|
if (docid == MU_STORE_INVALID_DOCID)
|
||||||
return server_error (err, MU_ERROR_XAPIAN, "failed to add path");
|
return server_error (err, MU_ERROR_XAPIAN, "failed to add path");
|
||||||
|
|
||||||
@ -670,8 +757,10 @@ handle_command (Cmd cmd, MuStore *store, MuQuery *query, GSList *args,
|
|||||||
case CMD_INDEX: rv = cmd_index (store, args, err); break;
|
case CMD_INDEX: rv = cmd_index (store, args, err); break;
|
||||||
case CMD_MKDIR: rv = cmd_mkdir (args, err); break;
|
case CMD_MKDIR: rv = cmd_mkdir (args, err); break;
|
||||||
case CMD_MOVE: rv = cmd_move (store, args, err); break;
|
case CMD_MOVE: rv = cmd_move (store, args, err); break;
|
||||||
|
case CMD_OPEN: rv = cmd_open (store, args, err); break;
|
||||||
case CMD_QUIT: rv = cmd_quit (args, err); break;
|
case CMD_QUIT: rv = cmd_quit (args, err); break;
|
||||||
case CMD_REMOVE: rv = cmd_remove (store, args, err); break;
|
case CMD_REMOVE: rv = cmd_remove (store, args, err); break;
|
||||||
|
case CMD_SAVE: rv = cmd_save (store, args, err); break;
|
||||||
case CMD_VERSION: rv = cmd_version (args, err); break;
|
case CMD_VERSION: rv = cmd_version (args, err); break;
|
||||||
case CMD_VIEW: rv = cmd_view (store, args, err); break;
|
case CMD_VIEW: rv = cmd_view (store, args, err); break;
|
||||||
|
|
||||||
|
|||||||
@ -95,6 +95,33 @@ part_foreach_cb (GMimeObject *parent, GMimeObject *part, PartData *pdata)
|
|||||||
pdata->_func(pdata->_msg, &pi, pdata->_user_data);
|
pdata->_func(pdata->_msg, &pi, pdata->_user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
load_msg_file_maybe (MuMsg *msg)
|
||||||
|
{
|
||||||
|
GError *err;
|
||||||
|
|
||||||
|
if (msg->_file)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
err = NULL;
|
||||||
|
msg->_file = mu_msg_file_new (mu_msg_get_path(msg), NULL,
|
||||||
|
&err);
|
||||||
|
if (!msg->_file) {
|
||||||
|
MU_HANDLE_G_ERROR(err); /* will free it */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!msg->_file->_mime_msg) {
|
||||||
|
mu_msg_file_destroy (msg->_file);
|
||||||
|
msg->_file = NULL;
|
||||||
|
g_warning ("failed to create mime-msg");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
mu_msg_part_foreach (MuMsg *msg, MuMsgPartForeachFunc func,
|
mu_msg_part_foreach (MuMsg *msg, MuMsgPartForeachFunc func,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
@ -103,18 +130,8 @@ mu_msg_part_foreach (MuMsg *msg, MuMsgPartForeachFunc func,
|
|||||||
|
|
||||||
g_return_if_fail (msg);
|
g_return_if_fail (msg);
|
||||||
|
|
||||||
/* if we don't have a file yet, we need to open it now... */
|
if (!load_msg_file_maybe (msg))
|
||||||
if (!msg->_file) {
|
return;
|
||||||
GError *err;
|
|
||||||
err = NULL;
|
|
||||||
msg->_file = mu_msg_file_new (mu_msg_get_path(msg), NULL,
|
|
||||||
&err);
|
|
||||||
if (!msg->_file) {
|
|
||||||
MU_HANDLE_G_ERROR(err); /* will free it */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_return_if_fail (GMIME_IS_OBJECT(msg->_file->_mime_msg));
|
|
||||||
|
|
||||||
pdata._msg = msg;
|
pdata._msg = msg;
|
||||||
pdata._idx = 0;
|
pdata._idx = 0;
|
||||||
@ -203,6 +220,9 @@ mu_msg_part_filepath (MuMsg *msg, const char* targetdir, guint partidx)
|
|||||||
char *fname, *filepath;
|
char *fname, *filepath;
|
||||||
GMimeObject* part;
|
GMimeObject* part;
|
||||||
|
|
||||||
|
if (!load_msg_file_maybe (msg))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
part = find_part (msg, partidx);
|
part = find_part (msg, partidx);
|
||||||
if (!part) {
|
if (!part) {
|
||||||
g_warning ("%s: cannot find part %u", __FUNCTION__, partidx);
|
g_warning ("%s: cannot find part %u", __FUNCTION__, partidx);
|
||||||
@ -235,6 +255,9 @@ mu_msg_part_filepath_cache (MuMsg *msg, guint partid)
|
|||||||
|
|
||||||
g_return_val_if_fail (msg, NULL);
|
g_return_val_if_fail (msg, NULL);
|
||||||
|
|
||||||
|
if (!load_msg_file_maybe (msg))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
path = mu_msg_get_path (msg);
|
path = mu_msg_get_path (msg);
|
||||||
if (!path)
|
if (!path)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -270,6 +293,9 @@ mu_msg_part_save (MuMsg *msg, const char *fullpath, guint partidx,
|
|||||||
g_return_val_if_fail (fullpath, FALSE);
|
g_return_val_if_fail (fullpath, FALSE);
|
||||||
g_return_val_if_fail (!overwrite||!use_cached, FALSE);
|
g_return_val_if_fail (!overwrite||!use_cached, FALSE);
|
||||||
|
|
||||||
|
if (!load_msg_file_maybe (msg))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
part = find_part (msg, partidx);
|
part = find_part (msg, partidx);
|
||||||
if (!GMIME_IS_PART(part)) {
|
if (!GMIME_IS_PART(part)) {
|
||||||
g_set_error (err, 0, MU_ERROR_GMIME,
|
g_set_error (err, 0, MU_ERROR_GMIME,
|
||||||
@ -338,6 +364,9 @@ mu_msg_part_find_cid (MuMsg *msg, const char* sought_cid)
|
|||||||
g_return_val_if_fail (msg, -1);
|
g_return_val_if_fail (msg, -1);
|
||||||
g_return_val_if_fail (sought_cid, -1);
|
g_return_val_if_fail (sought_cid, -1);
|
||||||
|
|
||||||
|
if (!load_msg_file_maybe (msg))
|
||||||
|
return -1;
|
||||||
|
|
||||||
cid = g_str_has_prefix (sought_cid, "cid:") ?
|
cid = g_str_has_prefix (sought_cid, "cid:") ?
|
||||||
sought_cid + 4 : sought_cid;
|
sought_cid + 4 : sought_cid;
|
||||||
|
|
||||||
@ -382,6 +411,9 @@ mu_msg_part_find_files (MuMsg *msg, const GRegex *pattern)
|
|||||||
g_return_val_if_fail (msg, NULL);
|
g_return_val_if_fail (msg, NULL);
|
||||||
g_return_val_if_fail (pattern, NULL);
|
g_return_val_if_fail (pattern, NULL);
|
||||||
|
|
||||||
|
if (!load_msg_file_maybe (msg))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
mdata._lst = NULL;
|
mdata._lst = NULL;
|
||||||
mdata._rx = pattern;
|
mdata._rx = pattern;
|
||||||
mdata._idx = 0;
|
mdata._idx = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user