* add support for message-references:

- mu_msg_get_references and mu_msg_get_references_str get the list of
    refences ("References:" and "In-reply-to:") as a GList,
    resp. comma-separated list
  - stored in database as a value, can be shown in mu find output using 'r'
    (db needs rebuild)
  - document in mu-find manpage
This commit is contained in:
Dirk-Jan C. Binnema 2011-04-30 13:50:56 +03:00
parent efa026648b
commit e33f927542
6 changed files with 129 additions and 3 deletions

View File

@ -1,4 +1,4 @@
.TH MU FIND 1 "March 2011" "User Manuals"
.TH MU FIND 1 "April 2011" "User Manuals"
.SH NAME
@ -273,6 +273,7 @@ search parameters; the complete list:
s Message \fBs\fRubject
i Message-\fBi\fRd
m \fBm\fRaildir
r \fBr\fReferences (message ids In-reply-to, References as comma-separated list)
.fi

View File

@ -158,6 +158,13 @@ static const MuMsgField FIELD_DATA[] = {
MU_MSG_FIELD_TYPE_TIME_T,
"timestamp", 'x', 0,
FLAG_GMIME
},
{
MU_MSG_FIELD_ID_REFS,
MU_MSG_FIELD_TYPE_STRING,
"refs", 'r', 'R',
FLAG_GMIME | FLAG_XAPIAN_VALUE
}
};

View File

@ -41,7 +41,8 @@ enum _MuMsgFieldId {
MU_MSG_FIELD_ID_TO,
MU_MSG_FIELD_ID_MSGID,
MU_MSG_FIELD_ID_TIMESTAMP,
MU_MSG_FIELD_ID_REFS,
MU_MSG_FIELD_ID_NUM,
/* fake fields */

View File

@ -43,6 +43,8 @@ enum _StringFields {
MDIR_FIELD, /* the maildir */
FLAGS_FIELD_STR, /* message flags */
REFS_FIELD, /* msg references, as a comma-sep'd string */
FIELD_NUM
};
@ -59,6 +61,8 @@ struct _MuMsg {
size_t _size;
time_t _timestamp;
MuMsgPrio _prio;
GSList *_refs; /* msgids of message we refer to */
};
G_END_DECLS

View File

@ -80,6 +80,9 @@ mu_msg_destroy (MuMsg *msg)
for (i = 0; i != FIELD_NUM; ++i)
g_free (msg->_fields[i]);
g_slist_foreach (msg->_refs, (GFunc)g_free, NULL);
g_slist_free (msg->_refs);
g_slice_free (MuMsg, msg);
}
@ -214,7 +217,8 @@ mu_msg_new (const char* filepath, const gchar* mdir, GError **err)
msg = g_slice_new0 (MuMsg);
msg->_prio = MU_MSG_PRIO_NONE;
msg->_refcount = 1;
msg->_refs = NULL;
if (!init_file_metadata(msg, filepath, mdir, err)) {
mu_msg_unref (msg);
return NULL;
@ -814,6 +818,92 @@ mu_msg_get_summary (MuMsg *msg, size_t max_lines)
}
static GSList*
get_msgids_from_header (MuMsg *msg, const char* header)
{
GSList *msgids;
const char *str;
msgids = NULL;
str = g_mime_object_get_header (GMIME_OBJECT(msg->_mime_msg),
header);
/* get stuff from the 'references' header */
if (str) {
const GMimeReferences *cur;
GMimeReferences *mime_refs;
mime_refs = g_mime_references_decode (str);
for (cur = mime_refs; cur; cur = g_mime_references_get_next(cur)) {
const char* msgid;
msgid = g_mime_references_get_message_id (cur);
if (msgid)
msgids = g_slist_prepend (msgids, g_strdup (msgid));
}
g_mime_references_free (mime_refs);
}
return g_slist_reverse (msgids);
}
const char*
mu_msg_get_references_str (MuMsg *msg)
{
const GSList *refs;
gchar *refsstr;
g_return_val_if_fail (msg, NULL);
if (msg->_fields[REFS_FIELD])
return msg->_fields[REFS_FIELD];
refsstr = NULL;
refs = mu_msg_get_references (msg);
if (refs) {
const GSList *cur;
for (cur = refs; cur; cur = g_slist_next(cur)) {
char *tmp;
tmp = g_strdup_printf ("%s%s%s",
refsstr ? refsstr : "",
refsstr ? "," : "",
g_strdup((gchar*)cur->data));
g_free (refsstr);
refsstr = tmp;
}
}
return msg->_fields[REFS_FIELD] = refsstr;
}
const GSList*
mu_msg_get_references (MuMsg *msg)
{
GSList *refs, *inreply;
g_return_val_if_fail (msg, NULL);
if (msg->_refs)
return msg->_refs;
refs = get_msgids_from_header (msg, "References");
/* now, add in-reply-to:, we only take the first one if there
* are more */
inreply = get_msgids_from_header (msg, "In-reply-to");
if (inreply) {
refs = g_slist_prepend (refs, g_strdup ((gchar*)inreply->data));
g_slist_foreach (inreply, (GFunc)g_free, NULL);
g_slist_free (inreply);
}
/* put in proper order */
msg->_refs = g_slist_reverse (refs);
return msg->_refs;
}
const char*
mu_msg_get_field_string (MuMsg *msg, MuMsgFieldId mfid)
{
@ -829,6 +919,7 @@ mu_msg_get_field_string (MuMsg *msg, MuMsgFieldId mfid)
case MU_MSG_FIELD_ID_TO: return mu_msg_get_to (msg);
case MU_MSG_FIELD_ID_MSGID: return mu_msg_get_msgid (msg);
case MU_MSG_FIELD_ID_MAILDIR: return mu_msg_get_maildir (msg);
case MU_MSG_FIELD_ID_REFS: return mu_msg_get_references_str (msg);
default:
g_return_val_if_reached (NULL);
}

View File

@ -292,6 +292,28 @@ MuMsgPrio mu_msg_get_prio (MuMsg *msg);
time_t mu_msg_get_timestamp (MuMsg *msg);
/**
* get a list of message ids this message refers to -- this is based
* on the References: and In-reply-to: headers.
*
* @param msg a valid MuMsg instance
*
* @return a list of message id, with the most immediate parent as the
* last element. Don't modify/free this list.
*/
const GSList *mu_msg_get_references (MuMsg *msg);
/**
* get the list of references as a comma-separated string
*
* @param msg a valid MuMsg
*
* @return a comma-separated string with the references or NULL if
* there are none. Don't modify/free
*/
const char* mu_msg_get_references_str (MuMsg *msg);
G_END_DECLS
#endif /*__MU_MSG_H__*/