changeset 22:6a6bb8ded046

Add a JID object, and use it in Lightstring.Connection.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Thu, 26 Jan 2012 22:11:51 +0100
parents b7d52bf259e0
children 99bf2bdcfd96
files jid.js lightstring.js
diffstat 2 files changed, 114 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/jid.js
@@ -0,0 +1,105 @@
+'use strict';
+
+/**
+  Copyright (c) 2012, Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
+
+  Permission to use, copy, modify, and/or distribute this software for any
+  purpose with or without fee is hereby granted, provided that the above
+  copyright notice and this permission notice appear in all copies.
+
+  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+
+/**
+ * @constructor Creates a new JID object.
+ * @param {String} [aJID] The host, bare or full JID.
+ * @memberOf Lightstring
+ */
+Lightstring.JID = function(aJID) {
+  this.node = null;
+  this.domain = null;
+  this.resource = null;
+
+  if (aJID)
+    this.full = aJID;
+
+  //TODO: use a stringprep library to validate the input.
+};
+
+Lightstring.JID.prototype = {
+  toString: function() {
+    return this.full;
+  },
+
+  get bare() {
+    if (!this.domain)
+      return null;
+
+    if (this.node)
+      return this.node + '@' + this.domain;
+
+    return this.domain;
+  },
+
+  set bare(aJID) {
+    if (!aJID)
+      return;
+
+    var s = aJID.indexOf('/');
+    if (s != -1)
+      aJID = aJID.substring(0, s);
+
+    s = aJID.indexOf('@');
+    if (s == -1) {
+      this.node = null;
+      this.domain = aJID;
+    } else {
+      this.node = aJID.substring(0, s);
+      this.domain = aJID.substring(s+1);
+    }
+  },
+
+  get full() {
+    if (!this.domain)
+      return null;
+
+    var full = this.domain;
+
+    if (this.node)
+      full = this.node + '@' + full;
+
+    if (this.resource)
+      full = full + '/' + this.resource;
+
+    return full;
+  },
+
+  set full(aJID) {
+    if (!aJID)
+      return;
+
+    var s = aJID.indexOf('/');
+    if (s == -1)
+      this.resource = null;
+    else {
+      this.resource = aJID.substring(s+1);
+      aJID = aJID.substring(0, s);
+    }
+
+    s = aJID.indexOf('@');
+    if (s == -1) {
+      this.node = null;
+      this.domain = aJID;
+    } else {
+      this.node = aJID.substring(0, s);
+      this.domain = aJID.substring(s+1);
+    }
+  }
+};
--- a/lightstring.js
+++ b/lightstring.js
@@ -138,7 +138,7 @@ Lightstring.Connection = function(aServi
   });
   this.on('success', function(stanza, that) {
     that.send(
-      "<stream:stream to='" + that.host + "'" +
+      "<stream:stream to='" + that.jid.domain + "'" +
                     " xmlns='jabber:client'" +
                     " xmlns:stream='http://etherx.jabber.org/streams'" +
                     " version='1.0'/>"
@@ -185,16 +185,16 @@ Lightstring.Connection = function(aServi
       }
     }
 
-    var digest_uri = 'xmpp/' + that.host;
+    var digest_uri = 'xmpp/' + that.jid.domain;
     if (host !== null)
         digest_uri = digest_uri + '/' + host;
-    var A1 = MD5.hash(that.node +
+    var A1 = MD5.hash(that.jid.node +
                       ':' + realm + ':' + that.password) +
-        ':' + nonce + ':' + cnonce;
+                      ':' + nonce + ':' + cnonce;
     var A2 = 'AUTHENTICATE:' + digest_uri;
 
     var responseText = '';
-    responseText += 'username=' + _quote(that.node) + ',';
+    responseText += 'username=' + _quote(that.jid.node) + ',';
     responseText += 'realm=' + _quote(realm) + ',';
     responseText += 'nonce=' + _quote(nonce) + ',';
     responseText += 'cnonce=' + _quote(cnonce) + ',';
@@ -221,17 +221,11 @@ Lightstring.Connection.prototype = {
    */
   connect: function(aJid, aPassword) {
     this.emit('connecting');
-    if (aJid)
-      this.jid = aJid;
-    if (this.jid) {
-      this.host = this.jid.split('@')[1];
-      this.node = this.jid.split('@')[0];
-      this.resource = this.jid.split('/')[1];
-    }
+    this.jid = new Lightstring.JID(aJid);
     if (aPassword)
       this.password = aPassword;
 
-    if (!this.jid)
+    if (!this.jid.bare)
       throw 'Lightstring: Connection.jid is undefined.';
     if (!this.password)
       throw 'Lightstring: Connection.password is undefined.';
@@ -251,7 +245,7 @@ Lightstring.Connection.prototype = {
       if (this.protocol !== 'xmpp')
         console.error('Lightstring: The server located at '+ that.service + ' doesn\'t seems to be XMPP aware.');
 
-      var stream = Lightstring.stanza.stream.open(that.host);
+      var stream = Lightstring.stanza.stream.open(that.jid.domain);
 
       that.socket.send(stream);
       that.emit('XMLOutput', stream);
@@ -270,7 +264,7 @@ Lightstring.Connection.prototype = {
       that.emit(elm.tagName, elm);
 
       if (elm.tagName === 'iq')
-        that.emit(elm.getAttribute('id'), elm);
+        that.emit(elm.getAttribute('id'), elm); //FIXME: possible attack vector.
     });
   },
   /**