package org.jivesoftware.xiff.core
{
import flash.events.DataEvent;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.events.TimerEvent;
import flash.net.XMLSocket;
import flash.utils.Timer;
import flash.xml.XMLDocument;
import flash.xml.XMLNode;
import org.jivesoftware.xiff.data.IExtension;
import org.jivesoftware.xiff.data.IQ;
import org.jivesoftware.xiff.data.Message;
import org.jivesoftware.xiff.data.Presence;
import org.jivesoftware.xiff.data.XMPPStanza;
import org.jivesoftware.xiff.data.auth.AuthExtension;
import org.jivesoftware.xiff.data.forms.FormExtension;
import org.jivesoftware.xiff.data.register.RegisterExtension;
import org.jivesoftware.xiff.events.*;
import org.jivesoftware.xiff.exception.SerializationException;
/**
* 当密码修改成功的时候被触发
*
* @eventType org.jivesoftware.xiff.events.ChangePasswordSuccessEvent.PASSWORD_SUCCESS
*/
[Event(name="changePasswordSuccess", type="org.jivesoftware.xiff.events.ChangePasswordSuccessEvent")]
/**
* 当成功的链接到服务器上的时候触发
*
* @eventType org.jivesoftware.xiff.events.ConnectionSuccessEvent.CONNECT_SUCCESS
*/
[Event(name="connection", type="org.jivesoftware.xiff.events.ConnectionSuccessEvent")]
/**
* 当与服务器断开的时候将会被触发
*
* @eventType org.jivesoftware.xiff.events.DisconnectionEvent.DISCONNECT
*/
[Event(name="disconnection", type="org.jivesoftware.xiff.events.DisconnectionEvent")]
/**
* Dispatched when there is some type of XMPP error.
* 当有xmpp 错误的时候将会被触发
* @eventType org.jivesoftware.xiff.events.XIFFErrorEvent.XIFF_ERROR
*/
[Event(name="error", type="org.jivesoftware.xiff.events.XIFFErrorEvent")]
/**
* Dispatched whenever there is incoming XML data.
* 当有传入的数据的时候将会被触发
* @eventType org.jivesoftware.xiff.events.IncomingDataEvent.INCOMING_DATA
*/
[Event(name="incomingData", type="org.jivesoftware.xiff.events.IncomingDataEvent")]
/**
* Dispatched on successful authentication (login) with the server.
* 当有用户登陆成功的时候将会被触发
* @eventType org.jivesoftware.xiff.events.LoginEvent.LOGIN
*/
[Event(name="login", type="org.jivesoftware.xiff.events.LoginEvent")]
/**
* Dispatched on incoming messages.
* 当有进入的消息的时候将会被触发
* @eventType org.jivesoftware.xiff.events.MessageEvent.MESSAGE
*/
[Event(name="message", type="org.jivesoftware.xiff.events.MessageEvent")]
/**
* Dispatched whenever data is sent to the server.
* 当有数据被传往服务器端的时候触发
* @eventType org.jivesoftware.xiff.events.OutgoingDataEvent.OUTGOING_DATA
*/
[Event(name="outgoingData", type="org.jivesoftware.xiff.events.OutgoingDataEvent")]
/**
* Dispatched on incoming presence data.
* 当进入是否在线相关数据的时候触发
* @eventType org.jivesoftware.xiff.events.PresenceEvent.PRESENCE
*/
[Event(name="presence", type="org.jivesoftware.xiff.events.PresenceEvent")]
/**
* Dispatched on when new user account registration is successful.
* 当用户注册成功的时候触发
* @eventType org.jivesoftware.xiff.events.RegistrationSuccessEvent.REGISTRATION_SUCCESS
*/
[Event(name="registrationSuccess", type="org.jivesoftware.xiff.events.RegistrationSuccessEvent")]
/**
* This class is used to connect to and manage data coming from an XMPP server. Use one instance
* of this class per connection.
* XMPPConnection这个类被用做连接和管理从服务器端发来的数据,每一个连接一个实例
*/
public class XMPPConnection extends EventDispatcher
{
/**
* @private
* 是否匿名登陆
*/
protected var _useAnonymousLogin:Boolean;
/**
* @private
*xmlsocket
*/
protected var _socket:XMLSocket;
/**
* @private
* 服务器地址或者名称
*/
protected var myServer:String;
/**
* @private
* 用户名
*/
protected var myUsername:String;
/**
* @private
* 绑定的资源名称 比如smark linkq msn 等
* */
protected var myResource:String;
/**
* @private
* 用户密码
*/
protected var myPassword:String;
/**
* @private
* 登陆端口
*/
protected var myPort:Number;
/**
* 是否已经激活
* @private
*/
protected var _active:Boolean;
/**
* 是否已经登陆
* @private
*/
protected var loggedIn:Boolean;
/**
* 是否忽略空白字符
* @private
*/
protected var ignoreWhitespace:Boolean;
/**
* @private
* 打开流的标签
*/
protected var openingStreamTag:String;
/**
* @private
* 关闭流的标签
*/
protected var closingStreamTag:String;
/**
* @private
* 会话id
*/
protected var sessionID:String;
/**
* @private
*/
protected var pendingIQs:Object;
/**
* @private
*/
protected var _expireTagSearch:Boolean;
protected static var _openConnections:Array = [];
public function XMPPConnection()
{
// Hash to hold callbacks for IQs
pendingIQs = new Object();
_useAnonymousLogin = false;
active = false;
loggedIn = false;
ignoreWhitespace = true;
//初始化为忽略空白字符
resource = "xiff";
//初始化资源为xiff
port = 5222;
AuthExtension.enable();
RegisterExtension.enable();
FormExtension.enable();
}
/**
* Connects to the server.
* 链接到服务器端
* @param streamType (Optional) The type of initial stream negotiation, either <flash:stream> or <stream:stream>.
* Some servers, like Jabber, Inc.'s XCP and Jabberd 1.4 expect <flash:stream> from a Flash client instead of the standard <stream:stream>.
* The options for this parameter are: "flash", "terminatedFlash", "standard" and "terminatedStandard". The default is "terminatedStandard".
*返回是否找到服务器
* @return A boolean indicating whether the server was found.
*/
public function connect( streamType:String = "terminatedStandard" ):Boolean
{
// Create the socket 创建一个socket连接字
_socket = _createXmlSocket();
active = false;
loggedIn = false;
/// 创建流样式 <stream:flash>
// Stream type lets user set opening/closing tag - some servers (jadc2s) prefer <stream:flash> to the standard
// <stream:stream>
switch( streamType ) {
/////在xiff中用flash
case "flash":
openingStreamTag = new String( "<?xml version=\"1.0\"?><flash:stream to=\"" + server + "\" xmlns=\"jabber:client\" xmlns:flash=\"http://www.jabber.com/streams/flash\" version=\"1.0\">" );
closingStreamTag = new String( "</flash:stream>" );
break;
case "terminatedFlash":
openingStreamTag = new String( "<?xml version=\"1.0\"?><flash:stream to=\"" + server + "\" xmlns=\"jabber:client\" xmlns:flash=\"http://www.jabber.com/streams/flash\" version=\"1.0\" />" );
closingStreamTag = new String( "</flash:stream>" );
break;
case "standard":
openingStreamTag = new String( "<?xml version=\"1.0\"?><stream:stream to=\"" + server + "\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">" );
closingStreamTag = new String( "</stream:stream>" );
break;
case "terminatedStandard":
default:
openingStreamTag = new String( "<?xml version=\"1.0\"?><stream:stream to=\"" + server + "\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\" />" );
closingStreamTag = new String( "</stream:stream>" );
break;
}
//链接到服务器如果成功返回true
_socket.connect( server, port );
return true;
}
/**
* 关闭与服务器的连接
* Disconnects from the server if currently connected. After disconnect,
* a <code>DisconnectionEvent.DISCONNECT</code> event is broadcast.
*/
public function disconnect():void
{
//如果链接是活动的,发送一个关闭流 设置活动状态为false
if( isActive() ) {
sendXML( closingStreamTag );
_socket.close();
active = false;
loggedIn = false;
var event:DisconnectionEvent = new DisconnectionEvent();
dispatchEvent(event);
//将关闭连接这个事件分发( 广播)
}
}
/**
* Sends data to the server. If the data to send cannot be serialized properly, this method throws a <code>SerializeException</code>.
*发送数据给服务器,如果数据不能被序列号则不能被发送
* @param o The data to send. This must be an instance of a class that implements the ISerializable interface.
* 参数必须是已经实现了ISerriable接口的实例
* * @see org.jivesoftware.xiff.data.ISerializable
* @example The following example sends a basic chat message to the user with the JID "sideshowbob@springfieldpenitentiary.gov".<br />
* <pre>var msg:Message = new Message( "sideshowbob@springfieldpenitentiary.gov", null, "Hi Bob.", "<b>Hi Bob.</b>", Message.CHAT_TYPE );
* myXMPPConnection.send( msg );</pre>
*/
public function send( o:XMPPStanza ):void
{
if( isActive() ) {
///主要是处理 IQ(info 、query)
if( o is IQ ) {
var iq:IQ = o as IQ;
if ((iq.callbackName != null && iq.callbackScope != null) || iq.callback != null)
{
addIQCallbackToPending( iq.id, iq.callbackName, iq.callbackScope, iq.callback );
}
}
var root:XMLNode = o.getNode().parentNode;
if (root == null) {
root = new XMLDocument();
}
if (o.serialize(root)) {
sendXML( root.firstChild );
} else {
throw new SerializationException();
}
}
}
///发送一个空包,保持这个联结
public function sendKeepAlive():void
{
if( isActive() ) {
sendXML(" ");
}
}
/**
* Determines whether the connection with the server is currently active. (Not necessarily logged in.
* For login status, use the <code>isLoggedIn()</code> method.)
* 检测这个连接是否是活动的
* @return A boolean indicating whether the connection is active.
* @see org.jivesoftware.xiff.core.XMPPConnection#isLoggedIn
*/
public function isActive():Boolean
{
return active;
}
/**
* Determines whether the user is connected and logged into the server.
* 判断用户是否已经登陆
* @return A boolean indicating whether the user is logged in.
* @see org.jivesoftware.xiff.core.XMPPConnection#isActive
*/
public function isLoggedIn():Boolean
{
return loggedIn;
}
/**
* Issues a request for the information that must be submitted for registration with the server.
* 发布一个请求去获取必须提交的信息以用来向服务器注册,注册用户时用到
* When the data returns, a <code>RegistrationFieldsEvent.REG_FIELDS</code> event is dispatched
* containing the requested data.
*/
public function getRegistrationFields():void
{
var regIQ:IQ = new IQ( new JID(server), IQ.GET_TYPE, XMPPStanza.generateID("reg_info_"), "getRegistrationFields_result", this, null);
regIQ.addExtension(new RegisterExtension(regIQ.getNode()));
send( regIQ );
}
/**
* Registers a new account with the server, sending the registration data as specified in the fieldMap paramter.
* 向服务注册一个新的帐号,发送注册所需的数据
* @param fieldMap An object map containing the data to use for registration. The map should be composed of
* attribute:value pairs for each registration data item.
* @param key (Optional) If a key was passed in the "data" field of the "registrationFields" event,
* that key must also be passed here.
* required field needed for registration.
*/
public function sendRegistrationFields( fieldMap:Object, key:String ):void
{
var regIQ:IQ = new IQ( new JID(server), IQ.SET_TYPE, XMPPStanza.generateID("reg_attempt_"), "sendRegistrationFields_result", this, null );
var ext:RegisterExtension = new RegisterExtension(regIQ.getNode());
for( var i:String in fieldMap ) {
ext[i] = fieldMap[i];
}
if (key != null) {
ext.key = key;
}
regIQ.addExtension(ext);
send( regIQ );
}
/**
* Changes the user's account password on the server. If the password change is successful,
* the class will broadcast a <code>ChangePasswordSuccessEvent.PASSWORD_SUCCESS</code> event.
*变更用户帐号密码, 如果成功将会触发事件:ChangePasswordSuccessEvent.PASSWORD_SUCCESS
* @param newPassword The new password
*/
public function changePassword( newPassword:String ):void
{
var passwdIQ:IQ = new IQ( new JID(server), IQ.SET_TYPE, XMPPStanza.generateID("pswd_change_"), "changePassword_result", this, null );
var ext:RegisterExtension = new RegisterExtension(passwdIQ.getNode());
ext.username = jid.toBareJID();
ext.password = newPassword;
passwdIQ.addExtension(ext);
send( passwdIQ );
}
/**
* Gets the fully qualified JID (user@server/resource) of the user. A fully-qualified JID includes
* the resource. A bare JID does not. To get the bare JID, use the <code>getBareJID()</code> method.
* 返回一个完整的jid user@server/resource
* @return The fully qualified JID
* @see #getBareJID
*/
public function get jid():JID
{
return new JID(myUsername + "@" + myServer + "/" + myResource);
}
/**
* @private 修改密码的返回情况
*/
protected function changePassword_result( resultIQ:IQ ):void
{
if( resultIQ.type == IQ.RESULT_TYPE ) {
var event:ChangePasswordSuccessEvent = new ChangePasswordSuccessEvent();
dispatchEvent(event);
}
else {
// We weren't expecting this
////400 修改密码错误
dispatchError( "unexpected-request", "Unexpected Request", "wait", 400 );
}
}
/**
* @private 注册用户的返回情况
*/
protected function getRegistrationFields_result( resultIQ:IQ ):void
{
try
{
var ext:RegisterExtension = resultIQ.getAllExtensionsByNS(RegisterExtension.NS)[0];
var fields:Array = ext.getRequiredFieldNames(); //TODO, phase this out
var event:RegistrationFieldsEvent = new RegistrationFieldsEvent();
event.fields = fields;
event.data = ext;
}
catch (e:Error)
{
trace(e.getStackTrace());
}
}
/**
* @private
*/
protected function sendRegistrationFields_result( resultIQ:IQ ):void
{
if( resultIQ.type == IQ.RESULT_TYPE ) {
var event:RegistrationSuccessEvent = new RegistrationSuccessEvent();
dispatchEvent( event );
}
else {
// We weren't expecting this
dispatchError( "unexpected-request", "Unexpected Request", "wait", 400 );
}
}
// Listener function from the ListenerXMLSocket
/**
* @private
*/
protected function socketConnected(ev:Event):void
{
active = true;
sendXML( openingStreamTag );
var event:ConnectionSuccessEvent = new ConnectionSuccessEvent();
dispatchEvent( event );
}
/**
* @private
*/
protected function socketReceivedData( ev:DataEvent ):void
{
// parseXML is more strict in AS3 so we must check for the presence of flash:stream
// the unterminated tag should be in the first string of xml data retured from the server
if (!_expireTagSearch)
{
var pattern:RegExp = new RegExp("<flash:stream");
var resultObj:Object = pattern.exec(ev.data);
if (resultObj != null) // stop searching for unterminated node
{
ev.data = ev.data.concat("</flash:stream>");
_expireTagSearch = true;
}
}
if(ev.data == "</flash:stream>")
{
socketClosed(null);
return;
}
var xmlData:XMLDocument = new XMLDocument();
xmlData.ignoreWhite = this.ignoreWhite;
xmlData.parseXML( ev.data );
var event:IncomingDataEvent = new IncomingDataEvent();
event.data = xmlData;
dispatchEvent( event );
// Read the data and send it to the appropriate parser
var firstNode:XMLNode = xmlData.firstChild;
var nodeName:String = firstNode.nodeName.toLowerCase();
//trace("RECV: " + firstNode);
switch( nodeName )
{
case "stream:stream":
case "flash:stream":
_expireTagSearch = false;
handleStream( firstNode );
break;
case "stream:error":
handleStreamError( firstNode );
break;
case "iq":
handleIQ( firstNode );
break;
case "message":
handleMessage( firstNode );
break;
case "presence":
handlePresence( firstNode );
break;
case "stream:features":
break;
default:
// silently ignore lack of or unknown stanzas
// if the app designer wishes to handle raw data they
// can on "incomingData".
// Use case: received null byte, XMLSocket parses empty document
// sends empty document
// I am enabling this for debugging
dispatchError( "undefined-condition", "Unknown Error", "modify", 500 );
break;
}
}
/**
* @private
*/
protected function socketClosed(e:Event):void
{
var event:DisconnectionEvent = new DisconnectionEvent();
dispatchEvent( event );
}
/**
* @private
*/
protected function handleStream( node:XMLNode ):void
{
sessionID = node.attributes.id;
server = node.attributes.from;
if(_useAnonymousLogin) {
// Begin anonymous login
sendAnonymousLogin();
} else if( username != null && username.length > 0 ) {
// Begin login sequence
beginAuthentication();
} else {
//get registration fields
getRegistrationFields();
}
}
/**
* @private
*/
protected function handleStreamError( node:XMLNode ):void
{
dispatchError( "service-unavailable", "Remote Server Error", "cancel", 502 );
// Cancel everything by closing connection
try {
_socket.close();
}
catch (error:Error){
}
active = false;
loggedIn = false;
var event:DisconnectionEvent = new DisconnectionEvent();
dispatchEvent( event );
}
protected function set active(flag:Boolean):void
{
if(flag)
{
_openConnections.push(this);
}
else
{
_openConnections.splice(_openConnections.indexOf(this), 1);
}
_active = flag;
}
protected function get active():Boolean
{
return _active;
}
public static function get openConnections():Array
{
return _openConnections;
}
/**
* @private
*/
protected function handleIQ( node:XMLNode ):IQ
{
var iq:IQ = new IQ();
// Populate the IQ with the incoming data
if( !iq.deserialize( node ) ) {
throw new SerializationException();
}
// If it's an error, handle it
if( iq.type == IQ.ERROR_TYPE && !pendingIQs[iq.id]) {
dispatchError( iq.errorCondition, iq.errorMessage, iq.errorType, iq.errorCode );
}
else {
// Start the callback for this IQ if one exists
if( pendingIQs[iq.id] !== undefined ) {
var callbackInfo:* = pendingIQs[iq.id];
if(callbackInfo.methodScope && callbackInfo.methodName) {
callbackInfo.methodScope[callbackInfo.methodName].apply( callbackInfo.methodScope, [iq] );
}
if (callbackInfo.func != null) {
callbackInfo.func( iq );
}
pendingIQs[iq.id] = null;
delete pendingIQs[iq.id];
}
else {
var exts:Array = iq.getAllExtensions();
for (var ns:String in exts) {
// Static type casting
var ext:IExtension = exts[ns] as IExtension;
if (ext != null) {
var event:IQEvent = new IQEvent(ext.getNS());
event.data = ext;
event.iq = iq;
dispatchEvent( event );
}
}
}
}
return iq;
}
/**
* @private
*/
protected function handleMessage( node:XMLNode ):Message
{
var msg:Message = new Message();
//trace(msg);
// Populate with data
if( !msg.deserialize( node ) ) {
throw new SerializationException();
}
// ADDED in error handling for messages
if( msg.type == Message.ERROR_TYPE ) {
dispatchError( msg.errorCondition, msg.errorMessage, msg.errorType, msg.errorCode );
}
else
{
var event:MessageEvent = new MessageEvent();
event.data = msg;
dispatchEvent( event );
}
return msg;
}
/**
* @private
*/
private var presenceQueue:Array = [];
private var presenceQueueTimer:Timer;
protected function handlePresence( node:XMLNode ):Presence
{
if(!presenceQueueTimer)
{
presenceQueueTimer = new Timer(1, 1);
presenceQueueTimer.addEventListener(TimerEvent.TIMER_COMPLETE, flushPresenceQueue);
}
var pres:Presence = new Presence();
// Populate
if( !pres.deserialize( node ) ) {
throw new SerializationException();
}
presenceQueue.push(pres);
presenceQueueTimer.reset();
presenceQueueTimer.start();
return pres;
}
protected function flushPresenceQueue(evt:TimerEvent):void
{
var event:PresenceEvent = new PresenceEvent();
event.data = presenceQueue;
dispatchEvent( event );
presenceQueue = [];
}
/**
* @private
*/
protected function onIOError(event:IOErrorEvent):void{
/*
this fires the standard dispatchError method. need to add
the appropriate error code
*/
dispatchError( "service-unavailable", "Service Unavailable", "cancel", 503 );
}
/**
* @private
*/
protected function securityError(event:SecurityErrorEvent):void{
trace("there was a security error of type: " + event.type + "\nError: " + event.text);
dispatchError( "not-authorized", "Not Authorized", "auth", 401 );
}
/**
* @private
*/
protected function dispatchError( condition:String, message:String, type:String, code:Number ):void
{
var event:XIFFErrorEvent = new XIFFErrorEvent();
event.errorCondition = condition;
event.errorMessage = message;
event.errorType = type;
event.errorCode = code;
dispatchEvent( event );
}
/**
* @private
*/
protected function sendXML( someData:* ):void
{
//trace("SEND: " + someData);
// Data is untyped because it could be a string or XML
_socket.send( someData );
var event:OutgoingDataEvent = new OutgoingDataEvent();
event.data = someData;
dispatchEvent( event );
}
// anonymous login
/**
* @private
*/
protected function sendAnonymousLogin():void
{
var anonIQ:IQ = new IQ(null, IQ.SET_TYPE, XMPPStanza.generateID("log_anom_"), "sendAnonymousLogin_result", this, null );
var authExt:AuthExtension = new AuthExtension(anonIQ.getNode());
anonIQ.addExtension(authExt);
send(anonIQ);
}
/**
* @private
*/
protected function sendAnonymousLogin_result(resultIQ:IQ):void
{resultIQ
if( resultIQ.type == IQ.RESULT_TYPE ) {
// update resource
var jid:JID = resultIQ.to;
resource = jid.resource;
username = jid.node;
// dispatch login event
loggedIn = true;
var event:LoginEvent = new LoginEvent();
dispatchEvent( event );
}
}
/**
* @private
*/
protected function beginAuthentication():void
{
var authIQ:IQ = new IQ( null, IQ.GET_TYPE, XMPPStanza.generateID("log_user_"), "beginAuthentication_result", this, null );
var authExt:AuthExtension = new AuthExtension(authIQ.getNode());
authExt.username = username
authIQ.addExtension(authExt);
send( authIQ );
}
/**
* @private
*/
protected function beginAuthentication_result( resultIQ:IQ ):void
{
var connectionType:String = "none";
// Begin authentication procedure
if( resultIQ.type == IQ.RESULT_TYPE ) {
var authIQ:IQ = new IQ( null, IQ.SET_TYPE, XMPPStanza.generateID("log_user2_"), "sendAuthentication_result", this, null );
try
{
var resultAuth:* = resultIQ.getAllExtensionsByNS(AuthExtension.NS)[0];
var responseAuth:AuthExtension = new AuthExtension(authIQ.getNode());
responseAuth.password = password;
responseAuth.username = username;
responseAuth.resource = resource;
authIQ.addExtension(responseAuth);
send( authIQ );
}
catch (e:Error)
{
trace("Error : null trapped. Resuming.");
}
}
else {
// We weren't expecting this
dispatchError( "unexpected-request", "Unexpected Request", "wait", 400 );
}
}
/**
* @private
*/
protected function sendAuthentication_result( resultIQ:IQ ):void
{
if( resultIQ.type == IQ.RESULT_TYPE ) {
loggedIn = true;
var event:LoginEvent = new LoginEvent();
dispatchEvent( event );
}
else {
// We weren't expecting this
dispatchError( "unexpected-request", "Unexpected Request", "wait", 400 );
}
}
/**
* @private
*/
protected function addIQCallbackToPending( id:String, callbackName:String, callbackScope:Object, callbackFunc:Function ):void
{
pendingIQs[id] = {methodName:callbackName, methodScope:callbackScope, func:callbackFunc};
}
/**
* The XMPP server to use for connection.
*/
public function get server():String
{
return myServer;
}
/**
* @private
*/
public function set server( theServer:String ):void
{
myServer = theServer;
}
/**
* The username to use for connection. If this property is null when <code>connect()</code> is called,
* the class will fetch registration field data rather than attempt to login.
*/
public function get username():String
{
return myUsername;
}
/**
* @private
*/
public function set username( theUsername:String ):void
{
myUsername = theUsername;
}
/**
* The password to use when logging in.
*/
public function get password():String
{
return myPassword;
}
public function set password( thePassword:String ):void
{
myPassword = thePassword;
}
/**
* The resource to use when logging in. A resource is required (defaults to "XIFF") and
* allows a user to login using the same account simultaneously (most likely from multiple machines).
* Typical examples of the resource include "Home" or "Office" to indicate the user's current location.
*/
public function get resource():String
{
return myResource;
}
/**
* @private
*/
public function set resource( theResource:String ):void
{
if( theResource.length > 0 )
{
myResource = theResource;
}
}
/**
* Whether to use anonymous login or not.
*/
public function get useAnonymousLogin():Boolean
{
return _useAnonymousLogin;
}
/**
* @private
*/
public function set useAnonymousLogin(value:Boolean):void
{
// set only if not connected
if(!isActive()) _useAnonymousLogin = value;
}
/**
* The port to use when connecting. The default XMPP port is 5222.
*/
public function get port():Number
{
return myPort;
}
public function set port( portNum:Number ):void
{
myPort = portNum;
}
/**
* Determines whether whitespace will be ignored on incoming XML data.
* Behaves the same as <code>XML.ignoreWhite</code>
*/
public function get ignoreWhite():Boolean
{
return ignoreWhitespace;
}
public function set ignoreWhite( val:Boolean ):void
{
ignoreWhitespace = val;
}
private function _createXmlSocket():XMLSocket {
var socket:XMLSocket = new XMLSocket(server, port);
socket.addEventListener(Event.CONNECT,socketConnected);
socket.addEventListener(IOErrorEvent.IO_ERROR,onIOError);
socket.addEventListener(Event.CLOSE,socketClosed);
socket.addEventListener(DataEvent.DATA,socketReceivedData);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityError);
return socket;
}
}
}
大盘预测
国富论
posted on 2008-03-26 14:59
华梦行 阅读(3267)
评论(0) 编辑 收藏