Creating Gravatar Web Image Avatars in FoxPro
February 02, 2012 •
Gravatar.com is a great and very popular Web service based way to associate an image with user accounts that are based on email addresses. It's easy to use and can provide a nice touch of personalization with very little effort to just about any Web application that uses email addresses for users. This post shows how you can use Gravatar from within your FoxPro based applications.
I recently restyled my West Wind Message Board support site and one of things that I think makes the messages look a little more interesting and personal is having an avatar - an image - associated with users. But rather than asking users to upload images and storing them on my servers, I opted to use Gravatar which is a Web based service that can be used in many applications and is supported by a large number of popular Web sites already. Ultimately it's a better choice for users who only have to sign up once to associate an email address with a Gravatar to be used on many sites.
Here's what the Gravatar image looks like on a message board message:
The Gravatar service simply returns an an image for a given email address and some other parameters that are encoded and point at the Gravatar.com site. As a developer you configure Gravatar by creating a URL and embedding that URL into an <img> control's src attribute.
Above you can see the image that is associated with my Email address. The cool thing about Gravatar - if they have a Gravatar account already - is that once users have provided an email address they don't have to do anything else to associate their gravatar image with your application. If they have a gravatar configured the image is shown. If not, a default image is shown.
If an email address is sent to Gravatar that doesn't exist you can either provide another URL to an alternate image (some sort of default that's appropriate for your app) or you can let Gravatar serve it's default icon which looks like this:
How it works
The Gravatar service works by calling a URL on their site and providing a few known parameters. An URL to retrieve an email address looks something like this:
http://www.gravatar.com/avatar/a4ec5092141a8649fe9d81527569a4c0?s=80&r=r
In an image control:
<img src="http://www.gravatar.com/avatar/a4ec5092141a8649fe9d81527569a4c0?s=80&r="
class="gravatar"
alt="Gratar Image based on email address" />
The components you need to send to get a Gravatar image are:
- The Email Address encoded with an MD5 Hash
- An image size
- A default image if the email address is not registered with
- A rating for the image (g, pg, r, x)
I've created a small reusable function that helps create Gravatar images in FoxPro. Using the function you can do:
? GravatarLink("rstrahl@west-wind.com",80) ? GravatarLink("invalid@west-wind.com",60,,"r")
Here's the code for the GravatarLink function:
************************************************************************ * GravatarLink **************************************** *** Function: Creates an image URL for a given email address *** that is registered with Gravatar.com. *** *** Gravatar is a very popular avatar service that *** requires only an email address to share a picture. *** Used on many web sites so once you sign up your *** picture will be used on many sites. *** Assume: *** Pass: lcEmail - Email Address *** lnSize - Image Size (square) 60-80 is usually good *** lcDefaultImage - Url to an image if no match is found *** for email. Empty shows Gravatar's default *** lcRating - g, pg, r, x (Default: pg) *** Return: URL to the Gravatar image ************************************************************************ FUNCTION GravatarLink(lcEmail,lnSize,lcDefaultImage, lcRating) LOCAL lcDefaultImage IF EMPTY(lnSize) lnSize = 80 ENDIF IF !EMPTY(lcEmail) lcHash = LOWER(STRCONV(HashMd5(lcEmail),15)) ELSE lcHash = "" ENDIF IF EMPTY(lcDefaultImage) *** Gravatar default image displays lcDefaultImage = "" ELSE lcDefaultImage = "&d=" + UrlEncode(lcDefaultImage) ENDIF IF EMPTY(lcRating) lcRating = "pg" ENDIF lcUrl = "http://www.gravatar.com/avatar/" + lcHash + "?" +; "s=" + TRANSFORM(lnSize) +; "&r=" + lcRating +; lcDefaultImage RETURN lcUrl * GravatarLink
The code is pretty straight forward - it basically builds up a URL as a string and adds the components provided by the parameters. The trickiest part of this is the MD5 encoding of the Email address. The MD5 hash creates a binary value which is then turned into a HexBinary string with STRCONV().
In order to encode the email address as an MD5 hash I use the following routine based on the content from the FoxPro Wiki a long while back:
************************************************************************ * wwAPI :: HashMD5 **************************************** *** Function: retrieved from the FoxWiki *** http://fox.wikis.com/wc.dll?fox~vfpmd5hashfunction *** Assume: Self standing function - not part of wwAPI class *** Pass: Data to encrypt *** Return: ************************************************************************ FUNCTION HashMD5(tcData) *** #include "c:\program files\microsoft visual foxpro 8\ffc\wincrypt.h" #DEFINE dnPROV_RSA_FULL 1 #DEFINE dnCRYPT_VERIFYCONTEXT 0xF0000000 #DEFINE dnALG_CLASS_HASH BITLSHIFT(4,13) #DEFINE dnALG_TYPE_ANY 0 #DEFINE dnALG_SID_MD5 3 #DEFINE dnCALG_MD5 BITOR(BITOR(dnALG_CLASS_HASH,dnALG_TYPE_ANY),dnALG_SID_MD5) #DEFINE dnHP_HASHVAL 0x0002 && Hash value LOCAL lnStatus, lnErr, lhProv, lhHashObject, lnDataSize, lcHashValue, lnHashSize lhProv = 0 lhHashObject = 0 lnDataSize = LEN(tcData) lcHashValue = REPLICATE(CHR(0), 16) lnHashSize = LEN(lcHashValue) DECLARE INTEGER GetLastError ; IN win32api AS GetLastError DECLARE INTEGER CryptAcquireContextA ; IN WIN32API AS CryptAcquireContext ; INTEGER @lhProvHandle, ; STRING cContainer, ; STRING cProvider, ; INTEGER nProvType, ; INTEGER nFlags * load a crypto provider lnStatus = CryptAcquireContext(@lhProv, 0, 0, dnPROV_RSA_FULL, dnCRYPT_VERIFYCONTEXT) IF lnStatus = 0 THROW GetLastError() ENDIF DECLARE INTEGER CryptCreateHash ; IN WIN32API AS CryptCreateHash ; INTEGER hProviderHandle, ; INTEGER nALG_ID, ; INTEGER hKeyhandle, ; INTEGER nFlags, ; INTEGER @hCryptHashHandle * create a hash object that uses MD5 algorithm lnStatus = CryptCreateHash(lhProv, dnCALG_MD5, 0, 0, @lhHashObject) IF lnStatus = 0 THROW GetLastError() ENDIF DECLARE INTEGER CryptHashData ; IN WIN32API AS CryptHashData ; INTEGER hHashHandle, ; STRING @cData, ; INTEGER nDataLen, ; INTEGER nFlags * add the input data to the hash object lnStatus = CryptHashData(lhHashObject, tcData, lnDataSize, 0) IF lnStatus = 0 THROW GetLastError() ENDIF DECLARE INTEGER CryptGetHashParam ; IN WIN32API AS CryptGetHashParam ; INTEGER hHashHandle, ; INTEGER nParam, ; STRING @cHashValue, ; INTEGER @nHashSize, ; INTEGER nFlags * retrieve the hash value, if caller did not provide enough storage (16 bytes for MD5) * this will fail with dnERROR_MORE_DATA and lnHashSize will contain needed storage size lnStatus = CryptGetHashParam(lhHashObject, dnHP_HASHVAL, @lcHashValue, @lnHashSize, 0) IF lnStatus = 0 THROW GetLastError() ENDIF DECLARE INTEGER CryptDestroyHash ; IN WIN32API AS CryptDestroyHash; INTEGER hKeyHandle *** free the hash object lnStatus = CryptDestroyHash(lhHashObject) IF lnStatus = 0 THROW GetLastError() ENDIF DECLARE INTEGER CryptReleaseContext ; IN WIN32API AS CryptReleaseContext ; INTEGER hProvHandle, ; INTEGER nReserved *** release the crypto provider lnStatus = CryptReleaseContext(lhProv, 0) IF lnStatus = 0 THROW GetLastError() ENDIF RETURN lcHashValue ENDFUNC * HashMD5
With this function in place it's now a snap to embed Gravatar images into HTML based applications. In a Web Connection (or any other template/script based environment that uses Fox code) you can now simply do:
<img src="<%= GravatarLink(poUser.Email,80,,"pg") %>" class="gravatar" />
And you're off to the races.
On the West Wind MessageBoard
If you're a user of the West Wind Message Board I recommend you head over to Gravatar.com and hook up your Avatar image if you are interested in showing an image for any of your messages. Go ahead post a message, and see your Gravatar pop up. Once you have a Gravatar you may find that a lot of sites where you participate also already use Gravatar images so this will be useful in a lot of places beyond just the message board or your own applications.
GravatarLink() is now also part of the wwUtils library in Web Connection and the West Wind Client Tools.
Frank Dietrich
February 05, 2012