Compare commits

...

35 Commits

Author SHA1 Message Date
Guillermo Rauch
d25c5484c3 Release 0.9.17 2014-05-22 11:03:55 -07:00
Guillermo Rauch
fea676b90e Merge pull request #1371 from surespot/channelfix
Use static channels for node syncing.
2014-05-22 10:49:53 -07:00
Adam Patacchiola
386d2a9c0c don't call non existant transport onDisconnect 2013-12-13 10:02:20 -07:00
Adam Patacchiola
8b47789414 use static channels for remote syncing instead of subscribing/unsubscribing 5 channels for every connection 2013-12-13 07:22:43 -07:00
Guillermo Rauch
47b06c0fcf Merge pull request #1333 from yujiosaka/0.9
http-polling : adding 'X-XSS-Protection : 0;' to headers necessary not o...
2013-12-09 08:17:42 -08:00
Guillermo Rauch
9823325a1f Merge pull request #1346 from DeadAlready/0.9-security-fix
Use destroy buffer size on websocket transport method as well
2013-11-15 04:01:16 -08:00
Karl Düüna
a47d76b990 Use destroy buffer size on websocket transport method as well 2013-11-15 10:31:00 +02:00
yujiosaka
db3ac4b415 http-polling : adding 'X-XSS-Protection : 0;' to headers necessary not only to jsonp-polling but http-polling 2013-10-24 14:53:19 +09:00
Guillermo Rauch
b9a2804b1a Merge pull request #1323 from tico8/0.9-bug
Memory leak : If a lot of connections continue being disconnected, a memory will leak.
2013-10-09 08:32:44 -07:00
tico8
b4182a5d42 Memory leak : If a lot of connections continue being disconnected, a memory will leak. 2013-10-09 01:06:02 +09:00
Guillermo Rauch
5120a706f2 Release 0.9.16 2013-06-06 08:39:48 -07:00
Guillermo Rauch
ee078cb124 transports: added tests for htmlfile escaping/unescaping 2013-06-06 08:38:57 -07:00
Guillermo Rauch
64d8f572aa Release 0.9.15 2013-06-06 08:22:29 -07:00
Guillermo Rauch
4e1ba9f872 transports: escaping (fixes #1251) 2013-06-06 08:17:40 -07:00
Guillermo Rauch
5d93af994a Release 0.9.14 2013-03-29 14:15:52 -07:00
Guillermo Rauch
6e25c802cc manager: fix memory leak with SSL 2013-03-29 14:14:42 -07:00
Guillermo Rauch
37690f78d7 Release 0.9.13 2012-12-13 15:15:38 -03:00
Guillermo Rauch
3cbd00ca70 package: fixed base64id requirement 2012-12-13 15:15:15 -03:00
Guillermo Rauch
b2a8ed1421 Release 0.9.12 2012-12-13 08:19:16 -03:00
Guillermo Rauch
0d3313f536 manager: fix for latest node which is returning a clone with listeners [viirya] 2012-12-13 08:18:42 -03:00
Guillermo Rauch
3b7224c7e0 Release 0.9.11 2012-11-02 08:03:15 -07:00
Guillermo Rauch
2030cf1432 package: move redis to optionalDependenices [3rd-Eden] 2012-11-02 08:01:24 -07:00
Guillermo Rauch
de9e8dffe1 Release 0.9.10 2012-08-10 13:34:50 -07:00
Guillermo Rauch
3a3044ebba Merge pull request #972 from Coreh/express-3.x-readme
Add express 3.0 instructions on Readme.md
2012-08-10 10:17:55 -07:00
Guillermo Rauch
d10b4dd1bd Merge pull request #985 from GICodeWarrior/log-case-fix
Don't lowercase log messages
2012-08-08 18:03:57 -07:00
Rusty Burchfield
12beee2d63 Don't lowercase log messages
Lowercasing log messages is unnecessary.  It makes some messages difficult to
read, and others difficult to search for.
2012-08-08 11:32:57 -07:00
Guillermo Rauch
875f14d16b Revert "Fix infinite recursion in Websocket parsers."
This reverts commit c218468f67.
2012-08-07 13:18:41 -07:00
Guillermo Rauch
8ca8990a0c Merge pull request #983 from GICodeWarrior/parser-recursion
Fix infinite recursion in Websocket parsers.
2012-08-06 13:16:37 -07:00
Rusty Burchfield
c218468f67 Fix infinite recursion in Websocket parsers.
If a client is feeding messages faster than server can handle them, infinite
recursion occurs.  Basically, the "overflow" data gets added to the parser and
it immediately parses a new message.

The fix pushes the processing of the next message (in this edge case) onto the
event queue.  This prevents the stack from recursing indefinitely.  This also
prevents a fast client from starving other clients.
2012-08-06 13:03:51 -07:00
Guillermo Rauch
4164e3bd7e Merge pull request #981 from doozr/honour-flash-settings
Honour flash settings
2012-08-06 08:59:17 -07:00
Guillermo Rauch
46227e7ac9 Merge pull request #980 from doozr/jsonp-error-crash
Always set the HTTP response in case an error should be returned to the client
2012-08-06 08:58:57 -07:00
Craig Andrews
d723d363b2 Always set the HTTP response in case an error should be returned to the client 2012-08-06 14:16:06 +01:00
Craig Andrews
fa1c1b2ada Create or destroy the flash policy server on configuration change 2012-08-06 14:14:15 +01:00
Craig Andrews
d32a848c3f Honour configuration to disable flash policy server 2012-08-06 14:14:14 +01:00
Marco Aurélio
bddf652c25 Add express 3.0 instructions on Readme.md 2012-07-30 15:53:47 -03:00
14 changed files with 308 additions and 82 deletions

View File

@@ -1,4 +1,52 @@
0.9.17 / 2014-05-22
===================
* use static channels for remote syncing instead of subscribing/unsubscribing 5 channels for every connection
* Use destroy buffer size on websocket transport method as well
* http-polling : adding 'X-XSS-Protection : 0;' to headers necessary not only to jsonp-polling but http-polling
0.9.16 / 2013-06-06
===================
* transports: added tests for htmlfile escaping/unescaping
0.9.15 / 2013-06-06
===================
* transports: added escaping to htmlfile (fixes #1251)
0.9.14 / 2013-03-29
===================
* manager: fix memory leak with SSL [jpallen]
0.9.13 / 2012-12-13
===================
* package: fixed `base64id` requirement
0.9.12 / 2012-12-13
===================
* manager: fix for latest node which is returning a clone with `listeners` [viirya]
0.9.11 / 2012-11-02
===================
* package: move redis to optionalDependenices [3rd-Eden]
* bumped client
0.9.10 / 2012-08-10
===================
* Don't lowercase log messages
* Always set the HTTP response in case an error should be returned to the client
* Create or destroy the flash policy server on configuration change
* Honour configuration to disable flash policy server
* Add express 3.0 instructions on Readme.md
* Bump client
0.9.9 / 2012-08-01
==================

View File

@@ -21,6 +21,25 @@ var io = require('socket.io');
Next, attach it to a HTTP/HTTPS server. If you're using the fantastic `express`
web framework:
#### Express 3.x
```js
var app = express()
, server = require('http').createServer(app)
, io = io.listen(server);
server.listen(80);
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
```
#### Express 2.x
```js
var app = express.createServer()
, io = io.listen(app);

View File

@@ -113,6 +113,7 @@ function Manager (server, options) {
// reset listeners
this.oldListeners = server.listeners('request').splice(0);
server.removeAllListeners('request');
server.on('request', function (req, res) {
self.handleRequest(req, res);
@@ -319,8 +320,46 @@ Manager.prototype.initStore = function () {
this.store.subscribe('disconnect', function (id) {
self.onDisconnect(id);
});
};
// we need to do this in a pub/sub way since the client can POST the message
// over a different socket (ie: different Transport instance)
//use persistent channel for these, don't add and remove 5 channels for every connection
//eg. for 10,000 concurrent users this creates 50,000 channels in redis, which kind of slows things down
//we only need 5 (extra) total channels at all times
this.store.subscribe('message-remote',function (id, packet) {
self.onClientMessage(id, packet);
});
this.store.subscribe('disconnect-remote', function (id, reason) {
self.onClientDisconnect(id, reason);
});
this.store.subscribe('dispatch-remote', function (id, packet, volatile) {
var transport = self.transports[id];
if (transport) {
transport.onDispatch(packet, volatile);
}
if (!volatile) {
self.onClientDispatch(id, packet);
}
});
this.store.subscribe('heartbeat-clear', function (id) {
var transport = self.transports[id];
if (transport) {
transport.onHeartbeatClear();
}
});
this.store.subscribe('disconnect-force', function (id) {
var transport = self.transports[id];
if (transport) {
transport.onForcedDisconnect();
}
});
};
/**
* Called when a client handshakes.
*
@@ -353,19 +392,17 @@ Manager.prototype.onOpen = function (id) {
if (this.closed[id]) {
var self = this;
this.store.unsubscribe('dispatch:' + id, function () {
var transport = self.transports[id];
if (self.closed[id] && self.closed[id].length && transport) {
var transport = self.transports[id];
if (self.closed[id] && self.closed[id].length && transport) {
// if we have buffered messages that accumulate between calling
// onOpen an this async callback, send them if the transport is
// still open, otherwise leave them buffered
if (transport.open) {
transport.payload(self.closed[id]);
self.closed[id] = [];
}
// if we have buffered messages that accumulate between calling
// onOpen an this async callback, send them if the transport is
// still open, otherwise leave them buffered
if (transport.open) {
transport.payload(self.closed[id]);
self.closed[id] = [];
}
});
}
}
// clear the current transport
@@ -456,12 +493,6 @@ Manager.prototype.onClose = function (id) {
this.closed[id] = [];
var self = this;
this.store.subscribe('dispatch:' + id, function (packet, volatile) {
if (!volatile) {
self.onClientDispatch(id, packet);
}
});
};
/**
@@ -511,7 +542,7 @@ Manager.prototype.onClientDisconnect = function (id, reason) {
* @param text
*/
Manager.prototype.onDisconnect = function (id, local) {
Manager.prototype.onDisconnect = function (id) {
delete this.handshaken[id];
if (this.open[id]) {
@@ -541,13 +572,6 @@ Manager.prototype.onDisconnect = function (id, local) {
}
this.store.destroyClient(id, this.get('client store expiration'));
this.store.unsubscribe('dispatch:' + id);
if (local) {
this.store.unsubscribe('message:' + id);
this.store.unsubscribe('disconnect:' + id);
}
};
/**
@@ -615,6 +639,7 @@ Manager.prototype.handleUpgrade = function (req, socket, head) {
req.head = head;
this.handleClient(data, req);
req.head = null;
};
/**
@@ -644,7 +669,7 @@ Manager.prototype.handleClient = function (data, req) {
if (this.transports[data.id] && this.transports[data.id].open) {
this.transports[data.id].onForcedDisconnect();
} else {
this.store.publish('disconnect-force:' + data.id);
this.store.publish('disconnect-force', data.id);
}
req.res.writeHead(200);
req.res.end();
@@ -697,14 +722,6 @@ Manager.prototype.handleClient = function (data, req) {
}
}
}
this.store.subscribe('message:' + data.id, function (packet) {
self.onClientMessage(data.id, packet);
});
this.store.subscribe('disconnect:' + data.id, function (reason) {
self.onClientDisconnect(data.id, reason);
});
}
} else {
if (transport.open) {
@@ -800,11 +817,11 @@ Manager.prototype.handleHandshake = function (data, req, res) {
res.writeHead(200, headers);
}
res.end(hs);
self.onHandshake(id, newData || handshakeData);
self.store.publish('handshake', id, newData || handshakeData);
res.end(hs);
self.log.info('handshake authorized', id);
} else {
writeErr(403, 'handshake unauthorized');

View File

@@ -15,7 +15,7 @@ var client = require('socket.io-client');
* Version.
*/
exports.version = '0.9.9';
exports.version = '0.9.16';
/**
* Supported protocol version.

View File

@@ -233,7 +233,7 @@ Socket.prototype.dispatch = function (packet, volatile) {
this.manager.onClientDispatch(this.id, packet, volatile);
}
this.manager.store.publish('dispatch:' + this.id, packet, volatile);
this.manager.store.publish('dispatch-remote', this.id, packet, volatile);
}
};
@@ -296,7 +296,7 @@ Socket.prototype.disconnect = function () {
this.manager.transports[this.id].onForcedDisconnect();
} else {
this.manager.onClientDisconnect(this.id);
this.manager.store.publish('disconnect:' + this.id);
this.manager.store.publish('disconnect-remote', this.id);
}
} else {
this.packet({type: 'disconnect'});

View File

@@ -89,20 +89,6 @@ Transport.prototype.onSocketConnect = function () { };
Transport.prototype.setHandlers = function () {
var self = this;
// we need to do this in a pub/sub way since the client can POST the message
// over a different socket (ie: different Transport instance)
this.store.subscribe('heartbeat-clear:' + this.id, function () {
self.onHeartbeatClear();
});
this.store.subscribe('disconnect-force:' + this.id, function () {
self.onForcedDisconnect();
});
this.store.subscribe('dispatch:' + this.id, function (packet, volatile) {
self.onDispatch(packet, volatile);
});
this.bound = {
end: this.onSocketEnd.bind(this)
, close: this.onSocketClose.bind(this)
@@ -126,10 +112,6 @@ Transport.prototype.setHandlers = function () {
Transport.prototype.clearHandlers = function () {
if (this.handlersSet) {
this.store.unsubscribe('disconnect-force:' + this.id);
this.store.unsubscribe('heartbeat-clear:' + this.id);
this.store.unsubscribe('dispatch:' + this.id);
this.socket.removeListener('end', this.bound.end);
this.socket.removeListener('close', this.bound.close);
this.socket.removeListener('error', this.bound.error);
@@ -350,7 +332,7 @@ Transport.prototype.onMessage = function (packet) {
if (current && current.open) {
current.onHeartbeatClear();
} else {
this.store.publish('heartbeat-clear:' + this.id);
this.store.publish('heartbeat-clear', this.id);
}
} else {
if ('disconnect' == packet.type && packet.endpoint == '') {
@@ -359,7 +341,7 @@ Transport.prototype.onMessage = function (packet) {
if (current) {
current.onForcedDisconnect();
} else {
this.store.publish('disconnect-force:' + this.id);
this.store.publish('disconnect-force', this.id);
}
return;
@@ -378,7 +360,7 @@ Transport.prototype.onMessage = function (packet) {
current.onDispatch(ack);
} else {
this.manager.onClientDispatch(this.id, ack);
this.store.publish('dispatch:' + this.id, ack);
this.store.publish('dispatch-remote', this.id, ack);
}
}
@@ -386,7 +368,7 @@ Transport.prototype.onMessage = function (packet) {
if (current) {
this.manager.onClientMessage(this.id, packet);
} else {
this.store.publish('message:' + this.id, packet);
this.store.publish('message-remote', this.id, packet);
}
}
};
@@ -464,10 +446,10 @@ Transport.prototype.end = function (reason) {
this.disconnected = true;
if (local) {
this.manager.onClientDisconnect(this.id, reason, true);
} else {
this.store.publish('disconnect:' + this.id, reason);
this.manager.onClientDisconnect(this.id, reason);
}
this.store.publish('disconnect-remote', this.id, reason);
}
};

View File

@@ -1,4 +1,3 @@
/*!
* socket.io-node
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
@@ -53,9 +52,16 @@ FlashSocket.prototype.name = 'flashsocket';
FlashSocket.init = function (manager) {
var server;
function create () {
// Drop out immediately if the user has
// disabled the flash policy server
if (!manager.get('flash policy server')) {
return;
}
server = require('policyfile').createServer({
log: function(msg){
manager.log.info(msg.toLowerCase());
manager.log.info(msg);
}
}, manager.get('origins'));
@@ -93,6 +99,23 @@ FlashSocket.init = function (manager) {
}
});
// create or destroy the server
manager.on('set:flash policy server', function (value, key) {
var transports = manager.get('transports');
if (~transports.indexOf('flashsocket')) {
if (server && !value) {
// destroy the server
try {
server.close();
}
catch (e) { /* ignore exception. could e.g. be that the server isn't started yet */ }
}
} else if (!server && value) {
// create the server
create();
}
});
// only start the server
manager.on('set:transports', function (value, key){
if (!server && ~manager.get('transports').indexOf('flashsocket')) {

View File

@@ -72,7 +72,8 @@ HTMLFile.prototype.handleRequest = function (req) {
*/
HTMLFile.prototype.write = function (data) {
data = '<script>_(' + JSON.stringify(data) + ');</script>';
// escape all forward slashes. see GH-1251
data = '<script>_(' + JSON.stringify(data).replace(/\//g, '\\/') + ');</script>';
if (this.response.write(data)) {
this.drained = true;

View File

@@ -42,6 +42,10 @@ HTTPTransport.prototype.__proto__ = Transport.prototype;
*/
HTTPTransport.prototype.handleRequest = function (req) {
// Always set the response in case an error is returned to the client
this.response = req.res;
if (req.method == 'POST') {
var buffer = ''
, res = req.res
@@ -75,10 +79,9 @@ HTTPTransport.prototype.handleRequest = function (req) {
// https://developer.mozilla.org/En/HTTP_Access_Control
headers['Access-Control-Allow-Origin'] = origin;
headers['Access-Control-Allow-Credentials'] = 'true';
headers['X-XSS-Protection'] = '0';
}
} else {
this.response = req.res;
Transport.prototype.handleRequest.call(this, req);
}
};

View File

@@ -30,7 +30,7 @@ function WebSocket (mng, data, req) {
// parser
var self = this;
this.parser = new Parser();
this.parser = new Parser({maxBuffer: mng.get('destroy buffer size')});
this.parser.on('data', function (packet) {
self.log.debug(self.name + ' received data packet', packet);
self.onMessage(parser.decodePacket(packet));
@@ -41,6 +41,11 @@ function WebSocket (mng, data, req) {
this.parser.on('error', function () {
self.end();
});
this.parser.on('kick', function (reason) {
self.log.warn(self.name + ' parser forced user kick: ' + reason);
self.onMessage({type: 'disconnect', endpoint: ''});
self.end();
});
Transport.call(this, mng, data, req);
};
@@ -293,7 +298,9 @@ WebSocket.prototype.doClose = function () {
* @api public
*/
function Parser () {
function Parser (opts) {
this._maxBuffer = (opts && opts.maxBuffer) || 10E7;
this._dataLength = 0;
this.buffer = '';
this.i = 0;
};
@@ -311,6 +318,13 @@ Parser.prototype.__proto__ = EventEmitter.prototype;
*/
Parser.prototype.add = function (data) {
this._dataLength += data.length;
if(this._dataLength > this._maxBuffer) {
this.buffer = ''; //Clear buffer
this.emit('kick', 'max buffer size reached');
return;
}
this.buffer += data;
this.parse();
};

View File

@@ -35,7 +35,7 @@ function WebSocket (mng, data, req) {
var self = this;
this.manager = mng;
this.parser = new Parser();
this.parser = new Parser({maxBuffer: mng.get('destroy buffer size')});
this.parser.on('data', function (packet) {
self.onMessage(parser.decodePacket(packet));
});
@@ -56,6 +56,11 @@ function WebSocket (mng, data, req) {
self.log.warn(self.name + ' parser error: ' + reason);
self.end();
});
this.parser.on('kick', function (reason) {
self.log.warn(self.name + ' parser forced user kick: ' + reason);
self.onMessage({type: 'disconnect', endpoint: ''});
self.end();
});
Transport.call(this, mng, data, req);
};
@@ -266,7 +271,7 @@ WebSocket.prototype.doClose = function () {
* @api public
*/
function Parser () {
function Parser (opts) {
this.state = {
activeFragmentedOperation: null,
lastFragment: false,
@@ -278,6 +283,8 @@ function Parser () {
this.expectBuffer = null;
this.expectHandler = null;
this.currentMessage = '';
this._maxBuffer = (opts && opts.maxBuffer) || 10E7;
this._dataLength = 0;
var self = this;
this.opcodeHandlers = {
@@ -448,6 +455,15 @@ Parser.prototype.__proto__ = EventEmitter.prototype;
*/
Parser.prototype.add = function(data) {
this._dataLength += data.length;
if (this._dataLength > this._maxBuffer) {
// Clear data
this.overflow = null;
this.expectBuffer = null;
// Kick client
this.emit('kick', 'max buffer size reached');
return;
}
if (this.expectBuffer == null) {
this.addToOverflow(data);
return;
@@ -491,6 +507,10 @@ Parser.prototype.addToOverflow = function(data) {
*/
Parser.prototype.expect = function(what, length, handler) {
if (length > this._maxBuffer) {
this.emit('kick', 'expected input larger than max buffer');
return;
}
this.expectBuffer = new Buffer(length);
this.expectOffset = 0;
this.expectHandler = handler;

View File

@@ -34,7 +34,7 @@ function WebSocket (mng, data, req) {
var self = this;
this.manager = mng;
this.parser = new Parser();
this.parser = new Parser({maxBuffer: mng.get('destroy buffer size')});
this.parser.on('data', function (packet) {
self.onMessage(parser.decodePacket(packet));
});
@@ -55,6 +55,11 @@ function WebSocket (mng, data, req) {
self.log.warn(self.name + ' parser error: ' + reason);
self.end();
});
this.parser.on('kick', function (reason) {
self.log.warn(self.name + ' parser forced user kick: ' + reason);
self.onMessage({type: 'disconnect', endpoint: ''});
self.end();
});
Transport.call(this, mng, data, req);
};
@@ -265,7 +270,7 @@ WebSocket.prototype.doClose = function () {
* @api public
*/
function Parser () {
function Parser (opts) {
this.state = {
activeFragmentedOperation: null,
lastFragment: false,
@@ -277,6 +282,8 @@ function Parser () {
this.expectBuffer = null;
this.expectHandler = null;
this.currentMessage = '';
this._maxBuffer = (opts && opts.maxBuffer) || 10E7;
this._dataLength = 0;
var self = this;
this.opcodeHandlers = {
@@ -447,6 +454,15 @@ Parser.prototype.__proto__ = EventEmitter.prototype;
*/
Parser.prototype.add = function(data) {
this._dataLength += data.length;
if (this._dataLength > this._maxBuffer) {
// Clear data
this.overflow = null;
this.expectBuffer = null;
// Kick client
this.emit('kick', 'max buffer size reached');
return;
}
if (this.expectBuffer == null) {
this.addToOverflow(data);
return;
@@ -490,6 +506,10 @@ Parser.prototype.addToOverflow = function(data) {
*/
Parser.prototype.expect = function(what, length, handler) {
if (length > this._maxBuffer) {
this.emit('kick', 'expected input larger than max buffer');
return;
}
this.expectBuffer = new Buffer(length);
this.expectOffset = 0;
this.expectHandler = handler;

View File

@@ -1,6 +1,6 @@
{
"name": "socket.io"
, "version": "0.9.9"
, "version": "0.9.17"
, "description": "Real-time apps made cross-browser & easy with a WebSocket-like API"
, "homepage": "http://socket.io"
, "keywords": ["websocket", "socket", "realtime", "socket.io", "comet", "ajax"]
@@ -16,9 +16,9 @@
, "url": "https://github.com/LearnBoost/socket.io.git"
}
, "dependencies": {
"socket.io-client": "0.9.9"
"socket.io-client": "0.9.16"
, "policyfile": "0.0.4"
, "redis": "0.7.2"
, "base64id": "0.1.0"
}
, "devDependencies": {
"expresso": "0.9.2"
@@ -27,6 +27,9 @@
, "microtime": "0.1.3-1"
, "colors": "0.5.1"
}
, "optionalDependencies": {
"redis": "0.7.3"
}
, "main": "index"
, "engines": { "node": ">= 0.4.0" }
, "scripts": {

View File

@@ -77,10 +77,14 @@ HTMLFile.prototype.data = function (path, opts, fn) {
case 2:
if (buf.indexOf(foot) != -1) {
var data = buf.slice(0, buf.indexOf(foot))
, obj = JSON.parse(data);
var data = buf.slice(0, buf.indexOf(foot));
fn(obj === '' ? obj : parser.decodePayload(obj), ++messages);
if (false === opts.parse) {
fn(data, ++messages);
} else {
var obj = JSON.parse(data);
fn(obj === '' ? obj : parser.decodePayload(obj), ++messages);
}
buf = buf.substr(data.length + foot.length);
state = 1;
@@ -453,6 +457,78 @@ module.exports = {
}
});
});
},
'test escaping for security': function (done) {
var port = ++ports
, cl = client(port)
, io = create(cl)
, messaged = false;
io.configure(function () {
io.set('close timeout', 0);
});
io.sockets.on('connection', function (socket) {
socket.emit('</script> woot');
socket.on('disconnect', function () {
io.server.close();
done();
});
});
cl.handshake(function (sid) {
cl.data('/socket.io/{protocol}/htmlfile/' + sid, { parse: false }, function (msg, i) {
switch (i) {
case 2:
msg.should.not.include('</script');
cl.end();
}
});
});
},
'test that unescaping works': function(done){
var port = ++ports
, cl = client(port)
, io = create(cl)
, messaged = false;
io.configure(function () {
io.set('close timeout', 0);
});
io.sockets.on('connection', function (socket) {
socket.emit('woot </script> <//script>', '</script><script>');
socket.on('disconnect', function () {
io.server.close();
done();
});
});
cl.handshake(function (sid) {
cl.data('/socket.io/{protocol}/htmlfile/' + sid, function (msgs, i) {
switch (i) {
case 1:
msgs.should.have.length(1);
msgs[0].type.should.eql('connect');
msgs[0].endpoint.should.eql('');
break;
case 2:
msgs.should.have.length(1);
msgs[0].should.eql({
type: 'event'
, name: 'woot </script> <//script>'
, endpoint: ''
, args: ['</script><script>']
});
cl.end();
}
});
});
}
};