/* '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; }
/* * 'index' (re)indexs maildir at path:<path>, and responds with (:info * index ... ) messages while doing so (see the code) */ static MuError cmd_index (ServerContext *ctx, GSList *args, GError **err) { MuIndex *index; const char *argpath; char *path; index = NULL; GET_STRING_OR_ERROR_RETURN (args, "path", &argpath, err); if (!(path = get_checked_path (argpath))) goto leave; set_my_addresses (ctx->store, get_string_from_args (args, "my-addresses", TRUE, NULL)); if (!(index = mu_index_new (ctx->store, err))) goto leave; index_and_cleanup (index, path, err); leave: g_free (path); if (err && *err) print_and_clear_g_error (err); mu_index_destroy (index); 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; }
/* '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; 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); g_free (escpath); } return MU_OK; }
/* 'mkdir' attempts to create a maildir directory at 'path:'; sends an * (:info mkdir ...) message when it succeeds */ static MuError cmd_mkdir (ServerContext *ctx, GSList *args, GError **err) { const char *path; GET_STRING_OR_ERROR_RETURN (args, "path", &path, err); if (!mu_maildir_mkdir (path, 0755, FALSE, err)) print_and_clear_g_error (err); else print_expr ("(:info mkdir :message \"%s has been created\")", path); return MU_OK; }
static MuError temp_part (MuMsg *msg, unsigned docid, unsigned index, GSList *args, GError **err) { const char *what, *param; char *path; GET_STRING_OR_ERROR_RETURN (args, "what", &what, err); param = get_string_from_args (args, "param", TRUE, NULL); path = mu_msg_part_get_cache_path (msg, MU_MSG_OPTION_NONE, index, err); if (!path) print_and_clear_g_error (err); else if (!mu_msg_part_save (msg, MU_MSG_OPTION_USE_EXISTING, path, index, err)) print_and_clear_g_error (err); else { gchar *escpath; escpath = mu_str_escape_c_literal (path, FALSE); if (param) { char *escparam; escparam = mu_str_escape_c_literal (param, FALSE); print_expr ("(:temp \"%s\"" " :what \"%s\"" " :docid %u" " :param \"%s\""")", escpath, what, docid, escparam); g_free (escparam); } else print_expr ("(:temp \"%s\" :what \"%s\" :docid %u)", escpath, what, docid); g_free (escpath); } g_free (path); return MU_OK; }
/* * 'find' finds a list of messages matching some query, and takes a * parameter 'query' with the search query, and (optionally) a * parameter 'maxnum' with the maximum number of messages to return. * * returns: * => list of s-expressions, each describing a message => * (:found <number of found messages>) */ static MuError cmd_find (ServerContext *ctx, GSList *args, GError **err) { MuMsgIter *iter; unsigned foundnum; int maxnum; gboolean threads, reverse; MuMsgFieldId sortfield; const char *querystr; GET_STRING_OR_ERROR_RETURN (args, "query", &querystr, err); if (get_find_params (args, &threads, &sortfield, &reverse, &maxnum, err) != MU_OK) { print_and_clear_g_error (err); return MU_OK; } /* note: when we're threading, we get *all* matching messages, * and then only return maxnum; this is so that we maximimize * the change of all messages in a thread showing up */ iter = mu_query_run (ctx->query, querystr, threads, sortfield, reverse, threads ? -1 : maxnum, err); if (!iter) { print_and_clear_g_error (err); return MU_OK; } /* before sending new results, send an 'erase' message, so the * frontend knows it should erase the headers buffer. this * will ensure that the output of two finds will not be * mixed. */ print_expr ("(:erase t)"); foundnum = print_sexps (iter, threads, maxnum > 0 ? maxnum : G_MAXINT32); print_expr ("(:found %u)", foundnum); mu_msg_iter_destroy (iter); return MU_OK; }
static MuError save_part (MuMsg *msg, unsigned docid, unsigned index, GSList *args, GError **err) { gboolean rv; const gchar *path; gchar *escpath; GET_STRING_OR_ERROR_RETURN (args, "path", &path, err); rv = mu_msg_part_save (msg, MU_MSG_OPTION_OVERWRITE, path, index, err); if (!rv) { print_and_clear_g_error (err); return MU_OK; } escpath = mu_str_escape_c_literal (path, FALSE); print_expr ("(:info save :message \"%s has been saved\")", escpath); g_free (escpath); return MU_OK; }