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; }
/* '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; }
/* * '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; }
/* '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; }
/* * 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; }