2012-01-04 23:08:27 +01:00
|
|
|
/*
|
2021-03-12 21:20:48 +01:00
|
|
|
** Copyright (C) 2011-2021 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
2012-01-04 23:08:27 +01:00
|
|
|
**
|
|
|
|
** This program is free software; you can redistribute it and/or modify it
|
|
|
|
** under the terms of the GNU General Public License as published by the
|
|
|
|
** Free Software Foundation; either version 3, or (at your option) any
|
|
|
|
** later version.
|
|
|
|
**
|
|
|
|
** This program is distributed in the hope that it will be useful,
|
|
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
** GNU General Public License for more details.
|
|
|
|
**
|
|
|
|
** You should have received a copy of the GNU General Public License
|
|
|
|
** along with this program; if not, write to the Free Software Foundation,
|
|
|
|
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
**
|
|
|
|
*/
|
2020-11-03 09:01:44 +01:00
|
|
|
#include "mu-guile-message.hh"
|
2022-02-19 17:59:42 +01:00
|
|
|
#include "libguile/scm.h"
|
2022-03-20 13:12:41 +01:00
|
|
|
#include "message/mu-message.hh"
|
2012-01-04 23:08:27 +01:00
|
|
|
#include <config.h>
|
2020-10-31 13:35:50 +01:00
|
|
|
|
2012-01-04 23:08:27 +01:00
|
|
|
#include <glib-object.h>
|
2020-11-03 09:01:44 +01:00
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
2012-01-04 23:08:27 +01:00
|
|
|
#include <libguile.h>
|
2020-11-03 09:01:44 +01:00
|
|
|
#pragma GCC diagnostic pop
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2020-11-03 09:01:44 +01:00
|
|
|
#include "mu-guile.hh"
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2020-11-07 13:06:23 +01:00
|
|
|
#include <mu-runtime.hh>
|
2019-07-28 13:27:05 +02:00
|
|
|
#include <mu-store.hh>
|
2020-11-03 09:01:44 +01:00
|
|
|
#include <mu-query.hh>
|
2020-11-28 09:08:04 +01:00
|
|
|
|
|
|
|
using namespace Mu;
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2012-07-14 11:32:15 +02:00
|
|
|
/* pseudo field, not in Xapian */
|
2022-03-20 13:12:41 +01:00
|
|
|
constexpr auto MU_GUILE_MSG_FIELD_ID_TIMESTAMP = Field::id_size() + 1;
|
2012-07-14 11:32:15 +02:00
|
|
|
|
|
|
|
/* some symbols */
|
|
|
|
static SCM SYMB_PRIO_LOW, SYMB_PRIO_NORMAL, SYMB_PRIO_HIGH;
|
2022-02-16 21:06:00 +01:00
|
|
|
static std::array<SCM, AllMessageFlagInfos.size()> SYMB_FLAGS;
|
2021-10-20 11:18:15 +02:00
|
|
|
static SCM SYMB_CONTACT_TO, SYMB_CONTACT_CC, SYMB_CONTACT_BCC, SYMB_CONTACT_FROM;
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2022-04-22 06:59:48 +02:00
|
|
|
struct MuMsgWrapper {
|
|
|
|
MuMsgWrapper(const Message& msg, bool unrefme):
|
|
|
|
_msg{msg}, _unrefme(unrefme)
|
|
|
|
{}
|
|
|
|
Message _msg;
|
|
|
|
bool _unrefme;
|
2012-01-04 23:08:27 +01:00
|
|
|
};
|
2022-04-22 06:59:48 +02:00
|
|
|
static long MSG_TAG;
|
2012-01-04 23:08:27 +01:00
|
|
|
|
|
|
|
static gboolean
|
2021-10-20 11:18:15 +02:00
|
|
|
mu_guile_scm_is_msg(SCM scm)
|
2012-01-04 23:08:27 +01:00
|
|
|
{
|
|
|
|
return SCM_NIMP(scm) && (long)SCM_CAR(scm) == MSG_TAG;
|
|
|
|
}
|
|
|
|
|
|
|
|
SCM
|
2022-04-22 06:59:48 +02:00
|
|
|
mu_guile_msg_to_scm(const Message& msg)
|
2012-01-04 23:08:27 +01:00
|
|
|
{
|
2021-10-20 11:18:15 +02:00
|
|
|
MuMsgWrapper* msgwrap;
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
msgwrap = (MuMsgWrapper*)scm_gc_malloc(sizeof(MuMsgWrapper), "msg");
|
|
|
|
msgwrap->_msg = msg;
|
2012-01-04 23:08:27 +01:00
|
|
|
msgwrap->_unrefme = FALSE;
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
SCM_RETURN_NEWSMOB(MSG_TAG, msgwrap);
|
2012-01-04 23:08:27 +01:00
|
|
|
}
|
|
|
|
|
2022-02-16 21:06:00 +01:00
|
|
|
typedef struct {
|
2022-03-20 13:12:41 +01:00
|
|
|
Flags flags;
|
|
|
|
SCM lst;
|
2022-02-16 21:06:00 +01:00
|
|
|
} FlagData;
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2022-01-30 13:33:25 +01:00
|
|
|
#define MU_GUILE_INITIALIZED_OR_ERROR \
|
|
|
|
do { \
|
|
|
|
if (!(mu_guile_initialized())) { \
|
|
|
|
mu_guile_error(FUNC_NAME, \
|
2022-02-19 17:59:42 +01:00
|
|
|
0, \
|
|
|
|
"mu not initialized; call mu:initialize", \
|
|
|
|
SCM_UNDEFINED); \
|
2022-01-30 13:33:25 +01:00
|
|
|
return SCM_UNSPECIFIED; \
|
|
|
|
} \
|
2021-03-12 21:20:48 +01:00
|
|
|
} while (0)
|
2012-07-14 11:32:15 +02:00
|
|
|
|
2012-01-04 23:08:27 +01:00
|
|
|
|
|
|
|
static SCM
|
2022-04-22 06:59:48 +02:00
|
|
|
get_flags_scm(const Message& msg)
|
2012-01-04 23:08:27 +01:00
|
|
|
{
|
2022-02-16 21:06:00 +01:00
|
|
|
SCM lst{SCM_EOL};
|
2022-04-22 06:59:48 +02:00
|
|
|
const auto flags{msg.flags()};
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2022-02-16 21:06:00 +01:00
|
|
|
for (auto i = 0; i != AllMessageFlagInfos.size(); ++i) {
|
|
|
|
const auto& info{AllMessageFlagInfos.at(i)};
|
|
|
|
if (any_of(info.flag & flags))
|
|
|
|
scm_append_x(scm_list_2(lst, scm_list_1(SYMB_FLAGS.at(i))));
|
|
|
|
}
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2022-02-16 21:06:00 +01:00
|
|
|
return lst;
|
2012-01-04 23:08:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static SCM
|
2022-04-22 06:59:48 +02:00
|
|
|
get_prio_scm(const Message& msg)
|
2012-01-04 23:08:27 +01:00
|
|
|
{
|
2022-04-22 06:59:48 +02:00
|
|
|
switch (msg.priority()) {
|
2022-03-20 13:12:41 +01:00
|
|
|
case Priority::Low: return SYMB_PRIO_LOW;
|
|
|
|
case Priority::Normal: return SYMB_PRIO_NORMAL;
|
|
|
|
case Priority::High: return SYMB_PRIO_HIGH;
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
default: g_return_val_if_reached(SCM_UNDEFINED);
|
2012-01-04 23:08:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static SCM
|
2022-04-22 06:59:48 +02:00
|
|
|
msg_string_list_field(const Message& msg, Field::Id field_id)
|
2012-01-04 23:08:27 +01:00
|
|
|
{
|
2022-04-22 06:59:48 +02:00
|
|
|
SCM scmlst{SCM_EOL};
|
|
|
|
for (auto&& val: msg.document().string_vec_value(field_id)) {
|
2012-01-04 23:08:27 +01:00
|
|
|
SCM item;
|
2022-04-22 06:59:48 +02:00
|
|
|
item = scm_list_1(mu_guile_scm_from_str(val.c_str()));
|
2021-10-20 11:18:15 +02:00
|
|
|
scmlst = scm_append_x(scm_list_2(scmlst, item));
|
2012-01-04 23:08:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return scmlst;
|
|
|
|
}
|
|
|
|
|
2012-09-17 10:13:37 +02:00
|
|
|
static SCM
|
2022-04-22 06:59:48 +02:00
|
|
|
get_body(const Message& msg, bool html)
|
2012-09-17 10:13:37 +02:00
|
|
|
{
|
2022-04-22 06:59:48 +02:00
|
|
|
if (const auto body = html ? msg.body_html() : msg.body_text(); body)
|
|
|
|
return mu_guile_scm_from_str(body->c_str());
|
2012-09-17 10:13:37 +02:00
|
|
|
else
|
2022-04-22 06:59:48 +02:00
|
|
|
return SCM_BOOL_F;
|
2012-09-17 10:13:37 +02:00
|
|
|
}
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
SCM_DEFINE(get_field,
|
2022-02-19 17:59:42 +01:00
|
|
|
"mu:c:get-field",
|
|
|
|
2,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
(SCM MSG, SCM FIELD),
|
|
|
|
"Get the field FIELD from message MSG.\n")
|
2012-01-04 23:08:27 +01:00
|
|
|
#define FUNC_NAME s_get_field
|
|
|
|
{
|
2021-10-20 11:18:15 +02:00
|
|
|
MuMsgWrapper* msgwrap;
|
2022-03-04 23:34:39 +01:00
|
|
|
size_t field_id;
|
2021-10-20 11:18:15 +02:00
|
|
|
msgwrap = (MuMsgWrapper*)SCM_CDR(MSG);
|
2022-04-22 06:59:48 +02:00
|
|
|
const auto& msg{msgwrap->_msg};
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2012-07-14 14:52:37 +02:00
|
|
|
MU_GUILE_INITIALIZED_OR_ERROR;
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
|
|
|
SCM_ASSERT(scm_integer_p(FIELD), FIELD, SCM_ARG2, FUNC_NAME);
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2022-03-04 23:34:39 +01:00
|
|
|
field_id = scm_to_int(FIELD);
|
|
|
|
if (field_id == MU_GUILE_MSG_FIELD_ID_TIMESTAMP)
|
2022-04-22 06:59:48 +02:00
|
|
|
return scm_from_uint((unsigned)msgwrap->_msg.date());
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2022-03-20 13:12:41 +01:00
|
|
|
const auto field_opt{field_from_number(static_cast<size_t>(field_id))};
|
|
|
|
SCM_ASSERT(!!field_opt, FIELD, SCM_ARG2, FUNC_NAME);
|
2012-01-12 23:45:46 +01:00
|
|
|
|
2022-03-20 13:12:41 +01:00
|
|
|
switch (field_opt->id) {
|
2022-03-04 23:34:39 +01:00
|
|
|
case Field::Id::Priority:
|
2022-04-22 06:59:48 +02:00
|
|
|
return get_prio_scm(msg);
|
2022-03-04 23:34:39 +01:00
|
|
|
case Field::Id::Flags:
|
2022-04-22 06:59:48 +02:00
|
|
|
return get_flags_scm(msg);
|
2022-03-04 23:34:39 +01:00
|
|
|
case Field::Id::BodyHtml:
|
2022-04-22 06:59:48 +02:00
|
|
|
return get_body(msg, true);
|
2022-03-04 23:34:39 +01:00
|
|
|
case Field::Id::BodyText:
|
2022-04-22 06:59:48 +02:00
|
|
|
return get_body(msg, false);
|
2012-01-12 23:45:46 +01:00
|
|
|
|
2012-01-04 23:08:27 +01:00
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
2022-03-20 13:12:41 +01:00
|
|
|
switch (field_opt->type) {
|
2022-03-04 23:34:39 +01:00
|
|
|
case Field::Type::String:
|
2022-04-22 06:59:48 +02:00
|
|
|
return mu_guile_scm_from_str(msg.document().string_value(field_opt->id).c_str());
|
2022-03-04 23:34:39 +01:00
|
|
|
case Field::Type::ByteSize:
|
|
|
|
case Field::Type::TimeT:
|
|
|
|
case Field::Type::Integer:
|
2022-04-22 06:59:48 +02:00
|
|
|
return scm_from_uint(msg.document().integer_value(field_opt->id));
|
2022-03-04 23:34:39 +01:00
|
|
|
case Field::Type::StringList:
|
2022-04-22 06:59:48 +02:00
|
|
|
return msg_string_list_field(msg, field_opt->id);
|
2021-10-20 11:18:15 +02:00
|
|
|
default: SCM_ASSERT(0, FIELD, SCM_ARG2, FUNC_NAME);
|
2012-01-04 23:08:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
2022-02-19 17:59:42 +01:00
|
|
|
static SCM
|
2022-04-22 06:59:48 +02:00
|
|
|
contacts_to_list(const Message& msg, Option<Field::Id> field_id)
|
2012-01-04 23:08:27 +01:00
|
|
|
{
|
2022-02-19 17:59:42 +01:00
|
|
|
SCM list{SCM_EOL};
|
|
|
|
|
2022-04-22 06:59:48 +02:00
|
|
|
const auto contacts{field_id ?
|
|
|
|
msg.document().contacts_value(*field_id) :
|
|
|
|
msg.all_contacts()};
|
|
|
|
|
|
|
|
for (auto&& contact: contacts) {
|
2022-02-19 17:59:42 +01:00
|
|
|
SCM item{scm_list_1(
|
|
|
|
scm_cons(mu_guile_scm_from_str(contact.name.c_str()),
|
|
|
|
mu_guile_scm_from_str(contact.email.c_str())))};
|
|
|
|
list = scm_append_x(scm_list_2(list, item));
|
|
|
|
}
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2022-02-19 17:59:42 +01:00
|
|
|
return list;
|
2012-01-04 23:08:27 +01:00
|
|
|
}
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
SCM_DEFINE(get_contacts,
|
2022-02-19 17:59:42 +01:00
|
|
|
"mu:c:get-contacts",
|
|
|
|
2,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
(SCM MSG, SCM CONTACT_TYPE),
|
|
|
|
"Get a list of contact information pairs.\n")
|
2012-01-04 23:08:27 +01:00
|
|
|
#define FUNC_NAME s_get_contacts
|
|
|
|
{
|
2022-02-19 17:59:42 +01:00
|
|
|
MuMsgWrapper* msgwrap;
|
|
|
|
SCM list;
|
2022-03-19 17:56:10 +01:00
|
|
|
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2012-07-14 14:52:37 +02:00
|
|
|
MU_GUILE_INITIALIZED_OR_ERROR;
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
|
|
|
SCM_ASSERT(scm_symbol_p(CONTACT_TYPE) || scm_is_bool(CONTACT_TYPE),
|
2022-02-19 17:59:42 +01:00
|
|
|
CONTACT_TYPE,
|
|
|
|
SCM_ARG2,
|
|
|
|
FUNC_NAME);
|
2012-01-04 23:08:27 +01:00
|
|
|
|
|
|
|
if (CONTACT_TYPE == SCM_BOOL_F)
|
|
|
|
return SCM_UNSPECIFIED; /* nothing to do */
|
2022-02-19 17:59:42 +01:00
|
|
|
|
2022-03-28 07:58:04 +02:00
|
|
|
Option<Field::Id> field_id;
|
2022-02-19 17:59:42 +01:00
|
|
|
if (CONTACT_TYPE == SCM_BOOL_T)
|
2022-03-19 17:56:10 +01:00
|
|
|
field_id = {}; /* get all */
|
2012-01-04 23:08:27 +01:00
|
|
|
else {
|
2021-10-20 11:18:15 +02:00
|
|
|
if (scm_is_eq(CONTACT_TYPE, SYMB_CONTACT_TO))
|
2022-03-19 17:56:10 +01:00
|
|
|
field_id = Field::Id::To;
|
2021-10-20 11:18:15 +02:00
|
|
|
else if (scm_is_eq(CONTACT_TYPE, SYMB_CONTACT_CC))
|
2022-03-19 17:56:10 +01:00
|
|
|
field_id = Field::Id::Cc;
|
2021-10-20 11:18:15 +02:00
|
|
|
else if (scm_is_eq(CONTACT_TYPE, SYMB_CONTACT_BCC))
|
2022-03-19 17:56:10 +01:00
|
|
|
field_id = Field::Id::Bcc;
|
2021-10-20 11:18:15 +02:00
|
|
|
else if (scm_is_eq(CONTACT_TYPE, SYMB_CONTACT_FROM))
|
2022-03-19 17:56:10 +01:00
|
|
|
field_id = Field::Id::From;
|
2020-11-03 09:01:44 +01:00
|
|
|
else {
|
2021-10-20 11:18:15 +02:00
|
|
|
mu_guile_error(FUNC_NAME, 0, "invalid contact type", SCM_UNDEFINED);
|
2021-03-12 21:20:48 +01:00
|
|
|
return SCM_UNSPECIFIED;
|
|
|
|
}
|
2012-01-04 23:08:27 +01:00
|
|
|
}
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
msgwrap = (MuMsgWrapper*)SCM_CDR(MSG);
|
2022-02-19 17:59:42 +01:00
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
#pragma GCC diagnostic push
|
2021-03-12 21:20:48 +01:00
|
|
|
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
2022-03-19 17:56:10 +01:00
|
|
|
list = contacts_to_list(msgwrap->_msg, field_id);
|
2021-03-12 21:20:48 +01:00
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
|
2012-07-14 11:32:15 +02:00
|
|
|
/* explicitly close the file backend, so we won't run out of fds */
|
2022-04-22 06:59:48 +02:00
|
|
|
msg.u
|
2012-01-12 23:45:46 +01:00
|
|
|
|
2022-02-19 17:59:42 +01:00
|
|
|
return list;
|
2012-01-04 23:08:27 +01:00
|
|
|
}
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
2012-01-12 23:45:46 +01:00
|
|
|
struct _AttInfo {
|
|
|
|
SCM attlist;
|
2012-01-15 13:37:30 +01:00
|
|
|
gboolean attachments_only;
|
2012-01-12 23:45:46 +01:00
|
|
|
};
|
|
|
|
typedef struct _AttInfo AttInfo;
|
|
|
|
|
|
|
|
static void
|
2021-10-20 11:18:15 +02:00
|
|
|
each_part(MuMsg* msg, MuMsgPart* part, AttInfo* attinfo)
|
2012-01-12 23:45:46 +01:00
|
|
|
{
|
2012-07-31 17:46:27 +02:00
|
|
|
char *mime_type, *filename;
|
2021-10-20 11:18:15 +02:00
|
|
|
SCM elm;
|
2012-01-12 23:45:46 +01:00
|
|
|
|
|
|
|
if (!part->type)
|
|
|
|
return;
|
2021-10-20 11:18:15 +02:00
|
|
|
if (attinfo->attachments_only && !mu_msg_part_maybe_attachment(part))
|
2012-01-12 23:45:46 +01:00
|
|
|
return;
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
mime_type = g_strdup_printf("%s/%s", part->type, part->subtype);
|
|
|
|
filename = mu_msg_part_get_filename(part, FALSE);
|
|
|
|
|
|
|
|
elm = scm_list_5(
|
|
|
|
/* msg */
|
|
|
|
mu_guile_scm_from_str(mu_msg_get_path(msg)),
|
|
|
|
/* index */
|
|
|
|
scm_from_uint(part->index),
|
|
|
|
/* filename or #f */
|
|
|
|
filename ? mu_guile_scm_from_str(filename) : SCM_BOOL_F,
|
|
|
|
/* mime-type */
|
|
|
|
mime_type ? mu_guile_scm_from_str(mime_type) : SCM_BOOL_F,
|
|
|
|
/* size */
|
|
|
|
part->size > 0 ? scm_from_uint(part->size) : SCM_BOOL_F);
|
|
|
|
|
|
|
|
g_free(mime_type);
|
|
|
|
g_free(filename);
|
|
|
|
|
|
|
|
attinfo->attlist = scm_cons(elm, attinfo->attlist);
|
2012-01-12 23:45:46 +01:00
|
|
|
}
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
SCM_DEFINE(get_parts,
|
2022-02-19 17:59:42 +01:00
|
|
|
"mu:c:get-parts",
|
|
|
|
1,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
(SCM MSG, SCM ATTS_ONLY),
|
|
|
|
"Get the list of mime-parts for MSG. If ATTS_ONLY is #t, only"
|
|
|
|
"get parts that are (look like) attachments. The resulting list has "
|
|
|
|
"elements which are list of the form (index name mime-type size).\n")
|
2012-01-12 23:45:46 +01:00
|
|
|
#define FUNC_NAME s_get_parts
|
|
|
|
{
|
2021-10-20 11:18:15 +02:00
|
|
|
MuMsgWrapper* msgwrap;
|
|
|
|
AttInfo attinfo;
|
2012-01-12 23:45:46 +01:00
|
|
|
|
2012-07-14 14:52:37 +02:00
|
|
|
MU_GUILE_INITIALIZED_OR_ERROR;
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
|
|
|
SCM_ASSERT(scm_is_bool(ATTS_ONLY), ATTS_ONLY, SCM_ARG2, FUNC_NAME);
|
2012-01-12 23:45:46 +01:00
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
attinfo.attlist = SCM_EOL; /* empty list */
|
2012-01-15 13:37:30 +01:00
|
|
|
attinfo.attachments_only = ATTS_ONLY == SCM_BOOL_T ? TRUE : FALSE;
|
2012-01-12 23:45:46 +01:00
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
msgwrap = (MuMsgWrapper*)SCM_CDR(MSG);
|
|
|
|
mu_msg_part_foreach(msgwrap->_msg,
|
2022-02-19 17:59:42 +01:00
|
|
|
MU_MSG_OPTION_NONE,
|
|
|
|
(MuMsgPartForeachFunc)each_part,
|
|
|
|
&attinfo);
|
2012-01-12 23:45:46 +01:00
|
|
|
|
|
|
|
/* explicitly close the file backend, so we won't run of fds */
|
2021-10-20 11:18:15 +02:00
|
|
|
mu_msg_unload_msg_file(msgwrap->_msg);
|
2012-01-12 23:45:46 +01:00
|
|
|
|
|
|
|
return attinfo.attlist;
|
|
|
|
}
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
SCM_DEFINE(get_header,
|
2022-02-19 17:59:42 +01:00
|
|
|
"mu:c:get-header",
|
|
|
|
2,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
(SCM MSG, SCM HEADER),
|
|
|
|
"Get an arbitrary HEADER from MSG.\n")
|
2012-01-04 23:08:27 +01:00
|
|
|
#define FUNC_NAME s_get_header
|
|
|
|
{
|
2021-10-20 11:18:15 +02:00
|
|
|
MuMsgWrapper* msgwrap;
|
|
|
|
char* header;
|
|
|
|
SCM val;
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2012-07-14 14:52:37 +02:00
|
|
|
MU_GUILE_INITIALIZED_OR_ERROR;
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
|
|
|
SCM_ASSERT(scm_is_string(HEADER) || HEADER == SCM_UNDEFINED, HEADER, SCM_ARG2, FUNC_NAME);
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
msgwrap = (MuMsgWrapper*)SCM_CDR(MSG);
|
|
|
|
header = scm_to_utf8_string(HEADER);
|
|
|
|
val = mu_guile_scm_from_str(mu_msg_get_header(msgwrap->_msg, header));
|
|
|
|
free(header);
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2012-01-12 23:45:46 +01:00
|
|
|
/* explicitly close the file backend, so we won't run of fds */
|
2021-10-20 11:18:15 +02:00
|
|
|
mu_msg_unload_msg_file(msgwrap->_msg);
|
2012-01-12 23:45:46 +01:00
|
|
|
|
2012-07-15 11:44:52 +02:00
|
|
|
return val;
|
2012-01-04 23:08:27 +01:00
|
|
|
}
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
2020-11-28 09:08:04 +01:00
|
|
|
static Mu::Option<Mu::QueryResults>
|
2021-10-20 11:18:15 +02:00
|
|
|
get_query_results(Mu::Store& store, const char* expr, int maxnum)
|
2012-01-04 23:08:27 +01:00
|
|
|
{
|
2022-03-04 23:34:39 +01:00
|
|
|
return store.run_query(expr, {}, Mu::QueryFlags::None, maxnum);
|
2012-01-04 23:08:27 +01:00
|
|
|
}
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
SCM_DEFINE(for_each_message,
|
2022-02-19 17:59:42 +01:00
|
|
|
"mu:c:for-each-message",
|
|
|
|
3,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
(SCM FUNC, SCM EXPR, SCM MAXNUM),
|
|
|
|
"Call FUNC for each msg in the message store matching EXPR. EXPR is"
|
|
|
|
"either a string containing a mu search expression or a boolean; in the former "
|
|
|
|
"case, limit the messages to only those matching the expression, in the "
|
|
|
|
"latter case, match /all/ messages if the EXPR equals #t, and match "
|
|
|
|
"none if EXPR equals #f.")
|
2012-07-14 11:32:15 +02:00
|
|
|
#define FUNC_NAME s_for_each_message
|
2012-01-04 23:08:27 +01:00
|
|
|
{
|
2020-11-28 09:08:04 +01:00
|
|
|
char* expr{};
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2012-07-14 14:52:37 +02:00
|
|
|
MU_GUILE_INITIALIZED_OR_ERROR;
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
SCM_ASSERT(scm_procedure_p(FUNC), FUNC, SCM_ARG1, FUNC_NAME);
|
|
|
|
SCM_ASSERT(scm_is_bool(EXPR) || scm_is_string(EXPR), EXPR, SCM_ARG2, FUNC_NAME);
|
|
|
|
SCM_ASSERT(scm_is_integer(MAXNUM), MAXNUM, SCM_ARG3, FUNC_NAME);
|
2012-05-17 19:44:20 +02:00
|
|
|
|
2012-01-04 23:08:27 +01:00
|
|
|
if (EXPR == SCM_BOOL_F)
|
|
|
|
return SCM_UNSPECIFIED; /* nothing to do */
|
|
|
|
|
|
|
|
if (EXPR == SCM_BOOL_T)
|
2021-10-20 11:18:15 +02:00
|
|
|
expr = strdup(""); /* note, "" matches *all* messages */
|
2012-01-04 23:08:27 +01:00
|
|
|
else
|
|
|
|
expr = scm_to_utf8_string(EXPR);
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
const auto res{get_query_results(mu_guile_store(), expr, scm_to_int(MAXNUM))};
|
|
|
|
free(expr);
|
2021-03-12 21:20:48 +01:00
|
|
|
if (!res)
|
2012-01-04 23:08:27 +01:00
|
|
|
return SCM_UNSPECIFIED;
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
for (auto&& mi : *res) {
|
2022-04-22 06:59:48 +02:00
|
|
|
if (auto msg{mi.message()}; msg) {
|
|
|
|
auto msgsmob{mu_guile_msg_to_scm(msg)};
|
2021-10-20 11:18:15 +02:00
|
|
|
scm_call_1(FUNC, msgsmob);
|
2021-03-12 21:20:48 +01:00
|
|
|
}
|
|
|
|
}
|
2012-12-23 14:23:54 +01:00
|
|
|
|
2021-03-12 21:20:48 +01:00
|
|
|
return SCM_UNSPECIFIED;
|
2012-01-04 23:08:27 +01:00
|
|
|
}
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
2012-07-14 11:32:15 +02:00
|
|
|
static SCM
|
2021-10-20 11:18:15 +02:00
|
|
|
register_symbol(const char* name)
|
2012-07-14 11:32:15 +02:00
|
|
|
{
|
|
|
|
SCM scm;
|
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
scm = scm_from_utf8_symbol(name);
|
|
|
|
scm_c_define(name, scm);
|
|
|
|
scm_c_export(name, NULL);
|
2012-07-14 11:32:15 +02:00
|
|
|
|
|
|
|
return scm;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-10-20 11:18:15 +02:00
|
|
|
define_symbols(void)
|
2012-07-14 11:32:15 +02:00
|
|
|
{
|
2021-10-20 11:18:15 +02:00
|
|
|
SYMB_CONTACT_TO = register_symbol("mu:contact:to");
|
|
|
|
SYMB_CONTACT_CC = register_symbol("mu:contact:cc");
|
|
|
|
SYMB_CONTACT_FROM = register_symbol("mu:contact:from");
|
|
|
|
SYMB_CONTACT_BCC = register_symbol("mu:contact:bcc");
|
|
|
|
|
|
|
|
SYMB_PRIO_LOW = register_symbol("mu:prio:low");
|
|
|
|
SYMB_PRIO_NORMAL = register_symbol("mu:prio:normal");
|
|
|
|
SYMB_PRIO_HIGH = register_symbol("mu:prio:high");
|
|
|
|
|
2022-02-16 21:06:00 +01:00
|
|
|
for (auto i = 0U; i != AllMessageFlagInfos.size(); ++i) {
|
|
|
|
const auto& info{AllMessageFlagInfos.at(i)};
|
|
|
|
const auto name = "mu:flag:" + std::string{info.name};
|
|
|
|
SYMB_FLAGS[i] = register_symbol(name.c_str());
|
|
|
|
}
|
2012-07-14 11:32:15 +02:00
|
|
|
}
|
|
|
|
static void
|
2021-10-20 11:18:15 +02:00
|
|
|
define_vars(void)
|
2012-07-14 11:32:15 +02:00
|
|
|
{
|
2022-03-20 13:12:41 +01:00
|
|
|
field_for_each([](auto&& field){
|
2022-03-04 23:34:39 +01:00
|
|
|
const auto name{"mu:field:" + std::string{field.name}};
|
|
|
|
scm_c_define(name.c_str(), scm_from_uint(field.value_no()));
|
|
|
|
scm_c_export(name.c_str(), NULL);
|
|
|
|
});
|
|
|
|
|
|
|
|
/* non-Xapian field: timestamp */
|
|
|
|
scm_c_define("mu:field:timestamp",
|
|
|
|
scm_from_uint(MU_GUILE_MSG_FIELD_ID_TIMESTAMP));
|
|
|
|
scm_c_export("mu:field:timestamp", NULL);
|
|
|
|
|
2012-07-14 11:32:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static SCM
|
2021-10-20 11:18:15 +02:00
|
|
|
msg_mark(SCM msg_smob)
|
2012-07-14 11:32:15 +02:00
|
|
|
{
|
2021-10-20 11:18:15 +02:00
|
|
|
MuMsgWrapper* msgwrap;
|
|
|
|
msgwrap = (MuMsgWrapper*)SCM_CDR(msg_smob);
|
2012-07-14 11:32:15 +02:00
|
|
|
|
|
|
|
msgwrap->_unrefme = TRUE;
|
|
|
|
|
|
|
|
return SCM_UNSPECIFIED;
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t
|
2021-10-20 11:18:15 +02:00
|
|
|
msg_free(SCM msg_smob)
|
2012-07-14 11:32:15 +02:00
|
|
|
{
|
2021-10-20 11:18:15 +02:00
|
|
|
MuMsgWrapper* msgwrap;
|
|
|
|
msgwrap = (MuMsgWrapper*)SCM_CDR(msg_smob);
|
2012-07-14 11:32:15 +02:00
|
|
|
|
|
|
|
if (msgwrap->_unrefme)
|
2021-10-20 11:18:15 +02:00
|
|
|
mu_msg_unref(msgwrap->_msg);
|
2012-07-14 11:32:15 +02:00
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
return sizeof(MuMsgWrapper);
|
2012-07-14 11:32:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-10-20 11:18:15 +02:00
|
|
|
msg_print(SCM msg_smob, SCM port, scm_print_state* pstate)
|
2012-07-14 11:32:15 +02:00
|
|
|
{
|
2021-10-20 11:18:15 +02:00
|
|
|
MuMsgWrapper* msgwrap;
|
|
|
|
msgwrap = (MuMsgWrapper*)SCM_CDR(msg_smob);
|
2012-07-14 11:32:15 +02:00
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
scm_puts("#<msg ", port);
|
2012-07-14 11:32:15 +02:00
|
|
|
|
|
|
|
if (msg_smob == SCM_BOOL_F)
|
2021-10-20 11:18:15 +02:00
|
|
|
scm_puts("#f", port);
|
2012-07-14 11:32:15 +02:00
|
|
|
else
|
2021-10-20 11:18:15 +02:00
|
|
|
scm_puts(mu_msg_get_path(msgwrap->_msg), port);
|
2012-07-14 11:32:15 +02:00
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
scm_puts(">", port);
|
2012-07-14 11:32:15 +02:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-01-04 23:08:27 +01:00
|
|
|
void*
|
2021-10-20 11:18:15 +02:00
|
|
|
mu_guile_message_init(void* data)
|
2012-01-04 23:08:27 +01:00
|
|
|
{
|
2021-10-20 11:18:15 +02:00
|
|
|
MSG_TAG = scm_make_smob_type("msg", sizeof(MuMsgWrapper));
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
scm_set_smob_mark(MSG_TAG, msg_mark);
|
|
|
|
scm_set_smob_free(MSG_TAG, msg_free);
|
|
|
|
scm_set_smob_print(MSG_TAG, msg_print);
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2021-10-20 11:18:15 +02:00
|
|
|
define_vars();
|
|
|
|
define_symbols();
|
2012-01-04 23:08:27 +01:00
|
|
|
|
2012-07-14 11:32:15 +02:00
|
|
|
#ifndef SCM_MAGIC_SNARFER
|
2012-01-04 23:08:27 +01:00
|
|
|
#include "mu-guile-message.x"
|
2012-07-14 11:32:15 +02:00
|
|
|
#endif /*SCM_MAGIC_SNARFER*/
|
2012-01-04 23:08:27 +01:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|