 			ExtensionClassRegistry.register( RosterExtension );
 			return true;
 		}
-		
+
 		/**
 		 * Adds a contact to the roster. Remember: All roster data is managed on the server-side,
 		 * so this contact is added to the server-side roster first, and upon successful addition,

					//setPresence( Presence.SHOW_NORMAL, "Online", 5 );
					setPresence( null, "Online", 5 );
					break;
					
				case RosterExtension.NS:
					try
					{
						var ext:RosterExtension = (eventObj.iq as IQ).getAllExtensionsByNS( RosterExtension.NS )[0] as RosterExtension;
						var items:Array = ext.getAllItems();
						for each(var item:* in items)
						{
							var jid:UnescapedJID = new UnescapedJID(item.jid);
							var rosterItemVO:RosterItemVO = RosterItemVO.get(jid, true);
							var rosterEvent:RosterEvent;
							
							if (contains(rosterItemVO))
							{
								switch (item.subscription.toLowerCase())
								{
									case RosterExtension.SUBSCRIBE_TYPE_NONE:
										rosterEvent = new RosterEvent(RosterEvent.SUBSCRIPTION_REVOCATION);
										rosterEvent.jid = jid;
										dispatchEvent( rosterEvent );
										break;
									
									case RosterExtension.SUBSCRIBE_TYPE_REMOVE:
										rosterEvent = new RosterEvent(RosterEvent.USER_REMOVED);
										for each(var group:RosterGroup in getContainingGroups(rosterItemVO))
										{
											group.removeItem(rosterItemVO);
										}
										//should be impossible for getItemIndex to return -1, since we just looked it up
										rosterEvent.data = removeItemAt(getItemIndex(rosterItemVO));;
										rosterEvent.jid = jid;
										dispatchEvent( rosterEvent );
										break;
														
									default:
										updateRosterItemSubscription(rosterItemVO, item.subscription.toLowerCase(), item.name, item.groupNames);
										break;
								}
							}
							else
							{
								var groupNames:Array = item.groupNames;
								var askType:String = item.askType != null ?
									item.askType.toLowerCase() : RosterExtension.ASK_TYPE_NONE;

								if ( item.subscription.toLowerCase() != RosterExtension.SUBSCRIBE_TYPE_REMOVE &&
									item.subscription.toLowerCase() != RosterExtension.SUBSCRIBE_TYPE_NONE)
								{
									// Add this item to the roster if it's not there and if the subscription type is not equal to 'remove' or 'none'
									addRosterItem( jid, item.name, RosterExtension.SHOW_UNAVAILABLE, "Offline",
										groupNames, item.subscription.toLowerCase(), askType );
								}
								else if ( (item.subscription.toLowerCase() == RosterExtension.SUBSCRIBE_TYPE_NONE ||
									item.subscription.toLowerCase() == RosterExtension.SUBSCRIBE_TYPE_FROM) &&
										item.askType == RosterExtension.ASK_TYPE_SUBSCRIBE )
								{
									// A contact was added to the roster, and its authorization is still pending.
									addRosterItem( jid, item.name, RosterExtension.SHOW_PENDING, "Pending", groupNames,
										item.subscription.toLowerCase(), askType );
								}
							}
						}
					}
					catch (e:Error)
					{
						trace(e.getStackTrace());
					}
					break;
			}
		}
		
		/**
		 * Dispathing <code>RosterEvent</code> based on the types of the <code>Presence</code>.
		 * @param	presenceArray	A pile of presences received at one time
		 */
		private function handlePresences( presenceArray:Array):void
		{
			for each(var aPresence:Presence in presenceArray)
			{
				var type:String = aPresence.type ? aPresence.type.toLowerCase() : null;
				var rosterEvent:RosterEvent = null;
				
				switch( type )
				{
					case Presence.SUBSCRIBE_TYPE:
						rosterEvent = new RosterEvent(RosterEvent.SUBSCRIPTION_REQUEST);
						break;
						
					case Presence.UNSUBSCRIBED_TYPE:
						rosterEvent = new RosterEvent(RosterEvent.SUBSCRIPTION_DENIAL);
						break;
					
					case Presence.UNAVAILABLE_TYPE:
						rosterEvent = new RosterEvent(RosterEvent.USER_UNAVAILABLE);
	
						var unavailableItem:RosterItemVO = RosterItemVO.get(aPresence.from.unescaped, false);
						if(!unavailableItem) return;
						updateRosterItemPresence( unavailableItem, aPresence );
						
						break;
					
					// null means available
					default:
						rosterEvent = new RosterEvent(RosterEvent.USER_AVAILABLE);
						rosterEvent.data = aPresence;
						
						// Change the item on the roster
						var availableItem:RosterItemVO;
						if(aPresence.from)
							availableItem = RosterItemVO.get(aPresence.from.unescaped, false);
						
						if(!availableItem) return;
						updateRosterItemPresence( availableItem, aPresence );
						
						break;
				}
				
				if (rosterEvent != null)
				{
					// from can sometimes not be set
					if (aPresence.from)
					{
						rosterEvent.jid = aPresence.from.unescaped;
					}
					dispatchEvent(rosterEvent);
				}
			}
		}
		
		private function addRosterItem( jid:UnescapedJID, displayName:String, show:String, status:String, groupNames:Array, type:String, askType:String = "none" ):Boolean
		{
			if (!jid)
			{
				return false;
			}
			
			var rosterItem:RosterItemVO = RosterItemVO.get(jid, true);
			if (!contains( rosterItem ))
			{
				addItem( rosterItem );
			}
			if (displayName)
			{
				rosterItem.displayName = displayName;
			}
			rosterItem.subscribeType = type;
			rosterItem.askType = askType;
			rosterItem.status = status;
			rosterItem.show = show;
			setContactGroups(rosterItem, groupNames);
			
			var event:RosterEvent = new RosterEvent(RosterEvent.USER_ADDED);
			event.jid = jid;
			event.data = rosterItem;
			dispatchEvent(event);

			return true;
		}
		
		private function setContactGroups( contact:RosterItemVO, groupNames:Array ):void
		{
			if (!groupNames || groupNames.length == 0)
			{
				groupNames = ["General"];
			}
			for each(var name:String in groupNames)
			{
				//if there's no group by this name already, we need to make one
				if(!getGroup(name))
					_groups[name] = new RosterGroup(name);
			}
			for each(var group:RosterGroup in _groups)
			{
				if (groupNames.indexOf(group.label) >= 0)
				{
					group.addItem(contact);
				}
				else
				{
					group.removeItem(contact);
				}
			}
		}
		
		private function updateRosterItemSubscription( item:RosterItemVO, type:String, name:String, newGroupNames:Array ):void
		{
			item.subscribeType = type;
			
			setContactGroups(item, newGroupNames);

			if (name)
			{
				item.displayName = name;
			}
			
			var event:RosterEvent = new RosterEvent(RosterEvent.USER_SUBSCRIPTION_UPDATED);
			event.jid = item.jid;
			event.data = item;
			dispatchEvent(event);
		}
		
		private function updateRosterItemPresence( item:RosterItemVO, presence:Presence ):void
		{
			try

		{
			var tempPresence:Presence = new Presence( tojid.escaped, null, Presence.SUBSCRIBED_TYPE );
			_connection.send( tempPresence );

			// Request a return subscription
			if ( requestAfterGrant )
			{
				requestSubscription( tojid, true );
			}
		}

		/**
		 * Removes a contact from the roster and revokes all presence subscriptions for that contact.
		 * This method will only attempt action if the contact you are trying to remove is currently on the
		 * roster in the first place.
		 *
		 * @param	rosterItem The value object which is to be removed
		 */
		public function removeContact( rosterItem:RosterItemVO ):void
		{
			if ( contains( rosterItem ) )
			{
				var tempIQ:IQ = new IQ( null, IQ.SET_TYPE, XMPPStanza.generateID( "remove_user_" ),
										"unsubscribe_result", this );
				var ext:RosterExtension = new RosterExtension( tempIQ.getNode() );
				ext.addItem( new EscapedJID( rosterItem.jid.bareJID ), RosterExtension.SUBSCRIBE_TYPE_REMOVE );
				tempIQ.addExtension( ext );
				_connection.send( tempIQ );

				//the roster item is not actually removed from the roster
				//until confirmation comes back from the XMPP server
			}
		}

		/**
		 * Requests subscription authorization with a user or service. In the XMPP-world, you cannot receive
		 * notifications on changes to a contact's presence until that contact has authorized you to subscribe
		 * to his/her/its presence.
		 *
		 * @param	id The JID of the user or service that you wish to subscribe to
		 * @param	isResponse
		 * @see	#subscriptionDenial
		 */
		public function requestSubscription( id:UnescapedJID, isResponse:Boolean = false ):void
		{
			// Roster length is 0 if it a response to a user request. we must handle this event.
			var presence:Presence;
			if ( isResponse )
			{
				presence = new Presence( id.escaped, null, Presence.SUBSCRIBE_TYPE );
				_connection.send( presence );
				return;
			}
			// Only request for items in the roster
			if ( contains( RosterItemVO.get( id, false ) ) )
			{
				presence = new Presence( id.escaped, null, Presence.SUBSCRIBE_TYPE );
				_connection.send( presence );
			}
		}

		/**
		 * Sets your current presence status. Calling this method notifies others who
		 * are subscribed to your presence of a presence change. You should use this to
