diff --git a/plugins/pom.xml b/plugins/pom.xml
index f986dea57a..b98e4801be 100644
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -24,6 +24,7 @@
scm-pam-plugin
scm-bzr-plugin
scm-auth-ldap-plugin
+ scm-gravatar-plugin
diff --git a/plugins/scm-gravatar-plugin/pom.xml b/plugins/scm-gravatar-plugin/pom.xml
new file mode 100644
index 0000000000..17323347d2
--- /dev/null
+++ b/plugins/scm-gravatar-plugin/pom.xml
@@ -0,0 +1,21 @@
+
+
+
+ 4.0.0
+
+
+ scm-plugins
+ sonia.scm.plugins
+ 1.2-SNAPSHOT
+
+
+ sonia.scm.plugins
+ scm-gravatar-plugin
+ 1.0-SNAPSHOT
+ scm-gravatar-plugin
+ https://bitbucket.org/sdorra/scm-manager
+ Gravatar icons for the changesetviewer.
+
+
+
diff --git a/plugins/scm-gravatar-plugin/src/main/java/sonia/scm/gravatar/GravatarChangesetPreProcessor.java b/plugins/scm-gravatar-plugin/src/main/java/sonia/scm/gravatar/GravatarChangesetPreProcessor.java
new file mode 100644
index 0000000000..814d5478dc
--- /dev/null
+++ b/plugins/scm-gravatar-plugin/src/main/java/sonia/scm/gravatar/GravatarChangesetPreProcessor.java
@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of SCM-Manager; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.gravatar;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.plugin.ext.Extension;
+import sonia.scm.repository.Changeset;
+import sonia.scm.repository.ChangesetPreProcessor;
+import sonia.scm.repository.Person;
+import sonia.scm.util.Util;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+@Extension
+public class GravatarChangesetPreProcessor implements ChangesetPreProcessor
+{
+
+ /** Field description */
+ public static final String PROPERTY_GRAVATARHASH = "gravatar-hash";
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param changeset
+ */
+ @Override
+ public void process(Changeset changeset)
+ {
+ Person author = changeset.getAuthor();
+
+ if (author != null)
+ {
+ String hash = MD5Util.md5Hex(author.getMail());
+
+ if (Util.isNotEmpty(hash))
+ {
+ changeset.getProperties().put(PROPERTY_GRAVATARHASH, hash);
+ }
+ }
+ }
+}
diff --git a/plugins/scm-gravatar-plugin/src/main/java/sonia/scm/gravatar/MD5Util.java b/plugins/scm-gravatar-plugin/src/main/java/sonia/scm/gravatar/MD5Util.java
new file mode 100644
index 0000000000..d57abb751b
--- /dev/null
+++ b/plugins/scm-gravatar-plugin/src/main/java/sonia/scm/gravatar/MD5Util.java
@@ -0,0 +1,116 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of SCM-Manager; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.gravatar;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.util.Util;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.UnsupportedEncodingException;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class MD5Util
+{
+
+ /** the logger for MD5Util */
+ private static final Logger logger = LoggerFactory.getLogger(MD5Util.class);
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param array
+ *
+ * @return
+ */
+ public static String hex(byte[] array)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = 0; i < array.length; ++i)
+ {
+ sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3));
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param message
+ *
+ * @return
+ */
+ public static String md5Hex(String message)
+ {
+ String out = null;
+
+ if (Util.isNotEmpty(message))
+ {
+ message = message.toLowerCase().trim();
+
+ try
+ {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+
+ out = hex(md.digest(message.getBytes("CP1252")));
+ }
+ catch (NoSuchAlgorithmException ex)
+ {
+ logger.error(ex.getMessage(), ex);
+ }
+ catch (UnsupportedEncodingException ex)
+ {
+ logger.error(ex.getMessage(), ex);
+ }
+ }
+
+ return out;
+ }
+}
diff --git a/plugins/scm-gravatar-plugin/src/main/resources/META-INF/scm/plugin.xml b/plugins/scm-gravatar-plugin/src/main/resources/META-INF/scm/plugin.xml
new file mode 100644
index 0000000000..2a6d22e5ea
--- /dev/null
+++ b/plugins/scm-gravatar-plugin/src/main/resources/META-INF/scm/plugin.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+ ${project.groupId}
+ ${project.artifactId}
+ ${project.version}
+ ${project.name}
+ ${project.description}
+ Sebastian Sdorra
+ ${project.url}
+
+
+
+ 1.2
+
+
+
+
+
+
+
diff --git a/plugins/scm-gravatar-plugin/src/main/resources/sonia/scm/gravatar/sonia.gravatar.js b/plugins/scm-gravatar-plugin/src/main/resources/sonia/scm/gravatar/sonia.gravatar.js
new file mode 100644
index 0000000000..3263f8bc78
--- /dev/null
+++ b/plugins/scm-gravatar-plugin/src/main/resources/sonia/scm/gravatar/sonia.gravatar.js
@@ -0,0 +1,78 @@
+/* *
+ * Copyright (c) 2010, Sebastian Sdorra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of SCM-Manager; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+if (Sonia.repository.ChangesetViewerGrid){
+
+ Sonia.repository.ChangesetViewerGrid.prototype.initComponentExt = Sonia.repository.ChangesetViewerGrid.prototype.initComponent;
+
+ Ext.override(Sonia.repository.ChangesetViewerGrid, {
+
+ gravatarSize: 32,
+ gravatarNotFoundType: 'identicon',
+ gravatarTemplate: '
',
+
+ initComponent: function(){
+ this.initComponentExt.apply(this, arguments);
+ if ( debug ){
+ console.debug('register gravatar plugin');
+ }
+ this.addColumn('properties', {
+ id: 'gravatar',
+ dataIndex: 'properties',
+ renderer: this.renderGravatar,
+ scope: this,
+ width: this.gravatarSize + 8
+ }, 0);
+ },
+
+ renderGravatar: function(properties){
+ var hash = '00000000000000000000000000000000';
+ if ( properties != null ){
+ for (var i=0; i