diff --git a/jabber/JID.hx b/jabber/JID.hx
index ced6561..b0ae3e7 100644
--- a/jabber/JID.hx
+++ b/jabber/JID.hx
@@ -17,8 +17,6 @@
*/
package jabber;
-import jabber.JIDUtil;
-
/**
An XMPP address (JID).<br/>
A JID is made up of a node (generally a username), a domain, and a resource.<br/>
@@ -36,29 +34,33 @@ class JID {
public static inline var MAX_PART_SIZE = 1023;
- public var node(default,null) : String;
- public var domain(default,null) : String;
+ //public var node(default,null) : String;
+ public var node : String;
+ //public var domain(default,null) : String;
+ public var domain : String;
public var resource : String;
/** JID without resource */
public var bare(getBare,null) : String;
public function new( str : String ) {
-
- if( !JIDUtil.isValid( str ) )
- throw "Invalid JID: "+str;
-
- this.node = JIDUtil.parseNode( str );
- this.domain = JIDUtil.parseDomain( str );
- this.resource = JIDUtil.parseResource( str );
+ if( str != null ) {
+ if( !JIDUtil.isValid( str ) )
+ throw "Invalid JID: "+str;
+
+ this.node = JIDUtil.parseNode( str );
+ this.domain = JIDUtil.parseDomain( str );
+ this.resource = JIDUtil.parseResource( str );
+ }
}
function getBare() : String {
- return node+"@"+domain;
+ return ( node == null || domain == null ) ? null : node+"@"+domain;
}
public function toString() : String {
var j = getBare();
- return ( resource == null ) ? j : j += "/"+resource;
+ if( j == null ) return null;
+ return ( resource == null ) ? j : j+="/"+resource;
}
}
diff --git a/jabber/Stream.hx b/jabber/Stream.hx
index eec6e74..7d7b6dc 100644
--- a/jabber/Stream.hx
+++ b/jabber/Stream.hx
@@ -17,7 +17,6 @@
*/
package jabber;
-import jabber.Stream;
import jabber.stream.Connection;
import jabber.stream.TPacketInterceptor;
import jabber.stream.PacketCollector;
@@ -73,31 +72,31 @@ class Stream {
public var jidstr(getJIDStr,null) : String;
public var server(default,null) : Server;
public var features(default,null) : StreamFeatures;
- /** Indicates if the version number of the XMPP stream ("1.0") should get added to the stream opening XML element */
- public var version : Bool;
- //TODO
+ public var version : Bool; //Indicates if the version number of the XMPP stream ("1.0") should get added to the stream opening XML element.
//public var dataFilters : List<TDataFilter>;
//public var dataInterceptors : List<TDataInterceptor>;
- var collectors : List<PacketCollector>; // public var collectors : Array<TPacketCollector>;
- var interceptors : List<TPacketInterceptor>; // public var interceptors : Array<TPacketCollector>;
+ var collectors : List<PacketCollector>; // public var packetCollectors : Array<TPacketCollector>;
+ var interceptors : List<TPacketInterceptor>; // public var packetInterceptors : Array<TPacketCollector>;
var isBOSH : Bool;
var numPacketsSent : Int;
+ //var numPacketsRecieved : Int;
- function new( cnx : Connection ) {
- if( cnx == null )
- throw "Stream connection is null";
- collectors = new List();
- interceptors = new List();
+ function new( ?cnx : Connection ) {
+// if( cnx == null )
+// throw "Stream connection is null";
+ status = StreamStatus.closed;
server = { features : new Hash() };
features = new StreamFeatures();
version = true;
- status = StreamStatus.closed;
+ collectors = new List();
+ interceptors = new List();
isBOSH = false;
numPacketsSent = 0;
- setConnection( cnx );
//dataFilters = new List();
//dataInterceptors = new List();
+ if( cnx != null )
+ setConnection( cnx );
}
function getJIDStr() : String {
@@ -119,7 +118,7 @@ class Stream {
cnx.onData = processData;
cnx.onError = errorHandler;
}
- isBOSH = ( Type.getClassName( Type.getClass( c ) ) == "jabber.BOSHConnection" );
+ isBOSH = ( Type.getClassName( Type.getClass( cnx ) ) == "jabber.BOSHConnection" );
return cnx;
}
@@ -137,10 +136,12 @@ class Stream {
/**
Request to open the XMPP stream.
*/
+ //TODO public function open( ?jid : String ) : Bool {
public function open() : Bool {
// if( status == StreamStatus.open ) return false;
if( !cnx.connected ) cnx.connect()
else connectHandler();
+ //( cnx.connected ) ? connectHandler() : cnx.connect();
return true;
}
@@ -154,7 +155,7 @@ class Stream {
}
if( disconnect )
cnx.disconnect();
- handleClose();
+ closeHandler();
}
/**
@@ -186,7 +187,6 @@ class Stream {
}
/*
- /*
TODO Send raw bytes data.
*/
/*
@@ -216,6 +216,7 @@ class Stream {
{
if( iq.id == null )
iq.id = nextID();
+ //iq.from = jidstr;
var c : PacketCollector = null;
if( handler != null ) {
c = new PacketCollector( [cast new PacketIDFilter( iq.id )], handler, permanent, timeout, block );
@@ -291,23 +292,28 @@ class Stream {
/**
*/
+ //TODO remove pos/length value
+ //public function processData( buf : haxe.io.Bytes ) : Bool {
public function processData( buf : haxe.io.Bytes, bufpos : Int, buflen : Int ) : Int {
if( status == StreamStatus.closed )
return -1;
//TODO .. data filters
- var t = buf.readString( bufpos, buflen );
+ //
+ var t : String = buf.readString( bufpos, buflen );
+ //TODO
if( xmpp.Stream.REGEXP_CLOSE.match( t ) ) {
close( true );
return -1;
}
+ //TODO
if( xmpp.Stream.REGEXP_ERROR.match( t ) ) {
//if( ~/stream:error/.match( t ) ) {
var err : xmpp.StreamError = null;
try {
err = xmpp.StreamError.parse( Xml.parse( t ) );
} catch( e : Dynamic ) {
- onClose( "Invalid stream:error" );
- close();
+ onClose( "Invalid XMPP stream "+e );
+ close( true );
return -1;
}
onClose( err );
@@ -320,18 +326,22 @@ class Stream {
case pending :
return processStreamInit( XmlUtil.removeXmlHeader( t ), buflen );
case open :
+
// HACK flash/js Xml bug !
#if (flash||js)
+ if( t.charAt( 0 ) != "<" || t.charAt( t.length-1 ) != ">" ) {
+ return 0;
+ }
+ /*
if( !StringTools.startsWith(t,"<") || !StringTools.endsWith(t, ">") ) {
if( !REG_HACK.match( t ) ) {
- //if( !StringTools.startsWith(t,"<") || !StringTools.endsWith(t, ">") ) {
#if JABBER_DEBUG
trace( "Invalid XML " );
#end
return 0;
}
-
}
+ */
#end
// filter data here ?
var x : Xml = null;
@@ -349,9 +359,11 @@ class Stream {
return 0;
}
+ //HACK
#if (flash||js)
- static inline var REG_HACK = ~/(.+)(\/[a-zA-Z-]*)>$/;
+ //static inline var REG_HACK = ~/(.+)(\/[a-zA-Z-]*)>$/;
#end
+ //HACK
/**
Inject incoming XML data to handle.<br/>
@@ -373,12 +385,6 @@ class Stream {
*/
public function handlePacket( p : xmpp.Packet ) : Bool {
#if XMPP_DEBUG
- /*
- if( p.errors.length > 0 )
- XMPPDebug.error( p.toString() );
- else
- XMPPDebug.inc( p.toString() );
- */
XMPPDebug.inc( p.toString() );
#end
var collected = false;
@@ -401,7 +407,7 @@ class Stream {
}
if( !collected ) {
#if JABBER_DEBUG
- trace( Type.enumConstructor( p._type )+" packet not handled", "warn" );
+ trace( "incoming '"+Type.enumConstructor( p._type )+"' packet not handled ( "+p.from+" -> "+p.to+" )", "warn" );
#end
if( p._type == xmpp.PacketType.iq ) { // send a 'feature not implemented' response
var q : xmpp.IQ = cast p;
@@ -423,25 +429,25 @@ class Stream {
}
*/
- function handleClose() {
+ function processStreamInit( t : String, buflen : Int ) : Int {
+ return throw "abstract";
+ }
+
+ function closeHandler() {
id = null;
numPacketsSent = 0;
onClose();
}
- function processStreamInit( t : String, buflen : Int ) : Int {
- return throw "abstract";//throw new error.AbstractError();
- }
-
function connectHandler() {
}
- function disconnectHandler() {
- handleClose();
- }
-
function errorHandler( m : Dynamic ) {
onClose( m );
}
+
+ function disconnectHandler() {
+ //? closeHandler();
+ }
}
diff --git a/jabber/client/SASLAuthentication.hx b/jabber/client/SASLAuthentication.hx
index d48d7e4..d46f535 100644
--- a/jabber/client/SASLAuthentication.hx
+++ b/jabber/client/SASLAuthentication.hx
@@ -23,13 +23,11 @@ import xmpp.IQType;
import xmpp.filter.PacketNameFilter;
import xmpp.filter.FilterGroup;
- //TODO use remaining mechanisms on fail (?)
-
/**
- Responsible for authenticating a client account using SASL, binding the resource to the connection
- and establishing a session with the server.<br>
- <a href="http://xmpp.org/rfcs/rfc3920.html#sasl">RFC3920-SASL</a><br>
- <a href="http://xmpp.org/rfcs/rfc3920.html#bind">RFC3920-BIND</a><br>
+ Responsible for authenticating a client account using SASL,
+ binding the resource to the connection and establishing a session with the server.<br>
+ <a href="http://xmpp.org/rfcs/rfc3920.html#sasl">RFC3920-SASL</a><br/>
+ <a href="http://xmpp.org/rfcs/rfc3920.html#bind">RFC3920-BIND</a><br/>
http://www.ietf.org/mail-archive/web/isms/current/msg00063.html
*/
class SASLAuthentication extends Authentication {
@@ -67,7 +65,8 @@ class SASLAuthentication extends Authentication {
public override function authenticate( password : String, ?resource : String ) : Bool {
this.resource = resource;
// update stream jid resource
- stream.jid.resource = resource;
+ if( stream.jid != null && resource != null )
+ stream.jid.resource = resource;
// locate mechanism to use.
if( handshake.mechanism == null ) {
for( amechs in mechanisms ) {
@@ -87,9 +86,6 @@ class SASLAuthentication extends Authentication {
#end
return false;
}
- //#if JABBER_DEBUG
- //trace( "Used SASL mechanism: "+handshake.mechanism.id, "info" );
- //#end
// collect failures
var f = new FilterGroup();
f.add( new PacketNameFilter( ~/failure/ ) ); //?
@@ -109,6 +105,7 @@ class SASLAuthentication extends Authentication {
c_challenge = new PacketCollector( [cast new PacketNameFilter( ~/challenge/ )], handleSASLChallenge, true );
stream.addCollector( c_challenge );
// send init auth
+ //trace("############## "+stream.jid );
var t = handshake.mechanism.createAuthenticationText( stream.jid.node, stream.jid.domain, password );
if( t != null ) t = util.Base64.encode( t );
return stream.sendData( xmpp.SASL.createAuthXml( handshake.mechanism.id, t ).toString() ) != null;
@@ -127,10 +124,8 @@ class SASLAuthentication extends Authentication {
}
function handleSASLSuccess( p : xmpp.Packet ) {
- // remove the challenge collector
- removeSASLCollectors();
- // relay the stream open event
- onStreamOpenHandler = stream.onOpen;
+ removeSASLCollectors(); // remove the challenge collector
+ onStreamOpenHandler = stream.onOpen; // relay the stream open event
stream.onOpen = handleStreamOpen;
onNegotiated();
//stream.version = false;
@@ -143,7 +138,7 @@ class SASLAuthentication extends Authentication {
//onStreamOpenHandler = null;
if( stream.server.features.exists( "bind" ) ) { // bind the resource
var iq = new IQ( IQType.set );
- iq.x = new xmpp.Bind( resource );
+ iq.x = new xmpp.Bind( ( handshake.mechanism.id == "ANONYMOUS" ) ? null : resource );
stream.sendIQ( iq, handleBind );
} else {
onSuccess(); // TODO ?
@@ -160,6 +155,11 @@ class SASLAuthentication extends Authentication {
throw "Unexpected resource bound ?";
}
*/
+ //onBind();
+ var b = xmpp.Bind.parse( iq.x.toXml() );
+ var jid = new jabber.JID( b.jid );
+ stream.jid.node = jid.node;
+ stream.jid.resource = jid.resource;
if( stream.server.features.exists( "session" ) ) {
// init session
var iq = new IQ( IQType.set );
@@ -174,8 +174,11 @@ class SASLAuthentication extends Authentication {
function handleSession( iq : IQ ) {
switch( iq.type ) {
- case result : onSuccess();
- case error : onFail( new jabber.XMPPError( this, iq ) );
+ case result :
+ ////onSession();
+ onSuccess();
+ case error :
+ onFail( new jabber.XMPPError( this, iq ) );
default : //#
}
}
diff --git a/jabber/client/Stream.hx b/jabber/client/Stream.hx
index 3465366..f251d5a 100644
--- a/jabber/client/Stream.hx
+++ b/jabber/client/Stream.hx
@@ -17,10 +17,12 @@
*/
package jabber.client;
+import jabber.JID;
+import jabber.StreamStatus;
import jabber.stream.Connection;
/**
- Base for client XMPP streams.<br/>
+ Client XMPP stream base.<br/>
*/
class Stream extends jabber.Stream {
@@ -28,11 +30,12 @@ class Stream extends jabber.Stream {
public static inline var PORT_SECURE_STANDARD = 5223;
public static var defaultPort = PORT_STANDARD;
+ public var jid(default,setJID) : JID;
// public var tls(default,null) : Bool;
- public var jid(default,null) : jabber.JID;
- public function new( jid : jabber.JID, cnx : Connection,
- version : Bool = true ) {
+ public function new( ?jid : JID, ?cnx : Connection, ?version : Bool = true ) {
+ if( jid == null )
+ jid = new JID(null);
super( cnx );
this.jid = jid;
this.version = version;
@@ -43,12 +46,18 @@ class Stream extends jabber.Stream {
return jid.toString();
}
+ function setJID( j : JID ) : JID {
+ if( status != StreamStatus.closed )
+ throw "Cannot change JID on active stream";
+ return jid = j;
+ }
+
override function processStreamInit( t : String, buflen : Int ) : Int {
if( isBOSH ) {
var sx = Xml.parse( t ).firstElement();
var sf = sx.firstElement();
parseStreamFeatures( sf );
- status = jabber.StreamStatus.open;
+ status = StreamStatus.open;
onOpen();
return buflen;
} else {
@@ -64,7 +73,7 @@ class Stream extends jabber.Stream {
var sx = Xml.parse( s ).firstElement();
id = sx.get( "id" );
if( !version ) {
- status = jabber.StreamStatus.open;
+ status = StreamStatus.open;
onOpen();
return buflen;
}
@@ -75,7 +84,7 @@ class Stream extends jabber.Stream {
return -1;
}
if( !version ) {
- status = jabber.StreamStatus.open;
+ status = StreamStatus.open;
onOpen();
return buflen;
}
@@ -89,7 +98,7 @@ class Stream extends jabber.Stream {
#if XMPP_DEBUG
jabber.XMPPDebug.inc( sfx.toString() );
#end
- status = jabber.StreamStatus.open;
+ status = StreamStatus.open;
onOpen();
return buflen;
} catch( e : Dynamic ) {
@@ -101,7 +110,7 @@ class Stream extends jabber.Stream {
}
override function connectHandler() {
- status = jabber.StreamStatus.pending;
+ status = StreamStatus.pending;
// TODO avoid HACK
if( !isBOSH ) {
sendData( xmpp.Stream.createOpenStream( xmpp.Stream.XMLNS_CLIENT, jid.domain, version, lang ) );
diff --git a/jabber/component/Stream.hx b/jabber/component/Stream.hx
index 7d26403..7747185 100644
--- a/jabber/component/Stream.hx
+++ b/jabber/component/Stream.hx
@@ -43,7 +43,7 @@ class Stream extends jabber.Stream {
/** */
public var connected(default,null) : Bool;
/** */
- public var items(default,null) : xmpp.disco.Items;
+ public var items(default,null) : xmpp.disco.Items; //TODO move into jabber.Stream? ( allowed by clients ? )
/** */
public var serviceListener(default,null) : ServiceDiscoveryListener;
@@ -68,6 +68,8 @@ class Stream extends jabber.Stream {
}
function getServiceName() : String {
+ if( subdomain == null || host == null )
+ return null;
return subdomain+"."+host;
}