* mu-cmd-server.c: improve error handling, support flagging message by message-id

This commit is contained in:
Dirk-Jan C. Binnema 2011-10-02 21:34:27 +03:00
parent 311c3b6847
commit a4646b29f1
1 changed files with 108 additions and 41 deletions

View File

@ -60,6 +60,8 @@
#define BOX "\376"
static void send_expr (const char* frm, ...) G_GNUC_PRINTF(1, 2);
static void
send_expr (const char* frm, ...)
{
@ -70,7 +72,7 @@ send_expr (const char* frm, ...)
va_start (ap, frm);
hdr = g_strdup_vprintf (frm, ap);
snprintf (pfx, sizeof(pfx), BOX "%u" BOX, strlen(hdr));
snprintf (pfx, sizeof(pfx), BOX "%u" BOX, strlen(hdr));
fputs (pfx, stdout);
fputs (hdr, stdout);
@ -80,15 +82,26 @@ send_expr (const char* frm, ...)
}
static MuError server_error (GError **err, MuError merr, const char* frm, ...)
G_GNUC_PRINTF(3, 4);
static MuError
server_error (GError **err, MuError merr, const char* str)
server_error (GError **err, MuError merr, const char* frm, ...)
{
gboolean has_err;
char *errmsg;
va_list ap;
va_start (ap, frm);
errmsg = g_strdup_vprintf (frm, ap);
has_err = err && *err;
send_expr ("(:error %u :error-message \"%s\") ",
has_err ? (unsigned)(*err)->code : merr,
has_err ? (*err)->message : str);
has_err ? (*err)->message : errmsg);
g_free (errmsg);
va_end (ap);
return has_err ? (unsigned)(*err)->code : merr;
}
@ -290,7 +303,7 @@ cmd_find (MuStore *store, MuQuery *query, GSList *lst, GError **err)
sexp = mu_msg_to_sexp (msg,
mu_msg_iter_get_docid (iter),
NULL, TRUE);
send_expr (sexp);
send_expr ("%s", sexp);
g_free (sexp);
++u;
}
@ -314,20 +327,68 @@ cmd_mkdir (GSList *lst, GError **err)
if (!mu_maildir_mkdir ((const char*)lst->data, 0755, FALSE, err))
return server_error (err, MU_G_ERROR_CODE (err),
"failed to create maildir");
"failed to create maildir '%s'",
(const char*)lst->data);
return MU_OK;
}
static unsigned
get_docid (const char* str)
get_docid_from_msgid (MuQuery *query, const char *str, GError **err)
{
gchar *querystr;
unsigned docid;
MuMsgIter *iter;
querystr = g_strdup_printf ("msgid:%s", str);
iter = mu_query_run (query, querystr, FALSE,
MU_MSG_FIELD_ID_NONE, FALSE, err);
g_free (querystr);
docid = MU_STORE_INVALID_DOCID;
if (!iter)
if (err && *err == NULL)
g_set_error (err, 0, MU_ERROR_NO_MATCHES,
"could not find message %s", str);
else
return docid;
else {
MuMsg *msg;
msg = mu_msg_iter_get_msg_floating (iter);
if (!mu_msg_is_readable(msg)) {
g_set_error (err, 0, MU_ERROR_FILE_CANNOT_READ,
"'%s' is not readable",
mu_msg_get_path(msg));
} else
docid = mu_msg_iter_get_docid (iter);
mu_msg_iter_destroy (iter);
}
return docid;
}
/* the string contains either a number (docid) or a message-id if it
* doesn't look like a number, and the query param is non-nil, try to
* locale the message with message-id in the database, and return its
* docid */
static unsigned
get_docid (MuQuery *query, const char *str, GError **err)
{
unsigned docid;
char *endptr;
docid = strtol (str, &endptr, 10);
if (*endptr != '\0')
return 0; /* something wrong with the docid */
if (*endptr != '\0') {
if (!query) {
g_set_error (err, 0, MU_ERROR_IN_PARAMETERS,
"invalid docid '%s'", str);
return MU_STORE_INVALID_DOCID;
} else
return get_docid_from_msgid (query, str, err);
}
return docid;
}
@ -382,7 +443,8 @@ do_move (MuStore *store, unsigned docid, MuMsg *msg, const char *maildir,
static MuError
move_or_flag (MuStore *store, GSList *lst, gboolean is_move, GError **err)
move_or_flag (MuStore *store, MuQuery *query, GSList *lst, gboolean is_move,
GError **err)
{
MuError merr;
unsigned docid;
@ -391,9 +453,10 @@ move_or_flag (MuStore *store, GSList *lst, gboolean is_move, GError **err)
GSList *flagitem;
const char *mdir;
if ((docid = get_docid ((const char*)lst->data)) == 0)
if ((docid = get_docid (query, (const char*)lst->data, err)) == 0)
return server_error (err, MU_ERROR_IN_PARAMETERS,
"invalid docid");
"invalid docid '%s'",
(const char*)lst->data);
msg = mu_store_get_msg (store, docid, err);
if (!msg)
@ -430,17 +493,17 @@ cmd_move (MuStore *store, GSList *lst, GError **err)
(NULL, MU_ERROR_IN_PARAMETERS,
"usage: move <docid> <maildir> [<flags>]");
return move_or_flag (store, lst, TRUE, err);
return move_or_flag (store, NULL, lst, TRUE, err);
}
static MuError
cmd_flag (MuStore *store, GSList *lst, GError **err)
cmd_flag (MuStore *store, MuQuery *query, GSList *lst, GError **err)
{
if (!check_param_num (lst, 2, 2))
return server_error (NULL, MU_ERROR_IN_PARAMETERS,
"usage: flag <docid> <flags>");
"usage: flag <docid>|<msgid> <flags>");
return move_or_flag (store, lst, FALSE, err);
return move_or_flag (store, query, lst, FALSE, err);
}
@ -456,9 +519,9 @@ cmd_remove (MuStore *store, GSList *lst, GError **err)
return server_error (NULL, MU_ERROR_IN_PARAMETERS,
"usage: remove <docid>");
docid = get_docid ((const char*)lst->data);
if (docid == 0)
return server_error (NULL, MU_ERROR_IN_PARAMETERS,
docid = get_docid (NULL, (const char*)lst->data, err);
if (docid == MU_STORE_INVALID_DOCID)
return server_error (err, MU_ERROR_IN_PARAMETERS,
"invalid docid");
path = get_path_from_docid (store, docid, err);
@ -490,7 +553,11 @@ save_or_open (MuStore *store, GSList *args, gboolean is_save, GError **err)
char* targetpath;
gboolean rv;
docid = get_docid ((const char*)args->data);
docid = get_docid (NULL, (const char*)args->data, err);
if (docid == MU_STORE_INVALID_DOCID)
return server_error (err, MU_ERROR_IN_PARAMETERS,
"invalid docid");
msg = mu_store_get_msg (store, docid, err);
if (!msg)
return server_error (err, MU_ERROR, "failed to get message");
@ -552,7 +619,6 @@ cmd_save (MuStore *store, GSList *args, GError **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,
@ -568,15 +634,15 @@ cmd_view (MuStore *store, GSList *args, GError **err)
{
MuMsg *msg;
unsigned docid;
char *sexp, *str;
char *sexp;
if (!check_param_num (args, 1, 1))
return server_error (NULL, MU_ERROR_IN_PARAMETERS,
"message <docid> <view|reply|forward>");
docid = get_docid ((const char*)args->data);
if (docid == 0)
return server_error (NULL, MU_ERROR_IN_PARAMETERS,
docid = get_docid (NULL, (const char*)args->data, err);
if (docid == MU_STORE_INVALID_DOCID)
return server_error (err, MU_ERROR_IN_PARAMETERS,
"invalid docid");
msg = mu_store_get_msg (store, docid, err);
@ -587,11 +653,9 @@ cmd_view (MuStore *store, GSList *args, GError **err)
sexp = mu_msg_to_sexp (msg, docid, NULL, FALSE);
mu_msg_unref (msg);
str = g_strdup_printf ("(:view %s)", sexp);
send_expr (str);
send_expr ("(:view %s)", sexp);
g_free (sexp);
g_free (str);
return MU_OK;
}
@ -604,31 +668,32 @@ cmd_compose (MuStore *store, GSList *args, GError **err)
MuMsg *msg;
unsigned docid;
char *sexp;
const char* action;
const char* ctype;
if ((!check_param_num (args, 2, 2)))
return server_error (NULL, MU_ERROR_IN_PARAMETERS,
"compose <reply|forward> <docid>");
"compose <reply|forward|edit> <docid>");
action = (const char*)args->data;
if (strcmp (action, "reply") != 0 && strcmp(action, "forward") != 0
&& strcmp (action, "draft") != 0)
ctype = (const char*)args->data;
if (strcmp (ctype, "reply") != 0 && strcmp(ctype, "forward") != 0
&& strcmp (ctype, "edit") != 0)
return server_error (NULL, MU_ERROR_IN_PARAMETERS,
"compose <reply|forward|draft> <docid>");
"compose <reply|forward|edit> <docid>");
docid = get_docid ((const char*)g_slist_nth(args, 1)->data);
if (docid == 0)
return server_error (NULL, MU_ERROR_IN_PARAMETERS,
docid = get_docid (NULL, (const char*)g_slist_nth(args, 1)->data, err);
if (docid == MU_STORE_INVALID_DOCID)
return server_error (err, MU_ERROR_IN_PARAMETERS,
"invalid docid");
msg = mu_store_get_msg (store, docid, err);
if (!msg)
return server_error (err, MU_ERROR,"failed to get message");
return server_error (err, MU_ERROR,
"failed to get message");
sexp = mu_msg_to_sexp (msg, docid, NULL, FALSE);
mu_msg_unref (msg);
send_expr ("(:compose %s :action %s)", sexp, action);
send_expr ("(:compose %s :compose-type %s)", sexp, ctype);
g_free (sexp);
@ -664,7 +729,8 @@ cmd_add (MuStore *store, GSList *lst, GError **err)
docid = mu_store_add_path (store, path, maildir, err);
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 '%s'", path);
escpath = mu_str_escape_c_literal (path, TRUE);
send_expr ("(:info add :path %s :docid %u)", escpath, docid);
@ -690,7 +756,8 @@ cmd_index (MuStore *store, GSList *lst, GError **err)
index = mu_index_new (store, err);
if (!index)
return server_error (err, MU_ERROR, "failed to create index");
return server_error (err, MU_ERROR,
"failed to create index object");
mu_index_stats_clear (&stats);
maildir = (const char*)lst->data;
@ -739,7 +806,7 @@ handle_command (Cmd cmd, MuStore *store, MuQuery *query, GSList *args,
case CMD_ADD: rv = cmd_add (store, args, err); break;
case CMD_COMPOSE: rv = cmd_compose (store, args, err); break;
case CMD_FIND: rv = cmd_find (store, query, args, err); break;
case CMD_FLAG: rv = cmd_flag (store, args, err); break;
case CMD_FLAG: rv = cmd_flag (store, query, args, err); break;
case CMD_INDEX: rv = cmd_index (store, args, err); break;
case CMD_MKDIR: rv = cmd_mkdir (args, err); break;
case CMD_MOVE: rv = cmd_move (store, args, err); break;