From a3ec21768c199ad01785f8ec177cf60470824759 Mon Sep 17 00:00:00 2001 From: Ricardo Mones Date: Wed, 12 Feb 2014 23:56:32 +0100 Subject: [PATCH 1/1] New hooklist to collect avatar data from headers MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Also: • Refactorize X-Face/Face capture as an internal plugin. • Add hidden preference ‘enable_avatars’ to control the internal capture/render process, and which allows disabling it by external plugins for example. --- manual/advanced.xml | 16 ++++++++++++ src/prefs_common.c | 1 + src/prefs_common.h | 10 ++++++++ src/procheader.c | 59 ++++++++++++++++++++++++++++++++------------- src/procheader.h | 2 ++ src/procmsg.c | 14 +++++++++++ src/procmsg.h | 8 ++++++ src/proctypes.h | 3 +++ 8 files changed, 96 insertions(+), 17 deletions(-) diff --git a/manual/advanced.xml b/manual/advanced.xml index dfcd319ac..5d4cb6718 100644 --- a/manual/advanced.xml +++ b/manual/advanced.xml @@ -629,6 +629,22 @@ + + enable_avatars + + + Enables capture and/or rendering of internal avatars (Face and + also X-Face headers if built with compface support). + '0' disables both, '1' enables capture only, '2' enables rendering + only and '3' enables both. + + + Note that external plugins already providing these features may + disable partially or completely this to speed up process, regardless + of the configured value. + + + enable_dotted_lines diff --git a/src/prefs_common.c b/src/prefs_common.c index e2c676b7a..93fcce6b8 100644 --- a/src/prefs_common.c +++ b/src/prefs_common.c @@ -1177,6 +1177,7 @@ static PrefParam param[] = { NULL, NULL, NULL}, {"address_search_wildcard", "TRUE", &prefs_common.address_search_wildcard, P_BOOL, NULL, NULL, NULL}, + {"enable_avatars", "3", &prefs_common.enable_avatars, P_INT, NULL, NULL, NULL}, {NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL} }; diff --git a/src/prefs_common.h b/src/prefs_common.h index cc89e33c5..37ccfe614 100644 --- a/src/prefs_common.h +++ b/src/prefs_common.h @@ -102,6 +102,14 @@ typedef enum SHOW_BOTH } SummaryFromShow; +typedef enum +{ + AVATARS_DISABLE = 0, + AVATARS_ENABLE_CAPTURE = 1, + AVATARS_ENABLE_RENDER = 2, + AVATARS_ENABLE_BOTH = 3 +} EnableAvatars; + struct _PrefsCommon { /* Receive */ @@ -522,6 +530,8 @@ struct _PrefsCommon gboolean folder_search_wildcard; gboolean address_search_wildcard; + + guint enable_avatars; }; extern PrefsCommon prefs_common; diff --git a/src/procheader.c b/src/procheader.c index 2acafb8ed..4b7ff05ff 100644 --- a/src/procheader.c +++ b/src/procheader.c @@ -38,6 +38,7 @@ #include "procmsg.h" #include "codeconv.h" #include "prefs_common.h" +#include "hooks.h" #include "utils.h" #include "defs.h" @@ -462,17 +463,37 @@ MsgInfo *procheader_parse_stream(FILE *fp, MsgFlags flags, gboolean full, return parse_stream(fp, FALSE, flags, full, decrypted); } +static gboolean avatar_from_some_face(gpointer source, gpointer userdata) +{ + AvatarCaptureData *acd = (AvatarCaptureData *)source; + + if (*(acd->content) == '\0') /* won't be null, but may be empty */ + return FALSE; + + if (!strcmp(acd->header, hentry_full[H_FACE].name)) { + debug_print("avatar_from_some_face: found 'Face' header\n"); + procmsg_msginfo_add_avatar(acd->msginfo, AVATAR_FACE, acd->content); + } +#if HAVE_LIBCOMPFACE + else if (!strcmp(acd->header, hentry_full[H_X_FACE].name)) { + debug_print("avatar_from_some_face: found 'X-Face' header\n"); + procmsg_msginfo_add_avatar(acd->msginfo, AVATAR_XFACE, acd->content); + } +#endif + return FALSE; +} + static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags, gboolean full, gboolean decrypted) { MsgInfo *msginfo; - MsgInfoAvatar *avatar; gchar buf[BUFFSIZE]; gchar *p, *tmp; gchar *hp; HeaderEntry *hentry; gint hnum; void *orig_data = data; + guint hook_id = -1; get_one_field_func get_one_field = isstring ? (get_one_field_func)string_get_one_field @@ -510,6 +531,10 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags, msginfo->inreplyto = NULL; + if (prefs_common.enable_avatars | AVATARS_ENABLE_CAPTURE) { + hook_id = hooks_register_hook(AVATAR_HEADER_UPDATE_HOOKLIST, avatar_from_some_face, NULL); + } + while ((hnum = get_one_field(buf, sizeof(buf), data, hentry)) != -1) { hp = buf + strlen(hentry[hnum].name); @@ -616,22 +641,6 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags, MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_NEW|MSG_UNREAD); break; #endif - case H_FACE: - if (!msginfo->extradata) - msginfo->extradata = g_new0(MsgInfoExtraData, 1); - avatar = g_new0(MsgInfoAvatar, 1); - avatar->avatar_id = AVATAR_FACE; - avatar->avatar_src = g_strdup(hp); - msginfo->extradata->avatars = g_slist_append(msginfo->extradata->avatars, avatar); - break; - case H_X_FACE: - if (!msginfo->extradata) - msginfo->extradata = g_new0(MsgInfoExtraData, 1); - avatar = g_new0(MsgInfoAvatar, 1); - avatar->avatar_id = AVATAR_XFACE; - avatar->avatar_src = g_strdup(hp); - msginfo->extradata->avatars = g_slist_append(msginfo->extradata->avatars, avatar); - break; case H_DISPOSITION_NOTIFICATION_TO: if (!msginfo->extradata) msginfo->extradata = g_new0(MsgInfoExtraData, 1); @@ -740,12 +749,28 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags, default: break; } + /* to avoid performance penalty hooklist is invoked only for + headers known to be able to generate avatars */ + if (hnum == H_FROM || hnum == H_X_FACE || hnum == H_FACE) { + AvatarCaptureData *acd = g_new0(AvatarCaptureData, 1); + /* no extra memory is wasted, hooks are expected to + take care of copying members when needed */ + acd->msginfo = msginfo; + acd->header = hentry_full[hnum].name; + acd->content = hp; + hooks_invoke(AVATAR_HEADER_UPDATE_HOOKLIST, (gpointer)acd); + g_free(acd); + } } if (!msginfo->inreplyto && msginfo->references) msginfo->inreplyto = g_strdup((gchar *)msginfo->references->data); + if (hook_id != -1) { + hooks_unregister_hook(AVATAR_HEADER_UPDATE_HOOKLIST, hook_id); + } + return msginfo; } diff --git a/src/procheader.h b/src/procheader.h index adbc82a66..b8e48fc3e 100644 --- a/src/procheader.h +++ b/src/procheader.h @@ -26,6 +26,8 @@ #include "proctypes.h" +#define AVATAR_HEADER_UPDATE_HOOKLIST "avatar_header_update" + struct _HeaderEntry { gchar *name; diff --git a/src/procmsg.c b/src/procmsg.c index 3bb41c9e0..767fe64ab 100644 --- a/src/procmsg.c +++ b/src/procmsg.c @@ -788,6 +788,20 @@ gchar *procmsg_msginfo_get_avatar(MsgInfo *msginfo, gint type) return NULL; } +void procmsg_msginfo_add_avatar(MsgInfo *msginfo, gint type, const gchar *data) +{ + MsgInfoAvatar *av; + + if (!msginfo->extradata) + msginfo->extradata = g_new0(MsgInfoExtraData, 1); + + av = g_new0(MsgInfoAvatar, 1); + av->avatar_id = type; + av->avatar_src = g_strdup(data); + + msginfo->extradata->avatars = g_slist_append(msginfo->extradata->avatars, av); +} + gchar *procmsg_msginfo_get_identifier(MsgInfo *msginfo) { gchar *folder_id; diff --git a/src/procmsg.h b/src/procmsg.h index 14d147ed0..52b04c065 100644 --- a/src/procmsg.h +++ b/src/procmsg.h @@ -285,6 +285,13 @@ struct _MailFilteringData PrefsAccount *account; }; +struct _AvatarCaptureData +{ + MsgInfo *msginfo; + const gchar *header; + const gchar *content; +}; + GSList *procmsg_read_cache (FolderItem *item, gboolean scan_file); void procmsg_msg_list_free (MsgInfoList *mlist); @@ -397,4 +404,5 @@ MsgInfo *procmsg_get_msginfo_from_identifier(const gchar *id); gchar *procmsg_msginfo_get_identifier(MsgInfo *msginfo); gchar *procmsg_msginfo_get_avatar(MsgInfo *msginfo, gint type); +void procmsg_msginfo_add_avatar(MsgInfo *msginfo, gint type, const gchar *data); #endif /* __PROCMSG_H__ */ diff --git a/src/proctypes.h b/src/proctypes.h index fd080c722..ef6ec5865 100644 --- a/src/proctypes.h +++ b/src/proctypes.h @@ -40,6 +40,9 @@ typedef struct _MsgInfoUpdate MsgInfoUpdate; struct _MailFilteringData; typedef struct _MailFilteringData MailFilteringData; +struct _AvatarCaptureData; +typedef struct _AvatarCaptureData AvatarCaptureData; + struct _MsgInfoExtraData; typedef struct _MsgInfoExtraData MsgInfoExtraData; -- 2.25.1