* mu-store*: detect 'my-addresses' in messages, so we can mark contacts as 'personal'
This commit is contained in:
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
#include "mu-store.h"
|
#include "mu-store.h"
|
||||||
#include "mu-contacts.h"
|
#include "mu-contacts.h"
|
||||||
|
#include "mu-str.h"
|
||||||
|
|
||||||
class MuStoreError {
|
class MuStoreError {
|
||||||
public:
|
public:
|
||||||
@ -49,9 +49,11 @@ private:
|
|||||||
struct _MuStore {
|
struct _MuStore {
|
||||||
public:
|
public:
|
||||||
/* create a read-write MuStore */
|
/* create a read-write MuStore */
|
||||||
_MuStore (const char *path, const char *contacts_path, bool rebuild) {
|
_MuStore (const char *path, const char *contacts_path,
|
||||||
|
const char **my_addresses,
|
||||||
|
bool rebuild) {
|
||||||
|
|
||||||
init (path, contacts_path, rebuild, false);
|
init (path, contacts_path, my_addresses, rebuild, false);
|
||||||
|
|
||||||
if (rebuild)
|
if (rebuild)
|
||||||
_db = new Xapian::WritableDatabase
|
_db = new Xapian::WritableDatabase
|
||||||
@ -64,7 +66,7 @@ public:
|
|||||||
|
|
||||||
if (contacts_path) {
|
if (contacts_path) {
|
||||||
_contacts = mu_contacts_new (contacts_path);
|
_contacts = mu_contacts_new (contacts_path);
|
||||||
if (!_contacts) /* don't bail-out for this */
|
if (!_contacts)
|
||||||
throw MuStoreError (MU_ERROR_FILE,
|
throw MuStoreError (MU_ERROR_FILE,
|
||||||
("failed to init contacts cache"));
|
("failed to init contacts cache"));
|
||||||
}
|
}
|
||||||
@ -76,7 +78,7 @@ public:
|
|||||||
/* create a read-only MuStore */
|
/* create a read-only MuStore */
|
||||||
_MuStore (const char *path) {
|
_MuStore (const char *path) {
|
||||||
|
|
||||||
init (path, NULL, false, false);
|
init (path, NULL, NULL, false, false);
|
||||||
|
|
||||||
_db = new Xapian::Database (path);
|
_db = new Xapian::Database (path);
|
||||||
if (mu_store_needs_upgrade(this))
|
if (mu_store_needs_upgrade(this))
|
||||||
@ -86,7 +88,7 @@ public:
|
|||||||
MU_WRITE_LOG ("%s: opened %s read-only", __FUNCTION__, this->path());
|
MU_WRITE_LOG ("%s: opened %s read-only", __FUNCTION__, this->path());
|
||||||
}
|
}
|
||||||
|
|
||||||
void init (const char *path, const char *contacts_path,
|
void init (const char *path, const char *contacts_path, const char **my_addresses,
|
||||||
bool rebuild, bool read_only) {
|
bool rebuild, bool read_only) {
|
||||||
|
|
||||||
_batch_size = DEFAULT_BATCH_SIZE;
|
_batch_size = DEFAULT_BATCH_SIZE;
|
||||||
@ -97,6 +99,15 @@ public:
|
|||||||
_read_only = read_only;
|
_read_only = read_only;
|
||||||
_ref_count = 1;
|
_ref_count = 1;
|
||||||
_version = NULL;
|
_version = NULL;
|
||||||
|
|
||||||
|
/* copy 'my adresses' */
|
||||||
|
_my_addresses = NULL;
|
||||||
|
while (my_addresses && *my_addresses) {
|
||||||
|
_my_addresses = g_slist_prepend
|
||||||
|
(_my_addresses, g_strdup (*my_addresses));
|
||||||
|
++my_addresses;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_set_version () {
|
void check_set_version () {
|
||||||
@ -125,6 +136,8 @@ public:
|
|||||||
if (!_read_only)
|
if (!_read_only)
|
||||||
mu_store_flush (this);
|
mu_store_flush (this);
|
||||||
|
|
||||||
|
mu_str_free_list (_my_addresses);
|
||||||
|
|
||||||
MU_WRITE_LOG ("closing xapian database with %d document(s)",
|
MU_WRITE_LOG ("closing xapian database with %d document(s)",
|
||||||
(int)db_read_only()->get_doccount());
|
(int)db_read_only()->get_doccount());
|
||||||
delete _db;
|
delete _db;
|
||||||
@ -201,6 +214,8 @@ public:
|
|||||||
return --_ref_count;
|
return --_ref_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GSList *my_addresses () { return _my_addresses; }
|
||||||
|
|
||||||
/* by default, use transactions of 30000 messages */
|
/* by default, use transactions of 30000 messages */
|
||||||
static const unsigned DEFAULT_BATCH_SIZE = 30000;
|
static const unsigned DEFAULT_BATCH_SIZE = 30000;
|
||||||
/* http://article.gmane.org/gmane.comp.search.xapian.general/3656 */
|
/* http://article.gmane.org/gmane.comp.search.xapian.general/3656 */
|
||||||
@ -220,8 +235,9 @@ private:
|
|||||||
|
|
||||||
Xapian::Database *_db;
|
Xapian::Database *_db;
|
||||||
bool _read_only;
|
bool _read_only;
|
||||||
|
|
||||||
guint _ref_count;
|
guint _ref_count;
|
||||||
|
|
||||||
|
GSList *_my_addresses;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -123,14 +123,14 @@ add_synonyms (MuStore *store)
|
|||||||
|
|
||||||
MuStore*
|
MuStore*
|
||||||
mu_store_new_writable (const char* xpath, const char *contacts_cache,
|
mu_store_new_writable (const char* xpath, const char *contacts_cache,
|
||||||
gboolean rebuild, GError **err)
|
const char **my_addresses, gboolean rebuild, GError **err)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (xpath, NULL);
|
g_return_val_if_fail (xpath, NULL);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
MuStore *store;
|
MuStore *store;
|
||||||
store = new _MuStore (xpath, contacts_cache,
|
store = new _MuStore (xpath, contacts_cache, my_addresses,
|
||||||
rebuild ? true : false);
|
rebuild ? true : false);
|
||||||
add_synonyms (store);
|
add_synonyms (store);
|
||||||
return store;
|
return store;
|
||||||
@ -506,6 +506,10 @@ struct _MsgDoc {
|
|||||||
MuMsg *_msg;
|
MuMsg *_msg;
|
||||||
MuStore *_store;
|
MuStore *_store;
|
||||||
GStringChunk *_strchunk;
|
GStringChunk *_strchunk;
|
||||||
|
|
||||||
|
/* callback data, to determine whether this message is 'personal' */
|
||||||
|
gboolean _personal;
|
||||||
|
GSList *_my_addresses;
|
||||||
};
|
};
|
||||||
typedef struct _MsgDoc MsgDoc;
|
typedef struct _MsgDoc MsgDoc;
|
||||||
|
|
||||||
@ -622,21 +626,51 @@ each_contact_info (MuMsgContact *contact, MsgDoc *msgdoc)
|
|||||||
if (msgdoc->_store->contacts())
|
if (msgdoc->_store->contacts())
|
||||||
mu_contacts_add (msgdoc->_store->contacts(),
|
mu_contacts_add (msgdoc->_store->contacts(),
|
||||||
contact->address, contact->name,
|
contact->address, contact->name,
|
||||||
|
msgdoc->_personal,
|
||||||
mu_msg_get_date(msgdoc->_msg));
|
mu_msg_get_date(msgdoc->_msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
each_contact_check_if_personal (MuMsgContact *contact, MsgDoc *msgdoc)
|
||||||
|
{
|
||||||
|
GSList *cur;
|
||||||
|
|
||||||
|
if (msgdoc->_personal || !contact->address)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (cur = msgdoc->_my_addresses; cur; cur = g_slist_next (cur)) {
|
||||||
|
//g_print ("%s <=> %s\n", contact->address, (const char*)cur->data);
|
||||||
|
if (g_ascii_strcasecmp (contact->address, (const char*)cur->data) == 0)
|
||||||
|
msgdoc->_personal = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define MU_STRING_CHUNK_SIZE 8192
|
#define MU_STRING_CHUNK_SIZE 8192
|
||||||
|
|
||||||
Xapian::Document
|
Xapian::Document
|
||||||
new_doc_from_message (MuStore *store, MuMsg *msg)
|
new_doc_from_message (MuStore *store, MuMsg *msg)
|
||||||
{
|
{
|
||||||
Xapian::Document doc;
|
Xapian::Document doc;
|
||||||
MsgDoc docinfo = {&doc, msg, store, 0};
|
MsgDoc docinfo = {&doc, msg, store, 0, FALSE, NULL};
|
||||||
docinfo._strchunk = g_string_chunk_new (MU_STRING_CHUNK_SIZE);
|
docinfo._strchunk = g_string_chunk_new (MU_STRING_CHUNK_SIZE);
|
||||||
|
|
||||||
mu_msg_field_foreach ((MuMsgFieldForeachFunc)add_terms_values, &docinfo);
|
mu_msg_field_foreach ((MuMsgFieldForeachFunc)add_terms_values, &docinfo);
|
||||||
/* also store the contact-info as separate terms */
|
|
||||||
|
/* determine whether this is 'personal' email, ie. one of my
|
||||||
|
* e-mail addresses is explicitly mentioned -- it's not a
|
||||||
|
* mailing list message. Callback will update docinfo->_personal */
|
||||||
|
if (store->my_addresses()) {
|
||||||
|
docinfo._my_addresses = store->my_addresses();
|
||||||
|
mu_msg_contact_foreach (msg, (MuMsgContactForeachFunc)each_contact_check_if_personal,
|
||||||
|
&docinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* also store the contact-info as separate terms, and add it
|
||||||
|
* to the cache */
|
||||||
mu_msg_contact_foreach (msg, (MuMsgContactForeachFunc)each_contact_info,
|
mu_msg_contact_foreach (msg, (MuMsgContactForeachFunc)each_contact_info,
|
||||||
&docinfo);
|
&docinfo);
|
||||||
|
|
||||||
|
|||||||
@ -36,12 +36,15 @@ typedef struct _MuStore MuStore;
|
|||||||
*
|
*
|
||||||
* @param path the path to the database
|
* @param path the path to the database
|
||||||
* @param ccachepath path where to cache the contacts information, or NULL
|
* @param ccachepath path where to cache the contacts information, or NULL
|
||||||
|
* @param my_addresses, array of strings with regexps for my e-mail addresses (or NULL)
|
||||||
|
* (used for the contactac information)
|
||||||
* @param err to receive error info or NULL. err->code is MuError value
|
* @param err to receive error info or NULL. err->code is MuError value
|
||||||
*
|
*
|
||||||
* @return a new MuStore object with ref count == 1, or NULL in case
|
* @return a new MuStore object with ref count == 1, or NULL in case
|
||||||
* of error; free with mu_store_unref
|
* of error; free with mu_store_unref
|
||||||
*/
|
*/
|
||||||
MuStore* mu_store_new_writable (const char *xpath, const char *ccachepath,
|
MuStore* mu_store_new_writable (const char *xpath,
|
||||||
|
const char *ccachepath, const char **my_addresses,
|
||||||
gboolean rebuild, GError **err)
|
gboolean rebuild, GError **err)
|
||||||
G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
|
G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,7 @@ test_mu_store_new_destroy (void)
|
|||||||
g_assert (tmpdir);
|
g_assert (tmpdir);
|
||||||
|
|
||||||
err = NULL;
|
err = NULL;
|
||||||
store = mu_store_new_writable (tmpdir, NULL, FALSE, &err);
|
store = mu_store_new_writable (tmpdir, NULL, NULL, FALSE, &err);
|
||||||
g_assert (store);
|
g_assert (store);
|
||||||
g_assert (err == NULL);
|
g_assert (err == NULL);
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ test_mu_store_version (void)
|
|||||||
g_assert (tmpdir);
|
g_assert (tmpdir);
|
||||||
|
|
||||||
err = NULL;
|
err = NULL;
|
||||||
store = mu_store_new_writable (tmpdir, NULL, FALSE, &err);
|
store = mu_store_new_writable (tmpdir, NULL, NULL, FALSE, &err);
|
||||||
g_assert (store);
|
g_assert (store);
|
||||||
mu_store_unref (store);
|
mu_store_unref (store);
|
||||||
store = mu_store_new_read_only (tmpdir, &err);
|
store = mu_store_new_read_only (tmpdir, &err);
|
||||||
@ -95,7 +95,7 @@ test_mu_store_store_msg_and_count (void)
|
|||||||
tmpdir = test_mu_common_get_random_tmpdir();
|
tmpdir = test_mu_common_get_random_tmpdir();
|
||||||
g_assert (tmpdir);
|
g_assert (tmpdir);
|
||||||
|
|
||||||
store = mu_store_new_writable (tmpdir, NULL, FALSE, NULL);
|
store = mu_store_new_writable (tmpdir, NULL, NULL, FALSE, NULL);
|
||||||
g_assert (store);
|
g_assert (store);
|
||||||
|
|
||||||
g_assert_cmpuint (0,==,mu_store_count (store, NULL));
|
g_assert_cmpuint (0,==,mu_store_count (store, NULL));
|
||||||
@ -151,7 +151,7 @@ test_mu_store_store_msg_remove_and_count (void)
|
|||||||
tmpdir = test_mu_common_get_random_tmpdir();
|
tmpdir = test_mu_common_get_random_tmpdir();
|
||||||
g_assert (tmpdir);
|
g_assert (tmpdir);
|
||||||
|
|
||||||
store = mu_store_new_writable (tmpdir, NULL, FALSE, NULL);
|
store = mu_store_new_writable (tmpdir, NULL, NULL, FALSE, NULL);
|
||||||
g_assert (store);
|
g_assert (store);
|
||||||
|
|
||||||
g_assert_cmpuint (0,==,mu_store_count (store, NULL));
|
g_assert_cmpuint (0,==,mu_store_count (store, NULL));
|
||||||
|
|||||||
Reference in New Issue
Block a user