Index: plugins/housekeeping/gsd-gravatar.c
===================================================================
--- plugins/housekeeping/gsd-gravatar.c	(revision 0)
+++ plugins/housekeeping/gsd-gravatar.c	(revision 0)
@@ -0,0 +1,220 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ * vim: set et sw=8 ts=8:
+ *
+ * Copyright (c) 2009, Philip Withnall
+ *
+ * Authors: Philip Withnall <philip@tecnocode.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* gcc -DHAVE_LIBSOUP -DHAVE_LIBEBOOK -DTEST -Wall `pkg-config --cflags --libs gobject-2.0 glib-2.0 gdk-2.0 gconf-2.0 libsoup-2.4 libebook-1.2` -o gsd-gravatar-test gsd-gravatar.c */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <glib/gstdio.h>
+#include <gdk/gdk.h>
+#include <gconf/gconf-client.h>
+
+#include "gsd-gravatar.h"
+
+#if (defined(HAVE_LIBSOUP) && defined(HAVE_LIBEBOOK))
+
+#include <libsoup/soup.h>
+#include <libebook/e-book.h>
+
+#define MAX_HEIGHT 150
+#define MAX_WIDTH  150
+#define GCONF_KEY  "/desktop/gnome/interface/gravatar_email_address"
+
+/* Modified from gnome-about-me.c in gnome-control-center's about-me capplet.
+ * Copyright (C) 2002 Diego Gonzalez <diego@pemas.net>
+ * GPLv2+ */
+static void
+update_photo (const gchar *data, gsize length)
+{
+        EContact      *contact;
+        EBook         *book;
+        EContactPhoto *photo;
+        gchar         *file;
+        GError        *error;
+
+        /* Get the contact/book data from Evolution */
+        if (e_book_get_self (&contact, &book, NULL) == FALSE) {
+                g_warning ("Could not get EBook/EContact");
+                return;
+        }
+
+        if (data != NULL) {
+                GdkPixbufLoader *loader = gdk_pixbuf_loader_new ();
+                GdkPixbuf *pixbuf, *scaled;
+                int height, width;
+                gboolean do_scale = FALSE;
+                char *scaled_data = NULL;
+                gsize scaled_length;
+                float scale;
+
+                /* Before updating the image in EDS scale it to a reasonable size
+                   so that the user doesn't get an application that does not respond
+                   or that takes 100% CPU */
+                gdk_pixbuf_loader_write (loader, (const guchar*) data, length, NULL);
+                gdk_pixbuf_loader_close (loader, NULL);
+
+                pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+
+                if (pixbuf)
+                        g_object_ref (pixbuf);
+
+                g_object_unref (loader);
+
+                height = gdk_pixbuf_get_height (pixbuf);
+                width = gdk_pixbuf_get_width (pixbuf);
+
+                if (height >= width && height > MAX_HEIGHT) {
+                        scale = (float)MAX_HEIGHT/height;
+                        do_scale = TRUE;
+                } else if (width > height && width > MAX_WIDTH) {
+                        scale = (float)MAX_WIDTH/width;
+                        do_scale = TRUE;
+                }
+
+                if (do_scale) {
+                        scaled = gdk_pixbuf_scale_simple (pixbuf, width*scale, height*scale, GDK_INTERP_BILINEAR);
+                        gdk_pixbuf_save_to_buffer (scaled, &scaled_data, &scaled_length, "png", NULL,
+                                                   "compression", "9", NULL);
+                } else {
+                        scaled_data = g_memdup (data, length);
+                        scaled_length = length;
+                }
+
+                photo = g_new0 (EContactPhoto, 1);
+                photo->type = E_CONTACT_PHOTO_TYPE_INLINED;
+                photo->data.inlined.data = (guchar*) scaled_data;
+                photo->data.inlined.length = scaled_length;
+                e_contact_set (contact, E_CONTACT_PHOTO, photo);
+
+                /* Save the image for GDM */
+                /* FIXME: I would have to read the default used by the gdmgreeter program */
+                error = NULL;
+                file = g_build_filename (g_get_home_dir (), ".face", NULL);
+                if (g_file_set_contents (file, scaled_data, scaled_length, &error) != FALSE) {
+                        g_chmod (file, 0644);
+                } else {
+                        g_warning ("Could not create %s: %s", file, error->message);
+                        g_error_free (error);
+                }
+
+                g_free (file);
+
+                e_contact_photo_free (photo);
+
+        } else {
+                /* Update the image in the card */
+                e_contact_set (contact, E_CONTACT_PHOTO, NULL);
+
+                file = g_build_filename (g_get_home_dir (), ".face", NULL);
+
+                g_unlink (file);
+
+                g_free (file);
+        }
+
+        if (!e_book_commit_contact (book, contact, NULL))
+                g_warning ("Could not save contact information");
+}
+
+static void
+download_gravatar_cb (SoupSession *session, SoupMessage *message, gpointer user_data)
+{
+        if (SOUP_STATUS_IS_REDIRECTION (message->status_code)) {
+                /* Gravatar doesn't exist for this e-mail address, so
+                 * blank the photo */
+                g_debug ("No Gravatar found for this e-mail address; unsetting image");
+                update_photo (NULL, 0);
+                goto done;
+        }
+
+        g_debug ("Gravatar downloaded; saving");
+        update_photo (message->response_body->data, message->response_body->length);
+
+done:
+        g_object_unref (session);
+}
+
+void
+gsd_gravatar_update (void)
+{
+        gchar *uri, *email, *email_md5;
+        SoupSession *session;
+        SoupMessage *message;
+        GConfClient *gconf_client;
+
+        gconf_client = gconf_client_get_default ();
+        email = gconf_client_get_string (gconf_client, GCONF_KEY, NULL); /* TODO: error? */
+        g_object_unref (gconf_client);
+
+        if (email == NULL || email[0] == '\0') {
+                g_debug ("Not updating Gravatar image; no Gravatar e-mail address");
+                g_free (email);
+                return;
+        }
+
+        g_debug ("Updating Gravatar image for %s", email);
+
+        /* Build the avatar URI (see http://en.gravatar.com/site/implement/url).
+         * We set http://example.com as the default Gravatar so we can catch the
+         * redirect to determine that an e-mail address doesn't have a Gravatar. */
+        email_md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, email, -1);
+        uri = g_strdup_printf ("http://www.gravatar.com/avatar/%s?s=%u&d=http%%3A%%2F%%2Fexample.com", email_md5, MAX_WIDTH);
+        g_free (email_md5);
+        g_free (email);
+
+        session = soup_session_async_new ();
+        message = soup_message_new ("GET", uri);
+        soup_message_set_flags (message, SOUP_MESSAGE_NO_REDIRECT);
+        g_free (uri);
+
+        soup_session_queue_message (session, message, download_gravatar_cb, NULL);
+}
+
+#else  /* HAVE_LIBSOUP && HAVE_LIBEBOOK */
+
+void
+gsd_gravatar_update (void)
+{
+}
+
+#endif /* !(HAVE_LIBSOUP && HAVE_LIBEBOOK) */
+
+#ifdef TEST
+int
+main (int argc, char **argv)
+{
+        GMainLoop *loop;
+
+        loop = g_main_loop_new (NULL, TRUE);
+        gsd_gravatar_update ();
+        g_main_loop_run (loop);
+        g_main_loop_unref (loop);
+
+        return 0;
+}
+#endif /* TEST */
Index: plugins/housekeeping/gsd-gravatar.h
===================================================================
--- plugins/housekeeping/gsd-gravatar.h	(revision 0)
+++ plugins/housekeeping/gsd-gravatar.h	(revision 0)
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ * vim: set et sw=8 ts=8:
+ *
+ * Copyright (c) 2009, Philip Withnall
+ *
+ * Authors: Philip Withnall <philip@tecnocode.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_GRAVATAR_H
+#define __GSD_GRAVATAR_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+void gsd_gravatar_update (void);
+
+G_END_DECLS
+
+#endif /* __GSD_GRAVATAR_H */
Index: plugins/housekeeping/Makefile.am
===================================================================
--- plugins/housekeeping/Makefile.am	(revision 689)
+++ plugins/housekeeping/Makefile.am	(working copy)
@@ -3,6 +3,8 @@
 libhousekeeping_la_SOURCES = 		\
 	gsd-disk-space.c		\
 	gsd-disk-space.h		\
+	gsd-gravatar.c			\
+	gsd-gravatar.h			\
 	gsd-housekeeping-manager.c	\
 	gsd-housekeeping-manager.h	\
 	gsd-housekeeping-plugin.c	\
@@ -17,11 +19,13 @@
 	$(SETTINGS_PLUGIN_CFLAGS)	\
 	$(GIOUNIX_CFLAGS)		\
 	$(LIBNOTIFY_CFLAGS)		\
+	$(LIBSOUP_CFLAGS)		\
+	$(LIBEBOOK_CFLAGS)		\
 	$(AM_CFLAGS)
 
 libhousekeeping_la_LDFLAGS = $(GSD_PLUGIN_LDFLAGS)
 
-libhousekeeping_la_LIBADD = $(SETTINGS_PLUGIN_LIBS) $(GIOUNIX_LIBS) $(LIBNOTIFY_LIBS)
+libhousekeeping_la_LIBADD = $(SETTINGS_PLUGIN_LIBS) $(GIOUNIX_LIBS) $(LIBNOTIFY_LIBS) $(LIBSOUP_LIBS) $(LIBEBOOK_LIBS)
 
 plugin_in_files = housekeeping.gnome-settings-plugin.in
 
Index: plugins/housekeeping/gsd-housekeeping-manager.c
===================================================================
--- plugins/housekeeping/gsd-housekeeping-manager.c	(revision 689)
+++ plugins/housekeeping/gsd-housekeeping-manager.c	(working copy)
@@ -26,6 +26,7 @@
 
 #include "gnome-settings-profile.h"
 #include "gsd-housekeeping-manager.h"
+#include "gsd-gravatar.h"
 
 
 /* General */
@@ -243,6 +244,7 @@
 do_cleanup (GsdHousekeepingManager *manager)
 {
         purge_thumbnail_cache ();
+        gsd_gravatar_update ();
         return TRUE;
 }
 
Index: configure.ac
===================================================================
--- configure.ac	(revision 689)
+++ configure.ac	(working copy)
@@ -220,6 +220,16 @@
 AC_SUBST(GIOUNIX_CFLAGS)
 AC_SUBST(GIOUNIX_LIBS)
 
+PKG_CHECK_MODULES(LIBSOUP, [libsoup-2.4],
+		  [AC_DEFINE([HAVE_LIBSOUP], 1,
+		  [Define if libsoup-2.4 is available])],
+		  has_libsoup=false)
+PKG_CHECK_MODULES(LIBEBOOK, [libebook-1.2 >= 1.7.90],
+		  [AC_DEFINE([HAVE_LIBEBOOK], 1,
+		  [Define if evolution-data-server libebook-1.2 is available])],
+		  has_libebook=false)
+
+
 dnl ==============================================
 dnl PulseAudio section
 dnl ==============================================
