faye 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of faye might be problematic. Click here for more details.
- data/History.txt +15 -3
- data/README.rdoc +2 -6
- data/lib/faye-browser-min.js +1 -1
- data/lib/faye.rb +25 -36
- data/lib/faye/adapters/rack_adapter.rb +43 -22
- data/lib/faye/engines/connection.rb +7 -10
- data/lib/faye/engines/memory.rb +28 -28
- data/lib/faye/engines/proxy.rb +109 -0
- data/lib/faye/mixins/logging.rb +1 -8
- data/lib/faye/mixins/timeouts.rb +1 -1
- data/lib/faye/protocol/channel.rb +3 -3
- data/lib/faye/protocol/client.rb +50 -45
- data/lib/faye/protocol/extensible.rb +11 -18
- data/lib/faye/protocol/server.rb +53 -38
- data/lib/faye/transport/http.rb +49 -27
- data/lib/faye/transport/transport.rb +3 -1
- data/lib/faye/transport/web_socket.rb +6 -10
- data/lib/faye/util/namespace.rb +2 -2
- data/spec/browser.html +3 -1
- data/spec/encoding_helper.rb +7 -0
- data/spec/javascript/client_spec.js +0 -5
- data/spec/javascript/engine/memory_spec.js +7 -0
- data/spec/javascript/engine_spec.js +22 -57
- data/spec/javascript/server/handshake_spec.js +10 -6
- data/spec/javascript/server/integration_spec.js +11 -10
- data/spec/javascript/server/publish_spec.js +85 -0
- data/spec/javascript/server_spec.js +5 -51
- data/spec/node.js +6 -6
- data/spec/ruby/client_spec.rb +1 -1
- data/spec/ruby/engine/memory_spec.rb +7 -0
- data/spec/ruby/{engine_spec.rb → engine_examples.rb} +28 -34
- data/spec/ruby/rack_adapter_spec.rb +1 -1
- data/spec/ruby/server/handshake_spec.rb +10 -6
- data/spec/ruby/server/publish_spec.rb +81 -0
- data/spec/ruby/server_spec.rb +6 -44
- data/spec/spec_helper.rb +5 -18
- data/spec/testswarm +1 -5
- metadata +105 -180
- data/lib/faye/engines/base.rb +0 -66
- data/lib/faye/engines/redis.rb +0 -225
- data/lib/faye/thin_extensions.rb +0 -75
- data/lib/faye/util/web_socket.rb +0 -89
- data/lib/faye/util/web_socket/api.rb +0 -103
- data/lib/faye/util/web_socket/client.rb +0 -82
- data/lib/faye/util/web_socket/draft75_parser.rb +0 -53
- data/lib/faye/util/web_socket/draft76_parser.rb +0 -53
- data/lib/faye/util/web_socket/protocol8_parser.rb +0 -324
- data/spec/javascript/web_socket/client_spec.js +0 -121
- data/spec/javascript/web_socket/draft75parser_spec.js +0 -39
- data/spec/javascript/web_socket/protocol8parser_spec.js +0 -153
- data/spec/redis.conf +0 -42
- data/spec/ruby/web_socket/client_spec.rb +0 -126
- data/spec/ruby/web_socket/draft75_parser_spec.rb +0 -41
- data/spec/ruby/web_socket/protocol8_parser_spec.rb +0 -145
data/History.txt
CHANGED
@@ -1,6 +1,18 @@
|
|
1
|
-
=== 0.
|
2
|
-
|
3
|
-
|
1
|
+
=== 0.8.0 / 2012-02-26
|
2
|
+
TestSwarm build: http://swarm.jcoglan.com/job/123/
|
3
|
+
|
4
|
+
* Extract the Redis engine into a separate library, faye-redis
|
5
|
+
* Stabilize and document the Engine API so others can write backends
|
6
|
+
* Extract WebSocket and EventSource tools into a separate library, faye-websocket
|
7
|
+
* Improve use of WebSocket so messages are immediately pushed rather than polling
|
8
|
+
* Introduce new EventSource-based transport, for proxies that block WebSocket
|
9
|
+
* Support the Rainbows and Goliath web servers for Ruby, same as faye-websocket
|
10
|
+
* Improve detection of network errors and switch to fixed-interval for reconnecting
|
11
|
+
* Add setHeader() method to Client (e.g. for connecting to Salesforce API)
|
12
|
+
* Add timeout() method to Faye.Deferrable to match EventMachine::Deferrable
|
13
|
+
* Fix some bugs in client-side message handlers created with subscribe()
|
14
|
+
* Improve speed and memory consumption of copyObject()
|
15
|
+
* Switch from JSON to Yajl for JSON parsing in Ruby
|
4
16
|
|
5
17
|
|
6
18
|
=== 0.7.1 / 2011-12-22
|
data/README.rdoc
CHANGED
@@ -34,14 +34,10 @@ should get you up and running:
|
|
34
34
|
bundle install
|
35
35
|
npm install
|
36
36
|
|
37
|
-
# Build
|
38
|
-
cd vendor/js.class
|
39
|
-
jake
|
40
|
-
cd ../../
|
37
|
+
# Build Faye
|
41
38
|
jake
|
42
39
|
|
43
40
|
# Run tests
|
44
|
-
redis-server spec/redis.conf
|
45
41
|
bundle exec rspec -c spec/
|
46
42
|
node spec/node.js
|
47
43
|
|
@@ -75,7 +71,7 @@ Missing protocol features:
|
|
75
71
|
|
76
72
|
(The MIT License)
|
77
73
|
|
78
|
-
Copyright (c) 2009-
|
74
|
+
Copyright (c) 2009-2012 James Coglan and contributors
|
79
75
|
|
80
76
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
81
77
|
this software and associated documentation files (the 'Software'), to deal in
|
data/lib/faye-browser-min.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
if(!this.Faye)Faye={};Faye.extend=function(a,b,c){if(!b)return a;for(var d in b){if(!b.hasOwnProperty(d))continue;if(a.hasOwnProperty(d)&&c===false)continue;if(a[d]!==b[d])a[d]=b[d]}return a};Faye.extend(Faye,{VERSION:'0.7.2',BAYEUX_VERSION:'1.0',ID_LENGTH:128,JSONP_CALLBACK:'jsonpcallback',CONNECTION_TYPES:['long-polling','cross-origin-long-polling','callback-polling','websocket','in-process'],MANDATORY_CONNECTION_TYPES:['long-polling','callback-polling','in-process'],ENV:(function(){return this})(),random:function(a){a=a||this.ID_LENGTH;if(a>32){var b=Math.ceil(a/32),c='';while(b--)c+=this.random(32);return c}var d=Math.pow(2,a)-1,f=d.toString(36).length,c=Math.floor(Math.random()*d).toString(36);while(c.length<f)c='0'+c;return c},copyObject:function(a){return JSON.parse(Faye.toJSON(a))},commonElement:function(a,b){for(var c=0,d=a.length;c<d;c++){if(this.indexOf(b,a[c])!==-1)return a[c]}return null},indexOf:function(a,b){for(var c=0,d=a.length;c<d;c++){if(a[c]===b)return c}return-1},each:function(a,b,c){if(a instanceof Array){for(var d=0,f=a.length;d<f;d++){if(a[d]!==undefined)b.call(c||null,a[d],d)}}else{for(var g in a){if(a.hasOwnProperty(g))b.call(c||null,g,a[g])}}},map:function(a,b,c){if(a.map)return a.map(b,c);var d=[];this.each(a,function(){d.push(b.apply(c||null,arguments))});return d},filter:function(a,b,c){var d=[];this.each(a,function(){if(b.apply(c,arguments))d.push(arguments[0])});return d},size:function(a){var b=0;this.each(a,function(){b+=1});return b},enumEqual:function(c,d){if(d instanceof Array){if(!(c instanceof Array))return false;var f=c.length;if(f!==d.length)return false;while(f--){if(c[f]!==d[f])return false}return true}else{if(!(c instanceof Object))return false;if(this.size(d)!==this.size(c))return false;var g=true;this.each(c,function(a,b){g=g&&(d[a]===b)});return g}},asyncEach:function(a,b,c,d){var f=a.length,g=-1,h=0,i=false;var j=function(){h-=1;g+=1;if(g===f)return c&&c.call(d);b(a[g],m)};var k=function(){if(i)return;i=true;while(h>0)j();i=false};var m=function(){h+=1;k()};m()},toJSON:function(a){if(this.stringify)return this.stringify(a,function(key,value){return(this[key]instanceof Array)?this[key]:value});return JSON.stringify(a)},timestamp:function(){var b=new Date(),c=b.getFullYear(),d=b.getMonth()+1,f=b.getDate(),g=b.getHours(),h=b.getMinutes(),i=b.getSeconds();var j=function(a){return a<10?'0'+a:String(a)};return j(c)+'-'+j(d)+'-'+j(f)+' '+j(g)+':'+j(h)+':'+j(i)}});Faye.Class=function(a,b){if(typeof a!=='function'){b=a;a=Object}var c=function(){if(!this.initialize)return this;return this.initialize.apply(this,arguments)||this};var d=function(){};d.prototype=a.prototype;c.prototype=new d();Faye.extend(c.prototype,b);return c};Faye.Namespace=Faye.Class({initialize:function(){this._d={}},exists:function(a){return this._d.hasOwnProperty(a)},generate:function(){var a=Faye.random();while(this._d.hasOwnProperty(a))a=Faye.random();return this._d[a]=a},release:function(a){delete this._d[a]}});Faye.Error=Faye.Class({initialize:function(a,b,c){this.code=a;this.params=Array.prototype.slice.call(b);this.message=c},toString:function(){return this.code+':'+this.params.join(',')+':'+this.message}});Faye.Error.parse=function(a){a=a||'';if(!Faye.Grammar.ERROR.test(a))return new this(null,[],a);var b=a.split(':'),c=parseInt(b[0]),d=b[1].split(','),a=b[2];return new this(c,d,a)};Faye.Error.versionMismatch=function(){return new this(300,arguments,"Version mismatch").toString()};Faye.Error.conntypeMismatch=function(){return new this(301,arguments,"Connection types not supported").toString()};Faye.Error.extMismatch=function(){return new this(302,arguments,"Extension mismatch").toString()};Faye.Error.badRequest=function(){return new this(400,arguments,"Bad request").toString()};Faye.Error.clientUnknown=function(){return new this(401,arguments,"Unknown client").toString()};Faye.Error.parameterMissing=function(){return new this(402,arguments,"Missing required parameter").toString()};Faye.Error.channelForbidden=function(){return new this(403,arguments,"Forbidden channel").toString()};Faye.Error.channelUnknown=function(){return new this(404,arguments,"Unknown channel").toString()};Faye.Error.channelInvalid=function(){return new this(405,arguments,"Invalid channel").toString()};Faye.Error.extUnknown=function(){return new this(406,arguments,"Unknown extension").toString()};Faye.Error.publishFailed=function(){return new this(407,arguments,"Failed to publish").toString()};Faye.Error.serverError=function(){return new this(500,arguments,"Internal server error").toString()};Faye.Deferrable={callback:function(a,b){if(!a)return;if(this._v==='succeeded')return a.apply(b,this._k);this._l=this._l||[];this._l.push([a,b])},errback:function(a,b){if(!a)return;if(this._v==='failed')return a.apply(b,this._k);this._m=this._m||[];this._m.push([a,b])},setDeferredStatus:function(){var a=Array.prototype.slice.call(arguments),b=a.shift(),c;this._v=b;this._k=a;if(b==='succeeded')c=this._l;else if(b==='failed')c=this._m;if(!c)return;var d;while(d=c.shift())d[0].apply(d[1],this._k)}};Faye.Publisher={countListeners:function(a){if(!this._3||!this._3[a])return 0;return this._3[a].length},bind:function(a,b,c){this._3=this._3||{};var d=this._3[a]=this._3[a]||[];d.push([b,c])},unbind:function(a,b,c){if(!this._3||!this._3[a])return;if(!b){delete this._3[a];return}var d=this._3[a],f=d.length;while(f--){if(b!==d[f][0])continue;if(c&&d[f][1]!==c)continue;d.splice(f,1)}},trigger:function(){var b=Array.prototype.slice.call(arguments),c=b.shift();if(!this._3||!this._3[c])return;Faye.each(this._3[c],function(a){a[0].apply(a[1],b)})}};Faye.Timeouts={addTimeout:function(a,b,c,d){this._4=this._4||{};if(this._4.hasOwnProperty(a))return;var f=this;this._4[a]=Faye.ENV.setTimeout(function(){delete f._4[a];c.call(d)},1000*b)},removeTimeout:function(a){this._4=this._4||{};var b=this._4[a];if(!b)return;clearTimeout(b);delete this._4[a]}};Faye.Logging={LOG_LEVELS:{error:3,warn:2,info:1,debug:0},logLevel:'error',log:function(a,b){if(!Faye.logger)return;var c=Faye.Logging.LOG_LEVELS;if(c[Faye.Logging.logLevel]>c[b])return;var a=Array.prototype.slice.apply(a),d=' ['+b.toUpperCase()+'] [Faye',f=this.className,g=a.shift().replace(/\?/g,function(){try{return Faye.toJSON(a.shift())}catch(e){return'[Object]'}});for(var h in Faye){if(f)continue;if(typeof Faye[h]!=='function')continue;if(this instanceof Faye[h])f=h}if(f)d+='.'+f;d+='] ';Faye.logger(Faye.timestamp()+d+g)}};Faye.each(Faye.Logging.LOG_LEVELS,function(a,b){Faye.Logging[a]=function(){this.log(arguments,a)}});Faye.Grammar={LOWALPHA:/^[a-z]$/,UPALPHA:/^[A-Z]$/,ALPHA:/^([a-z]|[A-Z])$/,DIGIT:/^[0-9]$/,ALPHANUM:/^(([a-z]|[A-Z])|[0-9])$/,MARK:/^(\-|\_|\!|\~|\(|\)|\$|\@)$/,STRING:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,TOKEN:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,INTEGER:/^([0-9])+$/,CHANNEL_SEGMENT:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,CHANNEL_SEGMENTS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,CHANNEL_NAME:/^\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,WILD_CARD:/^\*{1,2}$/,CHANNEL_PATTERN:/^(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*\/\*{1,2}$/,VERSION_ELEMENT:/^(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*$/,VERSION:/^([0-9])+(\.(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*)*$/,CLIENT_ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ERROR_MESSAGE:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,ERROR_ARGS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*$/,ERROR_CODE:/^[0-9][0-9][0-9]$/,ERROR:/^([0-9][0-9][0-9]:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*|[0-9][0-9][0-9]::(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)$/};Faye.Extensible={addExtension:function(a){this._5=this._5||[];this._5.push(a);if(a.added)a.added(this)},removeExtension:function(a){if(!this._5)return;var b=this._5.length;while(b--){if(this._5[b]!==a)continue;this._5.splice(b,1);if(a.removed)a.removed(this)}},pipeThroughExtensions:function(c,d,f,g){this.debug('Passing through ? extensions: ?',c,d);if(!this._5)return f.call(g,d);var h=this._5.slice();var i=function(a){if(!a)return f.call(g,a);var b=h.shift();if(!b)return f.call(g,a);if(b[c])b[c](a,i);else i(a)};i(d)}};Faye.extend(Faye.Extensible,Faye.Logging);Faye.Channel=Faye.Class({initialize:function(a){this.id=this.name=a},push:function(a){this.trigger('message',a)},isUnused:function(){return this.countListeners('message')===0}});Faye.extend(Faye.Channel.prototype,Faye.Publisher);Faye.extend(Faye.Channel,{HANDSHAKE:'/meta/handshake',CONNECT:'/meta/connect',SUBSCRIBE:'/meta/subscribe',UNSUBSCRIBE:'/meta/unsubscribe',DISCONNECT:'/meta/disconnect',META:'meta',SERVICE:'service',expand:function(a){var b=this.parse(a),c=['/**',a];var d=b.slice();d[d.length-1]='*';c.push(this.unparse(d));for(var f=1,g=b.length;f<g;f++){d=b.slice(0,f);d.push('**');c.push(this.unparse(d))}return c},isValid:function(a){return Faye.Grammar.CHANNEL_NAME.test(a)||Faye.Grammar.CHANNEL_PATTERN.test(a)},parse:function(a){if(!this.isValid(a))return null;return a.split('/').slice(1)},unparse:function(a){return'/'+a.join('/')},isMeta:function(a){var b=this.parse(a);return b?(b[0]===this.META):null},isService:function(a){var b=this.parse(a);return b?(b[0]===this.SERVICE):null},isSubscribable:function(a){if(!this.isValid(a))return null;return!this.isMeta(a)&&!this.isService(a)},Set:Faye.Class({initialize:function(){this._2={}},getKeys:function(){var c=[];Faye.each(this._2,function(a,b){c.push(a)});return c},remove:function(a){delete this._2[a]},hasSubscription:function(a){return this._2.hasOwnProperty(a)},subscribe:function(c,d,f){if(!d)return;Faye.each(c,function(a){var b=this._2[a]=this._2[a]||new Faye.Channel(a);b.bind('message',d,f)},this)},unsubscribe:function(a,b,c){var d=this._2[a];if(!d)return false;d.unbind('message',b,c);if(d.isUnused()){this.remove(a);return true}else{return false}},distributeMessage:function(c){var d=Faye.Channel.expand(c.channel);Faye.each(d,function(a){var b=this._2[a];if(b)b.trigger('message',c.data)},this)}})});Faye.Publication=Faye.Class(Faye.Deferrable);Faye.Subscription=Faye.Class({initialize:function(a,b,c,d){this._8=a;this._2=b;this._n=c;this._o=d;this._w=false},cancel:function(){if(this._w)return;this._8.unsubscribe(this._2,this._n,this._o);this._w=true},unsubscribe:function(){this.cancel()}});Faye.extend(Faye.Subscription.prototype,Faye.Deferrable);Faye.Client=Faye.Class({UNCONNECTED:1,CONNECTING:2,CONNECTED:3,DISCONNECTED:4,HANDSHAKE:'handshake',RETRY:'retry',NONE:'none',CONNECTION_TIMEOUT:60.0,DEFAULT_ENDPOINT:'/bayeux',INTERVAL:0.0,initialize:function(a,b){this.info('New client created for ?',a);this.endpoint=a||this.DEFAULT_ENDPOINT;this._x=b||{};this._p=[];this._y(Faye.MANDATORY_CONNECTION_TYPES);this._1=this.UNCONNECTED;this._2=new Faye.Channel.Set();this._e=0;this._q={};this._6={reconnect:this.RETRY,interval:1000*(this._x.interval||this.INTERVAL),timeout:1000*(this._x.timeout||this.CONNECTION_TIMEOUT)};if(Faye.Event)Faye.Event.on(Faye.ENV,'beforeunload',function(){if(Faye.indexOf(this._p,'autodisconnect')<0)this.disconnect()},this)},disable:function(a){this._p.push(a)},getClientId:function(){return this._0},getState:function(){switch(this._1){case this.UNCONNECTED:return'UNCONNECTED';case this.CONNECTING:return'CONNECTING';case this.CONNECTED:return'CONNECTED';case this.DISCONNECTED:return'DISCONNECTED'}},handshake:function(f,g){if(this._6.reconnect===this.NONE)return;if(this._1!==this.UNCONNECTED)return;this._1=this.CONNECTING;var h=this;this.info('Initiating handshake with ?',this.endpoint);this._9({channel:Faye.Channel.HANDSHAKE,version:Faye.BAYEUX_VERSION,supportedConnectionTypes:[this._f.connectionType]},function(c){if(c.successful){this._1=this.CONNECTED;this._0=c.clientId;var d=c.supportedConnectionTypes;Faye.each(this._p,function(a){var b=Faye.indexOf(d,a);if(b>=0)d.splice(b,1)},this);this._y(d);this.info('Handshake successful: ?',this._0);this.subscribe(this._2.getKeys(),true);if(f)f.call(g)}else{this.info('Handshake unsuccessful');Faye.ENV.setTimeout(function(){h.handshake(f,g)},this._6.interval);this._1=this.UNCONNECTED}},this)},connect:function(a,b){if(this._6.reconnect===this.NONE)return;if(this._1===this.DISCONNECTED)return;if(this._1===this.UNCONNECTED)return this.handshake(function(){this.connect(a,b)},this);this.callback(a,b);if(this._1!==this.CONNECTED)return;this.info('Calling deferred actions for ?',this._0);this.setDeferredStatus('succeeded');this.setDeferredStatus('deferred');if(this._r)return;this._r=true;this.info('Initiating connection for ?',this._0);this._9({channel:Faye.Channel.CONNECT,clientId:this._0,connectionType:this._f.connectionType},this._z,this)},disconnect:function(){if(this._1!==this.CONNECTED)return;this._1=this.DISCONNECTED;this.info('Disconnecting ?',this._0);this._9({channel:Faye.Channel.DISCONNECT,clientId:this._0},function(a){if(a.successful)this._f.close()},this);this.info('Clearing channel listeners for ?',this._0);this._2=new Faye.Channel.Set()},subscribe:function(c,d,f){if(c instanceof Array)return Faye.each(c,function(channel){this.subscribe(channel,d,f)},this);var g=new Faye.Subscription(this,c,d,f);var h=(d===true);if(!h&&this._2.hasSubscription(c)){this._2.subscribe([c],d,f);g.setDeferredStatus('succeeded');return g}this.connect(function(){this.info('Client ? attempting to subscribe to ?',this._0,c);this._9({channel:Faye.Channel.SUBSCRIBE,clientId:this._0,subscription:c},function(a){if(!a.successful)return g.setDeferredStatus('failed',Faye.Error.parse(a.error));var b=[].concat(a.subscription);this.info('Subscription acknowledged for ? to ?',this._0,b);if(!h)this._2.subscribe(b,d,f);g.setDeferredStatus('succeeded')},this)},this);return g},unsubscribe:function(c,d,f){if(c instanceof Array)return Faye.each(c,function(channel){this.unsubscribe(channel,d,f)},this);var g=this._2.unsubscribe(c,d,f);if(!g)return;this.connect(function(){this.info('Client ? attempting to unsubscribe from ?',this._0,c);this._9({channel:Faye.Channel.UNSUBSCRIBE,clientId:this._0,subscription:c},function(a){if(!a.successful)return;var b=[].concat(a.subscription);this.info('Unsubscription acknowledged for ? from ?',this._0,b)},this)},this)},publish:function(b,c){if(!Faye.Grammar.CHANNEL_NAME.test(b))throw new Error("Cannot publish: '"+b+"' is not a valid channel name");var d=new Faye.Publication();this.connect(function(){this.info('Client ? queueing published message to ?: ?',this._0,b,c);this._9({channel:b,data:c,clientId:this._0},function(a){if(a.successful)d.setDeferredStatus('succeeded');else d.setDeferredStatus('failed',Faye.Error.parse(a.error))},this)},this);return d},receiveMessage:function(c){this.pipeThroughExtensions('incoming',c,function(a){if(!a)return;if(a.advice)this._D(a.advice);var b=this._q[a.id];if(b){delete this._q[a.id];b[0].call(b[1],a)}this._E(a)},this)},_y:function(b){Faye.Transport.get(this,b,function(a){this._f=a;a.bind('down',function(){if(this._c!==undefined&&!this._c)return;this._c=false;this.trigger('transport:down')},this);a.bind('up',function(){if(this._c!==undefined&&this._c)return;this._c=true;this.trigger('transport:up')},this)},this)},_9:function(b,c,d){b.id=this._F();if(c)this._q[b.id]=[c,d];this.pipeThroughExtensions('outgoing',b,function(a){if(!a)return;this._f.send(a,this._6.timeout/1000)},this)},_F:function(){this._e+=1;if(this._e>=Math.pow(2,32))this._e=0;return this._e.toString(36)},_D:function(a){Faye.extend(this._6,a);if(this._6.reconnect===this.HANDSHAKE&&this._1!==this.DISCONNECTED){this._1=this.UNCONNECTED;this._0=null;this._z()}},_E:function(a){if(!a.channel||!a.data)return;this.info('Client ? calling listeners for ? with ?',this._0,a.channel,a.data);this._2.distributeMessage(a)},_G:function(){if(!this._r)return;this._r=null;this.info('Closed connection for ?',this._0)},_z:function(){this._G();var a=this;Faye.ENV.setTimeout(function(){a.connect()},this._6.interval)}});Faye.extend(Faye.Client.prototype,Faye.Deferrable);Faye.extend(Faye.Client.prototype,Faye.Publisher);Faye.extend(Faye.Client.prototype,Faye.Logging);Faye.extend(Faye.Client.prototype,Faye.Extensible);Faye.Transport=Faye.extend(Faye.Class({MAX_DELAY:0.0,batching:true,initialize:function(a,b){this.debug('Created new ? transport for ?',this.connectionType,b);this._8=a;this._a=b;this._g=[]},close:function(){},send:function(a,b){this.debug('Client ? sending message to ?: ?',this._8._0,this._a,a);if(!this.batching)return this.request([a],b);this._g.push(a);this._b=b;if(a.channel===Faye.Channel.HANDSHAKE)return this.flush();if(a.channel===Faye.Channel.CONNECT)this._s=a;this.addTimeout('publish',this.MAX_DELAY,this.flush,this)},flush:function(){this.removeTimeout('publish');if(this._g.length>1&&this._s)this._s.advice={timeout:0};this.request(this._g,this._b);this._s=null;this._g=[]},receive:function(a){this.debug('Client ? received from ?: ?',this._8._0,this._a,a);Faye.each(a,this._8.receiveMessage,this._8)},retry:function(a,b){var c=this,d=false;return function(){if(d)return;d=true;Faye.ENV.setTimeout(function(){c.request(a,2*b)},1000*b)}}}),{get:function(g,h,i,j){var k=g.endpoint;if(h===undefined)h=this.supportedConnectionTypes();Faye.asyncEach(this._t,function(b,c){var d=b[0],f=b[1];if(Faye.indexOf(h,d)<0)return c();f.isUsable(k,function(a){if(a)i.call(j,new f(g,k));else c()})},function(){throw new Error('Could not find a usable connection type for '+k);})},register:function(a,b){this._t.push([a,b]);b.prototype.connectionType=a},_t:[],supportedConnectionTypes:function(){return Faye.map(this._t,function(a){return a[0]})}});Faye.extend(Faye.Transport.prototype,Faye.Logging);Faye.extend(Faye.Transport.prototype,Faye.Publisher);Faye.extend(Faye.Transport.prototype,Faye.Timeouts);Faye.Event={_h:[],on:function(a,b,c,d){var f=function(){c.call(d)};if(a.addEventListener)a.addEventListener(b,f,false);else a.attachEvent('on'+b,f);this._h.push({_i:a,_u:b,_n:c,_o:d,_A:f})},detach:function(a,b,c,d){var f=this._h.length,g;while(f--){g=this._h[f];if((a&&a!==g._i)||(b&&b!==g._u)||(c&&c!==g._n)||(d&&d!==g._o))continue;if(g._i.removeEventListener)g._i.removeEventListener(g._u,g._A,false);else g._i.detachEvent('on'+g._u,g._A);this._h.splice(f,1);g=null}}};Faye.Event.on(Faye.ENV,'unload',Faye.Event.detach,Faye.Event);Faye.URI=Faye.extend(Faye.Class({queryString:function(){var c=[],d;Faye.each(this.params,function(a,b){c.push(encodeURIComponent(a)+'='+encodeURIComponent(b))});return c.join('&')},isLocal:function(){var a=Faye.URI.parse(Faye.ENV.location.href);var b=(a.hostname!==this.hostname)||(a.port!==this.port)||(a.protocol!==this.protocol);return!b},toURL:function(){var a=this.queryString();return this.protocol+this.hostname+':'+this.port+this.pathname+(a?'?'+a:'')}}),{parse:function(d,f){if(typeof d!=='string')return d;var g=new this();var h=function(b,c){d=d.replace(c,function(a){if(a)g[b]=a;return''})};h('protocol',/^https?\:\/+/);h('hostname',/^[^\/\:]+/);h('port',/^:[0-9]+/);Faye.extend(g,{protocol:Faye.ENV.location.protocol+'//',hostname:Faye.ENV.location.hostname,port:Faye.ENV.location.port},false);if(!g.port)g.port=(g.protocol==='https://')?'443':'80';g.port=g.port.replace(/\D/g,'');var i=d.split('?'),j=i.shift(),k=i.join('?'),m=k?k.split('&'):[],n=m.length,l={};while(n--){i=m[n].split('=');l[decodeURIComponent(i[0]||'')]=decodeURIComponent(i[1]||'')}if(typeof f==='object')Faye.extend(l,f);g.pathname=j;g.params=l;return g}});if(!this.JSON){JSON={}}(function(){function k(a){return a<10?'0'+a:a}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(a){return this.getUTCFullYear()+'-'+k(this.getUTCMonth()+1)+'-'+k(this.getUTCDate())+'T'+k(this.getUTCHours())+':'+k(this.getUTCMinutes())+':'+k(this.getUTCSeconds())+'Z'};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()}}var m=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,n=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,l,p,s={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},o;function r(c){n.lastIndex=0;return n.test(c)?'"'+c.replace(n,function(a){var b=s[a];return typeof b==='string'?b:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+c+'"'}function q(a,b){var c,d,f,g,h=l,i,j=b[a];if(j&&typeof j==='object'&&typeof j.toJSON==='function'){j=j.toJSON(a)}if(typeof o==='function'){j=o.call(b,a,j)}switch(typeof j){case'string':return r(j);case'number':return isFinite(j)?String(j):'null';case'boolean':case'null':return String(j);case'object':if(!j){return'null'}l+=p;i=[];if(Object.prototype.toString.apply(j)==='[object Array]'){g=j.length;for(c=0;c<g;c+=1){i[c]=q(c,j)||'null'}f=i.length===0?'[]':l?'[\n'+l+i.join(',\n'+l)+'\n'+h+']':'['+i.join(',')+']';l=h;return f}if(o&&typeof o==='object'){g=o.length;for(c=0;c<g;c+=1){d=o[c];if(typeof d==='string'){f=q(d,j);if(f){i.push(r(d)+(l?': ':':')+f)}}}}else{for(d in j){if(Object.hasOwnProperty.call(j,d)){f=q(d,j);if(f){i.push(r(d)+(l?': ':':')+f)}}}}f=i.length===0?'{}':l?'{\n'+l+i.join(',\n'+l)+'\n'+h+'}':'{'+i.join(',')+'}';l=h;return f}}Faye.stringify=function(a,b,c){var d;l='';p='';if(typeof c==='number'){for(d=0;d<c;d+=1){p+=' '}}else if(typeof c==='string'){p=c}o=b;if(b&&typeof b!=='function'&&(typeof b!=='object'||typeof b.length!=='number')){throw new Error('JSON.stringify');}return q('',{'':a})};if(typeof JSON.stringify!=='function'){JSON.stringify=Faye.stringify}if(typeof JSON.parse!=='function'){JSON.parse=function(g,h){var i;function j(a,b){var c,d,f=a[b];if(f&&typeof f==='object'){for(c in f){if(Object.hasOwnProperty.call(f,c)){d=j(f,c);if(d!==undefined){f[c]=d}else{delete f[c]}}}}return h.call(a,b,f)}m.lastIndex=0;if(m.test(g)){g=g.replace(m,function(a){return'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(g.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){i=eval('('+g+')');return typeof h==='function'?j({'':i},''):i}throw new SyntaxError('JSON.parse');}}}());Faye.Transport.WebSocket=Faye.extend(Faye.Class(Faye.Transport,{UNCONNECTED:1,CONNECTING:2,CONNECTED:3,batching:false,request:function(b,c){this._b=c||this._b;this._j=this._j||{};Faye.each(b,function(a){this._j[a.id]=a},this);this.withSocket(function(a){a.send(Faye.toJSON(b))})},withSocket:function(a,b){this.callback(a,b);this.connect()},close:function(){if(this._B)return;this._B=true;if(this._7)this._7.close()},connect:function(){if(this._B)return;this._1=this._1||this.UNCONNECTED;if(this._1!==this.UNCONNECTED)return;this._1=this.CONNECTING;var d=Faye.Transport.WebSocket.getClass();this._7=new d(Faye.Transport.WebSocket.getSocketUrl(this._a));var f=this;this._7.onopen=function(){f._1=f.CONNECTED;f.setDeferredStatus('succeeded',f._7);f.trigger('up')};this._7.onmessage=function(b){var c=[].concat(JSON.parse(b.data));Faye.each(c,function(a){delete f._j[a.id]});f.receive(c)};this._7.onclose=function(){var a=(f._1===f.CONNECTED);f.setDeferredStatus('deferred');f._1=f.UNCONNECTED;delete f._7;if(a)return f.resend();Faye.ENV.setTimeout(function(){f.connect()},1000*f._b);f._b=f._b*2;f.trigger('down')}},resend:function(){var c=Faye.map(this._j,function(a,b){return b});this.request(c)}}),{WEBSOCKET_TIMEOUT:1000,getSocketUrl:function(a){if(Faye.URI)a=Faye.URI.parse(a).toURL();return a.replace(/^http(s?):/ig,'ws$1:')},getClass:function(){if(Faye.WebSocket)return Faye.WebSocket.Client;return Faye.ENV.WebSocket||Faye.ENV.MozWebSocket},isUsable:function(a,b,c){var d=this.getClass();if(!d)return b.call(c,false);var f=false,g=false,h=this.getSocketUrl(a),i=new d(h);i.onopen=function(){f=true;i.close();b.call(c,true);g=true;i=null};var j=function(){if(!g&&!f)b.call(c,false);g=true};i.onclose=i.onerror=j;Faye.ENV.setTimeout(j,this.WEBSOCKET_TIMEOUT)}});Faye.extend(Faye.Transport.WebSocket.prototype,Faye.Deferrable);Faye.Transport.register('websocket',Faye.Transport.WebSocket);Faye.Transport.XHR=Faye.extend(Faye.Class(Faye.Transport,{request:function(b,c){var d=this.retry(b,c),f=Faye.URI.parse(this._a).pathname,g=this,h=Faye.ENV.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();h.open('POST',f,true);h.setRequestHeader('Content-Type','application/json');h.setRequestHeader('X-Requested-With','XMLHttpRequest');h.onreadystatechange=function(){if(h.readyState!==4)return;var a=h.status;try{if((a>=200&&a<300)||a===304||a===1223){g.receive(JSON.parse(h.responseText));g.trigger('up')}else{d();g.trigger('down')}}catch(e){d()}finally{Faye.Event.detach(Faye.ENV,'beforeunload',i);h.onreadystatechange=function(){};h=null}};var i=function(){h.abort()};Faye.Event.on(Faye.ENV,'beforeunload',i);h.send(Faye.toJSON(b))}}),{isUsable:function(a,b,c){b.call(c,Faye.URI.parse(a).isLocal())}});Faye.Transport.register('long-polling',Faye.Transport.XHR);Faye.Transport.CORS=Faye.extend(Faye.Class(Faye.Transport,{request:function(a,b){var c=Faye.ENV.XDomainRequest?XDomainRequest:XMLHttpRequest,d=new c(),f=this.retry(a,b),g=this;d.open('POST',this._a,true);var h=function(){if(!d)return false;d.onload=d.onerror=d.ontimeout=d.onprogress=null;d=null;Faye.ENV.clearTimeout(j);return true};d.onload=function(){try{g.receive(JSON.parse(d.responseText));g.trigger('up')}catch(e){f()}finally{h()}};var i=function(){h();f();g.trigger('down')};var j=Faye.ENV.setTimeout(i,1.5*1000*b);d.onerror=i;d.ontimeout=i;d.onprogress=function(){};d.send('message='+encodeURIComponent(Faye.toJSON(a)))}}),{isUsable:function(a,b,c){if(Faye.URI.parse(a).isLocal())return b.call(c,false);if(Faye.ENV.XDomainRequest)return b.call(c,true);if(Faye.ENV.XMLHttpRequest){var d=new Faye.ENV.XMLHttpRequest();return b.call(c,d.withCredentials!==undefined)}return b.call(c,false)}});Faye.Transport.register('cross-origin-long-polling',Faye.Transport.CORS);Faye.Transport.JSONP=Faye.extend(Faye.Class(Faye.Transport,{request:function(b,c){var d={message:Faye.toJSON(b)},f=document.getElementsByTagName('head')[0],g=document.createElement('script'),h=Faye.Transport.JSONP.getCallbackName(),i=Faye.URI.parse(this._a,d),j=this.retry(b,c),k=this;Faye.ENV[h]=function(a){n();k.receive(a);k.trigger('up')};var m=Faye.ENV.setTimeout(function(){n();j();k.trigger('down')},1.5*1000*c);var n=function(){if(!Faye.ENV[h])return false;Faye.ENV[h]=undefined;try{delete Faye.ENV[h]}catch(e){}Faye.ENV.clearTimeout(m);g.parentNode.removeChild(g);return true};i.params.jsonp=h;g.type='text/javascript';g.src=i.toURL();f.appendChild(g)}}),{_C:0,getCallbackName:function(){this._C+=1;return'__jsonp'+this._C+'__'},isUsable:function(a,b,c){b.call(c,true)}});Faye.Transport.register('callback-polling',Faye.Transport.JSONP);
|
1
|
+
var Faye=(typeof Faye==='object')?Faye:{};if(typeof window!=='undefined')window.Faye=Faye;Faye.extend=function(a,b,c){if(!b)return a;for(var d in b){if(!b.hasOwnProperty(d))continue;if(a.hasOwnProperty(d)&&c===false)continue;if(a[d]!==b[d])a[d]=b[d]}return a};Faye.extend(Faye,{VERSION:'0.8.0',BAYEUX_VERSION:'1.0',ID_LENGTH:128,JSONP_CALLBACK:'jsonpcallback',CONNECTION_TYPES:['long-polling','cross-origin-long-polling','callback-polling','websocket','eventsource','in-process'],MANDATORY_CONNECTION_TYPES:['long-polling','callback-polling','in-process'],ENV:(function(){return this})(),random:function(a){a=a||this.ID_LENGTH;if(a>32){var b=Math.ceil(a/32),c='';while(b--)c+=this.random(32);return c}var d=Math.pow(2,a)-1,f=d.toString(36).length,c=Math.floor(Math.random()*d).toString(36);while(c.length<f)c='0'+c;return c},copyObject:function(a){var b,c,d;if(a instanceof Array){b=[];c=a.length;while(c--)b[c]=Faye.copyObject(a[c]);return b}else if(typeof a==='object'){b={};for(d in a)b[d]=Faye.copyObject(a[d]);return b}else{return a}},commonElement:function(a,b){for(var c=0,d=a.length;c<d;c++){if(this.indexOf(b,a[c])!==-1)return a[c]}return null},indexOf:function(a,b){if(a.indexOf)return a.indexOf(b);for(var c=0,d=a.length;c<d;c++){if(a[c]===b)return c}return-1},map:function(a,b,c){if(a.map)return a.map(b,c);var d=[];if(a instanceof Array){for(var f=0,g=a.length;f<g;f++){d.push(b.call(c||null,a[f],f))}}else{for(var j in a){if(!a.hasOwnProperty(j))continue;d.push(b.call(c||null,j,a[j]))}}return d},filter:function(a,b,c){var d=[];for(var f=0,g=a.length;f<g;f++){if(b.call(c||null,a[f],f))d.push(a[f])}return d},asyncEach:function(a,b,c,d){var f=a.length,g=-1,j=0,i=false;var h=function(){j-=1;g+=1;if(g===f)return c&&c.call(d);b(a[g],m)};var k=function(){if(i)return;i=true;while(j>0)h();i=false};var m=function(){j+=1;k()};m()},toJSON:function(a){if(this.stringify)return this.stringify(a,function(key,value){return(this[key]instanceof Array)?this[key]:value});return JSON.stringify(a)},timestamp:function(){var b=new Date(),c=b.getFullYear(),d=b.getMonth()+1,f=b.getDate(),g=b.getHours(),j=b.getMinutes(),i=b.getSeconds();var h=function(a){return a<10?'0'+a:String(a)};return h(c)+'-'+h(d)+'-'+h(f)+' '+h(g)+':'+h(j)+':'+h(i)}});Faye.Class=function(a,b){if(typeof a!=='function'){b=a;a=Object}var c=function(){if(!this.initialize)return this;return this.initialize.apply(this,arguments)||this};var d=function(){};d.prototype=a.prototype;c.prototype=new d();Faye.extend(c.prototype,b);return c};Faye.Namespace=Faye.Class({initialize:function(){this._d={}},exists:function(a){return this._d.hasOwnProperty(a)},generate:function(){var a=Faye.random();while(this._d.hasOwnProperty(a))a=Faye.random();return this._d[a]=a},release:function(a){delete this._d[a]}});Faye.Error=Faye.Class({initialize:function(a,b,c){this.code=a;this.params=Array.prototype.slice.call(b);this.message=c},toString:function(){return this.code+':'+this.params.join(',')+':'+this.message}});Faye.Error.parse=function(a){a=a||'';if(!Faye.Grammar.ERROR.test(a))return new this(null,[],a);var b=a.split(':'),c=parseInt(b[0]),d=b[1].split(','),a=b[2];return new this(c,d,a)};Faye.Error.versionMismatch=function(){return new this(300,arguments,"Version mismatch").toString()};Faye.Error.conntypeMismatch=function(){return new this(301,arguments,"Connection types not supported").toString()};Faye.Error.extMismatch=function(){return new this(302,arguments,"Extension mismatch").toString()};Faye.Error.badRequest=function(){return new this(400,arguments,"Bad request").toString()};Faye.Error.clientUnknown=function(){return new this(401,arguments,"Unknown client").toString()};Faye.Error.parameterMissing=function(){return new this(402,arguments,"Missing required parameter").toString()};Faye.Error.channelForbidden=function(){return new this(403,arguments,"Forbidden channel").toString()};Faye.Error.channelUnknown=function(){return new this(404,arguments,"Unknown channel").toString()};Faye.Error.channelInvalid=function(){return new this(405,arguments,"Invalid channel").toString()};Faye.Error.extUnknown=function(){return new this(406,arguments,"Unknown extension").toString()};Faye.Error.publishFailed=function(){return new this(407,arguments,"Failed to publish").toString()};Faye.Error.serverError=function(){return new this(500,arguments,"Internal server error").toString()};Faye.Deferrable={callback:function(a,b){if(!a)return;if(this._v==='succeeded')return a.apply(b,this._j);this._k=this._k||[];this._k.push([a,b])},timeout:function(a,b){var c=this;var d=Faye.ENV.setTimeout(function(){c.setDeferredStatus('failed',b)},a*1000);this._w=d},errback:function(a,b){if(!a)return;if(this._v==='failed')return a.apply(b,this._j);this._l=this._l||[];this._l.push([a,b])},setDeferredStatus:function(){if(this._w)Faye.ENV.clearTimeout(this._w);var a=Array.prototype.slice.call(arguments),b=a.shift(),c;this._v=b;this._j=a;if(b==='succeeded')c=this._k;else if(b==='failed')c=this._l;if(!c)return;var d;while(d=c.shift())d[0].apply(d[1],this._j)}};Faye.Publisher={countListeners:function(a){if(!this._3||!this._3[a])return 0;return this._3[a].length},bind:function(a,b,c){this._3=this._3||{};var d=this._3[a]=this._3[a]||[];d.push([b,c])},unbind:function(a,b,c){if(!this._3||!this._3[a])return;if(!b){delete this._3[a];return}var d=this._3[a],f=d.length;while(f--){if(b!==d[f][0])continue;if(c&&d[f][1]!==c)continue;d.splice(f,1)}},trigger:function(){var a=Array.prototype.slice.call(arguments),b=a.shift();if(!this._3||!this._3[b])return;var c=this._3[b],d;for(var f=0,g=c.length;f<g;f++){d=c[f];d[0].apply(d[1],a)}}};Faye.Timeouts={addTimeout:function(a,b,c,d){this._5=this._5||{};if(this._5.hasOwnProperty(a))return;var f=this;this._5[a]=Faye.ENV.setTimeout(function(){delete f._5[a];c.call(d)},1000*b)},removeTimeout:function(a){this._5=this._5||{};var b=this._5[a];if(!b)return;clearTimeout(b);delete this._5[a]}};Faye.Logging={LOG_LEVELS:{error:3,warn:2,info:1,debug:0},logLevel:'error',log:function(a,b){if(!Faye.logger)return;var c=Faye.Logging.LOG_LEVELS;if(c[Faye.Logging.logLevel]>c[b])return;var a=Array.prototype.slice.apply(a),d=' ['+b.toUpperCase()+'] [Faye',f=this.className,g=a.shift().replace(/\?/g,function(){try{return Faye.toJSON(a.shift())}catch(e){return'[Object]'}});for(var j in Faye){if(f)continue;if(typeof Faye[j]!=='function')continue;if(this instanceof Faye[j])f=j}if(f)d+='.'+f;d+='] ';Faye.logger(Faye.timestamp()+d+g)}};(function(){for(var c in Faye.Logging.LOG_LEVELS)(function(a,b){Faye.Logging[a]=function(){this.log(arguments,a)}})(c,Faye.Logging.LOG_LEVELS[c])})();Faye.Grammar={LOWALPHA:/^[a-z]$/,UPALPHA:/^[A-Z]$/,ALPHA:/^([a-z]|[A-Z])$/,DIGIT:/^[0-9]$/,ALPHANUM:/^(([a-z]|[A-Z])|[0-9])$/,MARK:/^(\-|\_|\!|\~|\(|\)|\$|\@)$/,STRING:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,TOKEN:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,INTEGER:/^([0-9])+$/,CHANNEL_SEGMENT:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,CHANNEL_SEGMENTS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,CHANNEL_NAME:/^\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,WILD_CARD:/^\*{1,2}$/,CHANNEL_PATTERN:/^(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*\/\*{1,2}$/,VERSION_ELEMENT:/^(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*$/,VERSION:/^([0-9])+(\.(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*)*$/,CLIENT_ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ERROR_MESSAGE:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,ERROR_ARGS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*$/,ERROR_CODE:/^[0-9][0-9][0-9]$/,ERROR:/^([0-9][0-9][0-9]:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*|[0-9][0-9][0-9]::(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)$/};Faye.Extensible={addExtension:function(a){this._6=this._6||[];this._6.push(a);if(a.added)a.added(this)},removeExtension:function(a){if(!this._6)return;var b=this._6.length;while(b--){if(this._6[b]!==a)continue;this._6.splice(b,1);if(a.removed)a.removed(this)}},pipeThroughExtensions:function(c,d,f,g){this.debug('Passing through ? extensions: ?',c,d);if(!this._6)return f.call(g,d);var j=this._6.slice();var i=function(a){if(!a)return f.call(g,a);var b=j.shift();if(!b)return f.call(g,a);if(b[c])b[c](a,i);else i(a)};i(d)}};Faye.extend(Faye.Extensible,Faye.Logging);Faye.Channel=Faye.Class({initialize:function(a){this.id=this.name=a},push:function(a){this.trigger('message',a)},isUnused:function(){return this.countListeners('message')===0}});Faye.extend(Faye.Channel.prototype,Faye.Publisher);Faye.extend(Faye.Channel,{HANDSHAKE:'/meta/handshake',CONNECT:'/meta/connect',SUBSCRIBE:'/meta/subscribe',UNSUBSCRIBE:'/meta/unsubscribe',DISCONNECT:'/meta/disconnect',META:'meta',SERVICE:'service',expand:function(a){var b=this.parse(a),c=['/**',a];var d=b.slice();d[d.length-1]='*';c.push(this.unparse(d));for(var f=1,g=b.length;f<g;f++){d=b.slice(0,f);d.push('**');c.push(this.unparse(d))}return c},isValid:function(a){return Faye.Grammar.CHANNEL_NAME.test(a)||Faye.Grammar.CHANNEL_PATTERN.test(a)},parse:function(a){if(!this.isValid(a))return null;return a.split('/').slice(1)},unparse:function(a){return'/'+a.join('/')},isMeta:function(a){var b=this.parse(a);return b?(b[0]===this.META):null},isService:function(a){var b=this.parse(a);return b?(b[0]===this.SERVICE):null},isSubscribable:function(a){if(!this.isValid(a))return null;return!this.isMeta(a)&&!this.isService(a)},Set:Faye.Class({initialize:function(){this._2={}},getKeys:function(){var a=[];for(var b in this._2)a.push(b);return a},remove:function(a){delete this._2[a]},hasSubscription:function(a){return this._2.hasOwnProperty(a)},subscribe:function(a,b,c){if(!b)return;var d;for(var f=0,g=a.length;f<g;f++){d=a[f];var j=this._2[d]=this._2[d]||new Faye.Channel(d);j.bind('message',b,c)}},unsubscribe:function(a,b,c){var d=this._2[a];if(!d)return false;d.unbind('message',b,c);if(d.isUnused()){this.remove(a);return true}else{return false}},distributeMessage:function(a){var b=Faye.Channel.expand(a.channel);for(var c=0,d=b.length;c<d;c++){var f=this._2[b[c]];if(f)f.trigger('message',a.data)}}})});Faye.Publication=Faye.Class(Faye.Deferrable);Faye.Subscription=Faye.Class({initialize:function(a,b,c,d){this._7=a;this._2=b;this._m=c;this._n=d;this._x=false},cancel:function(){if(this._x)return;this._7.unsubscribe(this._2,this._m,this._n);this._x=true},unsubscribe:function(){this.cancel()}});Faye.extend(Faye.Subscription.prototype,Faye.Deferrable);Faye.Client=Faye.Class({UNCONNECTED:1,CONNECTING:2,CONNECTED:3,DISCONNECTED:4,HANDSHAKE:'handshake',RETRY:'retry',NONE:'none',CONNECTION_TIMEOUT:60.0,DEFAULT_RETRY:5.0,DEFAULT_ENDPOINT:'/bayeux',INTERVAL:0.0,initialize:function(a,b){this.info('New client created for ?',a);this.endpoint=a||this.DEFAULT_ENDPOINT;this._E=Faye.CookieJar&&new Faye.CookieJar();this._y={};this._o=b||{};this._p=[];this.retry=this._o.retry||this.DEFAULT_RETRY;this._z(Faye.MANDATORY_CONNECTION_TYPES);this._1=this.UNCONNECTED;this._2=new Faye.Channel.Set();this._e=0;this._q={};this._8={reconnect:this.RETRY,interval:1000*(this._o.interval||this.INTERVAL),timeout:1000*(this._o.timeout||this.CONNECTION_TIMEOUT)};if(Faye.Event)Faye.Event.on(Faye.ENV,'beforeunload',function(){if(Faye.indexOf(this._p,'autodisconnect')<0)this.disconnect()},this)},disable:function(a){this._p.push(a)},setHeader:function(a,b){this._y[a]=b},getClientId:function(){return this._0},getState:function(){switch(this._1){case this.UNCONNECTED:return'UNCONNECTED';case this.CONNECTING:return'CONNECTING';case this.CONNECTED:return'CONNECTED';case this.DISCONNECTED:return'DISCONNECTED'}},handshake:function(d,f){if(this._8.reconnect===this.NONE)return;if(this._1!==this.UNCONNECTED)return;this._1=this.CONNECTING;var g=this;this.info('Initiating handshake with ?',this.endpoint);this._9({channel:Faye.Channel.HANDSHAKE,version:Faye.BAYEUX_VERSION,supportedConnectionTypes:[this._a.connectionType]},function(b){if(b.successful){this._1=this.CONNECTED;this._0=b.clientId;var c=Faye.filter(b.supportedConnectionTypes,function(a){return Faye.indexOf(this._p,a)<0},this);this._z(c);this.info('Handshake successful: ?',this._0);this.subscribe(this._2.getKeys(),true);if(d)d.call(f)}else{this.info('Handshake unsuccessful');Faye.ENV.setTimeout(function(){g.handshake(d,f)},this._8.interval);this._1=this.UNCONNECTED}},this)},connect:function(a,b){if(this._8.reconnect===this.NONE)return;if(this._1===this.DISCONNECTED)return;if(this._1===this.UNCONNECTED)return this.handshake(function(){this.connect(a,b)},this);this.callback(a,b);if(this._1!==this.CONNECTED)return;this.info('Calling deferred actions for ?',this._0);this.setDeferredStatus('succeeded');this.setDeferredStatus('deferred');if(this._r)return;this._r=true;this.info('Initiating connection for ?',this._0);this._9({channel:Faye.Channel.CONNECT,clientId:this._0,connectionType:this._a.connectionType},this._A,this)},disconnect:function(){if(this._1!==this.CONNECTED)return;this._1=this.DISCONNECTED;this.info('Disconnecting ?',this._0);this._9({channel:Faye.Channel.DISCONNECT,clientId:this._0},function(a){if(a.successful)this._a.close()},this);this.info('Clearing channel listeners for ?',this._0);this._2=new Faye.Channel.Set()},subscribe:function(c,d,f){if(c instanceof Array){for(var g=0,j=c.length;g<j;g++){this.subscribe(c[g],d,f)}return}var i=new Faye.Subscription(this,c,d,f),h=(d===true),k=this._2.hasSubscription(c);if(!h){this._2.subscribe([c],d,f);if(k){i.setDeferredStatus('succeeded');return i}}this.connect(function(){this.info('Client ? attempting to subscribe to ?',this._0,c);this._9({channel:Faye.Channel.SUBSCRIBE,clientId:this._0,subscription:c},function(a){if(!a.successful){i.setDeferredStatus('failed',Faye.Error.parse(a.error));return this._2.unsubscribe(c,d,f)}var b=[].concat(a.subscription);this.info('Subscription acknowledged for ? to ?',this._0,b);i.setDeferredStatus('succeeded')},this)},this);return i},unsubscribe:function(c,d,f){if(c instanceof Array){for(var g=0,j=c.length;g<j;g++){this.unsubscribe(c[g],d,f)}return}var i=this._2.unsubscribe(c,d,f);if(!i)return;this.connect(function(){this.info('Client ? attempting to unsubscribe from ?',this._0,c);this._9({channel:Faye.Channel.UNSUBSCRIBE,clientId:this._0,subscription:c},function(a){if(!a.successful)return;var b=[].concat(a.subscription);this.info('Unsubscription acknowledged for ? from ?',this._0,b)},this)},this)},publish:function(b,c){var d=new Faye.Publication();this.connect(function(){this.info('Client ? queueing published message to ?: ?',this._0,b,c);this._9({channel:b,data:c,clientId:this._0},function(a){if(a.successful)d.setDeferredStatus('succeeded');else d.setDeferredStatus('failed',Faye.Error.parse(a.error))},this)},this);return d},receiveMessage:function(c){this.pipeThroughExtensions('incoming',c,function(a){if(!a)return;if(a.advice)this._F(a.advice);var b=this._q[a.id];if(b){delete this._q[a.id];b[0].call(b[1],a)}this._G(a)},this)},_z:function(b){Faye.Transport.get(this,b,function(a){this._a=a;this._a.cookies=this._E;this._a.headers=this._y;a.bind('down',function(){if(this._c!==undefined&&!this._c)return;this._c=false;this.trigger('transport:down')},this);a.bind('up',function(){if(this._c!==undefined&&this._c)return;this._c=true;this.trigger('transport:up')},this)},this)},_9:function(b,c,d){b.id=this._H();if(c)this._q[b.id]=[c,d];this.pipeThroughExtensions('outgoing',b,function(a){if(!a)return;this._a.send(a,this._8.timeout/1000)},this)},_H:function(){this._e+=1;if(this._e>=Math.pow(2,32))this._e=0;return this._e.toString(36)},_F:function(a){Faye.extend(this._8,a);if(this._8.reconnect===this.HANDSHAKE&&this._1!==this.DISCONNECTED){this._1=this.UNCONNECTED;this._0=null;this._A()}},_G:function(a){if(!a.channel||a.data===undefined)return;this.info('Client ? calling listeners for ? with ?',this._0,a.channel,a.data);this._2.distributeMessage(a)},_I:function(){if(!this._r)return;this._r=null;this.info('Closed connection for ?',this._0)},_A:function(){this._I();var a=this;Faye.ENV.setTimeout(function(){a.connect()},this._8.interval)}});Faye.extend(Faye.Client.prototype,Faye.Deferrable);Faye.extend(Faye.Client.prototype,Faye.Publisher);Faye.extend(Faye.Client.prototype,Faye.Logging);Faye.extend(Faye.Client.prototype,Faye.Extensible);Faye.Transport=Faye.extend(Faye.Class({MAX_DELAY:0.0,batching:true,initialize:function(a,b){this.debug('Created new ? transport for ?',this.connectionType,b);this._7=a;this._b=b;this._f=[]},close:function(){},send:function(a,b){this.debug('Client ? sending message to ?: ?',this._7._0,this._b,a);if(!this.batching)return this.request([a],b);this._f.push(a);this._J=b;if(a.channel===Faye.Channel.HANDSHAKE)return this.flush();if(a.channel===Faye.Channel.CONNECT)this._s=a;this.addTimeout('publish',this.MAX_DELAY,this.flush,this)},flush:function(){this.removeTimeout('publish');if(this._f.length>1&&this._s)this._s.advice={timeout:0};this.request(this._f,this._J);this._s=null;this._f=[]},receive:function(a){this.debug('Client ? received from ?: ?',this._7._0,this._b,a);for(var b=0,c=a.length;b<c;b++){this._7.receiveMessage(a[b])}},retry:function(a,b){var c=false,d=this._7.retry*1000,f=this;return function(){if(c)return;c=true;Faye.ENV.setTimeout(function(){f.request(a,b)},d)}}}),{get:function(g,j,i,h){var k=g.endpoint;if(j===undefined)j=this.supportedConnectionTypes();Faye.asyncEach(this._t,function(b,c){var d=b[0],f=b[1];if(Faye.indexOf(j,d)<0)return c();f.isUsable(k,function(a){if(a)i.call(h,new f(g,k));else c()})},function(){throw new Error('Could not find a usable connection type for '+k);})},register:function(a,b){this._t.push([a,b]);b.prototype.connectionType=a},_t:[],supportedConnectionTypes:function(){return Faye.map(this._t,function(a){return a[0]})}});Faye.extend(Faye.Transport.prototype,Faye.Logging);Faye.extend(Faye.Transport.prototype,Faye.Publisher);Faye.extend(Faye.Transport.prototype,Faye.Timeouts);Faye.Event={_g:[],on:function(a,b,c,d){var f=function(){c.call(d)};if(a.addEventListener)a.addEventListener(b,f,false);else a.attachEvent('on'+b,f);this._g.push({_h:a,_u:b,_m:c,_n:d,_B:f})},detach:function(a,b,c,d){var f=this._g.length,g;while(f--){g=this._g[f];if((a&&a!==g._h)||(b&&b!==g._u)||(c&&c!==g._m)||(d&&d!==g._n))continue;if(g._h.removeEventListener)g._h.removeEventListener(g._u,g._B,false);else g._h.detachEvent('on'+g._u,g._B);this._g.splice(f,1);g=null}}};Faye.Event.on(Faye.ENV,'unload',Faye.Event.detach,Faye.Event);Faye.URI=Faye.extend(Faye.Class({queryString:function(){var a=[];for(var b in this.params){if(!this.params.hasOwnProperty(b))continue;a.push(encodeURIComponent(b)+'='+encodeURIComponent(this.params[b]))}return a.join('&')},isLocal:function(){var a=Faye.URI.parse(Faye.ENV.location.href);var b=(a.hostname!==this.hostname)||(a.port!==this.port)||(a.protocol!==this.protocol);return!b},toURL:function(){var a=this.queryString();return this.protocol+this.hostname+':'+this.port+this.pathname+(a?'?'+a:'')}}),{parse:function(d,f){if(typeof d!=='string')return d;var g=new this();var j=function(b,c){d=d.replace(c,function(a){if(a)g[b]=a;return''})};j('protocol',/^https?\:\/+/);j('hostname',/^[^\/\:]+/);j('port',/^:[0-9]+/);Faye.extend(g,{protocol:Faye.ENV.location.protocol+'//',hostname:Faye.ENV.location.hostname,port:Faye.ENV.location.port},false);if(!g.port)g.port=(g.protocol==='https://')?'443':'80';g.port=g.port.replace(/\D/g,'');var i=d.split('?'),h=i.shift(),k=i.join('?'),m=k?k.split('&'):[],n=m.length,l={};while(n--){i=m[n].split('=');l[decodeURIComponent(i[0]||'')]=decodeURIComponent(i[1]||'')}if(typeof f==='object')Faye.extend(l,f);g.pathname=h;g.params=l;return g}});if(!this.JSON){JSON={}}(function(){function k(a){return a<10?'0'+a:a}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(a){return this.getUTCFullYear()+'-'+k(this.getUTCMonth()+1)+'-'+k(this.getUTCDate())+'T'+k(this.getUTCHours())+':'+k(this.getUTCMinutes())+':'+k(this.getUTCSeconds())+'Z'};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()}}var m=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,n=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,l,p,s={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},o;function r(c){n.lastIndex=0;return n.test(c)?'"'+c.replace(n,function(a){var b=s[a];return typeof b==='string'?b:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+c+'"'}function q(a,b){var c,d,f,g,j=l,i,h=b[a];if(h&&typeof h==='object'&&typeof h.toJSON==='function'){h=h.toJSON(a)}if(typeof o==='function'){h=o.call(b,a,h)}switch(typeof h){case'string':return r(h);case'number':return isFinite(h)?String(h):'null';case'boolean':case'null':return String(h);case'object':if(!h){return'null'}l+=p;i=[];if(Object.prototype.toString.apply(h)==='[object Array]'){g=h.length;for(c=0;c<g;c+=1){i[c]=q(c,h)||'null'}f=i.length===0?'[]':l?'[\n'+l+i.join(',\n'+l)+'\n'+j+']':'['+i.join(',')+']';l=j;return f}if(o&&typeof o==='object'){g=o.length;for(c=0;c<g;c+=1){d=o[c];if(typeof d==='string'){f=q(d,h);if(f){i.push(r(d)+(l?': ':':')+f)}}}}else{for(d in h){if(Object.hasOwnProperty.call(h,d)){f=q(d,h);if(f){i.push(r(d)+(l?': ':':')+f)}}}}f=i.length===0?'{}':l?'{\n'+l+i.join(',\n'+l)+'\n'+j+'}':'{'+i.join(',')+'}';l=j;return f}}Faye.stringify=function(a,b,c){var d;l='';p='';if(typeof c==='number'){for(d=0;d<c;d+=1){p+=' '}}else if(typeof c==='string'){p=c}o=b;if(b&&typeof b!=='function'&&(typeof b!=='object'||typeof b.length!=='number')){throw new Error('JSON.stringify');}return q('',{'':a})};if(typeof JSON.stringify!=='function'){JSON.stringify=Faye.stringify}if(typeof JSON.parse!=='function'){JSON.parse=function(g,j){var i;function h(a,b){var c,d,f=a[b];if(f&&typeof f==='object'){for(c in f){if(Object.hasOwnProperty.call(f,c)){d=h(f,c);if(d!==undefined){f[c]=d}else{delete f[c]}}}}return j.call(a,b,f)}m.lastIndex=0;if(m.test(g)){g=g.replace(m,function(a){return'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(g.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){i=eval('('+g+')');return typeof j==='function'?h({'':i},''):i}throw new SyntaxError('JSON.parse');}}}());Faye.Transport.WebSocket=Faye.extend(Faye.Class(Faye.Transport,{UNCONNECTED:1,CONNECTING:2,CONNECTED:3,batching:false,request:function(b,c){this._i=this._i||{};for(var d=0,f=b.length;d<f;d++){this._i[b[d].id]=b[d]}this.withSocket(function(a){a.send(Faye.toJSON(b))})},withSocket:function(a,b){this.callback(a,b);this.connect()},close:function(){if(this._C)return;this._C=true;if(this._4)this._4.close()},connect:function(){if(this._C)return;this._1=this._1||this.UNCONNECTED;if(this._1!==this.UNCONNECTED)return;this._1=this.CONNECTING;var f=Faye.Transport.WebSocket.getClass();this._4=new f(Faye.Transport.WebSocket.getSocketUrl(this._b));var g=this;this._4.onopen=function(){g._1=g.CONNECTED;g.setDeferredStatus('succeeded',g._4);g.trigger('up')};this._4.onmessage=function(a){var b=[].concat(JSON.parse(a.data));for(var c=0,d=b.length;c<d;c++){delete g._i[b[c].id]}g.receive(b)};this._4.onclose=function(){var a=(g._1===g.CONNECTED);g.setDeferredStatus('deferred');g._1=g.UNCONNECTED;delete g._4;if(a)return g.resend();var b=g._7.retry*1000;Faye.ENV.setTimeout(function(){g.connect()},b);g.trigger('down')}},resend:function(){var c=Faye.map(this._i,function(a,b){return b});this.request(c)}}),{WEBSOCKET_TIMEOUT:1000,getSocketUrl:function(a){if(Faye.URI)a=Faye.URI.parse(a).toURL();return a.replace(/^http(s?):/ig,'ws$1:')},getClass:function(){return(Faye.WebSocket&&Faye.WebSocket.Client)||Faye.ENV.WebSocket||Faye.ENV.MozWebSocket},isUsable:function(a,b,c){var d=this.getClass();if(!d)return b.call(c,false);var f=false,g=false,j=this.getSocketUrl(a),i=new d(j);i.onopen=function(){f=true;i.close();b.call(c,true);g=true;i=null};var h=function(){if(!g&&!f)b.call(c,false);g=true};i.onclose=i.onerror=h;Faye.ENV.setTimeout(h,this.WEBSOCKET_TIMEOUT)}});Faye.extend(Faye.Transport.WebSocket.prototype,Faye.Deferrable);Faye.Transport.register('websocket',Faye.Transport.WebSocket);Faye.Transport.EventSource=Faye.extend(Faye.Class(Faye.Transport,{initialize:function(b,c){Faye.Transport.prototype.initialize.call(this,b,c);this._K=new Faye.Transport.XHR(b,c);var d=new EventSource(c+'/'+b.getClientId()),f=this;d.onmessage=function(a){f.receive(JSON.parse(a.data))};this._4=d},request:function(a,b){this._K.request(a,b)},close:function(){this._4.close()}}),{isUsable:function(b,c,d){Faye.Transport.XHR.isUsable(b,function(a){c.call(d,a&&Faye.ENV.EventSource)})}});Faye.Transport.register('eventsource',Faye.Transport.EventSource);Faye.Transport.XHR=Faye.extend(Faye.Class(Faye.Transport,{request:function(d,f){var g=this.retry(d,f),j=Faye.URI.parse(this._b).pathname,i=this,h=Faye.ENV.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();h.open('POST',j,true);h.setRequestHeader('Content-Type','application/json');h.setRequestHeader('X-Requested-With','XMLHttpRequest');var k=this.headers;for(var m in k){if(!k.hasOwnProperty(m))continue;h.setRequestHeader(m,k[m])}var n=function(){h.abort()};Faye.Event.on(Faye.ENV,'beforeunload',n);var l=function(){Faye.Event.detach(Faye.ENV,'beforeunload',n);h.onreadystatechange=function(){};h=null};h.onreadystatechange=function(){if(h.readyState!==4)return;var a=null,b=h.status,c=((b>=200&&b<300)||b===304||b===1223);if(!c){l();g();return i.trigger('down')}try{a=JSON.parse(h.responseText)}catch(e){}l();if(a){i.receive(a);i.trigger('up')}else{g();i.trigger('down')}};h.send(Faye.toJSON(d))}}),{isUsable:function(a,b,c){b.call(c,Faye.URI.parse(a).isLocal())}});Faye.Transport.register('long-polling',Faye.Transport.XHR);Faye.Transport.CORS=Faye.extend(Faye.Class(Faye.Transport,{request:function(b,c){var d=Faye.ENV.XDomainRequest?XDomainRequest:XMLHttpRequest,f=new d(),g=this.retry(b,c),j=this;f.open('POST',this._b,true);var i=function(){if(!f)return false;f.onload=f.onerror=f.ontimeout=f.onprogress=null;f=null;Faye.ENV.clearTimeout(k);return true};f.onload=function(){var a=null;try{a=JSON.parse(f.responseText)}catch(e){}i();if(a){j.receive(a);j.trigger('up')}else{g();j.trigger('down')}};var h=function(){i();g();j.trigger('down')};var k=Faye.ENV.setTimeout(h,1.5*1000*c);f.onerror=h;f.ontimeout=h;f.onprogress=function(){};f.send('message='+encodeURIComponent(Faye.toJSON(b)))}}),{isUsable:function(a,b,c){if(Faye.URI.parse(a).isLocal())return b.call(c,false);if(Faye.ENV.XDomainRequest)return b.call(c,true);if(Faye.ENV.XMLHttpRequest){var d=new Faye.ENV.XMLHttpRequest();return b.call(c,d.withCredentials!==undefined)}return b.call(c,false)}});Faye.Transport.register('cross-origin-long-polling',Faye.Transport.CORS);Faye.Transport.JSONP=Faye.extend(Faye.Class(Faye.Transport,{request:function(b,c){var d={message:Faye.toJSON(b)},f=document.getElementsByTagName('head')[0],g=document.createElement('script'),j=Faye.Transport.JSONP.getCallbackName(),i=Faye.URI.parse(this._b,d),h=this.retry(b,c),k=this;Faye.ENV[j]=function(a){n();k.receive(a);k.trigger('up')};var m=Faye.ENV.setTimeout(function(){n();h();k.trigger('down')},1.5*1000*c);var n=function(){if(!Faye.ENV[j])return false;Faye.ENV[j]=undefined;try{delete Faye.ENV[j]}catch(e){}Faye.ENV.clearTimeout(m);g.parentNode.removeChild(g);return true};i.params.jsonp=j;g.type='text/javascript';g.src=i.toURL();f.appendChild(g)}}),{_D:0,getCallbackName:function(){this._D+=1;return'__jsonp'+this._D+'__'},isUsable:function(a,b,c){b.call(c,true)}});Faye.Transport.register('callback-polling',Faye.Transport.JSONP);
|
data/lib/faye.rb
CHANGED
@@ -1,25 +1,21 @@
|
|
1
|
-
require 'base64'
|
2
1
|
require 'cgi'
|
3
2
|
require 'cookiejar'
|
4
|
-
require 'digest/md5'
|
5
3
|
require 'digest/sha1'
|
6
4
|
require 'em-http'
|
7
5
|
require 'em-http/version'
|
8
6
|
require 'eventmachine'
|
7
|
+
require 'faye/websocket'
|
9
8
|
require 'forwardable'
|
10
|
-
require 'json'
|
11
|
-
require 'net/http'
|
12
9
|
require 'rack'
|
13
10
|
require 'set'
|
14
|
-
require 'thin'
|
15
11
|
require 'time'
|
16
12
|
require 'uri'
|
13
|
+
require 'yajl'
|
17
14
|
|
18
15
|
module Faye
|
19
|
-
VERSION = '0.
|
16
|
+
VERSION = '0.8.0'
|
20
17
|
|
21
18
|
ROOT = File.expand_path(File.dirname(__FILE__))
|
22
|
-
require File.join(ROOT, 'faye', 'thin_extensions')
|
23
19
|
|
24
20
|
autoload :Publisher, File.join(ROOT, 'faye', 'mixins', 'publisher')
|
25
21
|
autoload :Timeouts, File.join(ROOT, 'faye', 'mixins', 'timeouts')
|
@@ -27,7 +23,7 @@ module Faye
|
|
27
23
|
|
28
24
|
autoload :Namespace, File.join(ROOT, 'faye', 'util', 'namespace')
|
29
25
|
|
30
|
-
autoload :Engine, File.join(ROOT, 'faye', 'engines', '
|
26
|
+
autoload :Engine, File.join(ROOT, 'faye', 'engines', 'proxy')
|
31
27
|
|
32
28
|
autoload :Grammar, File.join(ROOT, 'faye', 'protocol', 'grammar')
|
33
29
|
autoload :Extensible, File.join(ROOT, 'faye', 'protocol', 'extensible')
|
@@ -41,38 +37,44 @@ module Faye
|
|
41
37
|
autoload :Error, File.join(ROOT, 'faye', 'error')
|
42
38
|
|
43
39
|
autoload :RackAdapter, File.join(ROOT, 'faye', 'adapters', 'rack_adapter')
|
44
|
-
autoload :WebSocket, File.join(ROOT, 'faye', 'util', 'web_socket')
|
45
40
|
|
46
41
|
BAYEUX_VERSION = '1.0'
|
47
|
-
ID_LENGTH = 128
|
48
42
|
JSONP_CALLBACK = 'jsonpcallback'
|
49
|
-
CONNECTION_TYPES = %w[long-polling cross-origin-long-polling callback-polling websocket in-process]
|
43
|
+
CONNECTION_TYPES = %w[long-polling cross-origin-long-polling callback-polling websocket eventsource in-process]
|
50
44
|
|
51
45
|
MANDATORY_CONNECTION_TYPES = %w[long-polling callback-polling in-process]
|
52
46
|
|
53
|
-
|
54
|
-
|
47
|
+
class << self
|
48
|
+
attr_accessor :logger
|
49
|
+
end
|
50
|
+
self.logger = method(:puts)
|
55
51
|
|
56
52
|
def self.ensure_reactor_running!
|
57
|
-
|
58
|
-
while not EM.reactor_running?; end
|
53
|
+
Engine.ensure_reactor_running!
|
59
54
|
end
|
60
55
|
|
61
|
-
def self.random(
|
62
|
-
|
63
|
-
max_size = limit.to_s(36).size
|
64
|
-
string = rand(limit).to_s(36)
|
65
|
-
string = '0' + string while string.size < max_size
|
66
|
-
string
|
56
|
+
def self.random(*args)
|
57
|
+
Engine.random(*args)
|
67
58
|
end
|
68
59
|
|
69
60
|
def self.copy_object(object)
|
70
|
-
|
61
|
+
case object
|
62
|
+
when Hash
|
63
|
+
clone = {}
|
64
|
+
object.each { |k,v| clone[k] = copy_object(v) }
|
65
|
+
clone
|
66
|
+
when Array
|
67
|
+
clone = []
|
68
|
+
object.each { |v| clone << copy_object(v) }
|
69
|
+
clone
|
70
|
+
else
|
71
|
+
object
|
72
|
+
end
|
71
73
|
end
|
72
74
|
|
73
75
|
def self.to_json(value)
|
74
76
|
case value
|
75
|
-
when Hash, Array then
|
77
|
+
when Hash, Array then Yajl::Encoder.encode(value)
|
76
78
|
when String, NilClass then value.inspect
|
77
79
|
else value.to_s
|
78
80
|
end
|
@@ -110,18 +112,5 @@ module Faye
|
|
110
112
|
end
|
111
113
|
resume.call
|
112
114
|
end
|
113
|
-
|
114
|
-
def self.encode(string, validate_encoding = false)
|
115
|
-
if Array === string
|
116
|
-
return nil if validate_encoding and !valid_utf8?(string)
|
117
|
-
string = string.pack('C*')
|
118
|
-
end
|
119
|
-
return string unless string.respond_to?(:force_encoding)
|
120
|
-
string.force_encoding('UTF-8')
|
121
|
-
end
|
122
|
-
|
123
|
-
def self.valid_utf8?(byte_array)
|
124
|
-
UTF8_MATCH =~ byte_array.pack('C*') ? true : false
|
125
|
-
end
|
126
115
|
end
|
127
116
|
|
@@ -6,7 +6,6 @@ module Faye
|
|
6
6
|
extend Forwardable
|
7
7
|
def_delegators "@server.engine", :bind, :unbind
|
8
8
|
|
9
|
-
# Only supported under Thin
|
10
9
|
ASYNC_RESPONSE = [-1, {}, []].freeze
|
11
10
|
|
12
11
|
DEFAULT_ENDPOINT = '/bayeux'
|
@@ -41,6 +40,7 @@ module Faye
|
|
41
40
|
end
|
42
41
|
|
43
42
|
def listen(port, ssl_options = nil)
|
43
|
+
Faye::WebSocket.load_adapter('thin')
|
44
44
|
handler = Rack::Handler.get('thin')
|
45
45
|
handler.run(self, :Port => port) do |s|
|
46
46
|
if ssl_options
|
@@ -72,7 +72,8 @@ module Faye
|
|
72
72
|
|
73
73
|
return serve_client_script(env) if request.path_info =~ /\.js$/
|
74
74
|
return handle_options(request) if env['REQUEST_METHOD'] == 'OPTIONS'
|
75
|
-
return
|
75
|
+
return handle_websocket(env) if Faye::WebSocket.websocket?(env)
|
76
|
+
return handle_eventsource(env) if Faye::EventSource.eventsource?(env)
|
76
77
|
|
77
78
|
handle_request(request)
|
78
79
|
end
|
@@ -101,47 +102,72 @@ module Faye
|
|
101
102
|
|
102
103
|
def handle_request(request)
|
103
104
|
json_msg = message_from_request(request)
|
104
|
-
message =
|
105
|
+
message = Yajl::Parser.parse(json_msg)
|
105
106
|
jsonp = request.params['jsonp'] || JSONP_CALLBACK
|
106
107
|
headers = request.get? ? TYPE_SCRIPT.dup : TYPE_JSON.dup
|
107
108
|
origin = request.env['HTTP_ORIGIN']
|
108
109
|
callback = request.env['async.callback']
|
109
|
-
body = DeferredBody.new
|
110
110
|
|
111
111
|
debug 'Received ?: ?', request.env['REQUEST_METHOD'], json_msg
|
112
112
|
@server.flush_connection(message) if request.get?
|
113
113
|
|
114
114
|
headers['Access-Control-Allow-Origin'] = origin if origin
|
115
115
|
headers['Cache-Control'] = 'no-cache, no-store' if request.get?
|
116
|
-
callback.call [200, headers, body]
|
117
116
|
|
118
117
|
@server.process(message, false) do |replies|
|
119
|
-
response =
|
118
|
+
response = Faye.to_json(replies)
|
120
119
|
response = "#{ jsonp }(#{ response });" if request.get?
|
121
120
|
debug 'Returning ?', response
|
122
|
-
|
121
|
+
callback.call [200, headers, [response]]
|
123
122
|
end
|
124
123
|
|
125
124
|
ASYNC_RESPONSE
|
126
|
-
rescue
|
125
|
+
rescue => e
|
126
|
+
error "#{e.message}\nBacktrace:\n#{e.backtrace * "\n"}"
|
127
127
|
[400, TYPE_TEXT, ['Bad request']]
|
128
128
|
end
|
129
129
|
|
130
|
-
def
|
131
|
-
|
130
|
+
def handle_websocket(env)
|
131
|
+
ws = Faye::WebSocket.new(env, nil, :ping => @options[:ping])
|
132
|
+
client_id = nil
|
132
133
|
|
133
|
-
|
134
|
+
ws.onmessage = lambda do |event|
|
134
135
|
begin
|
135
|
-
message
|
136
|
-
|
136
|
+
message = Yajl::Parser.parse(event.data)
|
137
|
+
client_id = [message].flatten[0]['clientId']
|
138
|
+
|
139
|
+
debug "Received via WebSocket[#{ws.version}]: ?", message
|
140
|
+
@server.open_socket(client_id, ws)
|
141
|
+
|
137
142
|
@server.process(message, false) do |replies|
|
138
|
-
|
139
|
-
socket.send(JSON.unparse(replies))
|
143
|
+
ws.send(Faye.to_json(replies)) if ws
|
140
144
|
end
|
141
|
-
rescue
|
145
|
+
rescue => e
|
146
|
+
error "#{e.message}\nBacktrace:\n#{e.backtrace * "\n"}"
|
142
147
|
end
|
143
148
|
end
|
144
|
-
|
149
|
+
|
150
|
+
ws.onclose = lambda do |event|
|
151
|
+
@server.close_socket(client_id)
|
152
|
+
ws = nil
|
153
|
+
end
|
154
|
+
|
155
|
+
ws.rack_response
|
156
|
+
end
|
157
|
+
|
158
|
+
def handle_eventsource(env)
|
159
|
+
es = Faye::EventSource.new(env, :ping => @options[:ping])
|
160
|
+
client_id = es.url.split('/').pop
|
161
|
+
|
162
|
+
debug 'Opened EventSource connection for ?', client_id
|
163
|
+
@server.open_socket(client_id, es)
|
164
|
+
|
165
|
+
es.onclose = lambda do |event|
|
166
|
+
@server.close_socket(client_id)
|
167
|
+
es = nil
|
168
|
+
end
|
169
|
+
|
170
|
+
es.rack_response
|
145
171
|
end
|
146
172
|
|
147
173
|
def message_from_request(request)
|
@@ -171,11 +197,6 @@ module Faye
|
|
171
197
|
[200, headers, ['']]
|
172
198
|
end
|
173
199
|
|
174
|
-
class DeferredBody
|
175
|
-
include EventMachine::Deferrable
|
176
|
-
alias :each :callback
|
177
|
-
end
|
178
|
-
|
179
200
|
end
|
180
201
|
end
|
181
202
|
|
@@ -5,7 +5,7 @@ module Faye
|
|
5
5
|
include EventMachine::Deferrable
|
6
6
|
include Timeouts
|
7
7
|
|
8
|
-
|
8
|
+
attr_accessor :socket
|
9
9
|
|
10
10
|
def initialize(engine, id, options = {})
|
11
11
|
@engine = engine
|
@@ -15,6 +15,7 @@ module Faye
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def deliver(message)
|
18
|
+
return socket.send(Faye.to_json([message])) if socket
|
18
19
|
return unless @inbox.add?(message)
|
19
20
|
begin_delivery_timeout
|
20
21
|
end
|
@@ -24,28 +25,24 @@ module Faye
|
|
24
25
|
timeout = options['timeout'] ? options['timeout'] / 1000.0 : @engine.timeout
|
25
26
|
|
26
27
|
set_deferred_status(:deferred)
|
27
|
-
|
28
28
|
callback(&block)
|
29
|
-
return if @connected
|
30
|
-
|
31
|
-
@connected = true
|
32
29
|
|
33
30
|
begin_delivery_timeout
|
34
31
|
begin_connection_timeout(timeout)
|
35
32
|
end
|
36
33
|
|
37
|
-
def flush!
|
38
|
-
release_connection!
|
34
|
+
def flush!(force = false)
|
35
|
+
release_connection!(force)
|
39
36
|
set_deferred_status(:succeeded, @inbox.entries)
|
37
|
+
@inbox = []
|
40
38
|
end
|
41
39
|
|
42
40
|
private
|
43
41
|
|
44
|
-
def release_connection!
|
45
|
-
@engine.close_connection(@id)
|
42
|
+
def release_connection!(force = false)
|
43
|
+
@engine.close_connection(@id) if force or socket.nil?
|
46
44
|
remove_timeout(:connection)
|
47
45
|
remove_timeout(:delivery)
|
48
|
-
@connected = false
|
49
46
|
end
|
50
47
|
|
51
48
|
def begin_delivery_timeout
|
data/lib/faye/engines/memory.rb
CHANGED
@@ -1,23 +1,28 @@
|
|
1
1
|
module Faye
|
2
2
|
module Engine
|
3
3
|
|
4
|
-
class Memory
|
4
|
+
class Memory
|
5
5
|
include Timeouts
|
6
6
|
|
7
|
-
def
|
7
|
+
def self.create(server, options)
|
8
|
+
new(server, options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(server, options)
|
12
|
+
@server = server
|
13
|
+
@options = options
|
8
14
|
@namespace = Namespace.new
|
9
15
|
@clients = {}
|
10
16
|
@channels = {}
|
11
17
|
@messages = {}
|
12
|
-
super
|
13
18
|
end
|
14
19
|
|
15
20
|
def create_client(&callback)
|
16
21
|
client_id = @namespace.generate
|
17
|
-
debug 'Created new client ?', client_id
|
22
|
+
@server.debug 'Created new client ?', client_id
|
18
23
|
ping(client_id)
|
24
|
+
@server.trigger(:handshake, client_id)
|
19
25
|
callback.call(client_id)
|
20
|
-
trigger(:handshake, client_id)
|
21
26
|
end
|
22
27
|
|
23
28
|
def destroy_client(client_id, &callback)
|
@@ -30,9 +35,9 @@ module Faye
|
|
30
35
|
remove_timeout(client_id)
|
31
36
|
@namespace.release(client_id)
|
32
37
|
@messages.delete(client_id)
|
33
|
-
debug 'Destroyed client ?', client_id
|
38
|
+
@server.debug 'Destroyed client ?', client_id
|
39
|
+
@server.trigger(:disconnect, client_id)
|
34
40
|
callback.call if callback
|
35
|
-
trigger(:disconnect, client_id)
|
36
41
|
end
|
37
42
|
|
38
43
|
def client_exists(client_id, &callback)
|
@@ -40,10 +45,11 @@ module Faye
|
|
40
45
|
end
|
41
46
|
|
42
47
|
def ping(client_id)
|
43
|
-
|
44
|
-
|
48
|
+
timeout = @server.timeout
|
49
|
+
return unless Numeric === timeout
|
50
|
+
@server.debug 'Ping ?, ?', client_id, timeout
|
45
51
|
remove_timeout(client_id)
|
46
|
-
add_timeout(client_id, 2 *
|
52
|
+
add_timeout(client_id, 2 * timeout) { destroy_client(client_id) }
|
47
53
|
end
|
48
54
|
|
49
55
|
def subscribe(client_id, channel, &callback)
|
@@ -53,8 +59,8 @@ module Faye
|
|
53
59
|
@channels[channel] ||= Set.new
|
54
60
|
@channels[channel].add(client_id)
|
55
61
|
|
56
|
-
debug 'Subscribed client ? to channel ?', client_id, channel
|
57
|
-
trigger(:subscribe, client_id, channel) if should_trigger
|
62
|
+
@server.debug 'Subscribed client ? to channel ?', client_id, channel
|
63
|
+
@server.trigger(:subscribe, client_id, channel) if should_trigger
|
58
64
|
callback.call(true) if callback
|
59
65
|
end
|
60
66
|
|
@@ -69,16 +75,15 @@ module Faye
|
|
69
75
|
@channels.delete(channel) if @channels[channel].empty?
|
70
76
|
end
|
71
77
|
|
72
|
-
debug 'Unsubscribed client ? from channel ?', client_id, channel
|
73
|
-
trigger(:unsubscribe, client_id, channel) if should_trigger
|
78
|
+
@server.debug 'Unsubscribed client ? from channel ?', client_id, channel
|
79
|
+
@server.trigger(:unsubscribe, client_id, channel) if should_trigger
|
74
80
|
callback.call(true) if callback
|
75
81
|
end
|
76
82
|
|
77
|
-
def publish(message)
|
78
|
-
debug 'Publishing message ?', message
|
83
|
+
def publish(message, channels)
|
84
|
+
@server.debug 'Publishing message ?', message
|
79
85
|
|
80
|
-
|
81
|
-
clients = Set.new
|
86
|
+
clients = Set.new
|
82
87
|
|
83
88
|
channels.each do |channel|
|
84
89
|
next unless subs = @channels[channel]
|
@@ -86,27 +91,22 @@ module Faye
|
|
86
91
|
end
|
87
92
|
|
88
93
|
clients.each do |client_id|
|
89
|
-
debug 'Queueing for client ?: ?', client_id, message
|
94
|
+
@server.debug 'Queueing for client ?: ?', client_id, message
|
90
95
|
@messages[client_id] ||= []
|
91
96
|
@messages[client_id] << Faye.copy_object(message)
|
92
97
|
empty_queue(client_id)
|
93
98
|
end
|
94
99
|
|
95
|
-
trigger(:publish, message['clientId'], message['channel'], message['data'])
|
100
|
+
@server.trigger(:publish, message['clientId'], message['channel'], message['data'])
|
96
101
|
end
|
97
102
|
|
98
|
-
private
|
99
|
-
|
100
103
|
def empty_queue(client_id)
|
101
|
-
return unless
|
102
|
-
|
103
|
-
|
104
|
-
messages.each(&conn.method(:deliver))
|
104
|
+
return unless @server.has_connection?(client_id)
|
105
|
+
@server.deliver(client_id, @messages[client_id])
|
106
|
+
@messages.delete(client_id)
|
105
107
|
end
|
106
108
|
end
|
107
109
|
|
108
|
-
register 'memory', Memory
|
109
|
-
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|