Beispiel #1
0
/* '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;
}
Beispiel #2
0
/*
 * '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;
}
Beispiel #3
0
/* '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;
}
Beispiel #4
0
/* '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;
}
Beispiel #5
0
/* '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;
}
Beispiel #6
0
/* '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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
/*
 * '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;
}
Beispiel #9
0
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;
}