Mercurial > eldonilo > lightstring
comparison lightstring.js @ 27:b6e4bc19ff5a
undoing
author | Sonny Piers <sonny.piers@gmail.com> |
---|---|
date | Sat, 28 Jan 2012 01:27:00 +0100 |
parents | 119ceb121908 |
children | 630b9579fe4a |
comparison
equal
deleted
inserted
replaced
19:fc577e5b2f4a | 27:b6e4bc19ff5a |
---|---|
33 */ | 33 */ |
34 stanza: { | 34 stanza: { |
35 stream: { | 35 stream: { |
36 open: function(aService) { | 36 open: function(aService) { |
37 //FIXME no ending "/" - node-xmpp-bosh bug | 37 //FIXME no ending "/" - node-xmpp-bosh bug |
38 return "<stream:stream to='" + aService + "'\ | 38 return "<stream:stream to='" + aService + "'" + |
39 xmlns='" + Lightstring.NS.jabberClient + "'\ | 39 " xmlns='" + Lightstring.NS.jabberClient + "'" + |
40 xmlns:stream='" + Lightstring.NS.stream + "'\ | 40 " xmlns:stream='" + Lightstring.NS.stream + "'" + |
41 version='1.0'/>"; | 41 " version='1.0'/>"; |
42 }, | 42 }, |
43 close: function() { | 43 close: function() { |
44 return '</stream:stream>'; | 44 return "</stream:stream>"; |
45 } | 45 } |
46 } | 46 } |
47 }, | 47 }, |
48 /** | 48 /** |
49 * @private | 49 * @private |
96 | 96 |
97 | 97 |
98 //FIXME support SCRAM-SHA1 && allow specify method preferences | 98 //FIXME support SCRAM-SHA1 && allow specify method preferences |
99 if ('DIGEST-MD5' in mechanisms) | 99 if ('DIGEST-MD5' in mechanisms) |
100 that.send( | 100 that.send( |
101 "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'\ | 101 "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'" + |
102 mechanism='DIGEST-MD5'/>" | 102 " mechanism='DIGEST-MD5'/>" |
103 ); | 103 ); |
104 else if ('PLAIN' in mechanisms) { | 104 else if ('PLAIN' in mechanisms) { |
105 var token = btoa( | 105 var token = btoa( |
106 that.jid + | 106 that.jid + |
107 '\u0000' + | 107 '\u0000' + |
108 that.jid.node + | 108 that.jid.node + |
109 '\u0000' + | 109 '\u0000' + |
110 that.password | 110 that.password |
111 ); | 111 ); |
112 that.send( | 112 that.send( |
113 "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'\ | 113 "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'" + |
114 mechanism='PLAIN'>" + token + '</auth>' | 114 " mechanism='PLAIN'>" + token + "</auth>" |
115 ); | 115 ); |
116 } | 116 } |
117 } | 117 } |
118 //XMPP features | 118 //XMPP features |
119 else { | 119 else { |
120 that.emit('features', stanza); | 120 that.emit('features', stanza); |
121 //Bind http://xmpp.org/rfcs/rfc3920.html#bind | 121 //Bind http://xmpp.org/rfcs/rfc3920.html#bind |
122 var bind = | |
123 "<iq type='set' xmlns='jabber:client'>" + | |
124 "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>" + | |
125 (that.jid.resource? "<resource>" + that.jid.resource + "</resource>": "") + | |
126 "</bind>" + | |
127 "</iq>"; | |
122 that.send( | 128 that.send( |
123 "<iq type='set' xmlns='jabber:client'>\ | 129 bind, |
124 <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>\ | 130 function(stanza) { |
125 </iq>", | 131 //Session http://xmpp.org/rfcs/rfc3921.html#session |
126 function() { | 132 that.jid = new Lightstring.JID(stanza.textContent); |
127 //Session http://xmpp.org/rfcs/rfc3921.html#session | 133 that.send( |
128 that.send( | 134 "<iq type='set' xmlns='jabber:client'>" + |
129 "<iq type='set' xmlns='jabber:client'>\ | 135 "<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>" + |
130 <session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>\ | 136 "</iq>", |
131 </iq>", | 137 function() { |
132 function() { | 138 that.emit('connected'); |
133 that.emit('connected'); | 139 } |
134 } | 140 ); |
135 ); | 141 } |
136 }); | 142 ); |
137 } | 143 } |
138 }); | 144 }); |
139 this.on('success', function(stanza, that) { | 145 this.on('success', function(stanza, that) { |
140 that.send( | 146 that.send( |
141 "<stream:stream to='" + that.host + "'\ | 147 "<stream:stream to='" + that.jid.domain + "'" + |
142 xmlns='jabber:client'\ | 148 " xmlns='jabber:client'" + |
143 xmlns:stream='http://etherx.jabber.org/streams'\ | 149 " xmlns:stream='http://etherx.jabber.org/streams'" + |
144 version='1.0' />" | 150 " version='1.0'/>" |
145 ); | 151 ); |
146 }); | 152 }); |
147 this.on('failure', function(stanza, that) { | 153 this.on('failure', function(stanza, that) { |
148 that.emit('conn-error', stanza.firstChild.tagName); | 154 that.emit('conn-error', stanza.firstChild.tagName); |
149 }); | 155 }); |
183 host = matches[2]; | 189 host = matches[2]; |
184 break; | 190 break; |
185 } | 191 } |
186 } | 192 } |
187 | 193 |
188 var digest_uri = 'xmpp/' + that.host; | 194 var digest_uri = 'xmpp/' + that.jid.domain; |
189 if (host !== null) { | 195 if (host !== null) |
190 digest_uri = digest_uri + '/' + host; | 196 digest_uri = digest_uri + '/' + host; |
191 } | 197 var A1 = MD5.hash(that.jid.node + |
192 var A1 = MD5.hash(that.node + | |
193 ':' + realm + ':' + that.password) + | 198 ':' + realm + ':' + that.password) + |
194 ':' + nonce + ':' + cnonce; | 199 ':' + nonce + ':' + cnonce; |
195 var A2 = 'AUTHENTICATE:' + digest_uri; | 200 var A2 = 'AUTHENTICATE:' + digest_uri; |
196 | 201 |
197 var responseText = ''; | 202 var responseText = ''; |
198 responseText += 'username=' + _quote(that.node) + ','; | 203 responseText += 'username=' + _quote(that.jid.node) + ','; |
199 responseText += 'realm=' + _quote(realm) + ','; | 204 responseText += 'realm=' + _quote(realm) + ','; |
200 responseText += 'nonce=' + _quote(nonce) + ','; | 205 responseText += 'nonce=' + _quote(nonce) + ','; |
201 responseText += 'cnonce=' + _quote(cnonce) + ','; | 206 responseText += 'cnonce=' + _quote(cnonce) + ','; |
202 responseText += 'nc="00000001",'; | 207 responseText += 'nc="00000001",'; |
203 responseText += 'qop="auth",'; | 208 responseText += 'qop="auth",'; |
207 nonce + ':00000001:' + | 212 nonce + ':00000001:' + |
208 cnonce + ':auth:' + | 213 cnonce + ':auth:' + |
209 MD5.hexdigest(A2))) + ','; | 214 MD5.hexdigest(A2))) + ','; |
210 responseText += 'charset="utf-8"'; | 215 responseText += 'charset="utf-8"'; |
211 that.send( | 216 that.send( |
212 "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" | 217 "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" + |
213 + btoa(responseText) + | 218 btoa(responseText) + |
214 '</response>'); | 219 "</response>"); |
215 }); | 220 }); |
216 }; | 221 }; |
217 Lightstring.Connection.prototype = { | 222 Lightstring.Connection.prototype = { |
218 /** | 223 /** |
219 * @function Create and open a websocket then go though the XMPP authentification process. | 224 * @function Create and open a websocket then go though the XMPP authentification process. |
220 * @param {String} [aJid] The JID (Jabber id) to use. | 225 * @param {String} [aJid] The JID (Jabber id) to use. |
221 * @param {String} [aPassword] The associated password. | 226 * @param {String} [aPassword] The associated password. |
222 */ | 227 */ |
223 connect: function(aJid, aPassword) { | 228 connect: function(aJid, aPassword) { |
224 this.emit('connecting'); | 229 this.emit('connecting'); |
225 if (aJid) | 230 this.jid = new Lightstring.JID(aJid); |
226 this.jid = aJid; | |
227 if (this.jid) { | |
228 this.host = this.jid.split('@')[1]; | |
229 this.node = this.jid.split('@')[0]; | |
230 this.resource = this.jid.split('/')[1]; | |
231 } | |
232 if (aPassword) | 231 if (aPassword) |
233 this.password = aPassword; | 232 this.password = aPassword; |
234 | 233 |
235 if (!this.jid) | 234 if (!this.jid.bare) |
236 throw 'Lightstring: Connection.jid is undefined.'; | 235 throw 'Lightstring: Connection.jid is undefined.'; |
237 if (!this.password) | 236 if (!this.password) |
238 throw 'Lightstring: Connection.password is undefined.'; | 237 throw 'Lightstring: Connection.password is undefined.'; |
239 if (!this.service) | 238 if (!this.service) |
240 throw 'Lightstring: Connection.service is undefined.'; | 239 throw 'Lightstring: Connection.service is undefined.'; |
250 var that = this; | 249 var that = this; |
251 this.socket.addEventListener('open', function() { | 250 this.socket.addEventListener('open', function() { |
252 if (this.protocol !== 'xmpp') | 251 if (this.protocol !== 'xmpp') |
253 console.error('Lightstring: The server located at '+ that.service + ' doesn\'t seems to be XMPP aware.'); | 252 console.error('Lightstring: The server located at '+ that.service + ' doesn\'t seems to be XMPP aware.'); |
254 | 253 |
255 var stream = Lightstring.stanza.stream.open(that.host); | 254 var stream = Lightstring.stanza.stream.open(that.jid.domain); |
256 | 255 |
257 that.socket.send(stream); | 256 that.socket.send(stream); |
258 that.emit('XMLOutput', stream); | 257 that.emit('XMLOutput', stream); |
259 }); | 258 }); |
260 this.socket.addEventListener('error', function(e) { | 259 this.socket.addEventListener('error', function(e) { |
268 that.emit('XMLInput', e.data); | 267 that.emit('XMLInput', e.data); |
269 var elm = Lightstring.xml2dom(e.data); | 268 var elm = Lightstring.xml2dom(e.data); |
270 that.emit('DOMInput', elm); | 269 that.emit('DOMInput', elm); |
271 that.emit(elm.tagName, elm); | 270 that.emit(elm.tagName, elm); |
272 | 271 |
272 <<<<<<< HEAD | |
273 if (elm.tagName === 'iq') | 273 if (elm.tagName === 'iq') |
274 that.emit(elm.getAttribute('id'), elm); | 274 that.emit(elm.getAttribute('id'), elm); |
275 ======= | |
276 if (elm.tagName === 'iq') { | |
277 var payload = elm.firstChild; | |
278 if (payload) | |
279 that.emit('iq/' + payload.namespaceURI + ':' + payload.localName, elm); | |
280 that.emit(elm.getAttribute('id'), elm); //FIXME: possible attack vector. | |
281 } | |
282 >>>>>>> f6a7c0f93d154c2cd34dfdda4ab8eec808b91b34 | |
275 }); | 283 }); |
276 }, | 284 }, |
277 /** | 285 /** |
278 * @function Send a message. | 286 * @function Send a message. |
279 * @param {String|Object} aStanza The message to send. | 287 * @param {String|Object} aStanza The message to send. |
301 str = Lightstring.dom2xml(elm); | 309 str = Lightstring.dom2xml(elm); |
302 } | 310 } |
303 if (aCallback) | 311 if (aCallback) |
304 this.on(elm.getAttribute('id'), aCallback); | 312 this.on(elm.getAttribute('id'), aCallback); |
305 } | 313 } |
306 else if (aCallback) { | 314 else if (aCallback) |
307 this.emit('warning', 'Callback can\'t be called with non-iq stanza.'); | 315 this.emit('warning', 'Callback can\'t be called with non-iq stanza.'); |
308 } | |
309 | 316 |
310 | 317 |
311 this.socket.send(str); | 318 this.socket.send(str); |
312 this.emit('XMLOutput', str); | 319 this.emit('XMLOutput', str); |
313 this.emit('DOMOutput', elm); | 320 this.emit('DOMOutput', elm); |