vCard for Developers

I’ve been researching vCard for a project involving contacts management. This is a quick overview on vCard aimed at developers, with a demo and stealing the example from wikipedia’s vCard entry. The official standard is here.

The Format

vCard is a standard for representing contact information, the kind of info you would see for a contact in an address book or email application – name, address, and so on. By convention, the file suffix is “.vcf”. The info is represented in a text file format as shown below:

N:Gump;Forrest (Name)
FN:Forrest Gump (Full Name)
ORG:Gump Shrimp Co.
TITLE:Shrimp Man
TEL;WORK;VOICE:(111) 555-1212
TEL;HOME;VOICE:(404) 555-1212
ADR;WORK:;;100 Waters Edge;Baytown;LA;30314;United States of America
LABEL;WORK;ENCODING=QUOTED-PRINTABLE:100 Waters Edge=0D=0ABaytown, LA 30314=0D=0AUnited States of America
ADR;HOME:;;42 Plantation St.;Baytown;LA;30314;United States of America
LABEL;HOME;ENCODING=QUOTED-PRINTABLE:42 Plantation St.=0D=0ABaytown, LA 30314=0D=0AUnited States of America
EMAIL;PREF;INTERNET:[email protected]

As you can see, the format is an ugly mainframe-style format that belies vCard’s 1995 birthdate. If it was created a year or two later, it likely would have been a prettier XML format. But don’t be scared, it’s mostly harmless. You basically have field-value pairs separated by “:”. The standard defines all possible fields and the format for their values.

The Fields

The fields defined are: FN (full name – e.g. “Mr. Homer J. Simpson”), N (name – e.g. “Simpson;Homer”), NICKNAME, PHOTO, BDAY (birthday), ADR, LABEL, TEL, EMAIL, MAILER, TZ, GEO (lat/long co-ordinates), TITLE, ROLE, LOGO, AGENT (e.g. a secretary or personal assistant – this is a recursive vCard instance!), ORG, CATEGORIES, NOTE, PRODID (which product created the vCard), REV (a revision ID for this vcard instance), SORT-STRING (the “primary key” on which this record should be sorted, e.g. if you want ‘Van Winkle’ to be sorted as ‘Winkle’), SOUND, URL, UID, VERSION (the version of vCard used to generate this vCard), CLASS (a security access level for this vCard instance – e.g. is it public, protected, private?), KEY (a public key, e.g. you could use it if you wanted to send the contact something encrypted). The only mandatory fields here are FN and N (the two most obscurely named fields, naturally ;)).

Each field-value pair is something like a database record or an object instance, insofar as it includes a number of values. I guess the standard could have avoided this by defining 200 different field names, but instead they grouped related attributes together into the same field. So you end up with just a single “name” field (“N”), which is actually an aggregation of several fields. e.g. ” N:Stevenson;John;Philip,Paul;Dr.;Jr.,M.D.,A.C.P.” contains surname, first name, other names, title, and honorifics.

Similarly, field names are not always just a single word, but can also be qualified by type. Therefore “TEL;WORK;VOICE;PREF” is equivalent to “TEL;TYPE=WORK,VOICE,PREF” and also “TEL;TYPE=WORK,TYPE=VOICE,TYPE=PREF”. (The first form actually appears in the wikipedia example, but the standard talks about the second and third form, so any parser would have to read all of them.). The multiple types are effectively tags/keywords, i.e. the telephone number here is at once a work number, a number supporting voice interaction, and a preferred usage number.

Fields like logo and photo can either be a URL or binary data embedded directly in the VCARD.

See the official standard for full details.

MIME Gubbins: How to Serve vCard from your Web App

If you ever show contacts in your web app, it’s polite to include a vCard export option as users will appreciate the ability to pluck it off the site and into their preferred desktop app. I found serving it to be remarkably easy.

The demo is here

  header('Content-Type: text/x-vcard; charset=utf-8');
  header('Content-Disposition: attachment; filename="vcard-example.vcf"');
FN:Forrest Gump

See? Just output those two headers, then bust out the vCard. The demo successfully opens in Apple Address Book and MS Outlook.

Apple Address Book

MS Outlook

So it works if you’re a Mac or a PC. Neat-O.

Portability, Limitations, and Variations

The great thing about standards is there are so many to choose from, as many a cynic has observed. The other great thing about most standards is they give you so much room for creativity, as this cynic responded. vCard is no exception and can be interpreted in different ways (whether or not these ways conform to the spec I don’t know, and is not especially relevant for real-world developers).

In particular, some people think a vCard file can include only one record, while others think it can include any number of records. I made a second demo to test this. The two-card demo is here. It contains one VCARD after another, as shown below. Well, Apple Address Book likes it and opens up both contacts, while MS Outlook ignores the second. So there.

  header('Content-Type: text/x-vcard; charset=utf-8');
  header('Content-Disposition: attachment; filename="vcard-example.vcf"');

Furthermore, there are “extensions”, which are new property types that go beyond the standard and are used by certain applications. Wikipedia identifies a veritable menagerie of extensions, including such species as X-MANAGER for manager details; X-AIM/X-MSN/X-ICQ/X-GADUGADU (awesome!)/etc for IM details, and X-ASSISTANT for assistant details (they probably forgot about the AGENT property). any other properties are prefixed with the company who introduced them, leading to the elegantly named X-FUNAMBOL-YOMIFIRSTNAME property (this will soon become the sixth page on the internet to use that term).

Related Standards

vCard is closely related to a wider standard around directory formats, RFC 2425. This standard defines the basic, mainframe, field-value pair structure, as well as some basic types – SOURCE (source for the record, e.g. an LDAP server), NAME (name of the record, which will usually be the same a the vCard “N” field), PROFILE (vaguely defined as something about “how the record will be used”), BEGIN, END. BEGIN and END naturally appear in all vCards, but examples I’ve seen don’t use the other three types.

This W3C note attempts to XMLise vCard within an RDF framework.

hCard attempts to HTMLise vCard as part of the more-lightweight-than-RDF microformats initiative. (examples).

iCalendar, aka iCal and formally vCal (which sounds like vCard doesn’t it?) came from the Versit consortium around the same time as vCard…both intended for similar types of applications. iCal is about exchanging event information.

Gadget Spam. Podcast Spam. All in One Excitement-Packed Piece of Juicy Spam.

Gadgets AND Podcasts – these spammers really know how to target me…no wonder it slipped the GMail spam net.

My name is Christy and I am currently an intern at a small business intelligence company, BLEEP, working in their Software as a Service division, BLOOP.

My reason for emailing is that I’m curious of whether or not it would be possible to submit a gadget for a possible podcast. has already had one podcast by BLOOP, from BLAAP, and we would love to have another on your site. BLEEP is a free SaaS site that allows users to upload and customize data, then easily share their new visual almost anywhere on the web. Hope to hear from you soon.

Thanks so much,



p>I’ve often thought I should put together a spam gallery. This will be my first contribution.

A Contact Form

I recently got fed up of spam. Well, that happened a long time ago. What bothered me recently, enough to take action, was false positives, i.e. real email that fell into my spam folder. My primary email address, [email protected], gets about 3000 mails a day…so what goes in my spam folder, stays in my spam folder. There’s no way known I will ever fish it out.

People I know usually get through to me okay, but of course I also receive mails from people I don’t know – who found my mail from my blog, websites, writings, or offline meetings. For them, there’s a good chance of being marked as spam, especially if they use a subject line like “hello” which is a perfectly natural thing to do when you’re just checking in with someone you’ve met at a conference, for example, so you can keep each other’s contact details. (Incidentally, I still find it astonishing how many people maintain blogs – many of them meticulous, comprehensive, and full of goodness – but include zero contact info.)

So I finally bit the bullet and made a little PHP/Javascript contact form. It’s been working great for several months now. This kind of form is nothing new, of course. Mail forms were once ubiquitous in every book on CGI. But there were a few modern twists worth mentioning.

The form looks as follows:

The gnarly twists:

  • Captcha. Or, really, ReCaptcha. Actually, I prefer Captcha to ReCaptcha – I think the benefit of scanning books is great, but can’t justify the usability cost of having to enter two words instead of one (for no extra security benefit). Still, I wanted to try out ReCaptcha, and I also like the way its a popular, centralised, service, which means it should be better at detecting evil clients than a standalone library installation. The PHP plugin and instructions turned out to be incredibly easy to follow. A pleasant surprise that meant spam prevention took about 20 minutes to set up in total.
  • SMS option. Instead of email, you can send the message as SMS (text message to my phone). I need to improve the UI here a bit, ideally creating separate tabs for SMS and email. Anyway, the way this works is via everybody’s favourite micro-blogging service, Twitter. On the Twitter website, I set preferences so direct messages are routed to my phone as SMS messages. Ideally, I would then send a direct message to myself each time someone wants to SMS me. But unfortunately Twitter doesn’t let you send messages to yourself (silly!), so I created a secondary account (the venerable “mahemoff1”). Each time someone submits a SMS, I use the Twitter API to end a direct message from the secondary account to the primary account. This gets me a text message several seconds after the form is submitted. I also receive a copy in my Twitter account, as a bonus. (For all the talk about Twitter’s unreliability, its text messaging is lightning fast. It shows up on my phone long before it shows up on Air clients, which only poll once a minute or so. Ideally I’d upload a video if I had the time, to show how quick it is.)
  • A web chat facility. Everyone should have it, to avoid making people install AIM etc just to chat with you one time! I installed an open-source chat client so anyone can talk to me. In an ideal world, browsers would notify me when someone is trying to chat, but for now, it requires pre-arrangement. I would like to enhance the app so it uses the same SMS mechanism to tell me each time someone enters the chat room.

A URL Parameter Engine (and Rambling about PHP Globals)

I’ve recently been playing around with PHP again, because (a) it’s vastly simpler to deploy personal projects in PHP than any other platform (aside from pure client-side Ajax of course!) (b) it’s so easy to get simple stuff done.

Anyway, one thing I’m doing is creating a RESTful service where parameter crunching is at an all-time high. The ancient way this was done was with magically created globals. i.e. For the URL, you would end up with a global called $id, set to 10. But the more contemporary way to do it is to use a global array called $_GET, i.e. $_GET[$id]. This is considered safer, to ensure malicious users don’t set important globals. And in PHP 6.0, the former way is being obliterated altogether, since the relevant configuration option – register_globals is being altogether removed.

Well, to me, this is throwing out the baby with the bathwater.

This comes down to how you view PHP. For me, if I want to build a massive, complex, piece of software, I will use Rails or Java. So I consider PHP a scripting language and I value concise expression highly. Features like namespaces (to be added in PHP 6) and even OO don’t mean all that much to me in this language. I am much more concerned with syntactic sugar.

Thus, I would prefer to see templates look like this:

  1. Your name: <?= $name ?>

… and not:

  1. Your name: <?= $_GET&#91;"name"] ?>

A little thing, but in the context of a large corpus of templates, each with many variables, it makes a big difference.

So I’m working on a little parameter-processing engine which will let me use the “evil” $globalVar notation, but in a way that requires each script to pass in a whitelist of acceptable variable names. It also has some other value-adds, such as passing in default values. And these default values can be other parameters that were passed in.

(Incidentally, even if I wasn’t building this script, the first thing I would do would be to globally alias $G or to the uglier and more verbose $_GET.)

REST turns the URL into a command line, and this should push web framework developers towards smarter ways of processing parameters. Think Getopts, but for the URL instead of the shell command line. And that’s where I’m heading.

Javascript, Rebranded

I’m listening to Steve Yegge’s talk on branding from last years OSCON.

He talks about how languages are branded, e.g. “Java” is enterprise. One of his main points is that brands are “const identifiers”, i.e. it takes an entire generation to change brand perception, so it’s often more effective to simply re-brand. e.g. GTE had a poor brand, so they tried a self-deprecating ad campaign, which backfired, and subsequently re-branded to Verizon.

He then mentions Javascript has a branding problem, because it represents “browser” and “toy language” and “damnit, I gotta learn Javascript” and it’s the language no-one wants to use. He also notes the name itself isn’t great either, nor the rhino imagery. (I’m not sure why Steve assumed many programmers would associate Javascript with rhinos; the Rhino product and O’Reilly cover weren’t really promiment enough to do that; rhino ain’t camel!). I don’t agree with this premise. Javascript has actually become at least somewhat cool in certain communities, pretty quickly. Not the obvious ones like Rails and general web 2.0 fanboys/girls, but also PHP and Perl folks who would have previously been uninterested in it.

Anyway, he leaves the issue open and implies Javascript needs to be re-branded. But isn’t the point here that Javascript, for most and intents and purposes, already has been re-branded, like sometime around February, 18, 2005? It now shares its name with that of a domestic cleaning product, Dutch football team, and Greek God. For most people, Javascript became cool and worthy the day Ajax was coined; and Ajax encapsulates most of what is meant by Javascript. Of course, the two aren’t strictly synonymous, but when you set out to learn Ajax, you’re predominately learning Javascript. Go read a day or two of Ajaxian news and the vast majority will involve Javascript at some level.

Javascript has already been rebranded. In fact, I’d go so far as to say “Ajax” was one of the most successful rebrandings in software history.

Paleosocial Patterns

Wolf Logan’s talking about paleosocial patterns (TOOLS Web 2.0 Patterns workshop). Very cool.

Marking – making permanent, public, marks. Dog marking its territory, “I was here” graffiti. e.g. blog comments, forums, guestbooks. Being obnoxious gets the comment noticed more.

Pointing – indicating resources to others, can be with opinions. Reputation will dictate how much people care. e.g. Reviewing/rating sites, Digg.

Competing – comparing self to others, ranking is dynamic Some people approach competition for their own value; others for their social value. Special case of marking – marking yourself – but with an element of objective measurement e.g. online gaming sites, xbox live, popularity contests.

Storytelling – describing sequence of events, often about yourself Different stories for different social groups e.g. blogs, journals, youtube

Grooming – small, ritualised, social interactions – can happen quickly and without much planning, Culturally bounded. Repeated frequently depending on relationshps. “Purring” – e.g. “how are you?” – don’t care, but it’s the purring that happens that makes it a grooming behaviour. The info transfer doesn’t matter, just that the event happened. e.g. friending, twitter, majority of IM content

Hunting – tracking, locating, acquiring resources. Serendipity plays a big part. Successful hunting leads to pointing – tell people what you found. e.g. web search, link following.

Wolf points out hunting and grooming are always the two critical patterns that are noted.

A Video Sharing Website based on Web 2.0 Patterns

We’ve done a little group exercise at the TOOLS web 2.0 patterns workshop. Designing a video website, with heavy emphasis on mashing up, e.g. show videos from youtube, grab recommendations from netflix, grab friend lists from Facebook, etc.

Here’s the full feature list (click for full image):

And the design:

We eventually identified features, at back end and front end, and listed similar sites where on might get inspiration for each feature. Interestingly, when you do this with web 2.0 sites, you end up realising you could actually implement the feature by actually using this service.

Dragos has transcribed the list we came up with (partly visible in the photo above):

Day 1: Design Exercise

Problems + Solutions (1) [MM - these were back-end features]
-Key-value store: Amazon Dynamo/S3, BigTable (Google)
-Streaming: Hulu, YouTube streaming (not Flash)
-Client time synchro service: NTP, MMORPG
-Social network integration services: Oauth, OpenID/Passport
-Mash-up engine: PopFly, Yahoo! pipes
-Monetization (social cash -> $, analytics, instrumentation): AdSense,, SiteMeter, Elance

Problems + Solutions (2) [MM - these were front-end features]
-Video: Vimeo,,
-Mood: Musicovery, Yahoo! IM,
-Friend states: Twitter
IM: Facebook/MySpace, Twitter, Shoutbox
-Recommendations: Tuneglue, Netflix, Facebook

Some Emerging Themes
-Taxonomy of social networks
-Social profile aggregation: InfoCard
-Integration of services transparent from user
(Tim O'Reilly’s innovation by assembly)
-Privacy (who sees what)
-Biggest pile wins
-Cooler than thou