comparison lightstring.js @ 41:2895891f19bb

s/that/this/ in handlers.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Tue, 31 Jan 2012 17:16:52 +0100
parents e02bfcb78428
children ee874d064650
comparison
equal deleted inserted replaced
40:e02bfcb78428 41:2895891f19bb
109 */ 109 */
110 Lightstring.Connection = function(aService) { 110 Lightstring.Connection = function(aService) {
111 if (aService) 111 if (aService)
112 this.service = aService; 112 this.service = aService;
113 this.handlers = {}; 113 this.handlers = {};
114 this.on('stream:features', function(stanza, that) { 114 this.on('stream:features', function(stanza) {
115 var nodes = stanza.DOM.querySelectorAll('mechanism'); 115 var nodes = stanza.DOM.querySelectorAll('mechanism');
116 //SASL/Auth features 116 //SASL/Auth features
117 if (nodes.length > 0) { 117 if (nodes.length > 0) {
118 that.emit('mechanisms', stanza); 118 this.emit('mechanisms', stanza);
119 var mechanisms = {}; 119 var mechanisms = {};
120 for (var i = 0; i < nodes.length; i++) 120 for (var i = 0; i < nodes.length; i++)
121 mechanisms[nodes[i].textContent] = true; 121 mechanisms[nodes[i].textContent] = true;
122 122
123 123
124 //FIXME support SCRAM-SHA1 && allow specify method preferences 124 //FIXME support SCRAM-SHA1 && allow specify method preferences
125 if ('DIGEST-MD5' in mechanisms) 125 if ('DIGEST-MD5' in mechanisms)
126 that.send( 126 this.send(
127 "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'" + 127 "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'" +
128 " mechanism='DIGEST-MD5'/>" 128 " mechanism='DIGEST-MD5'/>"
129 ); 129 );
130 else if ('PLAIN' in mechanisms) { 130 else if ('PLAIN' in mechanisms) {
131 var token = btoa( 131 var token = btoa(
132 that.jid + 132 this.jid +
133 '\u0000' + 133 '\u0000' +
134 that.jid.node + 134 this.jid.node +
135 '\u0000' + 135 '\u0000' +
136 that.password 136 this.password
137 ); 137 );
138 that.send( 138 this.send(
139 "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'" + 139 "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'" +
140 " mechanism='PLAIN'>" + token + "</auth>" 140 " mechanism='PLAIN'>" + token + "</auth>"
141 ); 141 );
142 } 142 }
143 } 143 }
144 //XMPP features 144 //XMPP features
145 else { 145 else {
146 that.emit('features', stanza); 146 this.emit('features', stanza);
147 //Bind http://xmpp.org/rfcs/rfc3920.html#bind 147 //Bind http://xmpp.org/rfcs/rfc3920.html#bind
148 var bind = 148 var bind =
149 "<iq type='set' xmlns='jabber:client'>" + 149 "<iq type='set' xmlns='jabber:client'>" +
150 "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>" + 150 "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>" +
151 (that.jid.resource? "<resource>" + that.jid.resource + "</resource>": "") + 151 (this.jid.resource? "<resource>" + this.jid.resource + "</resource>": "") +
152 "</bind>" + 152 "</bind>" +
153 "</iq>"; 153 "</iq>";
154 154
155 that.send( 155 this.send(
156 bind, 156 bind,
157 function(stanza) { 157 function(stanza) {
158 //Session http://xmpp.org/rfcs/rfc3921.html#session 158 //Session http://xmpp.org/rfcs/rfc3921.html#session
159 that.jid = new Lightstring.JID(stanza.DOM.textContent); 159 this.jid = new Lightstring.JID(stanza.DOM.textContent);
160 that.send( 160 this.send(
161 "<iq type='set' xmlns='jabber:client'>" + 161 "<iq type='set' xmlns='jabber:client'>" +
162 "<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>" + 162 "<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>" +
163 "</iq>", 163 "</iq>",
164 function() { 164 function() {
165 that.emit('connected'); 165 this.emit('connected');
166 } 166 }
167 ); 167 );
168 } 168 }
169 ); 169 );
170 } 170 }
171 }); 171 });
172 this.on('success', function(stanza, that) { 172 this.on('success', function(stanza) {
173 that.send( 173 this.send(
174 "<stream:stream to='" + that.jid.domain + "'" + 174 "<stream:stream to='" + this.jid.domain + "'" +
175 " xmlns='jabber:client'" + 175 " xmlns='jabber:client'" +
176 " xmlns:stream='http://etherx.jabber.org/streams'" + 176 " xmlns:stream='http://etherx.jabber.org/streams'" +
177 " version='1.0'/>" 177 " version='1.0'/>"
178 ); 178 );
179 }); 179 });
180 this.on('failure', function(stanza, that) { 180 this.on('failure', function(stanza) {
181 that.emit('conn-error', stanza.DOM.firstChild.tagName); 181 this.emit('conn-error', stanza.DOM.firstChild.tagName);
182 }); 182 });
183 this.on('challenge', function(stanza, that) { 183 this.on('challenge', function(stanza) {
184 //FIXME this is mostly Strophe code 184 //FIXME this is mostly Strophe code
185 185
186 function _quote(str) { 186 function _quote(str) {
187 return '"' + str.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"'; 187 return '"' + str.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
188 }; 188 };
216 host = matches[2]; 216 host = matches[2];
217 break; 217 break;
218 } 218 }
219 } 219 }
220 220
221 var digest_uri = 'xmpp/' + that.jid.domain; 221 var digest_uri = 'xmpp/' + this.jid.domain;
222 if (host !== null) 222 if (host !== null)
223 digest_uri = digest_uri + '/' + host; 223 digest_uri = digest_uri + '/' + host;
224 var A1 = MD5.hash(that.jid.node + 224 var A1 = MD5.hash(this.jid.node +
225 ':' + realm + ':' + that.password) + 225 ':' + realm + ':' + this.password) +
226 ':' + nonce + ':' + cnonce; 226 ':' + nonce + ':' + cnonce;
227 var A2 = 'AUTHENTICATE:' + digest_uri; 227 var A2 = 'AUTHENTICATE:' + digest_uri;
228 228
229 var responseText = ''; 229 var responseText = '';
230 responseText += 'username=' + _quote(that.jid.node) + ','; 230 responseText += 'username=' + _quote(this.jid.node) + ',';
231 responseText += 'realm=' + _quote(realm) + ','; 231 responseText += 'realm=' + _quote(realm) + ',';
232 responseText += 'nonce=' + _quote(nonce) + ','; 232 responseText += 'nonce=' + _quote(nonce) + ',';
233 responseText += 'cnonce=' + _quote(cnonce) + ','; 233 responseText += 'cnonce=' + _quote(cnonce) + ',';
234 responseText += 'nc="00000001",'; 234 responseText += 'nc="00000001",';
235 responseText += 'qop="auth",'; 235 responseText += 'qop="auth",';
238 MD5.hexdigest(MD5.hexdigest(A1) + ':' + 238 MD5.hexdigest(MD5.hexdigest(A1) + ':' +
239 nonce + ':00000001:' + 239 nonce + ':00000001:' +
240 cnonce + ':auth:' + 240 cnonce + ':auth:' +
241 MD5.hexdigest(A2))) + ','; 241 MD5.hexdigest(A2))) + ',';
242 responseText += 'charset="utf-8"'; 242 responseText += 'charset="utf-8"';
243 that.send( 243 this.send(
244 "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" + 244 "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" +
245 btoa(responseText) + 245 btoa(responseText) +
246 "</response>"); 246 "</response>");
247 }); 247 });
248 }; 248 };
308 if (stanza.DOM.tagName === 'iq') { 308 if (stanza.DOM.tagName === 'iq') {
309 var payload = stanza.DOM.firstChild; 309 var payload = stanza.DOM.firstChild;
310 if (payload) 310 if (payload)
311 that.emit('iq/' + payload.namespaceURI + ':' + payload.localName, stanza); 311 that.emit('iq/' + payload.namespaceURI + ':' + payload.localName, stanza);
312 that.emit(stanza.DOM.getAttribute('id'), stanza); //FIXME: possible attack vector. 312 that.emit(stanza.DOM.getAttribute('id'), stanza); //FIXME: possible attack vector.
313
314 //TODO: really needed?
315 } else if (stanza.DOM.tagName === 'message') {
316 var payloads = stanza.DOM.children;
317 for (var i = 0; i < payloads.length; i++)
318 that.emit('message/' + payloads[i].namespaceURI + ':' + payloads[i].localName, stanza);
313 } 319 }
314 }); 320 });
315 }, 321 },
316 /** 322 /**
317 * @function Send a message. 323 * @function Send a message.
364 emit: function(aName, aData) { 370 emit: function(aName, aData) {
365 var handlers = this.handlers[aName]; 371 var handlers = this.handlers[aName];
366 if (!handlers) 372 if (!handlers)
367 return; 373 return;
368 374
369 //FIXME Better idea than passing the context as argument?
370 for (var i = 0; i < handlers.length; i++) 375 for (var i = 0; i < handlers.length; i++)
371 handlers[i](aData, this); 376 handlers[i].call(this, aData);
372 377
373 if (aName.match('sendiq:')) 378 if (aName.match('sendiq:'))
374 delete this.handlers[aName]; 379 delete this.handlers[aName];
375 }, 380 },
376 /** 381 /**