* mu-contacts: add mu_contacts_clear, whitespace fixes
This commit is contained in:
@ -43,7 +43,7 @@ static ContactInfo *contact_info_new (char *email, char *name,
|
|||||||
|
|
||||||
struct _MuContacts {
|
struct _MuContacts {
|
||||||
GKeyFile *_ccache;
|
GKeyFile *_ccache;
|
||||||
gchar *_ccachefile;
|
gchar *_path;
|
||||||
|
|
||||||
GHashTable *_hash;
|
GHashTable *_hash;
|
||||||
gboolean _dirty;
|
gboolean _dirty;
|
||||||
@ -61,15 +61,15 @@ encode_email_address (const char *addr)
|
|||||||
{
|
{
|
||||||
static char enc[254 + 1]; /* max size for an e-mail addr */
|
static char enc[254 + 1]; /* max size for an e-mail addr */
|
||||||
char *cur;
|
char *cur;
|
||||||
|
|
||||||
if (!addr)
|
if (!addr)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* make sure chars are with {' ' .. '~'}, and not '[' ']' */
|
/* make sure chars are with {' ' .. '~'}, and not '[' ']' */
|
||||||
for (cur = strncpy(enc, addr, sizeof(enc)); *cur != '\0'; ++cur)
|
for (cur = strncpy(enc, addr, sizeof(enc)); *cur != '\0'; ++cur)
|
||||||
if (!isalnum(*cur))
|
if (!isalnum(*cur))
|
||||||
*cur = 'A' + (*cur % ('Z' - 'A'));
|
*cur = 'A' + (*cur % ('Z' - 'A'));
|
||||||
|
|
||||||
return enc;
|
return enc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ load_key_file (const char *path)
|
|||||||
gboolean file_exists;
|
gboolean file_exists;
|
||||||
|
|
||||||
err = NULL;
|
err = NULL;
|
||||||
|
|
||||||
/* of course this is racy, but it's only for giving more
|
/* of course this is racy, but it's only for giving more
|
||||||
* meaningful errors to users */
|
* meaningful errors to users */
|
||||||
file_exists = TRUE;
|
file_exists = TRUE;
|
||||||
@ -92,10 +92,10 @@ load_key_file (const char *path)
|
|||||||
}
|
}
|
||||||
file_exists = FALSE;
|
file_exists = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = NULL;
|
err = NULL;
|
||||||
keyfile = g_key_file_new ();
|
keyfile = g_key_file_new ();
|
||||||
|
|
||||||
if (file_exists && !g_key_file_load_from_file
|
if (file_exists && !g_key_file_load_from_file
|
||||||
(keyfile, path, G_KEY_FILE_KEEP_COMMENTS, &err)) {
|
(keyfile, path, G_KEY_FILE_KEEP_COMMENTS, &err)) {
|
||||||
g_warning ("could not load keyfile %s: %s", path, err->message);
|
g_warning ("could not load keyfile %s: %s", path, err->message);
|
||||||
@ -122,7 +122,7 @@ get_values (GKeyFile *kfile, const gchar *group,
|
|||||||
g_error_free (err);
|
g_error_free (err);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*tstamp = (time_t)g_key_file_get_integer (kfile, group, TSTAMP_KEY, &err);
|
*tstamp = (time_t)g_key_file_get_integer (kfile, group, TSTAMP_KEY, &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
g_warning ("cannot get timestamp for %s: %s",
|
g_warning ("cannot get timestamp for %s: %s",
|
||||||
@ -153,14 +153,14 @@ deserialize_cache (MuContacts *self)
|
|||||||
if (!get_values (self->_ccache, groups[i],
|
if (!get_values (self->_ccache, groups[i],
|
||||||
&email, &name, &tstamp))
|
&email, &name, &tstamp))
|
||||||
continue; /* ignore this one... */
|
continue; /* ignore this one... */
|
||||||
|
|
||||||
cinfo = contact_info_new (email, name, tstamp);
|
cinfo = contact_info_new (email, name, tstamp);
|
||||||
|
|
||||||
/* note, we're using the groups[i], so don't free with g_strfreev */
|
/* note, we're using the groups[i], so don't free with g_strfreev */
|
||||||
g_hash_table_insert (self->_hash, groups[i],
|
g_hash_table_insert (self->_hash, groups[i],
|
||||||
cinfo);
|
cinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (groups);
|
g_free (groups);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -171,7 +171,7 @@ set_comment (GKeyFile *kfile)
|
|||||||
GError *err;
|
GError *err;
|
||||||
const char *comment =
|
const char *comment =
|
||||||
" automatically generated -- do not edit";
|
" automatically generated -- do not edit";
|
||||||
|
|
||||||
err = NULL;
|
err = NULL;
|
||||||
if (!g_key_file_set_comment (kfile, NULL, NULL, comment, &err)) {
|
if (!g_key_file_set_comment (kfile, NULL, NULL, comment, &err)) {
|
||||||
g_warning ("could not write comment to keyfile: %s",
|
g_warning ("could not write comment to keyfile: %s",
|
||||||
@ -185,51 +185,65 @@ set_comment (GKeyFile *kfile)
|
|||||||
|
|
||||||
|
|
||||||
MuContacts*
|
MuContacts*
|
||||||
mu_contacts_new (const gchar *ccachefile)
|
mu_contacts_new (const gchar *path)
|
||||||
{
|
{
|
||||||
MuContacts *self;
|
MuContacts *self;
|
||||||
|
|
||||||
g_return_val_if_fail (ccachefile, NULL);
|
|
||||||
self = g_new0 (MuContacts, 1);
|
|
||||||
|
|
||||||
self->_ccachefile = g_strdup (ccachefile);
|
|
||||||
self->_ccache = load_key_file (ccachefile);
|
|
||||||
if (!self->_ccache || !set_comment (self->_ccache)) {
|
|
||||||
mu_contacts_destroy (self);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
g_return_val_if_fail (path, NULL);
|
||||||
|
self = g_new0 (MuContacts, 1);
|
||||||
|
|
||||||
|
self->_path = g_strdup (path);
|
||||||
self->_hash = g_hash_table_new_full
|
self->_hash = g_hash_table_new_full
|
||||||
(g_str_hash, g_str_equal, g_free,
|
(g_str_hash, g_str_equal, g_free,
|
||||||
(GDestroyNotify)contact_info_destroy);
|
(GDestroyNotify)contact_info_destroy);
|
||||||
|
|
||||||
|
self->_ccache = load_key_file (path);
|
||||||
|
if (!self->_ccache || !set_comment (self->_ccache)) {
|
||||||
|
mu_contacts_destroy (self);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
deserialize_cache (self);
|
deserialize_cache (self);
|
||||||
self->_dirty = FALSE;
|
|
||||||
MU_WRITE_LOG("deserialized contacts from cache %s",
|
MU_WRITE_LOG("deserialized contacts from cache %s",
|
||||||
ccachefile);
|
path);
|
||||||
|
|
||||||
|
self->_dirty = FALSE;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mu_contacts_clear (MuContacts *self)
|
||||||
|
{
|
||||||
|
g_return_if_fail (self);
|
||||||
|
|
||||||
|
if (self->_ccache)
|
||||||
|
g_key_file_free (self->_ccache);
|
||||||
|
|
||||||
|
g_hash_table_remove_all (self->_hash);
|
||||||
|
|
||||||
|
self->_ccache = g_key_file_new ();
|
||||||
|
self->_dirty = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
mu_contacts_add (MuContacts *self, const char *email, const char* name,
|
mu_contacts_add (MuContacts *self, const char *email, const char* name,
|
||||||
time_t tstamp)
|
time_t tstamp)
|
||||||
{
|
{
|
||||||
ContactInfo *cinfo;
|
ContactInfo *cinfo;
|
||||||
const char* group;
|
const char* group;
|
||||||
|
|
||||||
g_return_val_if_fail (self, FALSE);
|
g_return_val_if_fail (self, FALSE);
|
||||||
g_return_val_if_fail (email, FALSE);
|
g_return_val_if_fail (email, FALSE);
|
||||||
|
|
||||||
/* add the info, if either there is no info for this email
|
/* add the info, if either there is no info for this email
|
||||||
* yet, *OR* the new one is more recent and does not have an
|
* yet, *OR* the new one is more recent and does not have an
|
||||||
* empty name */
|
* empty name */
|
||||||
group = encode_email_address (email);
|
group = encode_email_address (email);
|
||||||
|
|
||||||
cinfo = (ContactInfo*) g_hash_table_lookup (self->_hash, group);
|
cinfo = (ContactInfo*) g_hash_table_lookup (self->_hash, group);
|
||||||
if (!cinfo || (cinfo->_tstamp < tstamp && !mu_str_is_empty(name))) {
|
if (!cinfo || (cinfo->_tstamp < tstamp && !mu_str_is_empty(name))) {
|
||||||
ContactInfo *ci;
|
ContactInfo *ci;
|
||||||
ci = contact_info_new (g_strdup(email),
|
ci = contact_info_new (g_strdup(email),
|
||||||
name ? g_strdup(name) : NULL,
|
name ? g_strdup(name) : NULL,
|
||||||
@ -239,7 +253,7 @@ mu_contacts_add (MuContacts *self, const char *email, const char* name,
|
|||||||
|
|
||||||
return self->_dirty = TRUE;
|
return self->_dirty = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +270,7 @@ each_contact (const char *group, ContactInfo *ci, EachContactData *ecdata)
|
|||||||
{
|
{
|
||||||
if (!ci->_email)
|
if (!ci->_email)
|
||||||
g_warning ("missing email: %u", (unsigned)ci->_tstamp);
|
g_warning ("missing email: %u", (unsigned)ci->_tstamp);
|
||||||
|
|
||||||
/* ignore this contact if we have a regexp, and it matches
|
/* ignore this contact if we have a regexp, and it matches
|
||||||
* neither email nor name (if we have a name) */
|
* neither email nor name (if we have a name) */
|
||||||
while (ecdata->_rx) { /* note, only once */
|
while (ecdata->_rx) { /* note, only once */
|
||||||
@ -268,7 +282,7 @@ each_contact (const char *group, ContactInfo *ci, EachContactData *ecdata)
|
|||||||
break; /* name matches? continue! */
|
break; /* name matches? continue! */
|
||||||
return; /* nothing matched, ignore this one */
|
return; /* nothing matched, ignore this one */
|
||||||
}
|
}
|
||||||
|
|
||||||
ecdata->_func (ci->_email, ci->_name,
|
ecdata->_func (ci->_email, ci->_name,
|
||||||
ci->_tstamp, ecdata->_user_data);
|
ci->_tstamp, ecdata->_user_data);
|
||||||
++ecdata->_num;
|
++ecdata->_num;
|
||||||
@ -282,7 +296,7 @@ mu_contacts_foreach (MuContacts *self, MuContactsForeachFunc func,
|
|||||||
|
|
||||||
g_return_val_if_fail (self, FALSE);
|
g_return_val_if_fail (self, FALSE);
|
||||||
g_return_val_if_fail (func, FALSE);
|
g_return_val_if_fail (func, FALSE);
|
||||||
|
|
||||||
if (pattern) {
|
if (pattern) {
|
||||||
GError *err;
|
GError *err;
|
||||||
err = NULL;
|
err = NULL;
|
||||||
@ -297,21 +311,21 @@ mu_contacts_foreach (MuContacts *self, MuContactsForeachFunc func,
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
ecdata._rx = NULL;
|
ecdata._rx = NULL;
|
||||||
|
|
||||||
ecdata._func = func;
|
ecdata._func = func;
|
||||||
ecdata._user_data = user_data;
|
ecdata._user_data = user_data;
|
||||||
ecdata._num = 0;
|
ecdata._num = 0;
|
||||||
|
|
||||||
g_hash_table_foreach (self->_hash,
|
g_hash_table_foreach (self->_hash,
|
||||||
(GHFunc)each_contact,
|
(GHFunc)each_contact,
|
||||||
&ecdata);
|
&ecdata);
|
||||||
|
|
||||||
if (ecdata._rx)
|
if (ecdata._rx)
|
||||||
g_regex_unref (ecdata._rx);
|
g_regex_unref (ecdata._rx);
|
||||||
|
|
||||||
if (num)
|
if (num)
|
||||||
*num = ecdata._num;
|
*num = ecdata._num;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,7 +337,7 @@ each_keyval (const char *group, ContactInfo *cinfo, MuContacts *self)
|
|||||||
if (cinfo->_name)
|
if (cinfo->_name)
|
||||||
g_key_file_set_value (self->_ccache, group, NAME_KEY,
|
g_key_file_set_value (self->_ccache, group, NAME_KEY,
|
||||||
cinfo->_name);
|
cinfo->_name);
|
||||||
|
|
||||||
g_key_file_set_value (self->_ccache, group, EMAIL_KEY,
|
g_key_file_set_value (self->_ccache, group, EMAIL_KEY,
|
||||||
cinfo->_email);
|
cinfo->_email);
|
||||||
g_key_file_set_integer (self->_ccache, group, TSTAMP_KEY,
|
g_key_file_set_integer (self->_ccache, group, TSTAMP_KEY,
|
||||||
@ -344,10 +358,10 @@ serialize_cache (MuContacts *self)
|
|||||||
if (len) {
|
if (len) {
|
||||||
GError *err;
|
GError *err;
|
||||||
err = NULL;
|
err = NULL;
|
||||||
rv = g_file_set_contents (self->_ccachefile, data, len, &err);
|
rv = g_file_set_contents (self->_path, data, len, &err);
|
||||||
if (!rv) {
|
if (!rv) {
|
||||||
g_warning ("failed to serialize cache to %s: %s",
|
g_warning ("failed to serialize cache to %s: %s",
|
||||||
self->_ccachefile, err->message);
|
self->_path, err->message);
|
||||||
g_error_free (err);
|
g_error_free (err);
|
||||||
}
|
}
|
||||||
g_free (data);
|
g_free (data);
|
||||||
@ -361,25 +375,26 @@ mu_contacts_destroy (MuContacts *self)
|
|||||||
{
|
{
|
||||||
if (!self)
|
if (!self)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (self->_ccache && self->_dirty) {
|
if (self->_ccache && self->_dirty) {
|
||||||
serialize_cache (self);
|
serialize_cache (self);
|
||||||
MU_WRITE_LOG("serialized contacts cache %s",
|
MU_WRITE_LOG("serialized contacts cache %s",
|
||||||
self->_ccachefile);
|
self->_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->_ccache)
|
if (self->_ccache)
|
||||||
g_key_file_free (self->_ccache);
|
g_key_file_free (self->_ccache);
|
||||||
|
|
||||||
g_free (self->_ccachefile);
|
g_free (self->_path);
|
||||||
|
|
||||||
if (self->_hash)
|
if (self->_hash)
|
||||||
g_hash_table_destroy (self->_hash);
|
g_hash_table_destroy (self->_hash);
|
||||||
|
|
||||||
g_free (self);
|
g_free (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clear_str (char* str)
|
clear_str (char* str)
|
||||||
{
|
{
|
||||||
@ -389,7 +404,7 @@ clear_str (char* str)
|
|||||||
*str = '_';
|
*str = '_';
|
||||||
++str;
|
++str;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str)
|
if (str)
|
||||||
g_strstrip (str);
|
g_strstrip (str);
|
||||||
}
|
}
|
||||||
@ -403,14 +418,14 @@ contact_info_new (char *email, char *name, time_t tstamp)
|
|||||||
|
|
||||||
/* email should not be NULL, name can */
|
/* email should not be NULL, name can */
|
||||||
g_return_val_if_fail (email, NULL);
|
g_return_val_if_fail (email, NULL);
|
||||||
|
|
||||||
cinfo = g_slice_new (ContactInfo);
|
cinfo = g_slice_new (ContactInfo);
|
||||||
|
|
||||||
/* we need to clear the strings from control chars because
|
/* we need to clear the strings from control chars because
|
||||||
* they could screw up the keyfile */
|
* they could screw up the keyfile */
|
||||||
clear_str (email);
|
clear_str (email);
|
||||||
clear_str (name);
|
clear_str (name);
|
||||||
|
|
||||||
cinfo->_email = email;
|
cinfo->_email = email;
|
||||||
cinfo->_name = name;
|
cinfo->_name = name;
|
||||||
cinfo->_tstamp = tstamp;
|
cinfo->_tstamp = tstamp;
|
||||||
@ -429,4 +444,4 @@ contact_info_destroy (ContactInfo *cinfo)
|
|||||||
|
|
||||||
g_slice_free (ContactInfo, cinfo);
|
g_slice_free (ContactInfo, cinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,9 +32,9 @@ typedef struct _MuContacts MuContacts;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* create a new MuContacts object; use mu_contacts_destroy when you no longer need it
|
* create a new MuContacts object; use mu_contacts_destroy when you no longer need it
|
||||||
*
|
*
|
||||||
* @param ccachefile full path to the file with cached list of contacts
|
* @param ccachefile full path to the file with cached list of contacts
|
||||||
*
|
*
|
||||||
* @return a new MuContacts* if succeeded, NULL otherwise
|
* @return a new MuContacts* if succeeded, NULL otherwise
|
||||||
*/
|
*/
|
||||||
MuContacts* mu_contacts_new (const gchar *ccachefile)
|
MuContacts* mu_contacts_new (const gchar *ccachefile)
|
||||||
@ -45,23 +45,45 @@ MuContacts* mu_contacts_new (const gchar *ccachefile)
|
|||||||
* add a contacts; if there's a contact with this e-mail address
|
* add a contacts; if there's a contact with this e-mail address
|
||||||
* already, it will not updated unless the timestamp of this one is
|
* already, it will not updated unless the timestamp of this one is
|
||||||
* higher and has a non-empty name
|
* higher and has a non-empty name
|
||||||
*
|
*
|
||||||
* @param contacts a contacts object
|
* @param contacts a contacts object
|
||||||
* @param email e-mail address of the contact (not NULL)
|
* @param email e-mail address of the contact (not NULL)
|
||||||
* @param name name of the contact (or NULL)
|
* @param name name of the contact (or NULL)
|
||||||
* @param tstamp timestamp for this address
|
* @param tstamp timestamp for this address
|
||||||
*
|
*
|
||||||
* @return TRUE if succeeded, FALSE otherwise
|
* @return TRUE if succeeded, FALSE otherwise
|
||||||
*/
|
*/
|
||||||
gboolean mu_contacts_add (MuContacts *contacts, const char *email,
|
gboolean mu_contacts_add (MuContacts *self, const char *email,
|
||||||
const char* name, time_t tstamp);
|
const char* name, time_t tstamp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* destroy the Contacts object
|
* destroy the Contacts object
|
||||||
*
|
*
|
||||||
* @param contacts a contacts object
|
* @param contacts a contacts object
|
||||||
*/
|
*/
|
||||||
void mu_contacts_destroy (MuContacts *contacts);
|
void mu_contacts_destroy (MuContacts *self);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clear all contacts from the cache
|
||||||
|
*
|
||||||
|
* @param self a MuContacts instance
|
||||||
|
*/
|
||||||
|
void mu_contacts_clear (MuContacts *self);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the path for the contacts cache file
|
||||||
|
*
|
||||||
|
* @param contacts a contacts object
|
||||||
|
*
|
||||||
|
* @return the path as a constant string (don't free), or NULL in case
|
||||||
|
* of error
|
||||||
|
*/
|
||||||
|
const gchar* mu_contacts_get_path (MuContacts *self);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* call called for mu_contacts_foreach; returns the e-mail address,
|
* call called for mu_contacts_foreach; returns the e-mail address,
|
||||||
@ -74,18 +96,18 @@ typedef void (*MuContactsForeachFunc) (const char *email, const char *name,
|
|||||||
/**
|
/**
|
||||||
* call a function for either each contact, or each contact satisfying
|
* call a function for either each contact, or each contact satisfying
|
||||||
* a regular expression,
|
* a regular expression,
|
||||||
*
|
*
|
||||||
* @param contacts contacts object
|
* @param contacts contacts object
|
||||||
* @param func callback function to be called for each
|
* @param func callback function to be called for each
|
||||||
* @param user_data user data to pass to the callback
|
* @param user_data user data to pass to the callback
|
||||||
* @param pattern a regular expression which matches either the e-mail
|
* @param pattern a regular expression which matches either the e-mail
|
||||||
* or name, to filter out contacts, or NULL to not do any filtering.
|
* or name, to filter out contacts, or NULL to not do any filtering.
|
||||||
* @param num receives the number of contacts found, or NULL
|
* @param num receives the number of contacts found, or NULL
|
||||||
*
|
*
|
||||||
* @return TRUE if the function succeeded, or FALSE if the provide
|
* @return TRUE if the function succeeded, or FALSE if the provide
|
||||||
* regular expression was invalid (and not NULL)
|
* regular expression was invalid (and not NULL)
|
||||||
*/
|
*/
|
||||||
gboolean mu_contacts_foreach (MuContacts *contacts, MuContactsForeachFunc func,
|
gboolean mu_contacts_foreach (MuContacts *self, MuContactsForeachFunc func,
|
||||||
gpointer user_data, const char* pattern, size_t *num);
|
gpointer user_data, const char* pattern, size_t *num);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|||||||
Reference in New Issue
Block a user