---
 cgit.c       |  3 +++
 cgit.h       |  8 ++++++++
 cgitrc.5.txt |  4 ++++
 parsing.c    | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 shared.c     | 23 +++++++++++++++++++++++
 ui-commit.c  | 10 ++++++++++
 ui-log.c     |  5 +++++
 ui-refs.c    | 10 ++++++++++
 ui-tag.c     |  5 +++++
 9 files changed, 119 insertions(+)

diff --git a/cgit.c b/cgit.c
index 861352a..fe82580 100644
--- a/cgit.c
+++ b/cgit.c
@@ -183,6 +183,8 @@ static void config_cb(const char *name, const char *value)
                ctx.cfg.enable_index_owner = atoi(value);
        else if (!strcmp(name, "enable-commit-graph"))
                ctx.cfg.enable_commit_graph = atoi(value);
+       else if (!strcmp(name, "enable-gravatar"))
+               ctx.cfg.enable_gravatar = atoi(value);
        else if (!strcmp(name, "enable-log-filecount"))
                ctx.cfg.enable_log_filecount = atoi(value);
        else if (!strcmp(name, "enable-log-linecount"))
@@ -368,6 +370,7 @@ static void prepare_context(struct cgit_context *ctx)
        ctx->cfg.logo = "/cgit.png";
        ctx->cfg.favicon = "/favicon.ico";
        ctx->cfg.local_time = 0;
+       ctx->cfg.enable_gravatar = 0;
        ctx->cfg.enable_http_clone = 1;
        ctx->cfg.enable_index_owner = 1;
        ctx->cfg.enable_tree_linenumbers = 1;
diff --git a/cgit.h b/cgit.h
index a474d77..c5c03fb 100644
--- a/cgit.h
+++ b/cgit.h
@@ -107,9 +107,11 @@ struct commitinfo {
        struct commit *commit;
        char *author;
        char *author_email;
+       char *author_gravatar;
        unsigned long author_date;
        char *committer;
        char *committer_email;
+       char *committer_gravatar;
        unsigned long committer_date;
        char *subject;
        char *msg;
@@ -119,6 +121,7 @@ struct commitinfo {
 struct taginfo {
        char *tagger;
        char *tagger_email;
+       char *tagger_gravatar;
        unsigned long tagger_date;
        char *msg;
 };
@@ -208,6 +211,7 @@ struct cgit_config {
        int enable_index_links;
        int enable_index_owner;
        int enable_commit_graph;
+       int enable_gravatar;
        int enable_log_filecount;
        int enable_log_linecount;
        int enable_remote_branches;
@@ -337,6 +341,7 @@ extern char *fmtalloc(const char *format,...);
 
 extern struct commitinfo *cgit_parse_commit(struct commit *commit);
 extern struct taginfo *cgit_parse_tag(struct tag *tag);
+char *cgit_get_gravatar(const char *email);
 extern void cgit_parse_url(const char *url);
 
 extern const char *cgit_repobasename(const char *reponame);
@@ -352,4 +357,7 @@ extern int readfile(const char *path, char **buf, size_t 
*size);
 
 extern char *expand_macros(const char *txt);
 
+void str_to_hex(char *dst_str, const unsigned char *src_bytes,
+               size_t src_len);
+
 #endif /* CGIT_H */
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 633cb00..b6017c2 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -180,6 +180,10 @@ enable-git-config::
        to the corresponding "repo." key in cgit. Default value: "0". See also:
        scan-path, section-from-path.
 
+enable-gravatar::
+       Flag which, when set to "1", will enable cgit to show gravatar icon
+       for author, committer and tagger email address. Default value: "0".
+
 favicon::
        Url used as link to a shortcut icon for cgit. It is suggested to use
        the value "/favicon.ico" since certain browsers will ignore other
diff --git a/parsing.c b/parsing.c
index 658621d..35087c3 100644
--- a/parsing.c
+++ b/parsing.c
@@ -8,6 +8,17 @@
 
 #include "cgit.h"
 
+/* we need md5 hashing algorithm to calculate Gravatar URL */
+#include <openssl/md5.h>
+
+/* This is the URL for Gravatar.
+ * Starting with double slash makes it automatically use the right protocol,
+ * e.g. https for cgit on encrypted sites. The default parameters make this
+ * fetch 16x16 pixel images, with "awesome generated, 8-bit arcade-style
+ * pixelated faces".
+ * https://en.gravatar.com/site/implement/images/ */
+#define GRAVATAR_URL "//www.gravatar.com/avatar/%s?s=16&d=retro"
+
 /*
  * url syntax: [repo ['/' cmd [ '/' path]]]
  *   repo: any valid repo url, may contain '/'
@@ -133,8 +144,10 @@ struct commitinfo *cgit_parse_commit(struct commit *commit)
        ret->commit = commit;
        ret->author = NULL;
        ret->author_email = NULL;
+       ret->author_gravatar = NULL;
        ret->committer = NULL;
        ret->committer_email = NULL;
+       ret->committer_gravatar = NULL;
        ret->subject = NULL;
        ret->msg = NULL;
        ret->msg_encoding = NULL;
@@ -155,11 +168,17 @@ struct commitinfo *cgit_parse_commit(struct commit 
*commit)
                        &ret->author_date);
        }
 
+       if (ctx.cfg.enable_gravatar && ret->author_email != NULL)
+               ret->author_gravatar = cgit_get_gravatar(ret->author_email);
+
        if (p && !strncmp(p, "committer ", 9)) {
                p = parse_user(p + 9, &ret->committer, &ret->committer_email,
                        &ret->committer_date);
        }
 
+       if (ctx.cfg.enable_gravatar && ret->committer_email != NULL)
+               ret->committer_gravatar = 
cgit_get_gravatar(ret->committer_email);
+
        if (p && !strncmp(p, "encoding ", 9)) {
                p += 9;
                t = strchr(p, '\n');
@@ -230,6 +249,7 @@ struct taginfo *cgit_parse_tag(struct tag *tag)
        ret = xmalloc(sizeof(*ret));
        ret->tagger = NULL;
        ret->tagger_email = NULL;
+       ret->tagger_gravatar = NULL;
        ret->tagger_date = 0;
        ret->msg = NULL;
 
@@ -249,6 +269,9 @@ struct taginfo *cgit_parse_tag(struct tag *tag)
                }
        }
 
+       if (ctx.cfg.enable_gravatar && ret->tagger_email != NULL)
+               ret->tagger_gravatar = cgit_get_gravatar(ret->tagger_email);
+
        // skip empty lines between headers and message
        while (p && *p == '\n')
                p++;
@@ -258,3 +281,31 @@ struct taginfo *cgit_parse_tag(struct tag *tag)
        free(data);
        return ret;
 }
+
+char * cgit_get_gravatar(const char *email) {
+       unsigned char digest[MD5_DIGEST_LENGTH];
+       char hex[MD5_DIGEST_LENGTH * 2 + 1], *lower, *tmp;
+       char *gravatar;
+
+       /* The URL includes %s, which is replaced later on. So we do not need
+        * extra space for termination. */
+       gravatar = malloc(strlen(GRAVATAR_URL) + MD5_DIGEST_LENGTH * 2);
+
+       /* duplicate to lower and skip brackets! */
+       lower = strdup(email + 1);
+       lower[strlen(lower) - 1] = '\0';
+
+       /* make the chars lower case */
+       for (tmp = lower; *tmp; ++tmp)
+               *tmp = tolower(*tmp);
+
+       MD5((unsigned char *)lower, strlen(lower), digest);
+
+       str_to_hex(hex, digest, MD5_DIGEST_LENGTH);
+
+       sprintf(gravatar, GRAVATAR_URL, hex);
+
+       free(lower);
+
+       return gravatar;
+}
diff --git a/shared.c b/shared.c
index 919a99e..a383dfa 100644
--- a/shared.c
+++ b/shared.c
@@ -93,8 +93,12 @@ void *cgit_free_commitinfo(struct commitinfo *info)
 {
        free(info->author);
        free(info->author_email);
+       if (info->author_gravatar)
+               free(info->author_gravatar);
        free(info->committer);
        free(info->committer_email);
+       if (info->committer_gravatar)
+               free(info->committer_gravatar);
        free(info->subject);
        free(info->msg);
        free(info->msg_encoding);
@@ -204,6 +208,8 @@ static void cgit_free_taginfo(struct taginfo *tag)
                free(tag->tagger);
        if (tag->tagger_email)
                free(tag->tagger_email);
+       if (tag->tagger_gravatar)
+               free(tag->tagger_gravatar);
        if (tag->msg)
                free(tag->msg);
        free(tag);
@@ -588,3 +594,20 @@ char *expand_macros(const char *txt)
        }
        return result;
 }
+
+/* gets a string representing the binary data. dst_str must have a
+ * size of at least src_len * 2 + 1 bytes. */
+void str_to_hex(char *dst_str, const unsigned char *src_bytes,
+               size_t src_len) {
+       const char *hex = "0123456789abcdef";
+       int n;
+
+       for (n = 0; n < src_len; ++n) {
+               unsigned char val = *src_bytes++;
+
+               *dst_str++ = hex[val >> 4];
+               *dst_str++ = hex[val & 0xf];
+       }
+
+       *dst_str = 0;
+}
diff --git a/ui-commit.c b/ui-commit.c
index ef85a49..4fa5b83 100644
--- a/ui-commit.c
+++ b/ui-commit.c
@@ -44,6 +44,11 @@ void cgit_print_commit(char *hex, const char *prefix)
        cgit_print_diff_ctrls();
        html("<table summary='commit info' class='commit-info'>\n");
        html("<tr><th>author</th><td>");
+       if (ctx.cfg.enable_gravatar && info->author_gravatar) {
+               html("<img src='");
+               html_txt(info->author_gravatar);
+               html("' width=16 height=16 alt='Gravatar' /> ");
+       }
        html_txt(info->author);
        if (!ctx.cfg.noplainemail) {
                html(" ");
@@ -53,6 +58,11 @@ void cgit_print_commit(char *hex, const char *prefix)
        cgit_print_date(info->author_date, FMT_LONGDATE, ctx.cfg.local_time);
        html("</td></tr>\n");
        html("<tr><th>committer</th><td>");
+       if (ctx.cfg.enable_gravatar && info->committer_gravatar) {
+               html("<img src='");
+               html_txt(info->committer_gravatar);
+               html("' width=16 height=16 alt='Gravatar' /> ");
+       }
        html_txt(info->committer);
        if (!ctx.cfg.noplainemail) {
                html(" ");
diff --git a/ui-log.c b/ui-log.c
index c154f69..24a5c47 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -168,6 +168,11 @@ static void print_commit(struct commit *commit, struct 
rev_info *revs)
                         sha1_to_hex(commit->object.sha1), ctx.qry.vpath, 0);
        show_commit_decorations(commit);
        html("</td><td>");
+       if (ctx.cfg.enable_gravatar && info->author_gravatar) {
+               html("<img src='");
+               html_txt(info->author_gravatar);
+               html("' width=16 height=16 alt='Gravatar' /> ");
+       }
        html_txt(info->author);
 
        if (revs->graph) {
diff --git a/ui-refs.c b/ui-refs.c
index 0ae0612..5e6dda9 100644
--- a/ui-refs.c
+++ b/ui-refs.c
@@ -77,6 +77,11 @@ static int print_branch(struct refinfo *ref)
        if (ref->object->type == OBJ_COMMIT) {
                cgit_commit_link(info->subject, NULL, NULL, name, NULL, NULL, 
0);
                html("</td><td>");
+               if (ctx.cfg.enable_gravatar && info->author_gravatar) {
+                       html("<img src='");
+                       html_txt(info->author_gravatar);
+                       html("' width=16 height=16 alt='Gravatar' /> ");
+               }
                html_txt(info->author);
                html("</td><td colspan='2'>");
                cgit_print_age(info->commit->date, -1, NULL);
@@ -154,6 +159,11 @@ static int print_tag(struct refinfo *ref)
                cgit_object_link(obj);
        html("</td><td>");
        if (info) {
+               if (ctx.cfg.enable_gravatar && info->tagger_gravatar) {
+                       html("<img src='");
+                       html_txt(info->tagger_gravatar);
+                       html("' width=16 height=16 alt='Gravatar' /> ");
+               }
                if (info->tagger)
                        html(info->tagger);
        } else if (ref->object->type == OBJ_COMMIT) {
diff --git a/ui-tag.c b/ui-tag.c
index aea7958..865d6d7 100644
--- a/ui-tag.c
+++ b/ui-tag.c
@@ -77,6 +77,11 @@ void cgit_print_tag(char *revname)
                }
                if (info->tagger) {
                        html("<tr><td>tagged by</td><td>");
+                       if (ctx.cfg.enable_gravatar && info->tagger_gravatar) {
+                               html("<img src='");
+                               html_txt(info->tagger_gravatar);
+                               html("' width=16 height=16 alt='Gravatar' /> ");
+                       }
                        html_txt(info->tagger);
                        if (info->tagger_email && !ctx.cfg.noplainemail) {
                                html(" ");
-- 
1.8.5.2

_______________________________________________
CGit mailing list
CGit@lists.zx2c4.com
http://lists.zx2c4.com/mailman/listinfo/cgit

Reply via email to