static MuError insert_or_update_maybe (const char* fullpath, const char* mdir, time_t filestamp, MuIndexCallbackData *data, gboolean *updated) { MuMsg *msg; GError *err; *updated = FALSE; if (!needs_index (data, fullpath, filestamp)) return MU_OK; /* nothing to do for this one */ err = NULL; msg = mu_msg_new_from_file (fullpath, mdir, &err); if ((G_UNLIKELY(!msg))) goto errexit; /* we got a valid id; scan the message contents as well */ if (G_UNLIKELY((!mu_store_add_msg (data->_store, msg, &err)))) goto errexit; mu_msg_unref (msg); *updated = TRUE; return MU_OK; errexit: { MuError me; me = err ? err->code : MU_ERROR; g_clear_error (&err); if (msg) mu_msg_unref (msg); return me; } }
gboolean mug_msg_view_set_msg (MugMsgView * self, const char *msgpath) { MugMsgViewPrivate *priv; g_return_val_if_fail (MUG_IS_MSG_VIEW (self), FALSE); priv = MUG_MSG_VIEW_GET_PRIVATE (self); if (!msgpath) mu_msg_view_set_message (MU_MSG_VIEW(priv->_view), NULL); else { MuMsg *msg; if (access (msgpath, R_OK) == 0) { msg = mu_msg_new_from_file (msgpath, NULL, NULL); mu_msg_view_set_message (MU_MSG_VIEW(priv->_view), msg); if (msg) mu_msg_unref (msg); } else { gchar *note; note = g_strdup_printf ( "<h1>Note</h1><hr>" "<p>Message <tt>%s</tt> does not seem to be present " "on the file system." "<p>Maybe you need to run <tt>mu index</tt>?", msgpath); mu_msg_view_set_note (MU_MSG_VIEW (priv->_view), note); g_free (note); } } return TRUE; }
static gboolean save_parts (const char *path, const char *filename, MuConfig *opts) { MuMsg* msg; gboolean rv; GError *err; err = NULL; msg = mu_msg_new_from_file (path, NULL, &err); if (!msg) { if (err) { g_warning ("error: %s", err->message); g_error_free (err); } return FALSE; } /* note, mu_cmd_extract already checks whether what's in opts * is somewhat, so no need for extensive checking here */ /* should we save some explicit parts? */ if (opts->parts) rv = save_numbered_parts (msg, opts); else if (filename) rv = save_part_with_filename (msg, filename, opts); else rv = save_certain_parts (msg, opts); mu_msg_unref (msg); return rv; }
/* 'add' adds a message to the database, and takes two parameters: * 'path', which is the full path to the message, and 'maildir', which * is the maildir this message lives in (e.g. "/inbox"). response with * an (:info ...) message with information about the newly added * message (details: see code below) */ static MuError cmd_add (ServerContext *ctx, GSList *args, GError **err) { unsigned docid; const char *maildir, *path; MuMsg *msg; gchar *sexp; GET_STRING_OR_ERROR_RETURN (args, "path", &path, err); GET_STRING_OR_ERROR_RETURN (args, "maildir", &maildir, err); docid = mu_store_add_path (ctx->store, path, maildir, err); if (docid == MU_STORE_INVALID_DOCID) print_and_clear_g_error (err); else { gchar *escpath; escpath = mu_str_escape_c_literal (path, TRUE); print_expr ("(:info add :path %s :docid %u)", escpath, docid); msg = mu_store_get_msg (ctx->store, docid, err); if (msg) { sexp = mu_msg_to_sexp (msg, docid, NULL, MU_MSG_OPTION_VERIFY); print_expr ("(:update %s :move nil)", sexp); mu_msg_unref(msg); g_free (sexp); } g_free (escpath); } return MU_OK; }
static MuError move_msgid (MuStore *store, unsigned docid, const char* flagstr, GError **err) { MuMsg *msg; MuError rv; MuFlags flags; rv = MU_ERROR; msg = mu_store_get_msg (store, docid, err); if (!msg) goto leave; flags = flagstr ? get_flags (mu_msg_get_path(msg), flagstr) : mu_msg_get_flags (msg); if (flags == MU_FLAG_INVALID) { mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, "invalid flags"); goto leave; } rv = do_move (store, docid, msg, NULL, flags, err); leave: if (msg) mu_msg_unref (msg); if (rv != MU_OK) print_and_clear_g_error (err); return rv; }
static gboolean handle_msg (const char *fname, MuConfig *opts, GError **err) { MuMsg *msg; gboolean rv; err = NULL; msg = mu_msg_new_from_file (fname, NULL, err); if (!msg) return FALSE; switch (opts->format) { case MU_CONFIG_FORMAT_PLAIN: rv = view_msg_plain (msg, NULL, opts->summary, !opts->nocolor); break; case MU_CONFIG_FORMAT_SEXP: rv = view_msg_sexp (msg); break; default: g_critical ("bug: should not be reached"); rv = FALSE; } mu_msg_unref (msg); return rv; }
int main(int argc, char *argv[]) { MuMsg *msg; GError *err; if (argc != 2) { g_print ("msg2pdf: generate pdf files from e-mail messages\n" "usage: msg2pdf <msgfile>\n"); return 1; } gtk_init (&argc, &argv); if (access (argv[1], R_OK) != 0) { g_printerr ("%s is not a readable file\n", argv[1]); return 1; } err = NULL; msg = mu_msg_new_from_file (argv[1], NULL, &err); if (!msg) { g_printerr ("failed to create msg for %s\n", argv[1]); goto err; } if (!convert_to_pdf (msg, &err)) { g_printerr ("failed to create pdf from %s\n", argv[1]); goto err; } /* it worked! */ mu_msg_unref (msg); return 0; err: /* some error occured */ mu_msg_unref (msg); if (err) g_printerr ("error: %s", err->message); g_clear_error (&err); return 1; }
void mu_container_destroy (MuContainer *c) { if (!c) return; if (c->msg) mu_msg_unref (c->msg); g_slice_free (MuContainer, c); }
/* * creating a message object just to get a path seems a bit excessive * maybe mu_store_get_path could be added if this turns out to be a * problem * * NOTE: not re-entrant. */ static const char* get_path_from_docid (MuStore *store, unsigned docid, GError **err) { MuMsg *msg; const char* msgpath; static char path[PATH_MAX + 1]; msg = mu_store_get_msg (store, docid, err); if (!msg) return NULL; msgpath = mu_msg_get_path (msg); if (!msgpath) { mu_msg_unref (msg); return NULL; } strncpy (path, msgpath, sizeof(path)); mu_msg_unref (msg); return path; }
static void set_message (MuMsgBodyView *self, MuMsg *msg) { if (self->_priv->_msg == msg) return; /* nothing to todo */ if (self->_priv->_msg) { mu_msg_unref (self->_priv->_msg); self->_priv->_msg = NULL; } if (msg) self->_priv->_msg = mu_msg_ref (msg); }
/* * 'move' moves a message to a different maildir and/or changes its * flags. parameters are *either* a 'docid:' or 'msgid:' pointing to * the message, a 'maildir:' for the target maildir, and a 'flags:' * parameter for the new flags. * * returns an (:update <new-msg-sexp>) * */ static MuError cmd_move (ServerContext *ctx, GHashTable *args, GError **err) { unsigned docid; MuMsg *msg; MuFlags flags; const char *maildir, *flagstr; gboolean new_name; /* check if the move is based on the message id; if so, handle * it in move_msgid_maybe */ if (move_msgid_maybe (ctx, args, err)) return MU_OK; maildir = get_string_from_args (args, "maildir", TRUE, err); flagstr = get_string_from_args (args, "flags", TRUE, err); new_name = get_bool_from_args (args, "newname", TRUE, err); docid = determine_docid (ctx->query, args, err); if (docid == MU_STORE_INVALID_DOCID || !(msg = mu_store_get_msg (ctx->store, docid, err))) { print_and_clear_g_error (err); return MU_OK; } /* if maildir was not specified, take the current one */ if (!maildir) maildir = mu_msg_get_maildir (msg); /* determine the real target flags, which come from the * flags-parameter we received (ie., flagstr), if any, plus * the existing message flags. */ if (flagstr) flags = get_flags (mu_msg_get_path(msg), flagstr); else flags = mu_msg_get_flags (msg); if (flags == MU_FLAG_INVALID) { print_error (MU_ERROR_IN_PARAMETERS, "invalid flags"); goto leave; } if ((do_move (ctx->store, docid, msg, maildir, flags, new_name, err) != MU_OK)) print_and_clear_g_error (err); leave: mu_msg_unref (msg); return MU_OK; }
/* 'extract' extracts some mime part from a message */ static MuError cmd_extract (ServerContext *ctx, GHashTable *args, GError **err) { MuMsg *msg; int docid, index, action; MuError rv; MuMsgOptions opts; const char* actionstr, *indexstr; opts = get_encrypted_msg_opts (args); rv = MU_ERROR; /* read parameters */ GET_STRING_OR_ERROR_RETURN (args, "action", &actionstr, err); GET_STRING_OR_ERROR_RETURN (args, "index", &indexstr, err); index = atoi (indexstr); docid = determine_docid (ctx->query, args, err); if (docid == MU_STORE_INVALID_DOCID) { print_and_clear_g_error (err); return MU_OK; } if ((action = action_type (actionstr)) == INVALID_ACTION) { print_error (MU_ERROR_IN_PARAMETERS, "invalid action"); return MU_OK; } msg = mu_store_get_msg (ctx->store, docid, err); if (!msg) { print_error (MU_ERROR, "failed to get message"); return MU_OK; } switch (action) { case SAVE: rv = save_part (msg, docid, index, opts, args, err); break; case OPEN: rv = open_part (msg, docid, index, opts, err); break; case TEMP: rv = temp_part (msg, docid, index, opts, args, err); break; default: print_error (MU_ERROR_INTERNAL, "unknown action"); } if (rv != MU_OK) print_and_clear_g_error (err); mu_msg_unref (msg); return MU_OK; }
/* 'compose' produces the un-changed *original* message sexp (ie., the message * to reply to, forward or edit) for a new message to compose). It takes two * parameters: 'type' with the compose type (either reply, forward or * edit/resend), and 'docid' for the message to reply to. Note, type:new does * not have an original message, and therefore does not need a docid * * In returns a (:compose <type> [:original <original-msg>] [:include] ) * message (detals: see code below) * * Note ':include' t or nil determines whether to include attachments */ static MuError cmd_compose (ServerContext *ctx, GHashTable *args, GError **err) { const gchar *typestr; char *sexp, *atts; unsigned ctype; MuMsgOptions opts; opts = get_encrypted_msg_opts (args); GET_STRING_OR_ERROR_RETURN (args, "type", &typestr, err); ctype = compose_type (typestr); if (ctype == INVALID_TYPE) { print_error (MU_ERROR_IN_PARAMETERS, "invalid type to compose"); return MU_OK; } if (ctype == REPLY || ctype == FORWARD || ctype == EDIT || ctype == RESEND) { MuMsg *msg; const char *docidstr; GET_STRING_OR_ERROR_RETURN (args, "docid", &docidstr, err); msg = mu_store_get_msg (ctx->store, atoi(docidstr), err); if (!msg) { print_and_clear_g_error (err); return MU_OK; } sexp = mu_msg_to_sexp (msg, atoi(docidstr), NULL, opts); atts = (ctype == FORWARD) ? include_attachments (msg, opts) : NULL; mu_msg_unref (msg); } else atts = sexp = NULL; print_expr ("(:compose %s :original %s :include %s)", typestr, sexp ? sexp : "nil", atts ? atts : "nil"); g_free (sexp); g_free (atts); return MU_OK; }
static gboolean show_parts (const char* path, MuConfig *opts, GError **err) { MuMsg* msg; msg = mu_msg_new_from_file (path, NULL, err); if (!msg) return FALSE; g_print ("MIME-parts in this message:\n"); mu_msg_part_foreach (msg, FALSE, (MuMsgPartForeachFunc)each_part_show, GUINT_TO_POINTER(!opts->nocolor)); mu_msg_unref (msg); return TRUE; }
static MuError insert_or_update_maybe (const char *fullpath, const char *mdir, time_t filestamp, MuIndexCallbackData *data, gboolean *updated) { MuMsg *msg; GError *err; gboolean rv; *updated = FALSE; if (!needs_index (data, fullpath, filestamp)) return MU_OK; /* nothing to do for this one */ err = NULL; msg = mu_msg_new_from_file (fullpath, mdir, &err); if (!msg) { if (!err) g_warning ("error creating message object: %s", fullpath); else { g_warning ("%s", err->message); g_clear_error (&err); } /* warn, then simply continue */ return MU_OK; } /* we got a valid id; scan the message contents as well */ rv = mu_store_add_msg (data->_store, msg, &err); mu_msg_unref (msg); if (!rv) { g_warning ("error storing message object: %s", err ? err->message : "cause unknown"); g_clear_error (&err); return MU_ERROR; } *updated = TRUE; return MU_OK; }
MuError mu_cmd_verify (MuConfig *opts, GError **err) { MuMsg *msg; MuMsgOptions msgopts; VData vdata; g_return_val_if_fail (opts, MU_ERROR_INTERNAL); g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_VERIFY, MU_ERROR_INTERNAL); msg = mu_msg_new_from_file (opts->params[1], NULL, err); if (!msg) return MU_ERROR; msgopts = mu_config_get_msg_options (opts); vdata.status = MU_MSG_PART_SIG_STATUS_UNKNOWN; vdata.opts = opts; vdata.msg = NULL; /* TODO: update for decryption */ mu_msg_part_foreach (msg, msgopts, (MuMsgPartForeachFunc)each_sig, &vdata); /* if there's anything bad, all goodness goes away */ if (vdata.status & MU_MSG_PART_SIG_STATUS_BAD || vdata.status & MU_MSG_PART_SIG_STATUS_ERROR) vdata.status &= ~MU_MSG_PART_SIG_STATUS_GOOD; if (!opts->quiet) { gchar *str; str = mu_msg_part_sig_statuses_to_string (vdata.status); g_print ("verdict: %s\n", str); g_free (str); } mu_msg_unref (msg); return vdata.status == MU_MSG_PART_SIG_STATUS_GOOD ? MU_OK : MU_ERROR; }
/* 'view' gets a full (including body etc.) sexp for some message, * identified by either docid: or msgid:; return a (:view <sexp>) */ static MuError cmd_view (ServerContext *ctx, GSList *args, GError **err) { MuMsg *msg; const gchar *path; char *sexp; MuMsgOptions opts; unsigned docid; opts = get_view_msg_opts (args); /* when 'path' is specified, get the message at path */ path = get_string_from_args (args, "path", FALSE, NULL); if (path) { docid = 0; msg = mu_msg_new_from_file (path, NULL, err); } else { docid = determine_docid (ctx->query, args, err); if (docid == MU_STORE_INVALID_DOCID) { print_and_clear_g_error (err); return MU_OK; } msg = mu_store_get_msg (ctx->store, docid, err); } if (!msg) { print_and_clear_g_error (err); return MU_OK; } sexp = mu_msg_to_sexp (msg, docid, NULL, opts); mu_msg_unref (msg); print_expr ("(:view %s)\n", sexp); g_free (sexp); return MU_OK; }
MuError mu_cmd_verify (MuConfig *opts, GError **err) { MuMsg *msg; MuMsgOptions msgopts; VData vdata; g_return_val_if_fail (opts, MU_ERROR_INTERNAL); g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_VERIFY, MU_ERROR_INTERNAL); if (!opts->params[1]) { mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, "missing message-file parameter"); return MU_ERROR_IN_PARAMETERS; } msg = mu_msg_new_from_file (opts->params[1], NULL, err); if (!msg) return MU_ERROR; msgopts = mu_config_get_msg_options (opts) | MU_MSG_OPTION_VERIFY; vdata.report = NULL; vdata.combined_status = MU_MSG_PART_SIG_STATUS_UNSIGNED; vdata.oneline = FALSE; mu_msg_part_foreach (msg, msgopts, (MuMsgPartForeachFunc)each_sig, &vdata); if (!opts->quiet) print_verdict (&vdata, !opts->nocolor); mu_msg_unref (msg); g_free (vdata.report); return vdata.combined_status == MU_MSG_PART_SIG_STATUS_GOOD ? MU_OK : MU_ERROR; }
static gboolean show_parts (const char* path, MuConfig *opts, GError **err) { MuMsg *msg; MuMsgOptions msgopts; msg = mu_msg_new_from_file (path, NULL, err); if (!msg) return FALSE; msgopts = mu_config_get_msg_options (opts); /* TODO: update this for crypto */ g_print ("MIME-parts in this message:\n"); mu_msg_part_foreach (msg, msgopts, (MuMsgPartForeachFunc)each_part_show, GUINT_TO_POINTER(!opts->nocolor)); mu_msg_unref (msg); return TRUE; }