talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit a3ec21768c199ad01785f8ec177cf60470824759
parent 37df4f1b3240328a17c03108319ad315447e7fb7
Author: Ricardo Mones <ricardo@mones.org>
Date:   Wed, 12 Feb 2014 23:56:32 +0100

New hooklist to collect avatar data from headers

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.

Diffstat:
Mmanual/advanced.xml | 16++++++++++++++++
Msrc/prefs_common.c | 1+
Msrc/prefs_common.h | 10++++++++++
Msrc/procheader.c | 59++++++++++++++++++++++++++++++++++++++++++-----------------
Msrc/procheader.h | 2++
Msrc/procmsg.c | 14++++++++++++++
Msrc/procmsg.h | 8++++++++
Msrc/proctypes.h | 3+++
8 files changed, 96 insertions(+), 17 deletions(-)

diff --git a/manual/advanced.xml b/manual/advanced.xml @@ -630,6 +630,22 @@ </listitem> </varlistentry> <varlistentry> + <term><literal>enable_avatars</literal></term> + <listitem> + <para> + 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. + </para> + <para> + Note that external plugins already providing these features may + disable partially or completely this to speed up process, regardless + of the configured value. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><literal>enable_dotted_lines</literal></term> <listitem> <para> diff --git 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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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;