* support getting all image attachments as temp files (change in mu-msg-sexp

api)
This commit is contained in:
djcb 2012-05-16 20:45:31 +03:00
parent 3bbff2e9ad
commit 47e7720464
6 changed files with 110 additions and 40 deletions

View File

@ -215,8 +215,11 @@ update the database accordingly.
Using the \fBview\fR command, we can all information (including the body) of a
particular e-mail message.
If the optional parameter \fBextract-images\fR is \fBtrue\fR, extract images
to temp files, and include links to them in the returned s-exp.
.nf
-> view docid:<docid>|msgid:<msgid>
-> view docid:<docid>|msgid:<msgid> [extract-images:true]
<- (:view <s-exp>)
.fi

View File

@ -743,7 +743,7 @@ output_sexp (MuMsgIter *iter, gboolean threads,
ti = threads ? mu_msg_iter_get_thread_info (iter) : NULL;
sexp = mu_msg_to_sexp (msg,
mu_msg_iter_get_docid (iter),
ti, TRUE);
ti, TRUE, FALSE);
fputs (sexp, stdout);
g_free (sexp);

View File

@ -188,7 +188,7 @@ read_line_as_list (GError **err)
}
const char*
static const char*
get_string_from_args (GSList *args, const char *param, gboolean optional,
GError **err)
{
@ -215,6 +215,27 @@ get_string_from_args (GSList *args, const char *param, gboolean optional,
return NULL;
}
static gboolean
get_bool_from_args (GSList *args, const char *param, gboolean optional, GError **err)
{
const char *val;
val = get_string_from_args (args, param, optional, err);
if (err && (*err != NULL))
return FALSE;
if (g_strcmp0 (val, "true") == 0)
return TRUE;
if (!val || g_strcmp0 (val, "false") == 0)
return FALSE;
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
"invalid value for parameter '%s'", param);
return FALSE;
}
#define GET_STRING_OR_ERROR_RETURN(ARGS,PARAM,SP,E) \
do { \
@ -479,7 +500,7 @@ cmd_compose (MuStore *store, MuQuery *query, GSList *args, GError **err)
print_and_clear_g_error (err);
return MU_OK;
}
sexp = mu_msg_to_sexp (msg, atoi(docidstr), NULL, FALSE);
sexp = mu_msg_to_sexp (msg, atoi(docidstr), NULL, FALSE, FALSE);
atts = (ctype == FORWARD) ? include_attachments (msg) : NULL;
mu_msg_unref (msg);
} else
@ -512,7 +533,7 @@ print_sexps (MuMsgIter *iter, int maxnum)
char *sexp;
sexp = mu_msg_to_sexp (msg, mu_msg_iter_get_docid (iter),
mu_msg_iter_get_thread_info (iter),
TRUE);
TRUE, FALSE);
print_expr ("%s", sexp);
g_free (sexp);
++u;
@ -846,7 +867,8 @@ do_move (MuStore *store, unsigned docid, MuMsg *msg, const char *maildir,
print_and_clear_g_error (err);
}
sexp = mu_msg_to_sexp (msg, docid, NULL, FALSE/*include body*/);
sexp = mu_msg_to_sexp (msg, docid, NULL, FALSE/*include body*/,
FALSE/*do not include images*/);
/* note, the :move t thing is a hint to the frontend that it
* could remove the particular header */
print_expr ("(:update %s :move %s)", sexp,
@ -1049,11 +1071,7 @@ cmd_remove (MuStore *store, MuQuery *query, GSList *args, GError **err)
path = get_path_from_docid (store, docid, err);
if (!path) {
if (err && *err)
print_and_clear_g_error (err);
else
print_error (MU_ERROR_IN_PARAMETERS,
"no path for docid");
print_and_clear_g_error (err);
return MU_OK;
}
@ -1114,6 +1132,13 @@ cmd_view (MuStore *store, MuQuery *query, GSList *args, GError **err)
MuMsg *msg;
unsigned docid;
char *sexp;
gboolean extract_images;
extract_images = get_bool_from_args (args, "extract-images", FALSE, err);
if (err && *err) {
print_and_clear_g_error (err);
return MU_OK;
}
docid = determine_docid (query, args, err);
if (docid == MU_STORE_INVALID_DOCID) {
@ -1123,15 +1148,11 @@ cmd_view (MuStore *store, MuQuery *query, GSList *args, GError **err)
msg = mu_store_get_msg (store, docid, err);
if (!msg) {
if (err && *err)
print_and_clear_g_error (err);
else
print_error (MU_ERROR_IN_PARAMETERS,
"failed to get message");
print_and_clear_g_error (err);
return MU_OK;
}
sexp = mu_msg_to_sexp (msg, docid, NULL, FALSE);
sexp = mu_msg_to_sexp (msg, docid, NULL, FALSE, extract_images);
mu_msg_unref (msg);
print_expr ("(:view %s)\n", sexp);

View File

@ -48,7 +48,7 @@ view_msg_sexp (MuMsg *msg)
{
char *sexp;
sexp = mu_msg_to_sexp (msg, 0, NULL, FALSE);
sexp = mu_msg_to_sexp (msg, 0, NULL, FALSE, FALSE);
fputs (sexp, stdout);
g_free (sexp);

View File

@ -1,5 +1,5 @@
/*
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** Copyright (C) 2011-2012 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
**
** 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
@ -201,12 +201,40 @@ append_sexp_flags (GString *gstr, MuMsg *msg)
g_free (fdata.flagstr);
}
static char*
get_temp_file (MuMsg *msg, unsigned index)
{
char *path;
GError *err;
err = NULL;
path = mu_msg_part_filepath_cache (msg, index);
if (!mu_msg_part_save (msg, path, index,
FALSE/*overwrite*/, TRUE/*use cache*/, &err)) {
g_warning ("failed to save mime part: %s",
err->message ? err->message : "something went wrong");
g_clear_error (&err);
g_free (path);
return NULL;
}
return path;
}
struct _PartInfo {
char *parts;
gboolean want_images;
};
typedef struct _PartInfo PartInfo;
static void
each_part (MuMsg *msg, MuMsgPart *part, gchar **parts)
each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo)
{
const char *fname;
char *name, *tmp;
char *tmpfile;
fname = mu_msg_part_file_name (part);
if (!fname)
@ -221,31 +249,44 @@ each_part (MuMsg *msg, MuMsgPart *part, gchar **parts)
part->subtype ? part->subtype : "octet-stream",
part->index);
tmpfile = NULL;
if (pinfo->want_images && g_ascii_strcasecmp (part->type, "image") == 0) {
char *tmp;
tmp = get_temp_file (msg, part->index);
if (tmp) {
tmpfile = mu_str_escape_c_literal (tmp, TRUE);
g_free (tmp);
}
}
tmp = g_strdup_printf
("%s(:index %d :name %s :mime-type \"%s/%s\" :attachment %s :size %i)",
*parts ? *parts : "", part->index, name,
("%s(:index %d :name %s :mime-type \"%s/%s\"%s%s :attachment %s :size %i)",
pinfo->parts ? pinfo->parts : "", part->index, name,
part->type ? part->type : "application",
part->subtype ? part->subtype : "octet-stream",
tmpfile ? " :temp" : "", tmpfile ? tmpfile : "",
mu_msg_part_looks_like_attachment (part, TRUE) ? "t" : "nil",
(int)part->size);
g_free (*parts);
*parts = tmp;
g_free (pinfo->parts);
pinfo->parts = tmp;
}
static void
append_sexp_parts (GString *gstr, MuMsg *msg)
append_sexp_parts (GString *gstr, MuMsg *msg, gboolean want_images)
{
char *parts;
PartInfo pinfo;
pinfo.parts = NULL;
pinfo.want_images = want_images;
parts = NULL;
mu_msg_part_foreach (msg, FALSE,
(MuMsgPartForeachFunc)each_part, &parts);
(MuMsgPartForeachFunc)each_part, &pinfo);
if (parts) {
g_string_append_printf (gstr, "\t:parts (%s)\n", parts);
g_free (parts);
if (pinfo.parts) {
g_string_append_printf (gstr, "\t:parts (%s)\n", pinfo.parts);
g_free (pinfo.parts);
}
}
@ -254,9 +295,7 @@ append_sexp_parts (GString *gstr, MuMsg *msg)
static void
append_sexp_message_file_attr (GString *gstr, MuMsg *msg)
{
append_sexp_parts (gstr, msg);
append_sexp_attr_list (gstr, "references", mu_msg_get_references (msg));
append_sexp_attr_list (gstr, "references", mu_msg_get_references (msg));
append_sexp_attr (gstr, "in-reply-to",
mu_msg_get_header (msg, "In-Reply-To"));
append_sexp_attr (gstr, "body-txt",
@ -285,18 +324,21 @@ append_sexp_thread_info (GString *gstr, const MuMsgIterThreadInfo *ti)
char*
mu_msg_to_sexp (MuMsg *msg, unsigned docid, const MuMsgIterThreadInfo *ti,
gboolean header)
gboolean header_only, gboolean extract_images)
{
GString *gstr;
time_t t;
gstr = g_string_sized_new (header ? 1024 : 8192);
g_return_val_if_fail (msg, NULL);
g_return_val_if_fail (!(header_only && extract_images), NULL);
gstr = g_string_sized_new (header_only ? 1024 : 8192);
g_string_append (gstr, "(\n");
if (docid != 0)
g_string_append_printf (gstr, "\t:docid %u\n", docid);
if (!header) /* force loading of file... should do this a bit
if (!header_only) /* force loading of file... should do this a bit
* more elegantly */
mu_msg_get_header (msg, "Reply-To");
@ -327,8 +369,10 @@ mu_msg_to_sexp (MuMsg *msg, unsigned docid, const MuMsgIterThreadInfo *ti,
*
* file attr things can only be gotten from the file (ie., mu
* view), not from the database (mu find). */
if (!header)
if (!header_only) {
append_sexp_message_file_attr (gstr, msg);
append_sexp_parts (gstr, msg, extract_images);
}
g_string_append (gstr, ")\n");

View File

@ -390,15 +390,17 @@ struct _MuMsgIterThreadInfo;
* @param msg a valid message
* @param docid the docid for this message, or 0
* @param ti thread info for the current message, or NULL
* @param dbonly if TRUE, only include message fields which can be
* @param headers if TRUE, only include message fields which can be
* obtained from the database (this is much faster if the MuMsg is
* database-backed, so no file needs to be opened)
* @param extract_images if TRUE, extract image attachments as temporary
* files and include links to those in the sexp
*
* @return a string with the sexp (free with g_free) or NULL in case of error
*/
char* mu_msg_to_sexp (MuMsg *msg, unsigned docid,
const struct _MuMsgIterThreadInfo *ti,
gboolean dbonly);
gboolean headers_only, gboolean extract_images);
/**
* move a message to another maildir; note that this does _not_ update