 							workCountry = adrXML.CTRY;
 							workCity = adrXML.LOCALITY;
 						}
-						else if(adrXML.HOME == '')
+						else if ( adrXML.HOME == '' )
 						{
 							homePostalCode = adrXML.PCODE;
 							homeStateProvince = adrXML.REGION;

						}
						break;
					case "TEL":
						var telXML:XML = new XML(child.toString());
						if(telXML.WORK == '')
						{
							if(telXML.VOICE == '')
								workVoiceNumber = telXML.NUMBER;
							else if(telXML.FAX == '')
								workFaxNumber = telXML.NUMBER;
							else if(telXML.PAGER == '')
								workPagerNumber = telXML.NUMBER;
							else if(telXML.CELL == '')
								workCellNumber = telXML.NUMBER;
						}
						else if(telXML.HOME == '')
						{
							if(telXML.VOICE == '')
								homeVoiceNumber = telXML.NUMBER;
							else if(telXML.FAX == '')
								homeFaxNumber = telXML.NUMBER;
							else if(telXML.PAGER == '')
								homePagerNumber = telXML.NUMBER;
							else if(telXML.CELL == '')
								homeCellNumber = telXML.NUMBER;
						}
						break;
                }
	     	}	     
	     	
	     	loaded = true;
	     	dispatchEvent(new VCardEvent(VCardEvent.LOADED, this, true, false));
		}
		
		public function get avatar():ByteArray
		{
			return _imageBytes;
		}
	}
}
	import org.igniterealtime.xiff.data.im.RosterItemVO;
	import org.igniterealtime.xiff.data.vcard.VCardExtension;
	import org.igniterealtime.xiff.events.VCardEvent;

	[Bindable]
	/**
	 *
	 */
	public class VCard extends EventDispatcher
	{
		/**
		 *
		 * @default
		 */
		private static var cache:Object = {};

		/**
		 * Flush the vcard cache every 6 hours
		 * @default
		 */
		private static var cacheFlushTimer:Timer = new Timer( 6 * 60 * 60 * 1000,
															  0 );

		/**
		 *
		 * @default
		 */
		private static var requestQueue:Array = [];

		/**
		 *
		 * @default
		 */
		private static var requestTimer:Timer;

		/**
		 *
		 * @default
		 */
		public var company:String;

		/**
		 *
		 * @default
		 */
		public var department:String;

		/**
		 *
		 * @default
		 */
		public var email:String;

		/**
		 *
		 * @default
		 */
		public var firstName:String;

		/**
		 *
		 * @default
		 */
		public var fullName:String;

		/**
		 *
		 * @default
		 */
		public var homeAddress:String;

		/**
		 *
		 * @default
		 */
		public var homeCellNumber:String;

		/**
		 *
		 * @default
		 */
		public var homeCity:String;

		/**
		 *
		 * @default
		 */
		public var homeCountry:String;

		/**
		 *
		 * @default
		 */
		public var homeFaxNumber:String;

		/**
		 *
		 * @default
		 */
		public var homePagerNumber:String;

		/**
		 *
		 * @default
		 */
		public var homePostalCode:String;

		/**
		 *
		 * @default
		 */
		public var homeStateProvince:String;

		/**
		 *
		 * @default
		 */
		public var homeVoiceNumber:String;

		/**
		 *
		 * @default
		 */
		public var jid:UnescapedJID;

		/**
		 *
		 * @default
		 */
		public var lastName:String;

		/**
		 *
		 * @default
		 */
		public var loaded:Boolean = false;

		/**
		 *
		 * @default
		 */
		public var middleName:String;

		/**
		 *
		 * @default
		 */
		public var nickname:String;

		/**
		 *
		 * @default
		 */
		public var title:String;

		/**
		 *
		 * @default
		 */
		public var url:String;

		/**
		 *
		 * @default
		 */
		public var workAddress:String;

		/**
		 *
		 * @default
		 */
		public var workCellNumber:String;

		/**
		 *
		 * @default
		 */
		public var workCity:String;

		/**
		 *
		 * @default
		 */
		public var workCountry:String;

		/**
		 *
		 * @default
		 */
		public var workFaxNumber:String;

		/**
		 *
		 * @default
		 */
		public var workPagerNumber:String;

		/**
		 *
		 * @default
		 */
		public var workPostalCode:String;

		/**
		 *
		 * @default
		 */
		public var workStateProvince:String;

		/**
		 *
		 * @default
		 */
		public var workVoiceNumber:String;

		/**
		 *
		 * @default
		 */
		private var _avatar:DisplayObject;

		/**
		 *
		 * @default
		 */
		private var _imageBytes:ByteArray;

		/**
		 *
		 * @default
		 */
		private var _loader:Loader;

		/**
		 *
		 * @default
		 */
		private var contact:RosterItemVO;

		/**
		 *
		 * @param con
		 * @param user
		 * @return
		 */
		public static function getVCard( con:XMPPConnection, user:RosterItemVO ):VCard
		{
			if ( !cacheFlushTimer.running )
			{
				cacheFlushTimer.start();
				cacheFlushTimer.addEventListener( TimerEvent.TIMER, function( event:TimerEvent ):void
					{
						var tempCache:Object = cache;
						cache = {};
						for each ( var cachedCard:VCard in tempCache )
						{
							pushRequest( con, vcard );
						}
					});
			}

			var jidString:String = user.jid.toString();

			var cachedCard:VCard = cache[ jidString ];
			if ( cachedCard )
				return cachedCard;

			var vcard:VCard = new VCard();
			vcard.contact = user;
			cache[ jidString ] = vcard;

			pushRequest( con, vcard );

			return vcard;
		}

		/**
		 *
		 * @param con
		 * @param vcard
		 */
		private static function pushRequest( con:XMPPConnection, vcard:VCard ):void
		{
			if ( !requestTimer )
			{
				requestTimer = new Timer( 1, 1 );
				requestTimer.addEventListener( TimerEvent.TIMER_COMPLETE, sendRequest );
			}
			requestQueue.push({ connection: con, card: vcard });
			requestTimer.reset();
			requestTimer.start();
		}

		/**
		 *
		 * @param event
		 */
		private static function sendRequest( event:TimerEvent ):void
		{
			if ( requestQueue.length == 0 )
				return;
			var req:Object = requestQueue.pop();
			var con:XMPPConnection = req.connection;
			var vcard:VCard = req.card;
			var user:RosterItemVO = vcard.contact;

			var iq:IQ = new IQ( user.jid.escaped, IQ.GET_TYPE );
			vcard.jid = user.jid;

			iq.callbackName = "handleVCard";
			iq.callbackScope = vcard;
			iq.addExtension( new VCardExtension());

			con.send( iq );
			requestTimer.reset();
			requestTimer.start();
		}

		/**
		 *
		 * @param resultIQ
		 */
		public function _vCardSent( resultIQ:IQ ):void
		{
			if ( resultIQ.type == IQ.ERROR_TYPE )
			{
				dispatchEvent( new VCardEvent( VCardEvent.ERROR, cache[ resultIQ.to.unescaped.toString()],
											   true, true ));
			}
			else
			{
				delete cache[ resultIQ.to.unescaped.toString()]; // Force profile refresh on next view
			}
		}

		/**
		 *
		 * @return
		 */
		public function get avatar():ByteArray
		{
			return _imageBytes;
		}

		/**
		 *
		 * @param iq
		 */
		public function handleVCard( iq:IQ ):void
		{
			var node:XMLNode = iq.getNode();
			var vCardNode:XMLNode = node.childNodes[ 0 ];
			if ( !vCardNode )
				return;

			for each ( var child:XMLNode in vCardNode.childNodes )
			{
				switch ( child.nodeName )
				{
					case "PHOTO":
						for each ( var sChild:XMLNode in child.childNodes )
						{
							if ( sChild.nodeName != 'BINVAL' )
								continue;
							try
							{
								//sometimes we get a packet with just <BINVAL/> ... no idea why
								if ( sChild.childNodes.length == 0 )
									continue;
								var value:String = sChild.childNodes[ 0 ].nodeValue;
								if ( value.length > 0 )
								{
									_loader = new Loader();
									var decoder:Base64Decoder = new Base64Decoder();
									decoder.decode( value );
									_imageBytes = decoder.flush();
									dispatchEvent( new VCardEvent( VCardEvent.AVATAR_LOADED,
																   this, true, false ));
								}
							}
							catch ( e:Error )
							{
								trace( "Error loading vcard image: " + e.message );
							}
						}
						break;

					case "N":
						// Get Family Name.
						var xml:XML = new XML( child.toString());
						firstName = xml.GIVEN;
						middleName = xml.MIDDLE;
						lastName = xml.FAMILY;
						break;

					case "FN":
						var fullnameNode:XMLNode = child.childNodes[ 0 ];
						if ( fullnameNode )
							fullName = fullnameNode.nodeValue;
						break;

					case "NICKNAME":
						var nicknameNode:XMLNode = child.childNodes[ 0 ];
						if ( nicknameNode )
							nickname = nicknameNode.nodeValue;
						break;

					case "EMAIL":
						for each ( var emailChild:XMLNode in child.childNodes )
						{
							if ( emailChild.nodeName == 'USERID' )
							{
								if ( emailChild.firstChild != null )
									email = emailChild.firstChild.nodeValue;
							}
						}
						break;
					case "ORG":
						var orgXML:XML = new XML( child.toString());
						company = orgXML.ORGNAME;
						department = orgXML.ORGUNIT;
						break;
					case "TITLE":
						var titleNode:XMLNode = child.childNodes[ 0 ];
						if ( titleNode )
							title = titleNode.nodeValue;
						break;
					case "URL":
						var urlNode:XMLNode = child.childNodes[ 0 ];
						if ( urlNode )
							url = urlNode.nodeValue;
						break;
					case "ADR":
						var adrXML:XML = new XML( child.toString());
						if ( adrXML.WORK == '' )
						{
							workPostalCode = adrXML.PCODE;
							workStateProvince = adrXML.REGION;
