├── dotcloud.yml ├── postinstall ├── third-party ├── Socket.IO-node │ ├── support │ │ └── socket.io-client │ │ │ ├── .gitignore │ │ │ ├── Makefile │ │ │ ├── lib │ │ │ ├── vendor │ │ │ │ └── web-socket-js │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── WebSocketMain.swf │ │ │ │ │ ├── WebSocketMainInsecure.zip │ │ │ │ │ └── sample.html │ │ │ ├── io.js │ │ │ ├── transports │ │ │ │ ├── xhr-multipart.js │ │ │ │ ├── xhr-polling.js │ │ │ │ ├── flashsocket.js │ │ │ │ ├── websocket.js │ │ │ │ ├── htmlfile.js │ │ │ │ ├── jsonp-polling.js │ │ │ │ └── xhr.js │ │ │ └── util.js │ │ │ ├── package.json │ │ │ ├── History.md │ │ │ └── bin │ │ │ └── build │ ├── lib │ │ └── socket.io │ │ │ ├── index.js │ │ │ ├── transports │ │ │ ├── jsonp-polling.js │ │ │ ├── htmlfile.js │ │ │ ├── xhr-multipart.js │ │ │ ├── xhr-polling.js │ │ │ ├── flashsocket.js │ │ │ └── websocket.js │ │ │ ├── utils.js │ │ │ ├── listener.js │ │ │ └── client.js │ └── example │ │ ├── cert.crt │ │ ├── key.key │ │ ├── server.js │ │ ├── json.js │ │ ├── server-ssl.js │ │ ├── chat-ssl.html │ │ └── chat.html ├── lib │ ├── PocketIO │ │ ├── Response │ │ │ └── Chunked.pm │ │ ├── Transport │ │ │ ├── XHRPolling.pm │ │ │ ├── JSONPPolling.pm │ │ │ ├── WebSocket.pm │ │ │ ├── Base.pm │ │ │ ├── XHRMultipart.pm │ │ │ ├── BasePolling.pm │ │ │ └── Htmlfile.pm │ │ ├── Resource.pm │ │ ├── Pool.pm │ │ └── Handle.pm │ └── PocketIO.pm ├── wikiwyg │ └── lib │ │ └── Document │ │ ├── Emitter.js │ │ ├── Emitter │ │ ├── ByteCode.js │ │ └── HTML.js │ │ ├── Parser.js │ │ └── Parser │ │ └── Wikitext.js ├── hippie │ ├── pretty.js │ ├── jquery.ev.js │ ├── jquery.cookie.js │ └── jquery.oembed.js └── class-js │ ├── lib │ └── Class.js │ └── README ├── LICENSE.txt ├── nginx.conf ├── docs └── hopscotch-yapctiny.txt ├── images ├── sc-1x1.gif ├── sc-cut.gif ├── sc-copy.gif ├── sc-logo.gif ├── sc-merge.gif ├── sc-paste.gif ├── sc-redo.gif ├── sc-undo.gif ├── sc-delete.gif ├── sc-divider1.gif ├── sc-endcap-h.gif ├── sc-endcap-v.gif ├── sc-filldown.gif ├── sc-less-hd.gif ├── sc-less-hh.gif ├── sc-less-hn.gif ├── sc-less-vd.gif ├── sc-less-vh.gif ├── sc-less-vn.gif ├── sc-linkout.gif ├── sc-main-h.gif ├── sc-main-v.gif ├── sc-more-hd.gif ├── sc-more-hh.gif ├── sc-more-hn.gif ├── sc-more-vd.gif ├── sc-more-vh.gif ├── sc-more-vn.gif ├── sc-movefrom.gif ├── sc-peerbg.gif ├── sc-range2.gif ├── sc-recalc.gif ├── sc-thumb-hd.gif ├── sc-thumb-hh.gif ├── sc-thumb-hn.gif ├── sc-thumb-vd.gif ├── sc-thumb-vh.gif ├── sc-thumb-vn.gif ├── sc-unmerge.gif ├── sc-wikiflag.gif ├── sc-alignleft.gif ├── sc-alignright.gif ├── sc-bordersoff.gif ├── sc-borderson.gif ├── sc-commentbg.gif ├── sc-deletecol.gif ├── sc-deleterow.gif ├── sc-fillright.gif ├── sc-insertcol.gif ├── sc-insertrow.gif ├── sc-linkdialog.gif ├── sc-moveinsert.gif ├── sc-movepaste.gif ├── sc-sumdialog.gif ├── sc-swapcolors.gif ├── sc-aligncenter.gif ├── sc-chooserarrow.gif ├── sc-defaultcolor.gif ├── sc-drag-handles.gif ├── sc-drag-handles.png ├── sc-formuladialog.gif ├── sc-movefromoff.gif ├── sc-moveinsertoff.gif ├── sc-movepasteoff.gif ├── sc-paneslider-h.gif ├── sc-paneslider-v.gif ├── sc-pasteformats.gif ├── sc-scrollarea-h.gif ├── sc-scrollarea-v.gif ├── sc-wikilinkflag.gif ├── sc-cursorinsertup.gif ├── sc-multilinedialog.gif ├── sc-trackingline-h.gif ├── sc-trackingline-v.gif └── sc-cursorinsertleft.gif ├── requirements.txt ├── multiserver.pl ├── Makefile.PL ├── index.css ├── cpan ├── socialcalc-multiplayer.pl ├── inc │ └── Module │ │ └── Install │ │ ├── Scripts.pm │ │ ├── ReadmeFromPod.pm │ │ ├── Base.pm │ │ ├── WriteAll.pm │ │ ├── Win32.pm │ │ ├── Can.pm │ │ ├── Fetch.pm │ │ └── Share.pm ├── META.yml ├── Makefile.PL └── Multiplayer.pm ├── TODO ├── README ├── app.psgi ├── socketpolicy.pl ├── LEGAL.txt ├── socialcalc.css └── player.js /dotcloud.yml: -------------------------------------------------------------------------------- 1 | www: 2 | type: perl 3 | -------------------------------------------------------------------------------- /postinstall: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | fliggy --port 8080 app.psgi & 3 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/.gitignore: -------------------------------------------------------------------------------- 1 | s3 -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/LICENSE.txt -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | location ^~ / { 2 | proxy_pass http://localhost:8080; 3 | } 4 | -------------------------------------------------------------------------------- /docs/hopscotch-yapctiny.txt: -------------------------------------------------------------------------------- 1 | http://pugs.blogs.com/talks/hopscotch-yapctiny.pdf 2 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/Makefile: -------------------------------------------------------------------------------- 1 | build: 2 | ./bin/build -------------------------------------------------------------------------------- /images/sc-1x1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-1x1.gif -------------------------------------------------------------------------------- /images/sc-cut.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-cut.gif -------------------------------------------------------------------------------- /images/sc-copy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-copy.gif -------------------------------------------------------------------------------- /images/sc-logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-logo.gif -------------------------------------------------------------------------------- /images/sc-merge.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-merge.gif -------------------------------------------------------------------------------- /images/sc-paste.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-paste.gif -------------------------------------------------------------------------------- /images/sc-redo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-redo.gif -------------------------------------------------------------------------------- /images/sc-undo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-undo.gif -------------------------------------------------------------------------------- /images/sc-delete.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-delete.gif -------------------------------------------------------------------------------- /images/sc-divider1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-divider1.gif -------------------------------------------------------------------------------- /images/sc-endcap-h.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-endcap-h.gif -------------------------------------------------------------------------------- /images/sc-endcap-v.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-endcap-v.gif -------------------------------------------------------------------------------- /images/sc-filldown.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-filldown.gif -------------------------------------------------------------------------------- /images/sc-less-hd.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-less-hd.gif -------------------------------------------------------------------------------- /images/sc-less-hh.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-less-hh.gif -------------------------------------------------------------------------------- /images/sc-less-hn.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-less-hn.gif -------------------------------------------------------------------------------- /images/sc-less-vd.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-less-vd.gif -------------------------------------------------------------------------------- /images/sc-less-vh.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-less-vh.gif -------------------------------------------------------------------------------- /images/sc-less-vn.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-less-vn.gif -------------------------------------------------------------------------------- /images/sc-linkout.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-linkout.gif -------------------------------------------------------------------------------- /images/sc-main-h.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-main-h.gif -------------------------------------------------------------------------------- /images/sc-main-v.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-main-v.gif -------------------------------------------------------------------------------- /images/sc-more-hd.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-more-hd.gif -------------------------------------------------------------------------------- /images/sc-more-hh.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-more-hh.gif -------------------------------------------------------------------------------- /images/sc-more-hn.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-more-hn.gif -------------------------------------------------------------------------------- /images/sc-more-vd.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-more-vd.gif -------------------------------------------------------------------------------- /images/sc-more-vh.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-more-vh.gif -------------------------------------------------------------------------------- /images/sc-more-vn.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-more-vn.gif -------------------------------------------------------------------------------- /images/sc-movefrom.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-movefrom.gif -------------------------------------------------------------------------------- /images/sc-peerbg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-peerbg.gif -------------------------------------------------------------------------------- /images/sc-range2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-range2.gif -------------------------------------------------------------------------------- /images/sc-recalc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-recalc.gif -------------------------------------------------------------------------------- /images/sc-thumb-hd.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-thumb-hd.gif -------------------------------------------------------------------------------- /images/sc-thumb-hh.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-thumb-hh.gif -------------------------------------------------------------------------------- /images/sc-thumb-hn.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-thumb-hn.gif -------------------------------------------------------------------------------- /images/sc-thumb-vd.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-thumb-vd.gif -------------------------------------------------------------------------------- /images/sc-thumb-vh.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-thumb-vh.gif -------------------------------------------------------------------------------- /images/sc-thumb-vn.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-thumb-vn.gif -------------------------------------------------------------------------------- /images/sc-unmerge.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-unmerge.gif -------------------------------------------------------------------------------- /images/sc-wikiflag.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-wikiflag.gif -------------------------------------------------------------------------------- /images/sc-alignleft.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-alignleft.gif -------------------------------------------------------------------------------- /images/sc-alignright.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-alignright.gif -------------------------------------------------------------------------------- /images/sc-bordersoff.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-bordersoff.gif -------------------------------------------------------------------------------- /images/sc-borderson.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-borderson.gif -------------------------------------------------------------------------------- /images/sc-commentbg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-commentbg.gif -------------------------------------------------------------------------------- /images/sc-deletecol.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-deletecol.gif -------------------------------------------------------------------------------- /images/sc-deleterow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-deleterow.gif -------------------------------------------------------------------------------- /images/sc-fillright.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-fillright.gif -------------------------------------------------------------------------------- /images/sc-insertcol.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-insertcol.gif -------------------------------------------------------------------------------- /images/sc-insertrow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-insertrow.gif -------------------------------------------------------------------------------- /images/sc-linkdialog.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-linkdialog.gif -------------------------------------------------------------------------------- /images/sc-moveinsert.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-moveinsert.gif -------------------------------------------------------------------------------- /images/sc-movepaste.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-movepaste.gif -------------------------------------------------------------------------------- /images/sc-sumdialog.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-sumdialog.gif -------------------------------------------------------------------------------- /images/sc-swapcolors.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-swapcolors.gif -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/lib/vendor/web-socket-js/.gitignore: -------------------------------------------------------------------------------- 1 | test.html 2 | -------------------------------------------------------------------------------- /images/sc-aligncenter.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-aligncenter.gif -------------------------------------------------------------------------------- /images/sc-chooserarrow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-chooserarrow.gif -------------------------------------------------------------------------------- /images/sc-defaultcolor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-defaultcolor.gif -------------------------------------------------------------------------------- /images/sc-drag-handles.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-drag-handles.gif -------------------------------------------------------------------------------- /images/sc-drag-handles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-drag-handles.png -------------------------------------------------------------------------------- /images/sc-formuladialog.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-formuladialog.gif -------------------------------------------------------------------------------- /images/sc-movefromoff.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-movefromoff.gif -------------------------------------------------------------------------------- /images/sc-moveinsertoff.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-moveinsertoff.gif -------------------------------------------------------------------------------- /images/sc-movepasteoff.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-movepasteoff.gif -------------------------------------------------------------------------------- /images/sc-paneslider-h.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-paneslider-h.gif -------------------------------------------------------------------------------- /images/sc-paneslider-v.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-paneslider-v.gif -------------------------------------------------------------------------------- /images/sc-pasteformats.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-pasteformats.gif -------------------------------------------------------------------------------- /images/sc-scrollarea-h.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-scrollarea-h.gif -------------------------------------------------------------------------------- /images/sc-scrollarea-v.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-scrollarea-v.gif -------------------------------------------------------------------------------- /images/sc-wikilinkflag.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-wikilinkflag.gif -------------------------------------------------------------------------------- /images/sc-cursorinsertup.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-cursorinsertup.gif -------------------------------------------------------------------------------- /images/sc-multilinedialog.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-multilinedialog.gif -------------------------------------------------------------------------------- /images/sc-trackingline-h.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-trackingline-h.gif -------------------------------------------------------------------------------- /images/sc-trackingline-v.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-trackingline-v.gif -------------------------------------------------------------------------------- /images/sc-cursorinsertleft.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/images/sc-cursorinsertleft.gif -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Fliggy 2 | Plack::Request 3 | File::ShareDir 4 | Protocol::WebSocket 5 | JSON 6 | Try::Tiny 7 | Plack::Middleware::ContentLength 8 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/lib/vendor/web-socket-js/WebSocketMain.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/third-party/Socket.IO-node/support/socket.io-client/lib/vendor/web-socket-js/WebSocketMain.swf -------------------------------------------------------------------------------- /multiserver.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use strict; 3 | use Plack::Runner; 4 | 5 | print "Please connnect to: http://localhost:9999/\n"; 6 | my $runner = Plack::Runner->new; 7 | $runner->parse_options(-s => Fliggy => -p => 9999); 8 | $runner->run; 9 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/lib/vendor/web-socket-js/WebSocketMainInsecure.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/audreyt/socialcalc/HEAD/third-party/Socket.IO-node/support/socket.io-client/lib/vendor/web-socket-js/WebSocketMainInsecure.zip -------------------------------------------------------------------------------- /Makefile.PL: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use ExtUtils::MakeMaker; 3 | 4 | WriteMakefile( 5 | PREREQ_PM => { qw[ 6 | File::ShareDir 0 7 | Fliggy 0 8 | JSON 0 9 | Protocol::WebSocket 0 10 | Try::Tiny 0 11 | ]} 12 | ); 13 | -------------------------------------------------------------------------------- /index.css: -------------------------------------------------------------------------------- 1 | div.wiki p { 2 | margin: 0; 3 | } 4 | 5 | div.wiki .wafl { 6 | white-space: nowrap; 7 | background: #ccc; 8 | border: 1px solid #333; 9 | padding-left: 2px; 10 | padding-right: 2px; 11 | border-radius: 5px; 12 | -moz-border-radius: 5px; 13 | -webkit-border-radius: 5px; 14 | } 15 | -------------------------------------------------------------------------------- /third-party/lib/PocketIO/Response/Chunked.pm: -------------------------------------------------------------------------------- 1 | package PocketIO::Response::Chunked; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub finalize { 7 | [ 200, 8 | ['Content-Type' => 'text/plain', 'Transfer-Encoding' => 'chunked'], 9 | ["2\x0d\x0aok\x0d\x0a" . "0\x0d\x0a\x0d\x0a"] 10 | ]; 11 | } 12 | 13 | 1; 14 | -------------------------------------------------------------------------------- /cpan/socialcalc-multiplayer.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use strict; 3 | use Plack::Runner; 4 | use File::ShareDir 'dist_dir'; 5 | my $home = dist_dir('App-SocialCalc-Multiplayer'); 6 | print "Please connnect to: http://localhost:9999/\n"; 7 | my $runner = Plack::Runner->new; 8 | $runner->parse_options(-s => Fliggy => -p => 9999 => "$home/app.psgi"); 9 | $runner->run; 10 | -------------------------------------------------------------------------------- /third-party/wikiwyg/lib/Document/Emitter.js: -------------------------------------------------------------------------------- 1 | Class('Document.Emitter', function() { 2 | 3 | var proto = this.prototype; 4 | proto.className = 'Document.Emitter'; 5 | 6 | proto.instantiate = function() { 7 | return eval('new ' + this.className + '()'); 8 | } 9 | 10 | proto.init = function() { 11 | this.output = ''; 12 | } 13 | 14 | proto.content = function() { 15 | return this.output; 16 | } 17 | 18 | proto.insert = function(receiver) { 19 | this.output += receiver.output; 20 | } 21 | 22 | }); 23 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/lib/socket.io/index.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Listener creation shorcut 4 | * 5 | * @param {Server} node HTTP server 6 | * @param {Object} options 7 | * @api public 8 | */ 9 | 10 | exports.listen = function(server, options){ 11 | return new exports.Listener(server, options); 12 | }; 13 | 14 | /** 15 | * Listener constructor 16 | * 17 | * @api public 18 | */ 19 | 20 | exports.Listener = require('./listener'); 21 | 22 | /** 23 | * Version 24 | */ 25 | 26 | exports.version = '0.6.18'; 27 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/package.json: -------------------------------------------------------------------------------- 1 | { "name": "socket.io-browser" 2 | , "description": "Browser-side code for Socket.IO" 3 | , "version": "0.6.2" 4 | , "main" : "./socket.io.js" 5 | , "homepage": "http://socket.io" 6 | , "repository": 7 | { "type": "git" 8 | , "url": "git://github.com/LearnBoost/Socket.IO.git" 9 | } 10 | , "author": "LearnBoost" 11 | , "licenses" : 12 | [ { "type" : "MIT" 13 | , "url" : "http://github.com/learnboost/Socket.IO/raw/master/README.md" 14 | } ] 15 | , "engines": { "node": "*" } 16 | , "scripts" : 17 | { "install" : "bin/build" } 18 | } 19 | -------------------------------------------------------------------------------- /third-party/wikiwyg/lib/Document/Emitter/ByteCode.js: -------------------------------------------------------------------------------- 1 | Class('Document.Emitter.ByteCode(Document.Emitter)', function() { 2 | 3 | var proto = this.prototype; 4 | proto.className = 'Document.Emitter.ByteCode'; 5 | 6 | proto.begin_node = function(node) { 7 | this.output += '+' + node.type + '\n'; 8 | return; 9 | } 10 | 11 | proto.end_node = function(node) { 12 | this.output += '-' + node.type + '\n'; 13 | return; 14 | } 15 | 16 | proto.text_node = function(text) { 17 | text = text.replace(/\n/g, '\n '); 18 | this.output += ' ' + text + '\n'; 19 | return; 20 | } 21 | 22 | 23 | }); 24 | -------------------------------------------------------------------------------- /cpan/inc/Module/Install/Scripts.pm: -------------------------------------------------------------------------------- 1 | #line 1 2 | package Module::Install::Scripts; 3 | 4 | use strict 'vars'; 5 | use Module::Install::Base (); 6 | 7 | use vars qw{$VERSION @ISA $ISCORE}; 8 | BEGIN { 9 | $VERSION = '1.01'; 10 | @ISA = 'Module::Install::Base'; 11 | $ISCORE = 1; 12 | } 13 | 14 | sub install_script { 15 | my $self = shift; 16 | my $args = $self->makemaker_args; 17 | my $exe = $args->{EXE_FILES} ||= []; 18 | foreach ( @_ ) { 19 | if ( -f $_ ) { 20 | push @$exe, $_; 21 | } elsif ( -d 'script' and -f "script/$_" ) { 22 | push @$exe, "script/$_"; 23 | } else { 24 | die("Cannot find script '$_'"); 25 | } 26 | } 27 | } 28 | 29 | 1; 30 | -------------------------------------------------------------------------------- /cpan/META.yml: -------------------------------------------------------------------------------- 1 | --- 2 | abstract: 'Multiplayer SocialCalc Server with WebSocket' 3 | author: 4 | - '唐鳳 ' 5 | build_requires: 6 | ExtUtils::MakeMaker: 6.42 7 | configure_requires: 8 | ExtUtils::MakeMaker: 6.42 9 | distribution_type: module 10 | generated_by: 'Module::Install version 1.01' 11 | license: cpal 12 | meta-spec: 13 | url: http://module-build.sourceforge.net/META-spec-v1.4.html 14 | version: 1.4 15 | name: App-SocialCalc-Multiplayer 16 | no_index: 17 | directory: 18 | - inc 19 | - socialcalc 20 | requires: 21 | File::ShareDir: 0 22 | Fliggy: 0 23 | JSON: 0 24 | Protocol::WebSocket: 0 25 | Try::Tiny: 0 26 | perl: 5.8.1 27 | resources: 28 | repository: http://github.com/audreyt/socialcalc 29 | version: 20110626 30 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/History.md: -------------------------------------------------------------------------------- 1 | 2 | 0.7.0 / 2011-??-?? 3 | ================== 4 | 5 | * Fixed JSONP interaction with jQuery. [saschagehlich] 6 | * Fixed; different port now considered cross-domain. 7 | * Added compatibility for inclusion in non-browser environments. 8 | * Added package.json. 9 | * Added noConflict support. [kreichgauer] 10 | * Added reconnection support with exponential backoff. [3rd-Eden] 11 | 12 | 0.6.2 / 2011-02-05 13 | ================== 14 | 15 | * Fixed problem with xhr-multipart buffering 16 | * Updated Flash websocket transport 17 | * Fixed tryTransportsOnConnectTimeout option 18 | * Added 'connect_failed' event after the last available transport fails to connect 19 | within the timeout 20 | * Add 'connecting' event emit on each connection attempt. 21 | 22 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | 02:28 < au> so in case of playing x,Y 2 | 02:28 < danb> That's the way to do it. The unwind would be done on the client. 3 | 02:28 < au> X1 -> Y1 -> X2 4 | 02:28 < au> but X says X1/X2 first because of latency 5 | 02:28 < au> then got Y1, then it needs to unwind X2 then reapply 6 | 02:28 < au> yeah, server can do that already; I'll check in client code to do that. 7 | 02:28 < au> danb++ 8 | 02:29 < au> and it needs to ensure that unwind doesn't affect the undo stack, so each player's undo 9 | stack remai nthe same 10 | 02:29 < danb> The case I though of was start edit, put in formula referring to cell. Other person 11 | deletes row. Save edit. There are probably variations that would not fix up the 12 | reference correctly. 13 | 02:29 < danb> Yes. 14 | 02:29 < au> (critical for Ctrl-Z to propagate correctly) 15 | -------------------------------------------------------------------------------- /cpan/Makefile.PL: -------------------------------------------------------------------------------- 1 | use 5.008001; 2 | use strict; 3 | use FindBin '$Bin'; 4 | use inc::Module::Install; 5 | 6 | if (-e "$Bin/../socialcalc.css" and -d "$Bin/../cpan" and $Bin =~ /cpan$/) { 7 | mkdir 'socialcalc' unless -d 'socialcalc'; 8 | system("rsync -av --delete --exclude cpan ../* socialcalc"); 9 | } 10 | 11 | name 'App-SocialCalc-Multiplayer'; 12 | author '唐鳳 '; 13 | license 'CPAL'; 14 | repository 'http://github.com/audreyt/socialcalc'; 15 | all_from 'Multiplayer.pm'; 16 | readme_from 'Multiplayer.pm'; 17 | requires 'Fliggy'; 18 | requires 'File::ShareDir'; 19 | 20 | # These are requirements to PocketIO.pm 21 | requires 'Protocol::WebSocket'; 22 | requires 'JSON'; 23 | requires 'Try::Tiny'; 24 | requires 'Plack::Middleware::ContentLength'; 25 | 26 | install_share 'socialcalc'; 27 | install_script 'socialcalc-multiplayer.pl'; 28 | 29 | sign; WriteAll; 30 | 31 | 1; 32 | -------------------------------------------------------------------------------- /third-party/lib/PocketIO/Transport/XHRPolling.pm: -------------------------------------------------------------------------------- 1 | package PocketIO::Transport::XHRPolling; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use base 'PocketIO::Transport::BasePolling'; 7 | 8 | sub name {'xhr-polling'} 9 | 10 | sub dispatch { 11 | my $self = shift; 12 | my ($cb) = @_; 13 | 14 | my $req = $self->req; 15 | my $name = $self->name; 16 | 17 | if ($req->method eq 'GET') { 18 | return $self->_dispatch_init($cb) if $req->path =~ m{^/$name//\d+$}; 19 | 20 | return $self->_dispatch_stream($1) 21 | if $req->path =~ m{^/$name/(\d+)/\d+$}; 22 | } 23 | 24 | return 25 | unless $req->method eq 'POST' 26 | && $req->path_info =~ m{^/$name/(\d+)/send$}; 27 | 28 | return $self->_dispatch_send($req, $1); 29 | } 30 | 31 | 1; 32 | __END__ 33 | 34 | =head1 NAME 35 | 36 | PocketIO::XHRPolling - XHRPolling transport 37 | 38 | =head1 DESCRIPTION 39 | 40 | L is a C transport 41 | implementation. 42 | 43 | =head1 METHODS 44 | 45 | =head2 C 46 | 47 | =head2 C 48 | 49 | =cut 50 | -------------------------------------------------------------------------------- /cpan/inc/Module/Install/ReadmeFromPod.pm: -------------------------------------------------------------------------------- 1 | #line 1 2 | package Module::Install::ReadmeFromPod; 3 | 4 | use 5.006; 5 | use strict; 6 | use warnings; 7 | use base qw(Module::Install::Base); 8 | use vars qw($VERSION); 9 | 10 | $VERSION = '0.12'; 11 | 12 | sub readme_from { 13 | my $self = shift; 14 | return unless $self->is_admin; 15 | 16 | my $file = shift || $self->_all_from 17 | or die "Can't determine file to make readme_from"; 18 | my $clean = shift; 19 | 20 | print "Writing README from $file\n"; 21 | 22 | require Pod::Text; 23 | my $parser = Pod::Text->new(); 24 | open README, '> README' or die "$!\n"; 25 | $parser->output_fh( *README ); 26 | $parser->parse_file( $file ); 27 | if ($clean) { 28 | $self->clean_files('README'); 29 | } 30 | return 1; 31 | } 32 | 33 | sub _all_from { 34 | my $self = shift; 35 | return unless $self->admin->{extensions}; 36 | my ($metadata) = grep { 37 | ref($_) eq 'Module::Install::Metadata'; 38 | } @{$self->admin->{extensions}}; 39 | return unless $metadata; 40 | return $metadata->{values}{all_from} || ''; 41 | } 42 | 43 | 'Readme!'; 44 | 45 | __END__ 46 | 47 | #line 112 48 | 49 | -------------------------------------------------------------------------------- /third-party/lib/PocketIO/Transport/JSONPPolling.pm: -------------------------------------------------------------------------------- 1 | package PocketIO::Transport::JSONPPolling; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use base 'PocketIO::Transport::BasePolling'; 7 | 8 | sub name {'jsonp-polling'} 9 | 10 | sub dispatch { 11 | my $self = shift; 12 | my ($cb) = @_; 13 | 14 | my $req = $self->req; 15 | my $name = $self->name; 16 | 17 | if ($req->method eq 'GET') { 18 | return $self->_dispatch_init($cb) 19 | if $req->path =~ m{^/$name//\d+/\d+$}; 20 | 21 | return $self->_dispatch_stream($1) 22 | if $req->path =~ m{^/$name/(\d+)/\d+/\d+$}; 23 | } 24 | 25 | return 26 | unless $req->method eq 'POST' 27 | && $req->path =~ m{^/$name/(\d+)/\d+/\d+$}; 28 | 29 | return $self->_dispatch_send($req, $1); 30 | } 31 | 32 | sub _format_message { 33 | my $self = shift; 34 | my ($message) = @_; 35 | 36 | $message =~ s/"/\\"/g; 37 | return qq{io.JSONP[0]._("$message");}; 38 | } 39 | 40 | 1; 41 | __END__ 42 | 43 | =head1 NAME 44 | 45 | PocketIO::JSONPPolling - JSONPPolling transport 46 | 47 | =head1 DESCRIPTION 48 | 49 | L is a C transport 50 | implementation. 51 | 52 | =head1 METHODS 53 | 54 | =head2 C 55 | 56 | =head2 C 57 | 58 | =cut 59 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/lib/socket.io/transports/jsonp-polling.js: -------------------------------------------------------------------------------- 1 | var XHRPolling = require('./xhr-polling') 2 | , util = require(process.binding('natives').util ? 'util' : 'sys'); 3 | 4 | JSONPPolling = module.exports = function(){ 5 | XHRPolling.apply(this, arguments); 6 | }; 7 | 8 | util.inherits(JSONPPolling, XHRPolling); 9 | 10 | JSONPPolling.prototype.getOptions = function(){ 11 | return { 12 | timeout: null, // no heartbeats 13 | closeTimeout: 8000, 14 | duration: 20000 15 | }; 16 | }; 17 | 18 | JSONPPolling.prototype._onConnect = function(req, res){ 19 | this._index = req.url.match(/\/([0-9]+)\/?$/).pop(); 20 | XHRPolling.prototype._onConnect.call(this, req, res); 21 | }; 22 | 23 | JSONPPolling.prototype._write = function(message){ 24 | if (this._open){ 25 | if (this.request.headers.origin && !this._verifyOrigin(this.request.headers.origin)){ 26 | message = "alert('Cross domain security restrictions not met');"; 27 | } else { 28 | message = "io.JSONP["+ this._index +"]._("+ JSON.stringify(message) +");"; 29 | } 30 | this.response.writeHead(200, {'Content-Type': 'text/javascript; charset=UTF-8', 'Content-Length': Buffer.byteLength(message)}); 31 | this.response.write(message); 32 | this.response.end(); 33 | this._onClose(); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/example/cert.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDXTCCAkWgAwIBAgIJAMUSOvlaeyQHMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV 3 | BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX 4 | aWRnaXRzIFB0eSBMdGQwHhcNMTAxMTE2MDkzMjQ5WhcNMTMxMTE1MDkzMjQ5WjBF 5 | MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 6 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 7 | CgKCAQEAz+LXZOjcQCJq3+ZKUFabj71oo/ex/XsBcFqtBThjjTw9CVEVwfPQQp4X 8 | wtPiB204vnYXwQ1/R2NdTQqCZu47l79LssL/u2a5Y9+0NEU3nQA5qdt+1FAE0c5o 9 | exPimXOrR3GWfKz7PmZ2O0117IeCUUXPG5U8umhDe/4mDF4ZNJiKc404WthquTqg 10 | S7rLQZHhZ6D0EnGnOkzlmxJMYPNHSOY1/6ivdNUUcC87awNEA3lgfhy25IyBK3QJ 11 | c+aYKNTbt70Lery3bu2wWLFGtmNiGlQTS4JsxImRsECTI727ObS7/FWAQsqW+COL 12 | 0Sa5BuMFrFIpjPrEe0ih7vRRbdmXRwIDAQABo1AwTjAdBgNVHQ4EFgQUDnV4d6mD 13 | tOnluLoCjkUHTX/n4agwHwYDVR0jBBgwFoAUDnV4d6mDtOnluLoCjkUHTX/n4agw 14 | DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAFwV4MQfTo+qMv9JMiyno 15 | IEiqfOz4RgtmBqRnXUffcjS2dhc7/z+FPZnM79Kej8eLHoVfxCyWRHFlzm93vEdv 16 | wxOCrD13EDOi08OOZfxWyIlCa6Bg8cMAKqQzd2OvQOWqlRWBTThBJIhWflU33izX 17 | Qn5GdmYqhfpc+9ZHHGhvXNydtRQkdxVK2dZNzLBvBlLlRmtoClU7xm3A+/5dddeP 18 | AQHEPtyFlUw49VYtZ3ru6KqPms7MKvcRhYLsy9rwSfuuniMlx4d0bDR7TOkw0QQS 19 | A0N8MGQRQpzl4mw4jLzyM5d5QtuGBh2P6hPGa0YQxtI3RPT/p6ENzzBiAKXiSfzo 20 | xw== 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /third-party/hippie/pretty.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JavaScript Pretty Date 3 | * Copyright (c) 2008 John Resig (jquery.com) 4 | * Licensed under the MIT license. 5 | */ 6 | 7 | // Takes an ISO time and returns a string representing how 8 | // long ago the date represents. 9 | function prettyDate(time){ 10 | var date = new Date(time); // (time || "").replace(/-/g,"/").replace(/[TZ]/g," ")), 11 | diff = (((new Date()).getTime() - date.getTime()) / 1000), 12 | day_diff = Math.floor(diff / 86400); 13 | 14 | if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 ) 15 | return; 16 | 17 | return day_diff == 0 && ( 18 | diff < 60 && "just now" || 19 | diff < 120 && "1 minute ago" || 20 | diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" || 21 | diff < 7200 && "1 hour ago" || 22 | diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") || 23 | day_diff == 1 && "Yesterday" || 24 | day_diff < 7 && day_diff + " days ago" || 25 | day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago"; 26 | } 27 | 28 | // If jQuery is included in the page, adds a jQuery plugin to handle it as well 29 | if ( typeof jQuery != "undefined" ) 30 | jQuery.fn.prettyDate = function(){ 31 | return this.each(function(){ 32 | var date = prettyDate(this.title); 33 | if ( date ) 34 | jQuery(this).text( date ); 35 | }); 36 | }; 37 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | -=[Multiplayer Socialcalc]=- 2 | 3 | >> See https://github.com/audreyt/socialcalc/wiki for a book chapter on this project! << 4 | 5 | .oO( Advertisement for EtherCalc )Oo. 6 | 7 | Please note that this repository hosts a proof-of-concept that provides 8 | no capability to save/load spreadsheetgs. 9 | 10 | However, a Node.js port with Redis storage backend is now available at: 11 | 12 | https://github.com/audreyt/ethercalc 13 | 14 | There are now two public playgrounds for experimenting EtherCalc: 15 | 16 | http://ethercalc.org/ 17 | http://ethercalc.no.de/ 18 | 19 | Please feel free to take a look at it too! 20 | 21 | .oO( Setup Instructions )Oo. 22 | 23 | 0. Install JSON, Fliggy, Protocol::WebSocket and Try::Tiny: 24 | 25 | sudo cpan 26 | cpan> notest install JSON Fliggy Protocol::WebSocket Try::Tiny 27 | 28 | 1. Then check out this project and run the stand-alone server: 29 | 30 | git clone git://github.com/audreyt/socialcalc.git 31 | 32 | cd socialcalc 33 | perl multiserver.pl 34 | 35 | 2. Open port 9999 in multiple browsers with WebSocket support. 36 | 37 | 3. See red triangles representing peer cursors. 38 | Type in a browser, appears in all others! 39 | 40 | Browsers currently tested: 41 | Native WebSocket: Safari 5, Chrome 5, Firefox 4 beta1. 42 | Flash emulation: Firefox 3, Opera 10. 43 | 44 | Share & Enjoy! 45 | Audrey 46 | -------------------------------------------------------------------------------- /cpan/inc/Module/Install/Base.pm: -------------------------------------------------------------------------------- 1 | #line 1 2 | package Module::Install::Base; 3 | 4 | use strict 'vars'; 5 | use vars qw{$VERSION}; 6 | BEGIN { 7 | $VERSION = '1.01'; 8 | } 9 | 10 | # Suspend handler for "redefined" warnings 11 | BEGIN { 12 | my $w = $SIG{__WARN__}; 13 | $SIG{__WARN__} = sub { $w }; 14 | } 15 | 16 | #line 42 17 | 18 | sub new { 19 | my $class = shift; 20 | unless ( defined &{"${class}::call"} ) { 21 | *{"${class}::call"} = sub { shift->_top->call(@_) }; 22 | } 23 | unless ( defined &{"${class}::load"} ) { 24 | *{"${class}::load"} = sub { shift->_top->load(@_) }; 25 | } 26 | bless { @_ }, $class; 27 | } 28 | 29 | #line 61 30 | 31 | sub AUTOLOAD { 32 | local $@; 33 | my $func = eval { shift->_top->autoload } or return; 34 | goto &$func; 35 | } 36 | 37 | #line 75 38 | 39 | sub _top { 40 | $_[0]->{_top}; 41 | } 42 | 43 | #line 90 44 | 45 | sub admin { 46 | $_[0]->_top->{admin} 47 | or 48 | Module::Install::Base::FakeAdmin->new; 49 | } 50 | 51 | #line 106 52 | 53 | sub is_admin { 54 | ! $_[0]->admin->isa('Module::Install::Base::FakeAdmin'); 55 | } 56 | 57 | sub DESTROY {} 58 | 59 | package Module::Install::Base::FakeAdmin; 60 | 61 | use vars qw{$VERSION}; 62 | BEGIN { 63 | $VERSION = $Module::Install::Base::VERSION; 64 | } 65 | 66 | my $fake; 67 | 68 | sub new { 69 | $fake ||= bless(\@_, $_[0]); 70 | } 71 | 72 | sub AUTOLOAD {} 73 | 74 | sub DESTROY {} 75 | 76 | # Restore warning handler 77 | BEGIN { 78 | $SIG{__WARN__} = $SIG{__WARN__}->(); 79 | } 80 | 81 | 1; 82 | 83 | #line 159 84 | -------------------------------------------------------------------------------- /third-party/lib/PocketIO/Resource.pm: -------------------------------------------------------------------------------- 1 | package PocketIO::Resource; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use PocketIO::Transport::Htmlfile; 7 | use PocketIO::Transport::JSONPPolling; 8 | use PocketIO::Transport::WebSocket; 9 | use PocketIO::Transport::XHRMultipart; 10 | use PocketIO::Transport::XHRPolling; 11 | 12 | use constant DEBUG => $ENV{POCKETIO_RESOURCE_DEBUG}; 13 | 14 | my %TRANSPORTS = ( 15 | 'xhr-multipart' => 'XHRMultipart', 16 | 'xhr-polling' => 'XHRPolling', 17 | 'jsonp-polling' => 'JSONPPolling', 18 | 'flashsocket' => 'WebSocket', 19 | 'websocket' => 'WebSocket', 20 | 'htmlfile' => 'Htmlfile' 21 | ); 22 | 23 | sub dispatch { 24 | my $self = shift; 25 | my ($env, $cb) = @_; 26 | 27 | my ($type) = $env->{PATH_INFO} =~ m{^/([^\/]+)/?}; 28 | return unless $type; 29 | 30 | my $transport = $self->_build_transport($type, env => $env); 31 | return unless $transport; 32 | 33 | return $transport->dispatch($cb); 34 | } 35 | 36 | sub _build_transport { 37 | my $self = shift; 38 | my ($type, @args) = @_; 39 | 40 | return unless exists $TRANSPORTS{$type}; 41 | 42 | my $class = "PocketIO::Transport::$TRANSPORTS{$type}"; 43 | 44 | DEBUG && warn "Building $class\n"; 45 | 46 | return $class->new(@args); 47 | } 48 | 49 | 1; 50 | __END__ 51 | 52 | =head1 NAME 53 | 54 | PocketIO::Resource - Resource class 55 | 56 | =head1 DESCRIPTION 57 | 58 | L is a transport dispatcher. 59 | 60 | =head1 METHODS 61 | 62 | =head2 C 63 | 64 | =cut 65 | -------------------------------------------------------------------------------- /cpan/inc/Module/Install/WriteAll.pm: -------------------------------------------------------------------------------- 1 | #line 1 2 | package Module::Install::WriteAll; 3 | 4 | use strict; 5 | use Module::Install::Base (); 6 | 7 | use vars qw{$VERSION @ISA $ISCORE}; 8 | BEGIN { 9 | $VERSION = '1.01'; 10 | @ISA = qw{Module::Install::Base}; 11 | $ISCORE = 1; 12 | } 13 | 14 | sub WriteAll { 15 | my $self = shift; 16 | my %args = ( 17 | meta => 1, 18 | sign => 0, 19 | inline => 0, 20 | check_nmake => 1, 21 | @_, 22 | ); 23 | 24 | $self->sign(1) if $args{sign}; 25 | $self->admin->WriteAll(%args) if $self->is_admin; 26 | 27 | $self->check_nmake if $args{check_nmake}; 28 | unless ( $self->makemaker_args->{PL_FILES} ) { 29 | # XXX: This still may be a bit over-defensive... 30 | unless ($self->makemaker(6.25)) { 31 | $self->makemaker_args( PL_FILES => {} ) if -f 'Build.PL'; 32 | } 33 | } 34 | 35 | # Until ExtUtils::MakeMaker support MYMETA.yml, make sure 36 | # we clean it up properly ourself. 37 | $self->realclean_files('MYMETA.yml'); 38 | 39 | if ( $args{inline} ) { 40 | $self->Inline->write; 41 | } else { 42 | $self->Makefile->write; 43 | } 44 | 45 | # The Makefile write process adds a couple of dependencies, 46 | # so write the META.yml files after the Makefile. 47 | if ( $args{meta} ) { 48 | $self->Meta->write; 49 | } 50 | 51 | # Experimental support for MYMETA 52 | if ( $ENV{X_MYMETA} ) { 53 | if ( $ENV{X_MYMETA} eq 'JSON' ) { 54 | $self->Meta->write_mymeta_json; 55 | } else { 56 | $self->Meta->write_mymeta_yaml; 57 | } 58 | } 59 | 60 | return 1; 61 | } 62 | 63 | 1; 64 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/lib/socket.io/utils.js: -------------------------------------------------------------------------------- 1 | exports.options = { 2 | options: function(options, merge){ 3 | this.options = exports.merge(options || {}, merge || {}); 4 | } 5 | }; 6 | 7 | exports.merge = function(source, merge){ 8 | for (var i in merge) source[i] = merge[i]; 9 | return source; 10 | }; 11 | 12 | var frame = '~m~'; 13 | 14 | function stringify(message){ 15 | if (Object.prototype.toString.call(message) == '[object Object]'){ 16 | return '~j~' + JSON.stringify(message); 17 | } else { 18 | return String(message); 19 | } 20 | }; 21 | 22 | exports.encode = function(messages){ 23 | var ret = '', message, 24 | messages = Array.isArray(messages) ? messages : [messages]; 25 | for (var i = 0, l = messages.length; i < l; i++){ 26 | message = messages[i] === null || messages[i] === undefined ? '' : stringify(messages[i]); 27 | ret += frame + message.length + frame + message; 28 | } 29 | return ret; 30 | }; 31 | 32 | exports.decode = function(data){ 33 | var messages = [], number, n; 34 | do { 35 | if (data.substr(0, 3) !== frame) return messages; 36 | data = data.substr(3); 37 | number = '', n = ''; 38 | for (var i = 0, l = data.length; i < l; i++){ 39 | n = Number(data.substr(i, 1)); 40 | if (data.substr(i, 1) == n){ 41 | number += n; 42 | } else { 43 | data = data.substr(number.length + frame.length) 44 | number = Number(number); 45 | break; 46 | } 47 | } 48 | messages.push(data.substr(0, number)); // here 49 | data = data.substr(number); 50 | } while(data !== ''); 51 | return messages; 52 | }; -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/lib/io.js: -------------------------------------------------------------------------------- 1 | /** 2 | * socket.io-node-client 3 | * Copyright(c) 2011 LearnBoost 4 | * MIT Licensed 5 | */ 6 | 7 | /** 8 | * @namespace 9 | */ 10 | var io = this.io = { 11 | 12 | /** 13 | * Library version. 14 | */ 15 | version: '0.6.3', 16 | 17 | /** 18 | * Updates the location of the WebSocketMain.swf file that is required for the Flashsocket transport. 19 | * This should only be needed if you want to load in the WebSocketMainInsecure.swf or if you want to 20 | * host the .swf file on a other server. 21 | * 22 | * @static 23 | * @deprecated Set the variable `WEB_SOCKET_SWF_LOCATION` pointing to WebSocketMain.swf 24 | * @param {String} path The path of the .swf file 25 | * @api public 26 | */ 27 | setPath: function(path){ 28 | if (window.console && console.error) console.error('io.setPath will be removed. Please set the variable WEB_SOCKET_SWF_LOCATION pointing to WebSocketMain.swf'); 29 | this.path = /\/$/.test(path) ? path : path + '/'; 30 | WEB_SOCKET_SWF_LOCATION = path + 'lib/vendor/web-socket-js/WebSocketMain.swf'; 31 | } 32 | }; 33 | 34 | /** 35 | * Expose Socket.IO in jQuery 36 | */ 37 | if ('jQuery' in this) jQuery.io = this.io; 38 | 39 | /** 40 | * Default path to the .swf file. 41 | */ 42 | if (typeof window != 'undefined'){ 43 | // WEB_SOCKET_SWF_LOCATION = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//cdn.socket.io/' + this.io.version + '/WebSocketMain.swf'; 44 | if (typeof WEB_SOCKET_SWF_LOCATION === 'undefined') 45 | WEB_SOCKET_SWF_LOCATION = '/socket.io/lib/vendor/web-socket-js/WebSocketMain.swf'; 46 | } 47 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/lib/socket.io/transports/htmlfile.js: -------------------------------------------------------------------------------- 1 | var Client = require('../client') 2 | , util = require(process.binding('natives').util ? 'util' : 'sys') 3 | , qs = require('querystring'); 4 | 5 | var HTMLFile = module.exports = function(){ 6 | Client.apply(this, arguments); 7 | }; 8 | 9 | util.inherits(HTMLFile, Client); 10 | 11 | HTMLFile.prototype._onConnect = function(req, res){ 12 | var self = this, body = ''; 13 | switch (req.method){ 14 | case 'GET': 15 | Client.prototype._onConnect.call(this, req, res); 16 | this.response.useChunkedEncodingByDefault = true; 17 | this.response.shouldKeepAlive = true; 18 | this.response.writeHead(200, { 19 | 'Content-Type': 'text/html', 20 | 'Connection': 'keep-alive', 21 | 'Transfer-Encoding': 'chunked' 22 | }); 23 | this.response.write('' + new Array(245).join(' ')); 24 | this._payload(); 25 | break; 26 | 27 | case 'POST': 28 | req.addListener('data', function(message){ 29 | body += message; 30 | }); 31 | req.addListener('end', function(){ 32 | try { 33 | var msg = qs.parse(body); 34 | self._onMessage(msg.data); 35 | } catch(e){ 36 | self.listener.options.log('htmlfile message handler error - ' + e.stack); 37 | } 38 | res.writeHead(200, {'Content-Type': 'text/plain'}); 39 | res.write('ok'); 40 | res.end(); 41 | }); 42 | break; 43 | } 44 | }; 45 | 46 | HTMLFile.prototype._write = function(message){ 47 | if (this._open) 48 | this.response.write(''); //json for escaping 49 | }; 50 | -------------------------------------------------------------------------------- /app.psgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use strict; 3 | use warnings; 4 | use Plack::Request; 5 | use Plack::Builder; 6 | use Plack::App::File; 7 | use Plack::App::Cascade; 8 | use File::Basename; 9 | BEGIN { chdir dirname(__FILE__) }; 10 | use lib dirname(__FILE__)."/third-party/lib"; 11 | 12 | my $html = do { 13 | local $/; 14 | open my $fh, '<', 'index.mt'; 15 | <$fh>; 16 | }; 17 | 18 | my $app = sub { 19 | my $env = shift; 20 | my $req = Plack::Request->new($env); 21 | my $res = $req->new_response(200); 22 | 23 | if ($req->path eq '/') { 24 | $res->content_type('text/html; charset=utf-8'); 25 | $res->content($html); 26 | } else { 27 | $res->code(404); 28 | } 29 | 30 | $res->finalize; 31 | }; 32 | 33 | use PocketIO; 34 | my $path_to_socket_io = "./third-party/Socket.IO-node"; 35 | 36 | builder { 37 | enable 'ContentLength'; 38 | 39 | mount '/socket.io/socket.io.js' => Plack::App::File->new( 40 | file => "$path_to_socket_io/support/socket.io-client/socket.io.js" 41 | ); 42 | mount '/socket.io/lib' => Plack::App::File->new( 43 | root => "$path_to_socket_io/support/socket.io-client/lib" 44 | ); 45 | mount '/socket.io' => PocketIO->new( 46 | handler => sub { 47 | my $self = shift; 48 | $self->on_message(sub { 49 | my $self = shift; 50 | my ($message) = @_; 51 | $self->send_broadcast($message); # {message => [$self->id, $message]}); 52 | }); 53 | } 54 | ); 55 | mount '/' => 56 | Plack::App::Cascade->new 57 | ( apps => [ $app, 58 | Plack::App::File->new( root => '.' )->to_app, 59 | ] ); 60 | }; 61 | -------------------------------------------------------------------------------- /cpan/Multiplayer.pm: -------------------------------------------------------------------------------- 1 | package App::SocialCalc::Multiplayer; 2 | use 5.008001; 3 | our $VERSION = 20110626; 4 | 5 | 1; 6 | 7 | __END__ 8 | 9 | =encoding utf8 10 | 11 | =head1 NAME 12 | 13 | App::SocialCalc::Multiplayer - Multiplayer SocialCalc Server with WebSocket 14 | 15 | =head1 SYNOPSIS 16 | 17 | Run this in a host computer: 18 | 19 | % socialcalc-multiplayer.pl 20 | Accepting requests at http://0.0.0.0:9999/ 21 | 22 | Then connect to port 9999 with two or more browsers, and start collaboratively 23 | edit a web-based spreadsheet. 24 | 25 | =head1 DESCRIPTION 26 | 27 | This is a convenient bundle around a prototypical WebSocket-SocialCalc 28 | integration hack, based on the demonstration in a YAPC::Tiny talk for Chupei.pm 29 | during late October 2009. 30 | 31 | Please see L for more information. 32 | 33 | =head1 AUTHORS 34 | 35 | 唐鳳 Ecpan@audreyt.orgE 36 | 37 | =head1 COPYRIGHT 38 | 39 | This work is derived from the SocialCalc program: 40 | 41 | Copyright (C) 2009-2011 Socialtext, Inc. 42 | All Rights Reserved. 43 | 44 | The upstream source tree was derived from: 45 | 46 | http://github.com/DanBricklin/socialcalc 47 | 48 | Other than the CPAL license asserted by copyright holders above (see 49 | F and F), 唐鳳 places no 50 | additional copyright claims over the collaborative editing extensions, 51 | as detailed in the paragraph below. 52 | 53 | =head1 CC0 1.0 Universal 54 | 55 | To the extent possible under law, 唐鳳 has waived all copyright and related 56 | or neighboring rights to L. 57 | 58 | This work is published from Taiwan. 59 | 60 | L 61 | 62 | =cut 63 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/example/key.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEAz+LXZOjcQCJq3+ZKUFabj71oo/ex/XsBcFqtBThjjTw9CVEV 3 | wfPQQp4XwtPiB204vnYXwQ1/R2NdTQqCZu47l79LssL/u2a5Y9+0NEU3nQA5qdt+ 4 | 1FAE0c5oexPimXOrR3GWfKz7PmZ2O0117IeCUUXPG5U8umhDe/4mDF4ZNJiKc404 5 | WthquTqgS7rLQZHhZ6D0EnGnOkzlmxJMYPNHSOY1/6ivdNUUcC87awNEA3lgfhy2 6 | 5IyBK3QJc+aYKNTbt70Lery3bu2wWLFGtmNiGlQTS4JsxImRsECTI727ObS7/FWA 7 | QsqW+COL0Sa5BuMFrFIpjPrEe0ih7vRRbdmXRwIDAQABAoIBAGe4+9VqZfJN+dsq 8 | 8Osyuz01uQ8OmC0sAWTIqUlQgENIyf9rCJsUBlYmwR5BT6Z69XP6QhHdpSK+TiAR 9 | XUz0EqG9HYzcxHIBaACP7j6iRoQ8R4kbbiWKo0z3WqQGIOqFjvD/mKEuQdE5mEYw 10 | eOUCG6BnX1WY2Yr8WKd2AA/tp0/Y4d8z04u9eodMpSTbHTzYMJb5SbBN1vo6FY7q 11 | 8zSuO0BMzXlAxUsCwHsk1GQHFr8Oh3zIR7bQGtMBouI+6Lhh7sjFYsfxJboqMTBV 12 | IKaA216M6ggHG7MU1/jeKcMGDmEfqQLQoyWp29rMK6TklUgipME2L3UD7vTyAVzz 13 | xbVOpZkCgYEA8CXW4sZBBrSSrLR5SB+Ubu9qNTggLowOsC/kVKB2WJ4+xooc5HQo 14 | mFhq1v/WxPQoWIxdYsfg2odlL+JclK5Qcy6vXmRSdAQ5lK9gBDKxZSYc3NwAw2HA 15 | zyHCTK+I0n8PBYQ+yGcrxu0WqTGnlLW+Otk4CejO34WlgHwbH9bbY5UCgYEA3ZvT 16 | C4+OoMHXlmICSt29zUrYiL33IWsR3/MaONxTEDuvgkOSXXQOl/8Ebd6Nu+3WbsSN 17 | bjiPC/JyL1YCVmijdvFpl4gjtgvfJifs4G+QHvO6YfsYoVANk4u6g6rUuBIOwNK4 18 | RwYxwDc0oysp+g7tPxoSgDHReEVKJNzGBe9NGGsCgYEA4O4QP4gCEA3B9BF2J5+s 19 | n9uPVxmiyvZUK6Iv8zP4pThTBBMIzNIf09G9AHPQ7djikU2nioY8jXKTzC3xGTHM 20 | GJZ5m6fLsu7iH+nDvSreDSeNkTBfZqGAvoGYQ8uGE+L+ZuRfCcXYsxIOT5s6o4c3 21 | Dle2rVFpsuKzCY00urW796ECgYBn3go75+xEwrYGQSer6WR1nTgCV29GVYXKPooy 22 | zmmMOT1Yw80NSkEw0pFD4cTyqVYREsTrPU0mn1sPfrOXxnGfZSVFpcR/Je9QVfQ7 23 | eW7GYxwfom335aqHVj10SxRqteP+UoWWnHujCPz94VRKZMakBddYCIGSan+G6YdS 24 | 7sdmwwKBgBc2qj0wvGXDF2kCLwSGfWoMf8CS1+5fIiUIdT1e/+7MfDdbmLMIFVjF 25 | QKS3zVViXCbrG5SY6wS9hxoc57f6E2A8vcaX6zy2xkZlGHQCpWRtEM5R01OWJQaH 26 | HsHMmQZGUQVoDm1oRkDhrTFK4K3ukc3rAxzeTZ96utOQN8/KJsTv 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/lib/transports/xhr-multipart.js: -------------------------------------------------------------------------------- 1 | /** 2 | * socket.io-node-client 3 | * Copyright(c) 2011 LearnBoost 4 | * MIT Licensed 5 | */ 6 | 7 | (function(){ 8 | var io = this.io, 9 | 10 | /** 11 | * The XHR-Multipart transport uses the a multipart XHR connection to 12 | * stream in the data from the Socket.IO server 13 | * 14 | * @constructor 15 | * @extends {io.Transport.XHR} 16 | * @api public 17 | */ 18 | XHRMultipart = io.Transport['xhr-multipart'] = function(){ 19 | io.Transport.XHR.apply(this, arguments); 20 | }; 21 | 22 | io.util.inherit(XHRMultipart, io.Transport.XHR); 23 | 24 | /** 25 | * The transport type, you use this to identify which transport was chosen. 26 | * 27 | * @type {String} 28 | * @api public 29 | */ 30 | XHRMultipart.prototype.type = 'xhr-multipart'; 31 | 32 | /** 33 | * Starts the multipart stream for incomming messages. 34 | * 35 | * @api private 36 | */ 37 | XHRMultipart.prototype.get = function(){ 38 | var self = this; 39 | this.xhr = this.request('', 'GET', true); 40 | this.xhr.onreadystatechange = function(){ 41 | if (self.xhr.readyState == 4) self.onData(self.xhr.responseText); 42 | }; 43 | this.xhr.send(null); 44 | }; 45 | 46 | /** 47 | * Checks if browser supports this transport. 48 | * 49 | * @return {Boolean} 50 | * @api public 51 | */ 52 | XHRMultipart.check = function(){ 53 | return 'XMLHttpRequest' in window && 'prototype' in XMLHttpRequest && 'multipart' in XMLHttpRequest.prototype; 54 | }; 55 | 56 | /** 57 | * Check if cross domain requests are supported. 58 | * 59 | * @returns {Boolean} 60 | * @api public 61 | */ 62 | XHRMultipart.xdomainCheck = function(){ 63 | return true; 64 | }; 65 | 66 | })(); -------------------------------------------------------------------------------- /third-party/Socket.IO-node/example/server.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Important note: this application is not suitable for benchmarks! 3 | */ 4 | 5 | var http = require('http') 6 | , url = require('url') 7 | , fs = require('fs') 8 | , io = require('../') 9 | , sys = require(process.binding('natives').util ? 'util' : 'sys') 10 | , server; 11 | 12 | server = http.createServer(function(req, res){ 13 | // your normal server code 14 | var path = url.parse(req.url).pathname; 15 | switch (path){ 16 | case '/': 17 | res.writeHead(200, {'Content-Type': 'text/html'}); 18 | res.write('

Welcome. Try the chat example.

'); 19 | res.end(); 20 | break; 21 | 22 | case '/json.js': 23 | case '/chat.html': 24 | fs.readFile(__dirname + path, function(err, data){ 25 | if (err) return send404(res); 26 | res.writeHead(200, {'Content-Type': path == 'json.js' ? 'text/javascript' : 'text/html'}) 27 | res.write(data, 'utf8'); 28 | res.end(); 29 | }); 30 | break; 31 | 32 | default: send404(res); 33 | } 34 | }), 35 | 36 | send404 = function(res){ 37 | res.writeHead(404); 38 | res.write('404'); 39 | res.end(); 40 | }; 41 | 42 | server.listen(8080); 43 | 44 | // socket.io, I choose you 45 | // simplest chat application evar 46 | var io = io.listen(server) 47 | , buffer = []; 48 | 49 | io.on('connection', function(client){ 50 | client.send({ buffer: buffer }); 51 | client.broadcast({ announcement: client.sessionId + ' connected' }); 52 | 53 | client.on('message', function(message){ 54 | var msg = { message: [client.sessionId, message] }; 55 | buffer.push(msg); 56 | if (buffer.length > 15) buffer.shift(); 57 | client.broadcast(msg); 58 | }); 59 | 60 | client.on('disconnect', function(){ 61 | client.broadcast({ announcement: client.sessionId + ' disconnected' }); 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/example/json.js: -------------------------------------------------------------------------------- 1 | if(!this.JSON){JSON=function(){function f(n){return n<10?'0'+n:n;} 2 | Date.prototype.toJSON=function(){return this.getUTCFullYear()+'-'+ 3 | f(this.getUTCMonth()+1)+'-'+ 4 | f(this.getUTCDate())+'T'+ 5 | f(this.getUTCHours())+':'+ 6 | f(this.getUTCMinutes())+':'+ 7 | f(this.getUTCSeconds())+'Z';};var m={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};function stringify(value,whitelist){var a,i,k,l,r=/["\\\x00-\x1f\x7f-\x9f]/g,v;switch(typeof value){case'string':return r.test(value)?'"'+value.replace(r,function(a){var c=m[a];if(c){return c;} 8 | c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+ 9 | (c%16).toString(16);})+'"':'"'+value+'"';case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';} 10 | if(typeof value.toJSON==='function'){return stringify(value.toJSON());} 11 | a=[];if(typeof value.length==='number'&&!(value.propertyIsEnumerable('length'))){l=value.length;for(i=0;iWelcome. Try the SSL Chat example.'); 22 | res.end(); 23 | break; 24 | 25 | case '/json.js': 26 | case '/chat-ssl.html': 27 | fs.readFile(__dirname + path, function(err, data){ 28 | if (err) return send404(res); 29 | res.writeHead(200, {'Content-Type': path == 'json.js' ? 'text/javascript' : 'text/html'}) 30 | res.write(data, 'utf8'); 31 | res.end(); 32 | }); 33 | break; 34 | 35 | default: send404(res); 36 | } 37 | }), 38 | 39 | send404 = function(res){ 40 | res.writeHead(404); 41 | res.write('404'); 42 | res.end(); 43 | }; 44 | 45 | server.listen(443); 46 | 47 | // socket.io, I choose you 48 | // simplest chat application evar 49 | var io = io.listen(server) 50 | , buffer = []; 51 | 52 | io.on('connection', function(client){ 53 | client.send({ buffer: buffer }); 54 | client.broadcast({ announcement: client.sessionId + ' connected' }); 55 | 56 | client.on('message', function(message){ 57 | var msg = { message: [client.sessionId, message] }; 58 | buffer.push(msg); 59 | if (buffer.length > 15) buffer.shift(); 60 | client.broadcast(msg); 61 | }); 62 | 63 | client.on('disconnect', function(){ 64 | client.broadcast({ announcement: client.sessionId + ' disconnected' }); 65 | }); 66 | }); 67 | -------------------------------------------------------------------------------- /cpan/inc/Module/Install/Win32.pm: -------------------------------------------------------------------------------- 1 | #line 1 2 | package Module::Install::Win32; 3 | 4 | use strict; 5 | use Module::Install::Base (); 6 | 7 | use vars qw{$VERSION @ISA $ISCORE}; 8 | BEGIN { 9 | $VERSION = '1.01'; 10 | @ISA = 'Module::Install::Base'; 11 | $ISCORE = 1; 12 | } 13 | 14 | # determine if the user needs nmake, and download it if needed 15 | sub check_nmake { 16 | my $self = shift; 17 | $self->load('can_run'); 18 | $self->load('get_file'); 19 | 20 | require Config; 21 | return unless ( 22 | $^O eq 'MSWin32' and 23 | $Config::Config{make} and 24 | $Config::Config{make} =~ /^nmake\b/i and 25 | ! $self->can_run('nmake') 26 | ); 27 | 28 | print "The required 'nmake' executable not found, fetching it...\n"; 29 | 30 | require File::Basename; 31 | my $rv = $self->get_file( 32 | url => 'http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe', 33 | ftp_url => 'ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe', 34 | local_dir => File::Basename::dirname($^X), 35 | size => 51928, 36 | run => 'Nmake15.exe /o > nul', 37 | check_for => 'Nmake.exe', 38 | remove => 1, 39 | ); 40 | 41 | die <<'END_MESSAGE' unless $rv; 42 | 43 | ------------------------------------------------------------------------------- 44 | 45 | Since you are using Microsoft Windows, you will need the 'nmake' utility 46 | before installation. It's available at: 47 | 48 | http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe 49 | or 50 | ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe 51 | 52 | Please download the file manually, save it to a directory in %PATH% (e.g. 53 | C:\WINDOWS\COMMAND\), then launch the MS-DOS command line shell, "cd" to 54 | that directory, and run "Nmake15.exe" from there; that will create the 55 | 'nmake.exe' file needed by this module. 56 | 57 | You may then resume the installation process described in README. 58 | 59 | ------------------------------------------------------------------------------- 60 | END_MESSAGE 61 | 62 | } 63 | 64 | 1; 65 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/bin/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Socket.IO client 5 | * 6 | * @author Guillermo Rauch 7 | * @license The MIT license. 8 | * @copyright Copyright (c) 2010 LearnBoost 9 | */ 10 | 11 | /* 12 | * This file will help you take all the Socket.IO client files and build socket.io.js. 13 | * You can later use Google Closure Compiler on it. 14 | */ 15 | 16 | var fs = require('fs'), 17 | socket = require('../lib/io'), 18 | jsp = require('../lib/vendor/uglifyjs/lib/parse-js'), 19 | pro = require("../lib/vendor/uglifyjs/lib/process"), 20 | ast, 21 | files = [ 22 | 'io.js', 23 | 'util.js', 24 | 'transport.js', 25 | 'transports/xhr.js', 26 | 'transports/websocket.js', 27 | 'transports/flashsocket.js', 28 | 'transports/htmlfile.js', 29 | 'transports/xhr-multipart.js', 30 | 'transports/xhr-polling.js', 31 | 'transports/jsonp-polling.js', 32 | 'socket.js', 33 | 'vendor/web-socket-js/swfobject.js', 34 | 'vendor/web-socket-js/web_socket.js' 35 | ], 36 | content = "/** Socket.IO "+ socket.io.version +" - Built with build.js */\n", 37 | license = "/* Socket.IO.min "+ socket.io.version +" @author Guillermo Rauch , @license The MIT license., @copyright Copyright (c) 2010 LearnBoost */\n"; 38 | 39 | console.log('Reading files…'); 40 | 41 | files.forEach(function(file){ 42 | var path = __dirname + '/../lib/' + file; 43 | console.log(' + ' + path); 44 | content += fs.readFileSync(path) + "\n"; 45 | }); 46 | 47 | console.log('Generating…'); 48 | 49 | fs.write(fs.openSync(__dirname + '/../socket.io.js', 'w'), content, 0, 'utf8'); 50 | console.log(' + ' + __dirname + '/../socket.io.js'); 51 | 52 | console.log('Uglyfying…'); 53 | ast = jsp.parse(content); 54 | ast = pro.ast_mangle(ast); // get a new AST with mangled names 55 | ast = pro.ast_squeeze(ast); 56 | fs.write(fs.openSync(__dirname + '/../socket.io.min.js', 'w'), license + pro.gen_code(ast), 0, 'utf8'); 57 | console.log(' + ' + __dirname + '/../socket.io.min.js'); 58 | 59 | console.log('All done!'); -------------------------------------------------------------------------------- /cpan/inc/Module/Install/Can.pm: -------------------------------------------------------------------------------- 1 | #line 1 2 | package Module::Install::Can; 3 | 4 | use strict; 5 | use Config (); 6 | use File::Spec (); 7 | use ExtUtils::MakeMaker (); 8 | use Module::Install::Base (); 9 | 10 | use vars qw{$VERSION @ISA $ISCORE}; 11 | BEGIN { 12 | $VERSION = '1.01'; 13 | @ISA = 'Module::Install::Base'; 14 | $ISCORE = 1; 15 | } 16 | 17 | # check if we can load some module 18 | ### Upgrade this to not have to load the module if possible 19 | sub can_use { 20 | my ($self, $mod, $ver) = @_; 21 | $mod =~ s{::|\\}{/}g; 22 | $mod .= '.pm' unless $mod =~ /\.pm$/i; 23 | 24 | my $pkg = $mod; 25 | $pkg =~ s{/}{::}g; 26 | $pkg =~ s{\.pm$}{}i; 27 | 28 | local $@; 29 | eval { require $mod; $pkg->VERSION($ver || 0); 1 }; 30 | } 31 | 32 | # check if we can run some command 33 | sub can_run { 34 | my ($self, $cmd) = @_; 35 | 36 | my $_cmd = $cmd; 37 | return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd)); 38 | 39 | for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') { 40 | next if $dir eq ''; 41 | my $abs = File::Spec->catfile($dir, $_[1]); 42 | return $abs if (-x $abs or $abs = MM->maybe_command($abs)); 43 | } 44 | 45 | return; 46 | } 47 | 48 | # can we locate a (the) C compiler 49 | sub can_cc { 50 | my $self = shift; 51 | my @chunks = split(/ /, $Config::Config{cc}) or return; 52 | 53 | # $Config{cc} may contain args; try to find out the program part 54 | while (@chunks) { 55 | return $self->can_run("@chunks") || (pop(@chunks), next); 56 | } 57 | 58 | return; 59 | } 60 | 61 | # Fix Cygwin bug on maybe_command(); 62 | if ( $^O eq 'cygwin' ) { 63 | require ExtUtils::MM_Cygwin; 64 | require ExtUtils::MM_Win32; 65 | if ( ! defined(&ExtUtils::MM_Cygwin::maybe_command) ) { 66 | *ExtUtils::MM_Cygwin::maybe_command = sub { 67 | my ($self, $file) = @_; 68 | if ($file =~ m{^/cygdrive/}i and ExtUtils::MM_Win32->can('maybe_command')) { 69 | ExtUtils::MM_Win32->maybe_command($file); 70 | } else { 71 | ExtUtils::MM_Unix->maybe_command($file); 72 | } 73 | } 74 | } 75 | } 76 | 77 | 1; 78 | 79 | __END__ 80 | 81 | #line 156 82 | -------------------------------------------------------------------------------- /third-party/lib/PocketIO/Pool.pm: -------------------------------------------------------------------------------- 1 | package PocketIO::Pool; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Scalar::Util qw(blessed); 7 | 8 | use PocketIO::Connection; 9 | 10 | use constant DEBUG => $ENV{POCKETIO_POOL_DEBUG}; 11 | 12 | sub find_connection { 13 | my $self = shift; 14 | my ($conn) = @_; 15 | 16 | my $id = blessed $conn ? $conn->id : $conn; 17 | 18 | return $self->_instance->{connections}->{$id}; 19 | } 20 | 21 | sub connections { 22 | my $self = shift; 23 | 24 | return values %{$self->_instance->{connections}}; 25 | } 26 | 27 | sub add_connection { 28 | my $self = shift; 29 | 30 | my $conn = $self->_build_connection(@_); 31 | 32 | $self->_instance->{connections}->{$conn->id} = $conn; 33 | 34 | $conn->connecting; 35 | 36 | DEBUG && warn "Added connection '" . $conn->id . "'\n"; 37 | 38 | return $conn; 39 | } 40 | 41 | sub remove_connection { 42 | my $self = shift; 43 | 44 | my $id = blessed $_[0] ? $_[0]->id : $_[0]; 45 | 46 | delete $self->_instance->{connections}->{$id}; 47 | 48 | DEBUG && warn "Removed connection '" . $id . "'\n"; 49 | } 50 | 51 | sub _instance { 52 | my $class = shift; 53 | 54 | no strict; 55 | 56 | ${"$class\::_instance"} ||= $class->_new_instance(@_); 57 | 58 | return ${"$class\::_instance"}; 59 | } 60 | 61 | sub _new_instance { 62 | my $class = shift; 63 | 64 | my $self = bless {@_}, $class; 65 | 66 | $self->{connections} = {}; 67 | 68 | return $self; 69 | } 70 | 71 | sub _build_connection { 72 | my $self = shift; 73 | 74 | return PocketIO::Connection->new(@_, 75 | on_connect_failed => sub { $self->remove_connection(@_) }); 76 | } 77 | 78 | 79 | 1; 80 | __END__ 81 | 82 | =head1 NAME 83 | 84 | PocketIO::Pool - Connection pool 85 | 86 | =head1 DESCRIPTION 87 | 88 | L is a singleton connection pool. 89 | 90 | =head1 METHODS 91 | 92 | =head2 C 93 | 94 | =head2 C 95 | 96 | =head2 C 97 | 98 | =head2 C 99 | 100 | =cut 101 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/lib/vendor/web-socket-js/sample.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | Sample of web_socket.js 8 | 9 | 10 | 11 | 12 | 13 | 68 | 69 |
70 | 71 | 72 | 73 |
74 |
75 | 76 | -------------------------------------------------------------------------------- /third-party/lib/PocketIO/Transport/WebSocket.pm: -------------------------------------------------------------------------------- 1 | package PocketIO::Transport::WebSocket; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use base 'PocketIO::Transport::Base'; 7 | 8 | use Protocol::WebSocket::Frame; 9 | use Protocol::WebSocket::Handshake::Server; 10 | 11 | use PocketIO::Handle; 12 | 13 | sub name {'websocket'} 14 | 15 | sub dispatch { 16 | my $self = shift; 17 | my ($cb) = @_; 18 | 19 | my $fh = $self->req->env->{'psgix.io'}; 20 | return unless $fh; 21 | 22 | my $hs = Protocol::WebSocket::Handshake::Server->new_from_psgi($self->req->env); 23 | return unless $hs->parse($fh); 24 | 25 | return unless $hs->is_done; 26 | 27 | my $handle = $self->_build_handle($fh); 28 | my $frame = Protocol::WebSocket::Frame->new; 29 | 30 | return sub { 31 | my $respond = shift; 32 | 33 | $handle->write( 34 | $hs->to_string => sub { 35 | my $handle = shift; 36 | 37 | my $conn = $self->add_connection(on_connect => $cb); 38 | 39 | my $close_cb = sub { 40 | $handle->close; 41 | $self->client_disconnected($conn); 42 | }; 43 | $handle->on_eof($close_cb); 44 | $handle->on_error($close_cb); 45 | 46 | $handle->on_heartbeat(sub { $conn->send_heartbeat }); 47 | 48 | $handle->on_read( 49 | sub { 50 | $frame->append($_[1]); 51 | 52 | while (my $message = $frame->next_bytes) { 53 | $conn->read($message); 54 | } 55 | } 56 | ); 57 | 58 | $conn->on_write( 59 | sub { 60 | my $bytes = $self->_build_frame($_[1]); 61 | 62 | $handle->write($bytes); 63 | } 64 | ); 65 | 66 | $self->client_connected($conn); 67 | 68 | $conn->send_id_message($conn->id); 69 | } 70 | ); 71 | }; 72 | } 73 | 74 | sub _build_frame { 75 | my $self = shift; 76 | my ($bytes) = @_; 77 | 78 | return Protocol::WebSocket::Frame->new($bytes)->to_bytes; 79 | } 80 | 81 | 1; 82 | __END__ 83 | 84 | =head1 NAME 85 | 86 | PocketIO::WebSocket - WebSocket transport 87 | 88 | =head1 DESCRIPTION 89 | 90 | L is a WebSocket transport implementation. 91 | 92 | =head1 SEE ALSO 93 | 94 | L 95 | 96 | =cut 97 | -------------------------------------------------------------------------------- /socketpolicy.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # Simple Flash Socket Policy Server 4 | # http://www.lightsphere.com/dev/articles/flash_socket_policy.html 5 | # 6 | # Copyright (C) 2008 Jacqueline Kira Hamilton 7 | # 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | 22 | use Socket; 23 | use IO::Handle; 24 | 25 | my $should_be_logging = 1; # change to 0 to turn off logging. 26 | 27 | my $logfile = 'log'; 28 | 29 | if ($should_be_logging) { 30 | open(LOG, ">$logfile") or warn "Can't open $logfile: $!\n"; 31 | LOG->autoflush(1); 32 | } 33 | 34 | my $port = 843; 35 | my $proto = getprotobyname('tcp'); 36 | 37 | # start the server: 38 | 39 | &log("Starting server on port $port"); 40 | socket(Server, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; 41 | setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, 1 ) or die "setsockopt: $!"; 42 | bind(Server,sockaddr_in($port,INADDR_ANY)) or die "bind: $!"; 43 | listen(Server,SOMAXCONN) or die "listen: $!"; 44 | 45 | Server->autoflush( 1 ); 46 | 47 | my $paddr; 48 | &log("Server started. Waiting for connections."); 49 | 50 | $/ = "\0"; # reset terminator to null char 51 | 52 | # listening loop. 53 | 54 | for ( ; $paddr = accept(Client,Server); close Client) { 55 | Client->autoflush(1); 56 | my($port,$iaddr) = sockaddr_in($paddr); 57 | my $ip_address = inet_ntoa($iaddr); 58 | my $name = gethostbyaddr($iaddr,AF_INET) || $ip_address; 59 | &log( scalar localtime() . ": Connection from $name" ); 60 | 61 | my $line = ; 62 | &log("Input: $line"); 63 | 64 | if ($line =~ /.*policy\-file.*/i) { 65 | print Client &xml_policy; 66 | } 67 | } 68 | 69 | sub xml_policy { 70 | my $str = qq(\0); 71 | return $str; 72 | } 73 | 74 | sub log { 75 | my($msg) = @_; 76 | if ($should_be_logging) { 77 | print LOG $msg,"\n"; 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/lib/socket.io/transports/xhr-multipart.js: -------------------------------------------------------------------------------- 1 | var Client = require('../client') 2 | , util = require(process.binding('natives').util ? 'util' : 'sys') 3 | , qs = require('querystring'); 4 | 5 | var Multipart = module.exports = function(){ 6 | Client.apply(this, arguments); 7 | }; 8 | 9 | util.inherits(Multipart, Client); 10 | 11 | Multipart.prototype._onConnect = function(req, res){ 12 | var self = this, body = '', headers = {}; 13 | // https://developer.mozilla.org/En/HTTP_Access_Control 14 | if (req.headers.origin && this._verifyOrigin(req.headers.origin)){ 15 | headers['Access-Control-Allow-Origin'] = '*'; 16 | headers['Access-Control-Allow-Credentials'] = 'true'; 17 | } 18 | if (typeof req.headers['access-control-request-method'] !== 'undefined'){ 19 | // CORS preflight message 20 | headers['Access-Control-Allow-Methods'] = req.headers['access-control-request-method']; 21 | res.writeHead(200, headers); 22 | res.write('ok'); 23 | res.end(); 24 | return; 25 | } 26 | switch (req.method){ 27 | case 'GET': 28 | Client.prototype._onConnect.apply(this, [req, res]); 29 | headers['Content-Type'] = 'multipart/x-mixed-replace;boundary="socketio"'; 30 | headers['Connection'] = 'keep-alive'; 31 | this.request.connection.addListener('end', function(){ self._onClose(); }); 32 | this.response.useChunkedEncodingByDefault = false; 33 | this.response.shouldKeepAlive = true; 34 | this.response.writeHead(200, headers); 35 | this.response.write("--socketio\n"); 36 | if ('flush' in this.response) this.response.flush(); 37 | this._payload(); 38 | break; 39 | 40 | case 'POST': 41 | headers['Content-Type'] = 'text/plain'; 42 | req.addListener('data', function(message){ 43 | body += message.toString(); 44 | }); 45 | req.addListener('end', function(){ 46 | try { 47 | var msg = qs.parse(body); 48 | self._onMessage(msg.data); 49 | } catch(e){ 50 | self.listener.options.log('xhr-multipart message handler error - ' + e.stack); 51 | } 52 | res.writeHead(200, headers); 53 | res.write('ok'); 54 | res.end(); 55 | body = ''; 56 | }); 57 | break; 58 | } 59 | }; 60 | 61 | Multipart.prototype._write = function(message){ 62 | if (this._open){ 63 | this.response.write("Content-Type: text/plain" + (message.length === 1 && message.charCodeAt(0) === 6 ? "; charset=us-ascii" : "") + "\n\n"); 64 | this.response.write(message + "\n"); 65 | this.response.write("--socketio\n"); 66 | } 67 | }; 68 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/lib/transports/xhr-polling.js: -------------------------------------------------------------------------------- 1 | /** 2 | * socket.io-node-client 3 | * Copyright(c) 2011 LearnBoost 4 | * MIT Licensed 5 | */ 6 | 7 | (function(){ 8 | var io = this.io, 9 | 10 | /** 11 | * A small stub function that will be used to reduce memory leaks. 12 | * 13 | * @type {Function} 14 | * @api private 15 | */ 16 | empty = new Function(), 17 | 18 | /** 19 | * The XHR-polling transport uses long polling XHR requests to create a 20 | * "persistent" connection with the server. 21 | * 22 | * @constructor 23 | * @extends {io.Transport.XHR} 24 | * @api public 25 | */ 26 | XHRPolling = io.Transport['xhr-polling'] = function(){ 27 | io.Transport.XHR.apply(this, arguments); 28 | }; 29 | 30 | io.util.inherit(XHRPolling, io.Transport.XHR); 31 | 32 | /** 33 | * The transport type, you use this to identify which transport was chosen. 34 | * 35 | * @type {string} 36 | * @api public 37 | */ 38 | XHRPolling.prototype.type = 'xhr-polling'; 39 | 40 | /** 41 | * Establish a connection, for iPhone and Android this will be done once the page 42 | * is loaded. 43 | * 44 | * @returns {Transport} Chaining. 45 | * @api public 46 | */ 47 | XHRPolling.prototype.connect = function(){ 48 | var self = this; 49 | io.util.defer(function(){ io.Transport.XHR.prototype.connect.call(self) }); 50 | return false; 51 | }; 52 | 53 | /** 54 | * Starts a XHR request to wait for incoming messages. 55 | * 56 | * @api private 57 | */ 58 | XHRPolling.prototype.get = function(){ 59 | var self = this; 60 | this.xhr = this.request(+ new Date, 'GET'); 61 | this.xhr.onreadystatechange = function(){ 62 | var status; 63 | if (self.xhr.readyState == 4){ 64 | self.xhr.onreadystatechange = empty; 65 | try { status = self.xhr.status; } catch(e){} 66 | if (status == 200){ 67 | self.onData(self.xhr.responseText); 68 | self.get(); 69 | } else { 70 | self.onDisconnect(); 71 | } 72 | } 73 | }; 74 | this.xhr.send(null); 75 | }; 76 | 77 | /** 78 | * Checks if browser supports this transport. 79 | * 80 | * @return {Boolean} 81 | * @api public 82 | */ 83 | XHRPolling.check = function(){ 84 | return io.Transport.XHR.check(); 85 | }; 86 | 87 | /** 88 | * Check if cross domain requests are supported 89 | * 90 | * @returns {Boolean} 91 | * @api public 92 | */ 93 | XHRPolling.xdomainCheck = function(){ 94 | return io.Transport.XHR.xdomainCheck(); 95 | }; 96 | 97 | })(); 98 | -------------------------------------------------------------------------------- /third-party/hippie/jquery.ev.js: -------------------------------------------------------------------------------- 1 | /* Title: jQuery.ev 2 | * 3 | * A COMET event loop for jQuery 4 | * 5 | * $.ev.loop long-polls on a URL and expects to get an array of JSON-encoded 6 | * objects back. Each of these objects should represent a message from the COMET 7 | * server that's telling your client-side Javascript to do something. 8 | * 9 | */ 10 | (function($){ 11 | 12 | $.ev = { 13 | 14 | handlers : {}, 15 | running : false, 16 | xhr : null, 17 | verbose : true, 18 | timeout : null, 19 | 20 | /* Method: run 21 | * 22 | * Respond to an array of messages using the object in this.handlers 23 | * 24 | */ 25 | run: function(messages) { 26 | var i, m, h; // index, event, handler 27 | for (i = 0; i < messages.length; i++) { 28 | m = messages[i]; 29 | if (!m) continue; 30 | h = this.handlers[m.type]; 31 | if (!h) h = this.handlers['*']; 32 | if ( h) h(m); 33 | } 34 | }, 35 | 36 | /* Method: stop 37 | * 38 | * Stop the loop 39 | * 40 | */ 41 | stop: function() { 42 | if (this.xhr) { 43 | this.xhr.abort(); 44 | this.xhr = null; 45 | } 46 | this.running = false; 47 | }, 48 | 49 | /* 50 | * Method: loop 51 | * 52 | * Long poll on a URL 53 | * 54 | * Arguments: 55 | * 56 | * url 57 | * handler 58 | * 59 | */ 60 | loop: function(url, handlers) { 61 | var self = this; 62 | if (handlers) { 63 | if (typeof handlers == "object") { 64 | this.handlers = handlers; 65 | } else if (typeof handlers == "function") { 66 | this.run = handlers; 67 | } else { 68 | throw("handlers must be an object or function"); 69 | } 70 | } 71 | this.running = true; 72 | this.xhr = $.ajax({ 73 | type : 'GET', 74 | dataType : 'json', 75 | url : url, 76 | timeout : self.timeout, 77 | success : function(messages, status) { 78 | // console.log('success', messages); 79 | self.run(messages) 80 | }, 81 | complete : function(xhr, status) { 82 | var delay; 83 | if (status == 'success') { 84 | delay = 100; 85 | } else { 86 | // console.log('status: ' + status, '; waiting before long-polling again...'); 87 | delay = 5000; 88 | } 89 | // "recursively" loop 90 | window.setTimeout(function(){ if (self.running) self.loop(url); }, delay); 91 | } 92 | }); 93 | } 94 | 95 | }; 96 | 97 | })(jQuery); 98 | -------------------------------------------------------------------------------- /LEGAL.txt: -------------------------------------------------------------------------------- 1 | SOCIALCALC LEGAL.txt FILE: 2 | 3 | LEGAL INFORMATION 4 | 5 | This LEGAL.txt file accompanies the SocialCalc program. It includes notices required by the 6 | licenses as well as general legal notices. 7 | 8 | ========================================= 9 | COPYRIGHT AND ATTRIBUTION NOTICES 10 | ========================================= 11 | 12 | Copyright (C) 2009 Socialtext, Inc. 13 | All Rights Reserved. 14 | 15 | image:sc-logo.gif 16 | "SocialCalc" 17 | http://www.socialcalc.org/xoattrib 18 | 19 | ========================================= 20 | SOURCE CODE AVAILABILITY NOTICE 21 | ========================================= 22 | 23 | The source code for this product is available from: 24 | http://socialcalc.org/. 25 | 26 | ========================================= 27 | GENERAL LEGAL NOTICES 28 | ========================================= 29 | 30 | wikiCalc, Garden, and Software Garden are registered trademarks of Software Garden, Inc. 31 | Socialtext and SocialCalc are registered trademarks of Socialtext, Inc. 32 | The Socialtext logo and Dreamcatcher are trademarks of Socialtext, Inc. 33 | 34 | ========================================= 35 | LEGAL NOTICES REQUIRED BY THE LICENSE 36 | ========================================= 37 | 38 | CHANGES MADE TO THE COVERED CODE (see CPAL Version 1.0 Section 3.3): 39 | 40 | 2008-02-08: 41 | Original Code started as a translation to JavaScript of code in SocialCalc 1.1.0 plus 42 | much new code. 43 | 44 | Python code for the OLPC XO-1 initially coded by Luke Closs of Socialtext, Inc. 45 | 46 | JavaScript initially coded by Dan Bricklin of Software Garden, Inc., for Socialtext, Inc. 47 | Based in part on the SocialCalc 1.1.0 code written in Perl. 48 | The SocialCalc 1.1.0 code was: 49 | Portions (c) Copyright 2005, 2006, 2007 Software Garden, Inc. 50 | All Rights Reserved. 51 | Portions (c) Copyright 2007 Socialtext, Inc. 52 | All Rights Reserved. 53 | The Perl SocialCalc started as modifications to the wikiCalc(R) program, version 1.0. 54 | wikiCalc 1.0 was written by Software Garden, Inc. 55 | Unless otherwise specified, referring to "SocialCalc" in comments refers to this 56 | JavaScript version of the code, not the SocialCalc Perl code. 57 | 58 | ---------- 59 | 60 | (Documentation of future changes as the result of Modifications, including the date of 61 | change, will go here in this LEGAL.txt file. This documentation may be summaries of 62 | changes with the more detailed descriptions included in the actual modified files as 63 | appropriate.) 64 | 65 | ========== 66 | 67 | THIRD PARTY CLAIMS (see CPAL Version 1.0 Section 3.4(a)): 68 | 69 | None. 70 | 71 | [End of LEGAL.txt] 72 | 73 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/example/chat-ssl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | socket.io client test 5 | 6 | 7 | 8 | 9 | 10 | 11 | 42 | 43 |

Sample chat client

44 |

Connecting...

45 |
46 | 47 |
48 | 49 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /cpan/inc/Module/Install/Fetch.pm: -------------------------------------------------------------------------------- 1 | #line 1 2 | package Module::Install::Fetch; 3 | 4 | use strict; 5 | use Module::Install::Base (); 6 | 7 | use vars qw{$VERSION @ISA $ISCORE}; 8 | BEGIN { 9 | $VERSION = '1.01'; 10 | @ISA = 'Module::Install::Base'; 11 | $ISCORE = 1; 12 | } 13 | 14 | sub get_file { 15 | my ($self, %args) = @_; 16 | my ($scheme, $host, $path, $file) = 17 | $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; 18 | 19 | if ( $scheme eq 'http' and ! eval { require LWP::Simple; 1 } ) { 20 | $args{url} = $args{ftp_url} 21 | or (warn("LWP support unavailable!\n"), return); 22 | ($scheme, $host, $path, $file) = 23 | $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; 24 | } 25 | 26 | $|++; 27 | print "Fetching '$file' from $host... "; 28 | 29 | unless (eval { require Socket; Socket::inet_aton($host) }) { 30 | warn "'$host' resolve failed!\n"; 31 | return; 32 | } 33 | 34 | return unless $scheme eq 'ftp' or $scheme eq 'http'; 35 | 36 | require Cwd; 37 | my $dir = Cwd::getcwd(); 38 | chdir $args{local_dir} or return if exists $args{local_dir}; 39 | 40 | if (eval { require LWP::Simple; 1 }) { 41 | LWP::Simple::mirror($args{url}, $file); 42 | } 43 | elsif (eval { require Net::FTP; 1 }) { eval { 44 | # use Net::FTP to get past firewall 45 | my $ftp = Net::FTP->new($host, Passive => 1, Timeout => 600); 46 | $ftp->login("anonymous", 'anonymous@example.com'); 47 | $ftp->cwd($path); 48 | $ftp->binary; 49 | $ftp->get($file) or (warn("$!\n"), return); 50 | $ftp->quit; 51 | } } 52 | elsif (my $ftp = $self->can_run('ftp')) { eval { 53 | # no Net::FTP, fallback to ftp.exe 54 | require FileHandle; 55 | my $fh = FileHandle->new; 56 | 57 | local $SIG{CHLD} = 'IGNORE'; 58 | unless ($fh->open("|$ftp -n")) { 59 | warn "Couldn't open ftp: $!\n"; 60 | chdir $dir; return; 61 | } 62 | 63 | my @dialog = split(/\n/, <<"END_FTP"); 64 | open $host 65 | user anonymous anonymous\@example.com 66 | cd $path 67 | binary 68 | get $file $file 69 | quit 70 | END_FTP 71 | foreach (@dialog) { $fh->print("$_\n") } 72 | $fh->close; 73 | } } 74 | else { 75 | warn "No working 'ftp' program available!\n"; 76 | chdir $dir; return; 77 | } 78 | 79 | unless (-f $file) { 80 | warn "Fetching failed: $@\n"; 81 | chdir $dir; return; 82 | } 83 | 84 | return if exists $args{size} and -s $file != $args{size}; 85 | system($args{run}) if exists $args{run}; 86 | unlink($file) if $args{remove}; 87 | 88 | print(((!exists $args{check_for} or -e $args{check_for}) 89 | ? "done!" : "failed! ($!)"), "\n"); 90 | chdir $dir; return !$?; 91 | } 92 | 93 | 1; 94 | -------------------------------------------------------------------------------- /cpan/inc/Module/Install/Share.pm: -------------------------------------------------------------------------------- 1 | #line 1 2 | package Module::Install::Share; 3 | 4 | use strict; 5 | use Module::Install::Base (); 6 | use File::Find (); 7 | use ExtUtils::Manifest (); 8 | 9 | use vars qw{$VERSION @ISA $ISCORE}; 10 | BEGIN { 11 | $VERSION = '1.01'; 12 | @ISA = 'Module::Install::Base'; 13 | $ISCORE = 1; 14 | } 15 | 16 | sub install_share { 17 | my $self = shift; 18 | my $dir = @_ ? pop : 'share'; 19 | my $type = @_ ? shift : 'dist'; 20 | unless ( defined $type and $type eq 'module' or $type eq 'dist' ) { 21 | die "Illegal or invalid share dir type '$type'"; 22 | } 23 | unless ( defined $dir and -d $dir ) { 24 | require Carp; 25 | Carp::croak("Illegal or missing directory install_share param: '$dir'"); 26 | } 27 | 28 | # Split by type 29 | my $S = ($^O eq 'MSWin32') ? "\\" : "\/"; 30 | 31 | my $root; 32 | if ( $type eq 'dist' ) { 33 | die "Too many parameters to install_share" if @_; 34 | 35 | # Set up the install 36 | $root = "\$(INST_LIB)${S}auto${S}share${S}dist${S}\$(DISTNAME)"; 37 | } else { 38 | my $module = Module::Install::_CLASS($_[0]); 39 | unless ( defined $module ) { 40 | die "Missing or invalid module name '$_[0]'"; 41 | } 42 | $module =~ s/::/-/g; 43 | 44 | $root = "\$(INST_LIB)${S}auto${S}share${S}module${S}$module"; 45 | } 46 | 47 | my $manifest = -r 'MANIFEST' ? ExtUtils::Manifest::maniread() : undef; 48 | my $skip_checker = $ExtUtils::Manifest::VERSION >= 1.54 49 | ? ExtUtils::Manifest::maniskip() 50 | : ExtUtils::Manifest::_maniskip(); 51 | my $postamble = ''; 52 | my $perm_dir = eval($ExtUtils::MakeMaker::VERSION) >= 6.52 ? '$(PERM_DIR)' : 755; 53 | File::Find::find({ 54 | no_chdir => 1, 55 | wanted => sub { 56 | my $path = File::Spec->abs2rel($_, $dir); 57 | if (-d $_) { 58 | return if $skip_checker->($File::Find::name); 59 | $postamble .=<<"END"; 60 | \t\$(NOECHO) \$(MKPATH) "$root${S}$path" 61 | \t\$(NOECHO) \$(CHMOD) $perm_dir "$root${S}$path" 62 | END 63 | } 64 | else { 65 | return if ref $manifest 66 | && !exists $manifest->{$File::Find::name}; 67 | return if $skip_checker->($File::Find::name); 68 | $postamble .=<<"END"; 69 | \t\$(NOECHO) \$(CP) "$dir${S}$path" "$root${S}$path" 70 | END 71 | } 72 | }, 73 | }, $dir); 74 | 75 | # Set up the install 76 | $self->postamble(<<"END_MAKEFILE"); 77 | config :: 78 | $postamble 79 | 80 | END_MAKEFILE 81 | 82 | # The above appears to behave incorrectly when used with old versions 83 | # of ExtUtils::Install (known-bad on RHEL 3, with 5.8.0) 84 | # So when we need to install a share directory, make sure we add a 85 | # dependency on a moderately new version of ExtUtils::MakeMaker. 86 | $self->build_requires( 'ExtUtils::MakeMaker' => '6.11' ); 87 | 88 | # 99% of the time we don't want to index a shared dir 89 | $self->no_index( directory => $dir ); 90 | } 91 | 92 | 1; 93 | 94 | __END__ 95 | 96 | #line 154 97 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/lib/socket.io/transports/xhr-polling.js: -------------------------------------------------------------------------------- 1 | var Client = require('../client') 2 | , util = require(process.binding('natives').util ? 'util' : 'sys') 3 | , qs = require('querystring'); 4 | 5 | var Polling = module.exports = function(){ 6 | Client.apply(this, arguments); 7 | }; 8 | 9 | util.inherits(Polling, Client); 10 | 11 | Polling.prototype.getOptions = function(){ 12 | return { 13 | timeout: null, // no heartbeats 14 | closeTimeout: 8000, 15 | duration: 20000 16 | }; 17 | }; 18 | 19 | Polling.prototype._onConnect = function(req, res){ 20 | var self = this, body = ''; 21 | switch (req.method){ 22 | case 'GET': 23 | Client.prototype._onConnect.apply(this, [req, res]); 24 | this._closeTimeout = setTimeout(function(){ 25 | self._write(''); 26 | }, this.options.duration); 27 | this._payload(); 28 | break; 29 | 30 | case 'POST': 31 | req.addListener('data', function(message){ 32 | body += message; 33 | }); 34 | req.addListener('end', function(){ 35 | var headers = {'Content-Type': 'text/plain'}; 36 | if (req.headers.origin){ 37 | if (self._verifyOrigin(req.headers.origin)){ 38 | headers['Access-Control-Allow-Origin'] = '*'; 39 | if (req.headers.cookie) headers['Access-Control-Allow-Credentials'] = 'true'; 40 | } else { 41 | res.writeHead(401); 42 | res.write('unauthorized'); 43 | res.end(); 44 | return; 45 | } 46 | } 47 | try { 48 | // optimization: just strip first 5 characters here? 49 | var msg = qs.parse(body); 50 | self._onMessage(msg.data); 51 | } catch(e){ 52 | self.listener.options.log('xhr-polling message handler error - ' + e.stack); 53 | } 54 | res.writeHead(200, headers); 55 | res.write('ok'); 56 | res.end(); 57 | }); 58 | break; 59 | } 60 | }; 61 | 62 | Polling.prototype._onClose = function(){ 63 | if (this._closeTimeout) clearTimeout(this._closeTimeout); 64 | return Client.prototype._onClose.call(this); 65 | }; 66 | 67 | Polling.prototype._write = function(message){ 68 | if (this._open){ 69 | var headers = {'Content-Type': 'text/plain; charset=UTF-8', 'Content-Length': Buffer.byteLength(message)}; 70 | // https://developer.mozilla.org/En/HTTP_Access_Control 71 | if (this.request.headers.origin && this._verifyOrigin(this.request.headers.origin)){ 72 | headers['Access-Control-Allow-Origin'] = (this.request.headers.origin === 'null' ? '*' : this.request.headers.origin); 73 | if (this.request.headers.cookie) headers['Access-Control-Allow-Credentials'] = 'true'; 74 | } 75 | this.response.writeHead(200, headers); 76 | this.response.write(message); 77 | this.response.end(); 78 | this._onClose(); 79 | } 80 | }; 81 | -------------------------------------------------------------------------------- /socialcalc.css: -------------------------------------------------------------------------------- 1 | /* 2 | // The optional default CSS style sheet for the SocialCalc package. 3 | // SocialCalc can run without a style sheet (the default) or with one. 4 | // 5 | // (c) Copyright 2008 Socialtext, Inc. 6 | // All Rights Reserved. 7 | // 8 | // The contents of this file are subject to the Artistic License 2.0; you may not 9 | // use this file except in compliance with the License. You may obtain a copy of 10 | // the License at http://socialcalc.org/licenses/al-20/. 11 | // 12 | // Some of the other files in the SocialCalc package are licensed under 13 | // different licenses. Please note the licenses of the modules you use. 14 | // 15 | // Code History: 16 | // 17 | // Initially coded by Dan Bricklin of Software Garden, Inc., for Socialtext, Inc. 18 | */ 19 | 20 | .defaultPeer { 21 | box-shadow: inset 0 0 0 2px blue; 22 | -webkit-box-shadow: inset 0 0 0 2px blue; 23 | -moz-box-shadow: inset 0 0 0 2px blue; 24 | /* 25 | * concat peer combinations into multishadows: 26 | inset 0 0 0 4px orange, 27 | inset 0 0 0 6px yellow, 28 | inset 0 0 0 8px lime, 29 | inset 0 0 0 10px cyan, 30 | inset 0 0 0 12px blue, 31 | inset 0 0 0 14px purple; 32 | */ 33 | } 34 | .defaultComment {background-repeat:no-repeat;background-position:top right;background-image:url(images/sc-commentbg.gif);} 35 | .defaultCommentNoGridStyle {} 36 | .defaultHighlightTypeCursor {color:#FFF;background-color:#A6A6A6;} 37 | .defaultHighlightTypeRange {color:#000;background-color:#E5E5E5;} 38 | .defaultColname {font-size:small;text-align:center;color:#FFFFFF;background-color:#808080;cursor:e-resize;} 39 | .defaultSelectedColname {font-size:small;text-align:center;color:#FFFFFF;background-color:#404040;cursor:e-resize;} 40 | .defaultRowname {font-size:small;text-align:right;color:#FFFFFF;background-color:#808080;} 41 | .defaultSelectedRowname {font-size:small;text-align:right;color:#FFFFFF;background-color:#404040;} 42 | .defaultUpperLeft {font-size:small;} 43 | .defaultSkippedCell {font-size:small;background-color:#CCC;} 44 | .defaultPaneDivider {font-size:small;background-color:#ECECEC;padding:0px;} 45 | .cteGriddiv {} 46 | .defaultInputEcho {background-color:#FFD;border:1px solid #884; 47 | font-size:small;padding:2px 10px 1px 2px;cursor:default;} 48 | .TCmain {background-color:#EEE;} 49 | .TCendcap {background-color:#FFF;} 50 | .TCpaneslider {background-color:#CCC;} 51 | .TClessbutton {background-color:#AAA;} 52 | .TCmorebutton {background-color:#AAA;} 53 | .TCscrollarea {background-color:#DDD;} 54 | .TCthumb {background-color:#CCC;} 55 | .TCPStrackingline {overflow:hidden;position:absolute;z-index:100;} 56 | .TCTDFSthumbstatus {height:20px;width:auto;border:1px solid black;padding:2px; 57 | background-color:#FFF;font-size:small;position:absolute;z-index:100;} 58 | .TDpopupElement {border:1px solid black;padding:1px 2px 2px 2px;text-align:center;background-color:#FFF; 59 | font-size:7pt;font-family:Verdana,Arial,Helvetica,sans-serif; 60 | position:absolute;width:auto;z-index:110;} 61 | 62 | 63 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/lib/transports/flashsocket.js: -------------------------------------------------------------------------------- 1 | /** 2 | * socket.io-node-client 3 | * Copyright(c) 2011 LearnBoost 4 | * MIT Licensed 5 | */ 6 | 7 | (function(){ 8 | var io = this.io, 9 | 10 | /** 11 | * The Flashsocket transport. This is a API wrapper for the HTML5 WebSocket specification. 12 | * It uses a .swf file to communicate with the server. If you want to serve the .swf file 13 | * from a other server than where the Socket.IO script is coming from you need to use the 14 | * insecure version of the .swf. More information about this can be found on the github page. 15 | * 16 | * @constructor 17 | * @extends {io.Transport.websocket} 18 | * @api public 19 | */ 20 | Flashsocket = io.Transport.flashsocket = function(){ 21 | io.Transport.websocket.apply(this, arguments); 22 | }; 23 | 24 | io.util.inherit(Flashsocket, io.Transport.websocket); 25 | 26 | /** 27 | * The transport type, you use this to identify which transport was chosen. 28 | * 29 | * @type {String} 30 | * @api public 31 | */ 32 | Flashsocket.prototype.type = 'flashsocket'; 33 | 34 | /** 35 | * Disconnect the established `Flashsocket` connection. This is done by adding a new 36 | * task to the Flashsocket. The rest will be handled off by the `WebSocket` transport. 37 | * 38 | * @returns {Transport} 39 | * @api public 40 | */ 41 | Flashsocket.prototype.connect = function(){ 42 | var self = this, args = arguments; 43 | WebSocket.__addTask(function(){ 44 | io.Transport.websocket.prototype.connect.apply(self, args); 45 | }); 46 | return this; 47 | }; 48 | 49 | /** 50 | * Sends a message to the Socket.IO server. This is done by adding a new 51 | * task to the Flashsocket. The rest will be handled off by the `WebSocket` transport. 52 | * 53 | * @returns {Transport} 54 | * @api public 55 | */ 56 | Flashsocket.prototype.send = function(){ 57 | var self = this, args = arguments; 58 | WebSocket.__addTask(function(){ 59 | io.Transport.websocket.prototype.send.apply(self, args); 60 | }); 61 | return this; 62 | }; 63 | 64 | /** 65 | * Check if the Flashsocket transport is supported as it requires that the Adobe Flash Player 66 | * plugin version `10.0.0` or greater is installed. And also check if the polyfill is correctly 67 | * loaded. 68 | * 69 | * @returns {Boolean} 70 | * @api public 71 | */ 72 | Flashsocket.check = function(){ 73 | if (typeof WebSocket == 'undefined' || !('__addTask' in WebSocket) || !swfobject) return false; 74 | return swfobject.hasFlashPlayerVersion("10.0.0"); 75 | }; 76 | 77 | /** 78 | * Check if the Flashsocket transport can be used as cross domain / cross origin transport. 79 | * Because we can't see which type (secure or insecure) of .swf is used we will just return true. 80 | * 81 | * @returns {Boolean} 82 | * @api public 83 | */ 84 | Flashsocket.xdomainCheck = function(){ 85 | return true; 86 | }; 87 | 88 | })(); -------------------------------------------------------------------------------- /third-party/Socket.IO-node/lib/socket.io/transports/flashsocket.js: -------------------------------------------------------------------------------- 1 | var net = require('net') 2 | , util = require(process.binding('natives').util ? 'util' : 'sys') 3 | , WebSocket = require('./websocket') 4 | , listeners = [] 5 | , netserver; 6 | 7 | var Flashsocket = module.exports = function(){ 8 | WebSocket.apply(this, arguments); 9 | }; 10 | 11 | util.inherits(Flashsocket, WebSocket); 12 | 13 | Flashsocket.httpUpgrade = true; 14 | 15 | Flashsocket.init = function(listener){ 16 | listeners.push(listener); 17 | 18 | listener.server.on('close', function(){ 19 | listeners.splice(listeners.indexOf(listener), 1); 20 | 21 | if (listeners.length === 0 && netserver){ 22 | try { 23 | netserver.close(); 24 | } catch(e){ 25 | listener.options.log('flashsocket netserver close error - ' + e.stack) 26 | } 27 | } 28 | }); 29 | 30 | if (listener.options.flashPolicyServer && netserver === undefined){ 31 | netserver = net.createServer(function(socket){ 32 | socket.addListener('error', function(err){ 33 | if (socket && socket.end){ 34 | socket.end(); 35 | socket.destroy(); 36 | } 37 | }); 38 | 39 | if(socket && socket.readyState == 'open') 40 | socket.end(policy(listeners)); 41 | }); 42 | 43 | try { 44 | netserver.listen(843); 45 | } catch(e){ 46 | if (e.errno == 13) 47 | listener.options.log('Your node instance does not have root privileges. ' 48 | + 'This means that the flash XML policy file will be ' 49 | + 'served inline instead of on port 843. This will slow ' 50 | + 'down initial connections slightly.'); 51 | netserver = null; 52 | } 53 | } 54 | 55 | // Could not listen on port 843 so policy requests will be inline 56 | listener.server.addListener('connection', function(stream){ 57 | var flashCheck = function (data) { 58 | // Only check the initial data 59 | stream.removeListener("data", flashCheck); 60 | if (data[0] === 60 && data.length == 23) { 61 | if (data == '\0') { 62 | listener.options.log("Answering flash policy request inline"); 63 | if (stream && stream.readyState == 'open'){ 64 | var xml = policy([listener]); 65 | stream.write(xml); 66 | stream.end(); 67 | } 68 | } 69 | } 70 | }; 71 | 72 | stream.on('data', flashCheck); 73 | }); 74 | }; 75 | 76 | function policy(listeners) { 77 | var xml = '\n\n\n'; 79 | 80 | listeners.forEach(function(l){ 81 | [].concat(l.options.origins).forEach(function(origin){ 82 | var parts = origin.split(':'); 83 | xml += '\n'; 84 | }); 85 | }); 86 | 87 | xml += '\n'; 88 | return xml; 89 | }; 90 | -------------------------------------------------------------------------------- /third-party/lib/PocketIO/Transport/Base.pm: -------------------------------------------------------------------------------- 1 | package PocketIO::Transport::Base; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use JSON (); 7 | use Encode (); 8 | use Try::Tiny; 9 | use Scalar::Util qw(weaken); 10 | 11 | use Plack::Request; 12 | use PocketIO::Handle; 13 | use PocketIO::Pool; 14 | 15 | sub new { 16 | my $class = shift; 17 | 18 | my $self = bless {@_}, $class; 19 | 20 | weaken $self->{env}; 21 | $self->{req} = Plack::Request->new($self->{env}); 22 | 23 | return $self; 24 | } 25 | 26 | sub req { shift->{req} } 27 | sub env { shift->{req}->{env} } 28 | 29 | sub add_connection { 30 | my $self = shift; 31 | 32 | return PocketIO::Pool->add_connection(type => $self->name, req => $self->{req}, @_); 33 | } 34 | 35 | sub remove_connection { 36 | my $self = shift; 37 | 38 | PocketIO::Pool->remove_connection($_[0]); 39 | 40 | return $self; 41 | } 42 | 43 | sub find_connection { 44 | my $self = shift; 45 | 46 | return PocketIO::Pool->find_connection(@_); 47 | } 48 | 49 | sub client_connected { 50 | my $self = shift; 51 | my ($conn) = @_; 52 | 53 | return if $conn->is_connected; 54 | 55 | $self->_log_client_connected($conn); 56 | 57 | $conn->connected; 58 | } 59 | 60 | sub client_disconnected { 61 | my $self = shift; 62 | my ($conn) = @_; 63 | 64 | $self->_log_client_disconnected($conn); 65 | 66 | $conn->disconnected; 67 | 68 | $self->remove_connection($conn); 69 | 70 | return $self; 71 | } 72 | 73 | sub _log_client_connected { 74 | my $self = shift; 75 | my ($conn) = @_; 76 | 77 | my $logger = $self->_get_logger; 78 | return unless $logger; 79 | 80 | $logger->( 81 | { level => 'debug', 82 | message => sprintf( 83 | "Client '%s' connected via '%s'", 84 | $conn->id, $conn->type 85 | ) 86 | } 87 | ); 88 | } 89 | 90 | sub _log_client_disconnected { 91 | my $self = shift; 92 | my ($conn) = @_; 93 | 94 | my $logger = $self->_get_logger; 95 | return unless $logger; 96 | 97 | $logger->( 98 | { level => 'debug', 99 | message => sprintf("Client '%s' disconnected", $conn->id) 100 | } 101 | ); 102 | } 103 | 104 | sub _get_logger { 105 | my $self = shift; 106 | 107 | return $self->env->{'psgix.logger'}; 108 | } 109 | 110 | sub _build_handle { 111 | my $self = shift; 112 | 113 | return PocketIO::Handle->new(@_); 114 | } 115 | 116 | 1; 117 | __END__ 118 | 119 | =head1 NAME 120 | 121 | PocketIO::Base - Base class for transports 122 | 123 | =head1 DESCRIPTION 124 | 125 | L is a base class for the transports. 126 | 127 | =head1 METHODS 128 | 129 | =head2 C 130 | 131 | =head2 C 132 | 133 | =head2 C 134 | 135 | =head2 C 136 | 137 | =head2 C 138 | 139 | =head2 C 140 | 141 | =head2 C 142 | 143 | =head2 C 144 | 145 | =cut 146 | -------------------------------------------------------------------------------- /third-party/lib/PocketIO/Transport/XHRMultipart.pm: -------------------------------------------------------------------------------- 1 | package PocketIO::Transport::XHRMultipart; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use base 'PocketIO::Transport::Base'; 7 | 8 | use PocketIO::Handle; 9 | use PocketIO::Response::Chunked; 10 | 11 | sub new { 12 | my $self = shift->SUPER::new(@_); 13 | 14 | $self->{boundary} ||= 'socketio'; 15 | 16 | return $self; 17 | } 18 | 19 | sub name {'xhr-multipart'} 20 | 21 | sub dispatch { 22 | my $self = shift; 23 | my ($cb) = @_; 24 | 25 | my $req = $self->req; 26 | my $name = $self->name; 27 | 28 | return $self->_dispatch_stream($req, $cb) if $req->method eq 'GET'; 29 | 30 | return 31 | unless $req->method eq 'POST' && $req->path =~ m{^/$name/(\d+)/send$}; 32 | 33 | return $self->_dispatch_send($req, $1); 34 | } 35 | 36 | sub _dispatch_stream { 37 | my $self = shift; 38 | my ($req, $cb) = @_; 39 | 40 | my $handle = $self->_build_handle($req->env->{'psgix.io'}); 41 | return unless $handle; 42 | 43 | return sub { 44 | my $respond = shift; 45 | 46 | my $conn = $self->add_connection(on_connect => $cb); 47 | 48 | my $close_cb = sub { $handle->close; $self->client_disconnected($conn); }; 49 | $handle->on_eof($close_cb); 50 | $handle->on_error($close_cb); 51 | 52 | my $boundary = $self->{boundary}; 53 | 54 | $conn->on_write( 55 | sub { 56 | my $self = shift; 57 | my ($message) = @_; 58 | 59 | my $string = ''; 60 | 61 | $string .= "Content-Type: text/plain\x0a\x0a"; 62 | if ($message eq '') { 63 | $string .= "-1--$boundary--\x0a"; 64 | } 65 | else { 66 | $string .= "$message\x0a--$boundary\x0a"; 67 | } 68 | 69 | $handle->write($string); 70 | } 71 | ); 72 | 73 | $handle->on_heartbeat(sub { $conn->send_heartbeat }); 74 | 75 | $handle->write( 76 | join "\x0d\x0a" => 'HTTP/1.1 200 OK', 77 | qq{Content-Type: multipart/x-mixed-replace;boundary="$boundary"}, 78 | 'Connection: keep-alive', '', '' 79 | ); 80 | 81 | $conn->send_id_message($conn->id); 82 | 83 | $self->client_connected($conn); 84 | }; 85 | } 86 | 87 | sub _dispatch_send { 88 | my $self = shift; 89 | my ($req, $id) = @_; 90 | 91 | my $conn = $self->find_connection($id); 92 | return unless $conn; 93 | 94 | my $data = $req->body_parameters->get('data'); 95 | 96 | $conn->read($data); 97 | 98 | return PocketIO::Response::Chunked->finalize; 99 | } 100 | 101 | 1; 102 | __END__ 103 | 104 | =head1 NAME 105 | 106 | PocketIO::XHRMultipart - XHRMultipart transport 107 | 108 | =head1 DESCRIPTION 109 | 110 | L is a C transport 111 | implementation. 112 | 113 | =head1 METHODS 114 | 115 | =head2 C 116 | 117 | =head2 C 118 | 119 | =head2 C 120 | 121 | =cut 122 | -------------------------------------------------------------------------------- /third-party/lib/PocketIO/Transport/BasePolling.pm: -------------------------------------------------------------------------------- 1 | package PocketIO::Transport::BasePolling; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use base 'PocketIO::Transport::Base'; 7 | 8 | use PocketIO::Response::Chunked; 9 | 10 | sub _dispatch_init { 11 | my $self = shift; 12 | my ($cb) = @_; 13 | 14 | my $conn; 15 | $conn = $self->add_connection( 16 | on_connect => $cb, 17 | on_reconnect_failed => sub { 18 | $self->client_disconnected($conn); 19 | } 20 | ); 21 | 22 | my $body = $self->_format_message($conn->build_id_message); 23 | 24 | return [ 25 | 200, 26 | [ 'Content-Type' => 'text/plain', 27 | 'Content-Length' => length($body), 28 | 'Connection' => 'keep-alive' 29 | ], 30 | [$body] 31 | ]; 32 | } 33 | 34 | sub _dispatch_stream { 35 | my $self = shift; 36 | my ($id) = @_; 37 | 38 | my $conn = $self->find_connection($id); 39 | return unless $conn; 40 | 41 | my $handle = $self->_build_handle($self->env->{'psgix.io'}); 42 | 43 | return sub { 44 | my $respond = shift; 45 | 46 | my $close_cb = sub { $handle->close; $self->client_disconnected($conn); }; 47 | $handle->on_eof($close_cb); 48 | $handle->on_error($close_cb); 49 | 50 | $handle->on_heartbeat(sub { $conn->send_heartbeat }); 51 | 52 | if ($conn->has_staged_messages) { 53 | $self->_write($conn, $handle, $conn->staged_message); 54 | } 55 | else { 56 | $conn->on_write( 57 | sub { 58 | my $conn = shift; 59 | my ($message) = @_; 60 | 61 | $conn->on_write(undef); 62 | $self->_write($conn, $handle, $message); 63 | } 64 | ); 65 | } 66 | 67 | if ($conn->is_connected) { 68 | $conn->reconnected; 69 | } 70 | else { 71 | $self->client_connected($conn); 72 | } 73 | }; 74 | } 75 | 76 | sub _dispatch_send { 77 | my $self = shift; 78 | my ($req, $id) = @_; 79 | 80 | my $conn = $self->find_connection($id); 81 | return unless $conn; 82 | 83 | my $data = $req->body_parameters->get('data'); 84 | 85 | $conn->read($data); 86 | 87 | return PocketIO::Response::Chunked->finalize; 88 | } 89 | 90 | sub _write { 91 | my $self = shift; 92 | my ($conn, $handle, $message) = @_; 93 | 94 | $message = $self->_format_message($message); 95 | 96 | $handle->write( 97 | join( 98 | "\x0d\x0a" => 'HTTP/1.1 200 OK', 99 | 'Content-Type: text/plain', 100 | 'Content-Length: ' . length($message), '', $message 101 | ), 102 | sub { 103 | $handle->close; 104 | $conn->reconnecting; 105 | } 106 | ); 107 | } 108 | 109 | sub _format_message { $_[1] } 110 | 111 | 1; 112 | __END__ 113 | 114 | =head1 NAME 115 | 116 | PocketIO::Polling - Basic class for polling transports 117 | 118 | =head1 DESCRIPTION 119 | 120 | =cut 121 | -------------------------------------------------------------------------------- /third-party/lib/PocketIO/Transport/Htmlfile.pm: -------------------------------------------------------------------------------- 1 | package PocketIO::Transport::Htmlfile; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use base 'PocketIO::Transport::Base'; 7 | 8 | use HTTP::Body; 9 | use PocketIO::Response::Chunked; 10 | 11 | sub name {'htmlfile'} 12 | 13 | sub dispatch { 14 | my $self = shift; 15 | my ($cb) = @_; 16 | 17 | my $req = $self->req; 18 | my $name = $self->name; 19 | 20 | if ($req->method eq 'GET') { 21 | return $self->_dispatch_stream($cb) if $req->path =~ m{^/$name//\d+$}; 22 | } 23 | 24 | return 25 | unless $req->method eq 'POST' 26 | && $req->path_info =~ m{^/$name/(\d+)/send$}; 27 | 28 | return $self->_dispatch_send($req, $1); 29 | } 30 | 31 | sub _dispatch_stream { 32 | my $self = shift; 33 | my ($cb) = @_; 34 | 35 | my $handle = $self->_build_handle($self->env->{'psgix.io'}); 36 | 37 | return sub { 38 | my $conn = $self->add_connection(on_connect => $cb); 39 | 40 | my $close_cb = sub { $handle->close; $self->client_disconnected($conn); }; 41 | $handle->on_eof($close_cb); 42 | $handle->on_error($close_cb); 43 | 44 | $handle->on_heartbeat(sub { $conn->send_heartbeat }); 45 | 46 | my $id = $self->_wrap_into_script($conn->build_id_message); 47 | 48 | $handle->write( 49 | join "\x0d\x0a" => 'HTTP/1.1 200 OK', 50 | 'Content-Type: text/html', 51 | 'Connection: keep-alive', 52 | 'Transfer-Encoding: chunked', 53 | '', 54 | sprintf('%x', 244 + 12), 55 | '' . (' ' x 244), 56 | sprintf('%x', length($id)), 57 | $id, 58 | '' 59 | ); 60 | 61 | $conn->on_write( 62 | sub { 63 | my $conn = shift; 64 | my ($message) = @_; 65 | 66 | $message = $self->_wrap_into_script($message); 67 | 68 | $handle->write( 69 | join "\x0d\x0a" => sprintf('%x', length($message)), 70 | $message, 71 | '' 72 | ); 73 | } 74 | ); 75 | 76 | $self->client_connected($conn); 77 | }; 78 | } 79 | 80 | sub _dispatch_send { 81 | my $self = shift; 82 | my ($req, $id) = @_; 83 | 84 | my $conn = $self->find_connection($id); 85 | return unless $conn; 86 | 87 | my $raw_body = $req->content; 88 | my $zeros = $raw_body =~ s/\0//g; 89 | 90 | my $body = HTTP::Body->new($self->env->{CONTENT_TYPE}, 91 | $self->env->{CONTENT_LENGTH} - $zeros); 92 | $body->add($raw_body); 93 | 94 | my $data = $body->param->{data}; 95 | 96 | $conn->read($data); 97 | 98 | return PocketIO::Response::Chunked->finalize; 99 | } 100 | 101 | sub _wrap_into_script { 102 | my $self = shift; 103 | my ($message) = @_; 104 | 105 | $message =~ s/"/\\"/g; 106 | return qq{}; 107 | } 108 | 109 | 1; 110 | __END__ 111 | 112 | =head1 NAME 113 | 114 | PocketIO::Htmlfile - Htmlfile transport 115 | 116 | =head1 DESCRIPTION 117 | 118 | L is a C transport 119 | implementation. 120 | 121 | =cut 122 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/example/chat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | socket.io client test 5 | 6 | 7 | 8 | 9 | 10 | 11 | 50 | 51 |

Sample chat client

52 |

Connecting...

53 |
54 | 55 |
56 | 57 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /third-party/lib/PocketIO/Handle.pm: -------------------------------------------------------------------------------- 1 | package PocketIO::Handle; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use AnyEvent::Handle; 7 | 8 | use constant DEBUG => $ENV{POCKETIO_HANDLE_DEBUG}; 9 | 10 | sub new { 11 | my $class = shift; 12 | my ($fh) = @_; 13 | 14 | my $self = {handle => AnyEvent::Handle->new(fh => $fh)}; 15 | bless $self, $class; 16 | 17 | $self->{heartbeat_timeout} ||= 10; 18 | 19 | $fh->autoflush; 20 | 21 | $self->{handle}->no_delay(1); 22 | $self->{handle}->on_eof(sub { warn "Unhandled handle eof" }); 23 | $self->{handle}->on_error(sub { warn "Unhandled handle error: $_[2]" }); 24 | 25 | # This is needed for the correct EOF handling 26 | $self->{handle}->on_read(sub { }); 27 | 28 | return $self; 29 | } 30 | 31 | sub on_heartbeat { 32 | my $self = shift; 33 | my ($cb) = @_; 34 | 35 | $self->{handle}->timeout($self->{heartbeat_timeout}); 36 | $self->{handle}->on_timeout($cb); 37 | 38 | return $self; 39 | } 40 | 41 | sub on_read { 42 | my $self = shift; 43 | my ($cb) = @_; 44 | 45 | $self->{handle}->on_read( 46 | sub { 47 | my $handle = shift; 48 | 49 | $handle->push_read( 50 | sub { 51 | $cb->($self, $_[0]->rbuf); 52 | } 53 | ); 54 | } 55 | ); 56 | 57 | return $self; 58 | } 59 | 60 | sub on_eof { 61 | my $self = shift; 62 | my ($cb) = @_; 63 | 64 | $self->{handle}->on_eof( 65 | sub { 66 | $cb->($self); 67 | } 68 | ); 69 | 70 | return $self; 71 | } 72 | 73 | sub on_error { 74 | my $self = shift; 75 | my ($cb) = @_; 76 | 77 | $self->{handle}->on_error( 78 | sub { 79 | $cb->($self); 80 | } 81 | ); 82 | 83 | return $self; 84 | } 85 | 86 | sub write { 87 | my $self = shift; 88 | my ($chunk, $cb) = @_; 89 | 90 | my $handle = $self->{handle}; 91 | return $self unless $handle && $handle->fh; 92 | 93 | $handle->push_write($chunk); 94 | 95 | if ($cb) { 96 | $handle->on_drain( 97 | sub { 98 | my $handle = shift; 99 | 100 | $handle->on_drain(undef); 101 | 102 | $cb->($self); 103 | } 104 | ); 105 | } 106 | 107 | return $self; 108 | } 109 | 110 | sub close { 111 | my $self = shift; 112 | 113 | my $handle = delete $self->{handle}; 114 | return $self unless $handle; 115 | 116 | $handle->timeout(0); 117 | 118 | $handle->on_drain; 119 | $handle->on_error; 120 | 121 | $handle->on_drain(sub { 122 | shutdown $_[0]->fh, 1; 123 | close $handle->fh; 124 | 125 | $_[0]->destroy; 126 | undef $handle; 127 | }); 128 | 129 | return $self; 130 | } 131 | 132 | 1; 133 | __END__ 134 | 135 | =head1 NAME 136 | 137 | PocketIO::Handle - Handle 138 | 139 | =head1 DESCRIPTION 140 | 141 | L is a wrapper on top of 142 | L. 143 | 144 | =head1 METHODS 145 | 146 | =head2 C 147 | 148 | =head2 C 149 | 150 | =head2 C 151 | 152 | =head2 C 153 | 154 | =head2 C 155 | 156 | =head2 C 157 | 158 | =head2 C 159 | 160 | =head1 SEE ALSO 161 | 162 | L 163 | 164 | =cut 165 | -------------------------------------------------------------------------------- /third-party/class-js/lib/Class.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | Class = function(classDefinition, classWrapper) { 4 | if (!classDefinition) throw("Class requires a class definition string as its first argument"); 5 | if (!classWrapper) throw("Class requires a class wrapper function as its second argument"); 6 | 7 | if (! classDefinition.match(/^([\w\.]+)(?:\(\s*([\w\.]+)\s*\))?(?:\s+(.*?)\s*)?$/)) 8 | throw("Can't parse Class Definition: '" + classDefinition + "'"); 9 | var className = RegExp.$1; 10 | var baseClassName = RegExp.$2 || ''; 11 | var options = []; 12 | if (RegExp.$3) { 13 | options = RegExp.$3.split(/\s+/); 14 | } 15 | var incValues = []; 16 | var strict = true; 17 | for (var i = 0, l = options.length; i < l; i++) { 18 | var option = options[i]; 19 | if (option == '-nostrict') { 20 | strict = false; 21 | } 22 | if (option.match(/^-inc=(.+)$/)) { 23 | incValues = RegExp.$1.split(','); 24 | } 25 | } 26 | 27 | var parts = className.split('.'); 28 | var klass = Class.global; 29 | for (var i = 0; i < parts.length; i++) { 30 | if (! klass[parts[i]]) { 31 | klass[parts[i]] = function() { 32 | try { this.init() } catch(e) {} 33 | }; 34 | } 35 | klass = klass[parts[i]]; 36 | } 37 | klass.className = className; 38 | 39 | klass.isa = function(baseName) { 40 | klass.baseClassName = baseName; 41 | if (baseName) { 42 | klass.prototype = eval('new ' + baseName + '()'); 43 | klass.prototype.superFunc = function(name) { 44 | return eval(baseName).prototype[name]; 45 | } 46 | } 47 | }; 48 | klass.isa(baseClassName); 49 | 50 | klass.global = Class.global; 51 | 52 | klass.addGlobal = function() { 53 | this.newGlobals++; 54 | return Class.global; 55 | } 56 | 57 | klass.extend = function(pairs) { 58 | if (typeof pairs != 'object') { 59 | throw("extend requires an object of name:value pairs"); 60 | } 61 | for (var name in pairs) { 62 | klass.prototype[name] = pairs[name]; 63 | } 64 | } 65 | 66 | for (var ii = 0, ll = incValues.length; ii < ll; ii++) { 67 | var value = incValues[ii]; 68 | if (value == 'proto') { 69 | incValues[ii] = klass.prototype; 70 | } 71 | else if (value == 'this') { 72 | incValues[ii] = klass; 73 | } 74 | else { 75 | incValues[ii] = Class.global[value]; 76 | } 77 | } 78 | 79 | if (strict) { 80 | Class.eval_strict(classWrapper, klass, incValues); 81 | } 82 | else { 83 | classWrapper.apply(klass, incValues); 84 | } 85 | 86 | return klass; 87 | }; 88 | 89 | })(); 90 | 91 | Class.global = this; 92 | 93 | Class.eval_strict = function(classWrapper, klass, incValues) { 94 | var globals = 0; 95 | var last_key; 96 | 97 | for (var k in Class.global) { 98 | globals++; 99 | last_key = k; 100 | } 101 | 102 | klass.newGlobals = 0; 103 | 104 | classWrapper.apply(klass, incValues); 105 | 106 | var globals_after = 0; 107 | for (var k in Class.global) { 108 | globals_after++; 109 | } 110 | 111 | if (globals + klass.newGlobals != globals_after) { 112 | throw("Class '" + klass.className + "' defines " + (globals_after - globals) + " new global JavaScript variables without using this.addGlobal()"); 113 | } 114 | 115 | delete klass.newGlobals; 116 | }; 117 | 118 | -------------------------------------------------------------------------------- /third-party/wikiwyg/lib/Document/Emitter/HTML.js: -------------------------------------------------------------------------------- 1 | Class('Document.Emitter.HTML(Document.Emitter)', function() { 2 | 3 | var proto = this.prototype; 4 | proto.className = 'Document.Emitter.HTML'; 5 | 6 | proto.begin_node = function(node) { 7 | var tag = node.type; 8 | switch (tag) { 9 | case 'asis': case 'line': return; 10 | case 'br': case 'hr': { 11 | this.output += '<'+tag+' />'; 12 | return; 13 | } 14 | case 'html': { 15 | this.output += 'Raw HTML section. Edit in Wiki Text mode.'; 16 | return; 17 | } 18 | case 'waflparagraph': case 'waflphrase': case 'im': { 19 | if (node._wafl.match(/^image:\s*(\S+)(?:\s+size=(\w+))?/)) { 20 | var onload = "if (typeof(ss) != 'undefined' && ss.editor) { var recalc = function () { try { ss.editor.DoPositionCalculations() } catch (e) { setTimeout(recalc, 500) } }; recalc() } if (!window.image_dimension_cache) window.image_dimension_cache = {};window.image_dimension_cache['/data/wafl/"+node._label.replace(/&/g,"&").replace(/"/g,""").replace(//g, ">").replace(/'/g, "\\'").replace(/\\/g, "\\\\")+"'] = [ this.offsetWidth, this.offsetHeight ]; this.style.width = this.offsetWidth + 'px'; this.style.height = this.offsetHeight + 'px'"; 21 | 22 | var imageName = RegExp.$1; 23 | var width = RegExp.$2; 24 | switch (width) { 25 | case 'small': { width = '100'; break; } 26 | case 'medium': { width = '300'; break; } 27 | case 'large': { width = '600'; break; } 28 | } 29 | if (width) { 30 | width = ' width="'+width+'"'; 31 | } 32 | this.output += '/g, ">")+'" onload="'+onload+'"'+width+' />'; 33 | return; 34 | } 35 | this.output += ''+node._label.replace(/&/g,"&").replace(/"/g,""").replace(//g, ">").replace(/'/g, "\\'").replace(/\\/g, "\\\\")+''; 36 | 37 | return; 38 | } 39 | case 'a': case 'wikilink': { 40 | this.output += ''; 41 | return; 42 | } 43 | case 'file': { 44 | this.output += ''; 45 | return; 46 | } 47 | case 'ul': case 'ol': case 'table': case 'tr': { 48 | this.output += '<'+tag+">\n"; 49 | return; 50 | } 51 | default: { 52 | this.output += '<'+tag+'>'; 53 | return; 54 | } 55 | } 56 | } 57 | 58 | proto.end_node = function(node) { 59 | var tag = node.type; 60 | switch (tag) { 61 | case 'asis': case 'br': case 'hr': case 'html': case 'waflparagraph': case 'waflphrase': case 'im': return; 62 | case 'line': { 63 | this.output += '
'; 64 | return; 65 | } 66 | case 'file': case 'wikilink': { 67 | this.output += '
'; 68 | return; 69 | } 70 | default: { 71 | if (tag.search(/^(?:p|ul|ol|li|h\d|table|tr|td)$/) == 0) { 72 | this.output += '\n"; 73 | } 74 | else { 75 | this.output += ''; 76 | } 77 | return; 78 | } 79 | } 80 | return; 81 | } 82 | 83 | proto.text_node = function(text) { 84 | this.output += text 85 | .replace(/&/g, '&') 86 | .replace(/>/g, '>') 87 | .replace(/ 4 | * MIT Licensed 5 | */ 6 | 7 | (function(){ 8 | var io = this.io, 9 | 10 | /** 11 | * The WebSocket transport uses the HTML5 WebSocket API to establish an persistent 12 | * connection with the Socket.IO server. This transport will also be inherited by the 13 | * FlashSocket fallback as it provides a API compatible polyfill for the WebSockets. 14 | * 15 | * @constructor 16 | * @extends {io.Transport} 17 | * @api public 18 | */ 19 | WS = io.Transport.websocket = function(){ 20 | io.Transport.apply(this, arguments); 21 | }; 22 | 23 | io.util.inherit(WS, io.Transport); 24 | 25 | /** 26 | * The transport type, you use this to identify which transport was chosen. 27 | * 28 | * @type {String} 29 | * @api public 30 | */ 31 | WS.prototype.type = 'websocket'; 32 | 33 | /** 34 | * Initializes a new `WebSocket` connection with the Socket.IO server. We attach 35 | * all the appropriate listeners to handle the responses from the server. 36 | * 37 | * @returns {Transport} 38 | * @api public 39 | */ 40 | WS.prototype.connect = function(){ 41 | var self = this; 42 | this.socket = new WebSocket(this.prepareUrl()); 43 | this.socket.onmessage = function(ev){ self.onData(ev.data); }; 44 | this.socket.onclose = function(ev){ self.onDisconnect(); }; 45 | this.socket.onerror = function(e){ self.onError(e); }; 46 | return this; 47 | }; 48 | 49 | /** 50 | * Send a message to the Socket.IO server. The message will automatically be encoded 51 | * in the correct message format. 52 | * 53 | * @returns {Transport} 54 | * @api public 55 | */ 56 | WS.prototype.send = function(data){ 57 | if (this.socket) this.socket.send(this.encode(data)); 58 | return this; 59 | }; 60 | 61 | /** 62 | * Disconnect the established `WebSocket` connection. 63 | * 64 | * @returns {Transport} 65 | * @api public 66 | */ 67 | WS.prototype.disconnect = function(){ 68 | if (this.socket) this.socket.close(); 69 | return this; 70 | }; 71 | 72 | /** 73 | * Handle the errors that `WebSocket` might be giving when we 74 | * are attempting to connect or send messages. 75 | * 76 | * @param {Error} e The error. 77 | * @api private 78 | */ 79 | WS.prototype.onError = function(e){ 80 | this.base.emit('error', [e]); 81 | }; 82 | 83 | /** 84 | * Generate a `WebSocket` compatible URL based on the options 85 | * the user supplied in our Socket.IO base. 86 | * 87 | * @returns {String} Connection url 88 | * @api private 89 | */ 90 | WS.prototype.prepareUrl = function(){ 91 | return (this.base.options.secure ? 'wss' : 'ws') 92 | + '://' + this.base.host 93 | + ':' + this.base.options.port 94 | + '/' + this.base.options.resource 95 | + '/' + this.type 96 | + (this.sessionid ? ('/' + this.sessionid) : ''); 97 | }; 98 | 99 | /** 100 | * Checks if the browser has support for native `WebSockets` and that 101 | * it's not the polyfill created for the FlashSocket transport. 102 | * 103 | * @return {Boolean} 104 | * @api public 105 | */ 106 | WS.check = function(){ 107 | // we make sure WebSocket is not confounded with a previously loaded flash WebSocket 108 | return 'WebSocket' in window && WebSocket.prototype && ( WebSocket.prototype.send && !!WebSocket.prototype.send.toString().match(/native/i)) && typeof WebSocket !== "undefined"; 109 | }; 110 | 111 | /** 112 | * Check if the `WebSocket` transport support cross domain communications. 113 | * 114 | * @returns {Boolean} 115 | * @api public 116 | */ 117 | WS.xdomainCheck = function(){ 118 | return true; 119 | }; 120 | 121 | })(); 122 | -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/lib/transports/htmlfile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * socket.io-node-client 3 | * Copyright(c) 2011 LearnBoost 4 | * MIT Licensed 5 | */ 6 | 7 | (function(){ 8 | var io = this.io, 9 | 10 | /** 11 | * The HTMLFile transport creates a `forever iframe` based transport 12 | * for Internet Explorer. Regular forever iframe implementations will 13 | * continuously trigger the browsers buzy indicators. If the forever iframe 14 | * is created inside a `htmlfile` these indicators will not be trigged. 15 | * 16 | * @constructor 17 | * @extends {io.Transport.XHR} 18 | * @api public 19 | */ 20 | HTMLFile = io.Transport.htmlfile = function(){ 21 | io.Transport.XHR.apply(this, arguments); 22 | }; 23 | 24 | io.util.inherit(HTMLFile, io.Transport.XHR); 25 | 26 | /** 27 | * The transport type, you use this to identify which transport was chosen. 28 | * 29 | * @type {String} 30 | * @api public 31 | */ 32 | HTMLFile.prototype.type = 'htmlfile'; 33 | 34 | /** 35 | * Starts the HTMLFile data stream for incoming messages. And registers a 36 | * onunload event listener so the HTMLFile will be destroyed. 37 | * 38 | * @api private 39 | */ 40 | HTMLFile.prototype.get = function(){ 41 | var self = this; 42 | this.open(); 43 | window.attachEvent('onunload', function(){ self.destroy(); }); 44 | }; 45 | 46 | /** 47 | * Creates a new ActiveX `htmlfile` with a forever loading iframe 48 | * that can be used to listen to messages. Inside the generated 49 | * `htmlfile` a reference will be made to the HTMLFile transport. 50 | * 51 | * @api private 52 | */ 53 | HTMLFile.prototype.open = function(){ 54 | this.doc = new ActiveXObject('htmlfile'); 55 | this.doc.open(); 56 | this.doc.write(''); 57 | this.doc.parentWindow.s = this; 58 | this.doc.close(); 59 | 60 | var iframeC = this.doc.createElement('div'); 61 | this.doc.body.appendChild(iframeC); 62 | this.iframe = this.doc.createElement('iframe'); 63 | iframeC.appendChild(this.iframe); 64 | this.iframe.src = this.prepareUrl() + '/' + (+ new Date); 65 | }; 66 | 67 | /** 68 | * The Socket.IO server will write script tags inside the forever 69 | * iframe, this function will be used as callback for the incoming 70 | * information. 71 | * 72 | * @param {String} data The message 73 | * @param {document} doc Reference to the context 74 | * @api private 75 | */ 76 | HTMLFile.prototype._ = function(data, doc){ 77 | this.onData(data); 78 | var script = doc.getElementsByTagName('script')[0]; 79 | script.parentNode.removeChild(script); 80 | }; 81 | 82 | /** 83 | * Destroy the established connection, iframe and `htmlfile`. 84 | * And calls the `CollectGarbage` function of Internet Explorer 85 | * to release the memory. 86 | * 87 | * @api private 88 | */ 89 | HTMLFile.prototype.destroy = function(){ 90 | if (this.iframe){ 91 | try { 92 | this.iframe.src = 'about:blank'; 93 | } catch(e){} 94 | this.doc = null; 95 | CollectGarbage(); 96 | } 97 | }; 98 | 99 | /** 100 | * Disconnects the established connection. 101 | * 102 | * @returns {Transport} Chaining. 103 | * @api public 104 | */ 105 | HTMLFile.prototype.disconnect = function(){ 106 | this.destroy(); 107 | return io.Transport.XHR.prototype.disconnect.call(this); 108 | }; 109 | 110 | /** 111 | * Checks if the browser supports this transport. The browser 112 | * must have an `ActiveXObject` implementation. 113 | * 114 | * @return {Boolean} 115 | * @api public 116 | */ 117 | HTMLFile.check = function(){ 118 | if ('ActiveXObject' in window){ 119 | try { 120 | var a = new ActiveXObject('htmlfile'); 121 | return a && io.Transport.XHR.check(); 122 | } catch(e){} 123 | } 124 | return false; 125 | }; 126 | 127 | /** 128 | * Check if cross domain requests are supported. 129 | * 130 | * @returns {Boolean} 131 | * @api public 132 | */ 133 | HTMLFile.xdomainCheck = function(){ 134 | // we can probably do handling for sub-domains, we should test that it's cross domain but a subdomain here 135 | return false; 136 | }; 137 | 138 | })(); -------------------------------------------------------------------------------- /player.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | var socket; 3 | var cookieName = 'socialcalc'; 4 | var _username = Math.random().toString(); 5 | var _hadSnapshot = false; 6 | var isConnected = false; 7 | var mq = []; 8 | 9 | SocialCalc.Callbacks.broadcast = function(type, data) { 10 | if (!isConnected) return; 11 | data = data || {}; 12 | data.user = _username; 13 | data.type = type; 14 | socket.send(data); 15 | } 16 | 17 | socket = new io.Socket(null, {}); 18 | socket.connect(); 19 | socket.on('connect', function () { 20 | isConnected = true; 21 | SocialCalc.Callbacks.broadcast('ask.snapshot'); 22 | /* Wait for 30 secs for someone to send over the current snapshot before timing out. */ 23 | setTimeout(function(){ _hadSnapshot = true }, 30000); 24 | }); 25 | socket.on('message', function (obj) { 26 | onNewEvent(obj); 27 | }); 28 | 29 | var onNewEvent = function(data) { 30 | if (!isConnected) return; 31 | if (data.user == _username) return; 32 | if (data.to && data.to != _username) return; 33 | if (typeof SocialCalc == 'undefined') return; 34 | 35 | var editor = SocialCalc.CurrentSpreadsheetControlObject.editor; 36 | 37 | switch (data.type) { 38 | case 'ecell': { 39 | var peerClass = ' ' + data.user + ' defaultPeer'; 40 | var find = new RegExp(peerClass, 'g'); 41 | 42 | if (data.original) { 43 | var origCR = SocialCalc.coordToCr(data.original); 44 | var origCell = SocialCalc.GetEditorCellElement(editor, origCR.row, origCR.col); 45 | origCell.element.className = origCell.element.className.replace(find, ''); 46 | } 47 | 48 | var cr = SocialCalc.coordToCr(data.ecell); 49 | var cell = SocialCalc.GetEditorCellElement(editor, cr.row, cr.col); 50 | if (cell.element.className.search(find) == -1) { 51 | cell.element.className += peerClass; 52 | } 53 | break; 54 | } 55 | case 'ask.snapshot': { 56 | SocialCalc.Callbacks.broadcast('snapshot', { 57 | to: data.user, 58 | snapshot: SocialCalc.CurrentSpreadsheetControlObject.CreateSpreadsheetSave() 59 | }); 60 | // FALL THROUGH 61 | } 62 | case 'ask.ecell': { 63 | SocialCalc.Callbacks.broadcast('ecell', { 64 | to: data.user, 65 | ecell: editor.ecell.coord 66 | }); 67 | break; 68 | } 69 | case 'snapshot': { 70 | if (_hadSnapshot) break; 71 | _hadSnapshot = true; 72 | var spreadsheet = SocialCalc.CurrentSpreadsheetControlObject; 73 | var parts = spreadsheet.DecodeSpreadsheetSave(data.snapshot); 74 | if (parts) { 75 | if (parts.sheet) { 76 | spreadsheet.sheet.ResetSheet(); 77 | spreadsheet.ParseSheetSave(data.snapshot.substring(parts.sheet.start, parts.sheet.end)); 78 | } 79 | if (parts.edit) { 80 | spreadsheet.editor.LoadEditorSettings(data.snapshot.substring(parts.edit.start, parts.edit.end)); 81 | } 82 | } 83 | if (spreadsheet.editor.context.sheetobj.attribs.recalc=="off") { 84 | spreadsheet.ExecuteCommand('redisplay', ''); 85 | spreadsheet.ExecuteCommand('set sheet defaulttextvalueformat text-wiki'); 86 | } 87 | else { 88 | spreadsheet.ExecuteCommand('recalc', ''); 89 | spreadsheet.ExecuteCommand('set sheet defaulttextvalueformat text-wiki'); 90 | } 91 | 92 | break; 93 | } 94 | case 'execute': { 95 | SocialCalc.CurrentSpreadsheetControlObject.context.sheetobj.ScheduleSheetCommands( 96 | data.cmdstr, 97 | data.saveundo, 98 | true // isRemote = true 99 | ); 100 | break; 101 | } 102 | } 103 | }; 104 | })(); 105 | -------------------------------------------------------------------------------- /third-party/lib/PocketIO.pm: -------------------------------------------------------------------------------- 1 | package PocketIO; 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use base 'Plack::Component'; 7 | 8 | our $VERSION = '0.00904'; 9 | 10 | use Plack::Util (); 11 | use Plack::Util::Accessor qw(resource handler class instance method); 12 | 13 | use PocketIO::Resource; 14 | 15 | sub new { 16 | my $self = shift->SUPER::new(@_); 17 | 18 | $self->handler($self->_get_handler); 19 | 20 | return $self; 21 | } 22 | 23 | sub call { 24 | my $self = shift; 25 | my ($env) = @_; 26 | 27 | return PocketIO::Resource->dispatch($env, $self->handler) 28 | || [400, ['Content-Type' => 'text/plain'], ['Bad request']]; 29 | } 30 | 31 | sub _get_handler { 32 | my $self = shift; 33 | 34 | return $self->handler if $self->handler; 35 | 36 | die q{Either 'handler', 'class' or 'instance' must be specified} 37 | unless $self->instance || $self->class; 38 | 39 | my $method = $self->method || 'run'; 40 | 41 | my $instance = $self->instance 42 | || do { Plack::Util::load_class($self->class); $self->class->new; }; 43 | 44 | return $instance->run; 45 | } 46 | 47 | 1; 48 | __END__ 49 | 50 | =head1 NAME 51 | 52 | PocketIO - Socket.IO middleware 53 | 54 | =head1 SYNOPSIS 55 | 56 | use Plack::Builder; 57 | 58 | builder { 59 | enable "SocketIO", handler => sub { 60 | my $self = shift; 61 | 62 | $self->on_message( 63 | sub { 64 | my $self = shift; 65 | my ($message) = @_; 66 | 67 | ... 68 | } 69 | ); 70 | 71 | $self->send_message({buffer => []}); 72 | }; 73 | 74 | $app; 75 | }; 76 | 77 | # or 78 | 79 | builder { 80 | enable "SocketIO", class => 'MyApp::Handler', method => 'run'; 81 | 82 | $app; 83 | }; 84 | 85 | =head1 DESCRIPTION 86 | 87 | L is a server implmentation of SocketIO in Perl. 88 | 89 | =head2 SocketIO 90 | 91 | More information about SocketIO you can find on the website L, or 92 | on the GitHub L. 93 | 94 | =head2 Transports 95 | 96 | All the transports are supported. 97 | 98 | WebSocket 99 | Adobe(R) Flash(R) Socket 100 | AJAX long polling 101 | AJAX multipart streaming 102 | Forever Iframe 103 | JSONP Polling 104 | 105 | =head2 TLS/SSL 106 | 107 | For TLS/SSL a secure proxy is needed. C or L is 108 | recommended. 109 | 110 | =head1 CONFIGURATIONS 111 | 112 | =over 4 113 | 114 | =item resource 115 | 116 | enable "SocketIO", 117 | resource => 'socket.io', ...; 118 | 119 | Specifies the path prefix under which all the requests are handled. This is done 120 | so the rest of your application won't interfere with Socket.IO specific calls. 121 | 122 | =item handler 123 | 124 | enable "SocketIO", 125 | handler => sub { 126 | my $socket = shift; 127 | 128 | $socket->on_message(sub { 129 | my $socket = shift; 130 | }); 131 | 132 | $socket->send_message('hello'); 133 | }; 134 | 135 | =item class or instance, method 136 | 137 | enable "SocketIO", 138 | class => 'MyHandler', method => 'run'; 139 | 140 | # or 141 | 142 | enable "SocketIO", 143 | instance => MyHandler->new(foo => 'bar'), method => 'run'; 144 | 145 | package MyHandler; 146 | 147 | sub new { ... } # or use Moose, Boose, Goose, Doose 148 | 149 | sub run { 150 | my $self = shift; 151 | 152 | return sub { 153 | 154 | # same code as above 155 | } 156 | } 157 | 158 | Loads C using L, creates a new object or uses 159 | a passed C and runs C method expecting it to return an anonymous 160 | subroutine. 161 | 162 | =back 163 | 164 | =head1 DEVELOPMENT 165 | 166 | =head2 Repository 167 | 168 | http://github.com/vti/plack-middleware-socketio 169 | 170 | =head1 CREDITS 171 | 172 | Socket.IO author(s) and contributors. 173 | 174 | =head1 AUTHOR 175 | 176 | Viacheslav Tykhanovskyi, C. 177 | 178 | =head1 COPYRIGHT AND LICENSE 179 | 180 | Copyright (C) 2011, Viacheslav Tykhanovskyi 181 | 182 | This program is free software, you can redistribute it and/or modify it under 183 | the terms of the Artistic License version 2.0. 184 | 185 | =cut 186 | -------------------------------------------------------------------------------- /third-party/hippie/jquery.cookie.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Cookie plugin 3 | * 4 | * Copyright (c) 2006 Klaus Hartl (stilbuero.de) 5 | * Dual licensed under the MIT and GPL licenses: 6 | * http://www.opensource.org/licenses/mit-license.php 7 | * http://www.gnu.org/licenses/gpl.html 8 | * 9 | */ 10 | 11 | /** 12 | * Create a cookie with the given name and value and other optional parameters. 13 | * 14 | * @example $.cookie('the_cookie', 'the_value'); 15 | * @desc Set the value of a cookie. 16 | * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true }); 17 | * @desc Create a cookie with all available options. 18 | * @example $.cookie('the_cookie', 'the_value'); 19 | * @desc Create a session cookie. 20 | * @example $.cookie('the_cookie', null); 21 | * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain 22 | * used when the cookie was set. 23 | * 24 | * @param String name The name of the cookie. 25 | * @param String value The value of the cookie. 26 | * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. 27 | * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. 28 | * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. 29 | * If set to null or omitted, the cookie will be a session cookie and will not be retained 30 | * when the the browser exits. 31 | * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). 32 | * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). 33 | * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will 34 | * require a secure protocol (like HTTPS). 35 | * @type undefined 36 | * 37 | * @name $.cookie 38 | * @cat Plugins/Cookie 39 | * @author Klaus Hartl/klaus.hartl@stilbuero.de 40 | */ 41 | 42 | /** 43 | * Get the value of a cookie with the given name. 44 | * 45 | * @example $.cookie('the_cookie'); 46 | * @desc Get the value of a cookie. 47 | * 48 | * @param String name The name of the cookie. 49 | * @return The value of the cookie. 50 | * @type String 51 | * 52 | * @name $.cookie 53 | * @cat Plugins/Cookie 54 | * @author Klaus Hartl/klaus.hartl@stilbuero.de 55 | */ 56 | jQuery.cookie = function(name, value, options) { 57 | if (typeof value != 'undefined') { // name and value given, set cookie 58 | options = options || {}; 59 | if (value === null) { 60 | value = ''; 61 | options.expires = -1; 62 | } 63 | var expires = ''; 64 | if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) { 65 | var date; 66 | if (typeof options.expires == 'number') { 67 | date = new Date(); 68 | date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000)); 69 | } else { 70 | date = options.expires; 71 | } 72 | expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE 73 | } 74 | // CAUTION: Needed to parenthesize options.path and options.domain 75 | // in the following expressions, otherwise they evaluate to undefined 76 | // in the packed version for some reason... 77 | var path = options.path ? '; path=' + (options.path) : ''; 78 | var domain = options.domain ? '; domain=' + (options.domain) : ''; 79 | var secure = options.secure ? '; secure' : ''; 80 | document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join(''); 81 | } else { // only name given, get cookie 82 | var cookieValue = null; 83 | if (document.cookie && document.cookie != '') { 84 | var cookies = document.cookie.split(';'); 85 | for (var i = 0; i < cookies.length; i++) { 86 | var cookie = jQuery.trim(cookies[i]); 87 | // Does this cookie string begin with the name we want? 88 | if (cookie.substring(0, name.length + 1) == (name + '=')) { 89 | cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); 90 | break; 91 | } 92 | } 93 | } 94 | return cookieValue; 95 | } 96 | }; -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/lib/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * socket.io-node-client 3 | * Copyright(c) 2011 LearnBoost 4 | * MIT Licensed 5 | */ 6 | 7 | (function(){ 8 | var io = this.io, 9 | 10 | /** 11 | * Set when the `onload` event is executed on the page. This variable is used by 12 | * `io.util.load` to detect if we need to execute the function immediately or add 13 | * it to a onload listener. 14 | * 15 | * @type {Boolean} 16 | * @api private 17 | */ 18 | pageLoaded = false; 19 | 20 | /** 21 | * @namespace 22 | */ 23 | io.util = { 24 | /** 25 | * Executes the given function when the page is loaded. 26 | * 27 | * Example: 28 | * 29 | * io.util.load(function(){ console.log('page loaded') }); 30 | * 31 | * @param {Function} fn 32 | * @api public 33 | */ 34 | load: function(fn){ 35 | if (/loaded|complete/.test(document.readyState) || pageLoaded) return fn(); 36 | if ('attachEvent' in window){ 37 | window.attachEvent('onload', fn); 38 | } else { 39 | window.addEventListener('load', fn, false); 40 | } 41 | }, 42 | 43 | /** 44 | * Defers the function untill it's the function can be executed without 45 | * blocking the load process. This is especially needed for WebKit based 46 | * browsers. If a long running connection is made before the onload event 47 | * a loading indicator spinner will be present at all times untill a 48 | * reconnect has been made. 49 | * 50 | * @param {Function} fn 51 | * @api public 52 | */ 53 | defer: function(fn){ 54 | if (!io.util.webkit) return fn(); 55 | io.util.load(function(){ 56 | setTimeout(fn,100); 57 | }); 58 | }, 59 | 60 | /** 61 | * Inherit the prototype methods from one constructor into another. 62 | * 63 | * Example: 64 | * 65 | * function foo(){}; 66 | * foo.prototype.hello = function(){ console.log( this.words )}; 67 | * 68 | * function bar(){ 69 | * this.words = "Hello world"; 70 | * }; 71 | * 72 | * io.util.inherit(bar,foo); 73 | * var person = new bar(); 74 | * person.hello(); 75 | * // => "Hello World" 76 | * 77 | * @param {Constructor} ctor The constructor that needs to inherit the methods. 78 | * @param {Constructor} superCtor The constructor to inherit from. 79 | * @api public 80 | */ 81 | inherit: function(ctor, superCtor){ 82 | // no support for `instanceof` for now 83 | for (var i in superCtor.prototype){ 84 | ctor.prototype[i] = superCtor.prototype[i]; 85 | } 86 | }, 87 | 88 | /** 89 | * Finds the index of item in a given Array. 90 | * 91 | * Example: 92 | * 93 | * var data = ['socket',2,3,4,'socket',5,6,7,'io']; 94 | * io.util.indexOf(data,'socket',1); 95 | * // => 4 96 | * 97 | * @param {Array} arr The array 98 | * @param item The item that we need to find 99 | * @param {Integer} from Starting point 100 | * @api public 101 | */ 102 | indexOf: function(arr, item, from){ 103 | for (var l = arr.length, i = (from < 0) ? Math.max(0, l + from) : from || 0; i < l; i++){ 104 | if (arr[i] === item) return i; 105 | } 106 | return -1; 107 | }, 108 | 109 | /** 110 | * Checks if the given object is an Array. 111 | * 112 | * Example: 113 | * 114 | * io.util.isArray([]); 115 | * // => true 116 | * io.util.isArray({}); 117 | * // => false 118 | * 119 | * @param obj 120 | * @api public 121 | */ 122 | isArray: function(obj){ 123 | return Object.prototype.toString.call(obj) === '[object Array]'; 124 | }, 125 | 126 | /** 127 | * Merges the properties of two objects. 128 | * 129 | * Example: 130 | * 131 | * var a = {foo:'bar'} 132 | * , b = {bar:'baz'}; 133 | * 134 | * io.util.merge(a,b); 135 | * // => {foo:'bar',bar:'baz'} 136 | * 137 | * @param {Object} target The object that receives the keys 138 | * @param {Object} additional The object that supplies the keys 139 | * @api public 140 | */ 141 | merge: function(target, additional){ 142 | for (var i in additional) 143 | if (additional.hasOwnProperty(i)) 144 | target[i] = additional[i]; 145 | } 146 | }; 147 | 148 | /** 149 | * Detect the Webkit platform based on the userAgent string. 150 | * This includes Mobile Webkit. 151 | * 152 | * @type {Boolean} 153 | * @api public 154 | */ 155 | io.util.webkit = /webkit/i.test(navigator.userAgent); 156 | 157 | io.util.load(function(){ 158 | pageLoaded = true; 159 | }); 160 | 161 | })(); -------------------------------------------------------------------------------- /third-party/Socket.IO-node/support/socket.io-client/lib/transports/jsonp-polling.js: -------------------------------------------------------------------------------- 1 | /** 2 | * socket.io-node-client 3 | * Copyright(c) 2011 LearnBoost 4 | * MIT Licensed 5 | */ 6 | 7 | (function(){ 8 | var io = this.io, 9 | 10 | /** 11 | * The JSONP transport creates an persistent connection by dynamically 12 | * inserting a script tag in the page. This script tag will receive the 13 | * information of the Socket.IO server. When new information is received 14 | * it creates a new script tag for the new data stream. 15 | * 16 | * @constructor 17 | * @extends {io.Transport.xhr-polling} 18 | * @api public 19 | */ 20 | JSONPPolling = io.Transport['jsonp-polling'] = function(){ 21 | io.Transport.XHR.apply(this, arguments); 22 | this.insertAt = document.getElementsByTagName('script')[0]; 23 | this.index = io.JSONP.length; 24 | io.JSONP.push(this); 25 | }; 26 | 27 | io.util.inherit(JSONPPolling, io.Transport['xhr-polling']); 28 | 29 | /** 30 | * A list of all JSONPolling transports, this is used for by 31 | * the Socket.IO server to distribute the callbacks. 32 | * 33 | * @type {Array} 34 | * @api private 35 | */ 36 | io.JSONP = []; 37 | 38 | /** 39 | * The transport type, you use this to identify which transport was chosen. 40 | * 41 | * @type {String} 42 | * @api public 43 | */ 44 | JSONPPolling.prototype.type = 'jsonp-polling'; 45 | 46 | /** 47 | * Posts a encoded message to the Socket.IO server using an iframe. 48 | * The iframe is used because script tags can create POST based requests. 49 | * The iframe is positioned outside of the view so the user does not 50 | * notice it's existence. 51 | * 52 | * @param {String} data A encoded message. 53 | * @api private 54 | */ 55 | JSONPPolling.prototype.sendIORequest = function(data){ 56 | var self = this; 57 | if (!('form' in this)){ 58 | var form = document.createElement('FORM'), 59 | area = document.createElement('TEXTAREA'), 60 | id = this.iframeId = 'socket_io_iframe_' + this.index, 61 | iframe; 62 | 63 | form.style.position = 'absolute'; 64 | form.style.top = '-1000px'; 65 | form.style.left = '-1000px'; 66 | form.target = id; 67 | form.method = 'POST'; 68 | form.action = this.prepareUrl() + '/' + (+new Date) + '/' + this.index; 69 | area.name = 'data'; 70 | form.appendChild(area); 71 | this.insertAt.parentNode.insertBefore(form, this.insertAt); 72 | document.body.appendChild(form); 73 | 74 | this.form = form; 75 | this.area = area; 76 | } 77 | 78 | function complete(){ 79 | initIframe(); 80 | self.posting = false; 81 | self.checkSend(); 82 | }; 83 | 84 | function initIframe(){ 85 | if (self.iframe){ 86 | self.form.removeChild(self.iframe); 87 | } 88 | 89 | try { 90 | // ie6 dynamic iframes with target="" support (thanks Chris Lambacher) 91 | iframe = document.createElement('