├── .gitignore ├── README.md ├── node_modules ├── .bin │ └── express ├── express │ ├── .npmignore │ ├── History.md │ ├── LICENSE │ ├── Makefile │ ├── Readme.md │ ├── bin │ │ └── express │ ├── index.js │ ├── lib │ │ ├── express.js │ │ ├── request.js │ │ ├── response.js │ │ ├── router │ │ │ ├── index.js │ │ │ └── route.js │ │ ├── utils.js │ │ └── view.js │ ├── node_modules │ │ └── connect │ │ │ ├── .npmignore │ │ │ ├── LICENSE │ │ │ ├── index.js │ │ │ ├── lib │ │ │ ├── connect.js │ │ │ ├── index.js │ │ │ ├── middleware │ │ │ │ ├── basicAuth.js │ │ │ │ ├── bodyParser.js │ │ │ │ ├── cookieParser.js │ │ │ │ ├── errorHandler.js │ │ │ │ ├── favicon.js │ │ │ │ ├── limit.js │ │ │ │ ├── logger.js │ │ │ │ ├── methodOverride.js │ │ │ │ ├── responseTime.js │ │ │ │ ├── session.js │ │ │ │ ├── session │ │ │ │ │ ├── cookie.js │ │ │ │ │ ├── memory.js │ │ │ │ │ ├── session.js │ │ │ │ │ └── store.js │ │ │ │ ├── static.js │ │ │ │ └── vhost.js │ │ │ ├── patch.js │ │ │ ├── public │ │ │ │ ├── error.html │ │ │ │ ├── favicon.ico │ │ │ │ └── style.css │ │ │ └── utils.js │ │ │ ├── package.json │ │ │ └── test.js │ └── package.json └── socket.io │ ├── History.md │ ├── Makefile │ ├── README.md │ ├── index.js │ └── package.json ├── package.json ├── public ├── favicon.ico ├── index.html ├── paint.js └── style.css └── server.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Fancy Collaboritive Painting App Based on Node.js 2 | 3 | Free to use and distribute or hack or whatever. 4 | 5 | ## Example: 6 | http://xpaintx.jit.su 7 | 8 | ## Credits: 9 | This app was created fully by Jamund Ferguson 10 | jamund@gmail.com 11 | http://www.jamund.com/ 12 | http://www.twitter.com/xjamundx/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /node_modules/.bin/express: -------------------------------------------------------------------------------- 1 | ../express/bin/express -------------------------------------------------------------------------------- /node_modules/express/.npmignore: -------------------------------------------------------------------------------- 1 | .git* 2 | docs/ 3 | examples/ 4 | support/ 5 | test/ 6 | testing.js 7 | .DS_Store 8 | coverage.html 9 | lib-cov 10 | -------------------------------------------------------------------------------- /node_modules/express/LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2009-2011 TJ Holowaychuk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /node_modules/express/Makefile: -------------------------------------------------------------------------------- 1 | 2 | MOCHA_OPTS= --check-leaks 3 | REPORTER = dot 4 | 5 | check: test 6 | 7 | test: test-unit test-acceptance 8 | 9 | test-unit: 10 | @NODE_ENV=test ./node_modules/.bin/mocha \ 11 | --reporter $(REPORTER) \ 12 | $(MOCHA_OPTS) 13 | 14 | test-acceptance: 15 | @NODE_ENV=test ./node_modules/.bin/mocha \ 16 | --reporter $(REPORTER) \ 17 | --bail \ 18 | test/acceptance/*.js 19 | 20 | test-cov: lib-cov 21 | @EXPRESS_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html 22 | 23 | lib-cov: 24 | @jscoverage lib lib-cov 25 | 26 | benchmark: 27 | @./support/bench 28 | 29 | clean: 30 | rm -f coverage.html 31 | rm -fr lib-cov 32 | 33 | .PHONY: test test-unit test-acceptance benchmark clean 34 | -------------------------------------------------------------------------------- /node_modules/express/Readme.md: -------------------------------------------------------------------------------- 1 | ![express logo](http://f.cl.ly/items/0V2S1n0K1i3y1c122g04/Screen%20Shot%202012-04-11%20at%209.59.42%20AM.png) 2 | 3 | Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). [![Build Status](https://secure.travis-ci.org/visionmedia/express.png)](http://travis-ci.org/visionmedia/express) [![Dependency Status](https://gemnasium.com/visionmedia/express.png)](https://gemnasium.com/visionmedia/express) 4 | 5 | ```js 6 | var express = require('express'); 7 | var app = express(); 8 | 9 | app.get('/', function(req, res){ 10 | res.send('Hello World'); 11 | }); 12 | 13 | app.listen(3000); 14 | ``` 15 | 16 | ## Installation 17 | 18 | $ npm install -g express 19 | 20 | ## Quick Start 21 | 22 | The quickest way to get started with express is to utilize the executable `express(1)` to generate an application as shown below: 23 | 24 | Create the app: 25 | 26 | $ npm install -g express 27 | $ express /tmp/foo && cd /tmp/foo 28 | 29 | Install dependencies: 30 | 31 | $ npm install 32 | 33 | Start the server: 34 | 35 | $ node app 36 | 37 | ## Features 38 | 39 | * Built on [Connect](http://github.com/senchalabs/connect) 40 | * Robust routing 41 | * HTTP helpers (redirection, caching, etc) 42 | * View system supporting 14+ template engines 43 | * Content negotiation 44 | * Focus on high performance 45 | * Environment based configuration 46 | * Executable for generating applications quickly 47 | * High test coverage 48 | 49 | ## Philosophy 50 | 51 | The Express philosophy is to provide small, robust tooling for HTTP servers. Making 52 | it a great solution for single page applications, web sites, hybrids, or public 53 | HTTP APIs. 54 | 55 | Built on Connect you can use _only_ what you need, and nothing more, applications 56 | can be as big or as small as you like, even a single file. Express does 57 | not force you to use any specific ORM or template engine. With support for over 58 | 14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js) 59 | you can quickly craft your perfect framework. 60 | 61 | ## More Information 62 | 63 | * Join #express on freenode 64 | * [Google Group](http://groups.google.com/group/express-js) for discussion 65 | * Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates 66 | * Visit the [Wiki](http://github.com/visionmedia/express/wiki) 67 | * [Русскоязычная документация](http://jsman.ru/express/) 68 | * Run express examples [online](https://runnable.com/express) 69 | 70 | ## Viewing Examples 71 | 72 | Clone the Express repo, then install the dev dependencies to install all the example / test suite deps: 73 | 74 | $ git clone git://github.com/visionmedia/express.git --depth 1 75 | $ cd express 76 | $ npm install 77 | 78 | then run whichever tests you want: 79 | 80 | $ node examples/content-negotiation 81 | 82 | ## Running Tests 83 | 84 | To run the test suite first invoke the following command within the repo, installing the development dependencies: 85 | 86 | $ npm install 87 | 88 | then run the tests: 89 | 90 | $ make test 91 | 92 | ## Contributors 93 | 94 | ``` 95 | project: express 96 | commits: 3559 97 | active : 468 days 98 | files : 237 99 | authors: 100 | 1891 Tj Holowaychuk 53.1% 101 | 1285 visionmedia 36.1% 102 | 182 TJ Holowaychuk 5.1% 103 | 54 Aaron Heckmann 1.5% 104 | 34 csausdev 1.0% 105 | 26 ciaranj 0.7% 106 | 21 Robert Sköld 0.6% 107 | 6 Guillermo Rauch 0.2% 108 | 3 Dav Glass 0.1% 109 | 3 Nick Poulden 0.1% 110 | 2 Randy Merrill 0.1% 111 | 2 Benny Wong 0.1% 112 | 2 Hunter Loftis 0.1% 113 | 2 Jake Gordon 0.1% 114 | 2 Brian McKinney 0.1% 115 | 2 Roman Shtylman 0.1% 116 | 2 Ben Weaver 0.1% 117 | 2 Dave Hoover 0.1% 118 | 2 Eivind Fjeldstad 0.1% 119 | 2 Daniel Shaw 0.1% 120 | 1 Matt Colyer 0.0% 121 | 1 Pau Ramon 0.0% 122 | 1 Pero Pejovic 0.0% 123 | 1 Peter Rekdal Sunde 0.0% 124 | 1 Raynos 0.0% 125 | 1 Teng Siong Ong 0.0% 126 | 1 Viktor Kelemen 0.0% 127 | 1 ctide 0.0% 128 | 1 8bitDesigner 0.0% 129 | 1 isaacs 0.0% 130 | 1 mgutz 0.0% 131 | 1 pikeas 0.0% 132 | 1 shuwatto 0.0% 133 | 1 tstrimple 0.0% 134 | 1 ewoudj 0.0% 135 | 1 Adam Sanderson 0.0% 136 | 1 Andrii Kostenko 0.0% 137 | 1 Andy Hiew 0.0% 138 | 1 Arpad Borsos 0.0% 139 | 1 Ashwin Purohit 0.0% 140 | 1 Benjen 0.0% 141 | 1 Darren Torpey 0.0% 142 | 1 Greg Ritter 0.0% 143 | 1 Gregory Ritter 0.0% 144 | 1 James Herdman 0.0% 145 | 1 Jim Snodgrass 0.0% 146 | 1 Joe McCann 0.0% 147 | 1 Jonathan Dumaine 0.0% 148 | 1 Jonathan Palardy 0.0% 149 | 1 Jonathan Zacsh 0.0% 150 | 1 Justin Lilly 0.0% 151 | 1 Ken Sato 0.0% 152 | 1 Maciej Małecki 0.0% 153 | 1 Masahiro Hayashi 0.0% 154 | ``` 155 | 156 | ## License 157 | 158 | (The MIT License) 159 | 160 | Copyright (c) 2009-2012 TJ Holowaychuk <tj@vision-media.ca> 161 | 162 | Permission is hereby granted, free of charge, to any person obtaining 163 | a copy of this software and associated documentation files (the 164 | 'Software'), to deal in the Software without restriction, including 165 | without limitation the rights to use, copy, modify, merge, publish, 166 | distribute, sublicense, and/or sell copies of the Software, and to 167 | permit persons to whom the Software is furnished to do so, subject to 168 | the following conditions: 169 | 170 | The above copyright notice and this permission notice shall be 171 | included in all copies or substantial portions of the Software. 172 | 173 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 174 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 175 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 176 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 177 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 178 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 179 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 180 | -------------------------------------------------------------------------------- /node_modules/express/bin/express: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var exec = require('child_process').exec 8 | , program = require('commander') 9 | , mkdirp = require('mkdirp') 10 | , pkg = require('../package.json') 11 | , version = pkg.version 12 | , os = require('os') 13 | , fs = require('fs'); 14 | 15 | // CLI 16 | 17 | program 18 | .version(version) 19 | .option('-s, --sessions', 'add session support') 20 | .option('-e, --ejs', 'add ejs engine support (defaults to jade)') 21 | .option('-J, --jshtml', 'add jshtml engine support (defaults to jade)') 22 | .option('-H, --hogan', 'add hogan.js engine support') 23 | .option('-c, --css ', 'add stylesheet support (less|stylus) (defaults to plain css)') 24 | .option('-f, --force', 'force on non-empty directory') 25 | .parse(process.argv); 26 | 27 | // Path 28 | 29 | var path = program.args.shift() || '.'; 30 | 31 | // end-of-line code 32 | 33 | var eol = os.EOL 34 | 35 | // Template engine 36 | 37 | program.template = 'jade'; 38 | if (program.ejs) program.template = 'ejs'; 39 | if (program.jshtml) program.template = 'jshtml'; 40 | if (program.hogan) program.template = 'hjs'; 41 | 42 | /** 43 | * Routes index template. 44 | */ 45 | 46 | var index = [ 47 | '' 48 | , '/*' 49 | , ' * GET home page.' 50 | , ' */' 51 | , '' 52 | , 'exports.index = function(req, res){' 53 | , ' res.render(\'index\', { title: \'Express\' });' 54 | , '};' 55 | ].join(eol); 56 | 57 | /** 58 | * Routes users template. 59 | */ 60 | 61 | var users = [ 62 | '' 63 | , '/*' 64 | , ' * GET users listing.' 65 | , ' */' 66 | , '' 67 | , 'exports.list = function(req, res){' 68 | , ' res.send("respond with a resource");' 69 | , '};' 70 | ].join(eol); 71 | 72 | /** 73 | * Jade layout template. 74 | */ 75 | 76 | var jadeLayout = [ 77 | 'doctype 5' 78 | , 'html' 79 | , ' head' 80 | , ' title= title' 81 | , ' link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')' 82 | , ' body' 83 | , ' block content' 84 | ].join(eol); 85 | 86 | /** 87 | * Jade index template. 88 | */ 89 | 90 | var jadeIndex = [ 91 | 'extends layout' 92 | , '' 93 | , 'block content' 94 | , ' h1= title' 95 | , ' p Welcome to #{title}' 96 | ].join(eol); 97 | 98 | /** 99 | * EJS index template. 100 | */ 101 | 102 | var ejsIndex = [ 103 | '' 104 | , '' 105 | , ' ' 106 | , ' <%= title %>' 107 | , ' ' 108 | , ' ' 109 | , ' ' 110 | , '

<%= title %>

' 111 | , '

Welcome to <%= title %>

' 112 | , ' ' 113 | , '' 114 | ].join(eol); 115 | 116 | /** 117 | * JSHTML layout template. 118 | */ 119 | 120 | var jshtmlLayout = [ 121 | '' 122 | , '' 123 | , ' ' 124 | , ' @write(title) ' 125 | , ' ' 126 | , ' ' 127 | , ' ' 128 | , ' @write(body)' 129 | , ' ' 130 | , '' 131 | ].join(eol); 132 | 133 | /** 134 | * JSHTML index template. 135 | */ 136 | 137 | var jshtmlIndex = [ 138 | '

@write(title)

' 139 | , '

Welcome to @write(title)

' 140 | ].join(eol); 141 | 142 | /** 143 | * Hogan.js index template. 144 | */ 145 | var hoganIndex = [ 146 | '' 147 | , '' 148 | , ' ' 149 | , ' {{ title }}' 150 | , ' ' 151 | , ' ' 152 | , ' ' 153 | , '

{{ title }}

' 154 | , '

Welcome to {{ title }}

' 155 | , ' ' 156 | , '' 157 | ].join(eol); 158 | 159 | /** 160 | * Default css template. 161 | */ 162 | 163 | var css = [ 164 | 'body {' 165 | , ' padding: 50px;' 166 | , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;' 167 | , '}' 168 | , '' 169 | , 'a {' 170 | , ' color: #00B7FF;' 171 | , '}' 172 | ].join(eol); 173 | 174 | /** 175 | * Default less template. 176 | */ 177 | 178 | var less = [ 179 | 'body {' 180 | , ' padding: 50px;' 181 | , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;' 182 | , '}' 183 | , '' 184 | , 'a {' 185 | , ' color: #00B7FF;' 186 | , '}' 187 | ].join(eol); 188 | 189 | /** 190 | * Default stylus template. 191 | */ 192 | 193 | var stylus = [ 194 | 'body' 195 | , ' padding: 50px' 196 | , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif' 197 | , 'a' 198 | , ' color: #00B7FF' 199 | ].join(eol); 200 | 201 | /** 202 | * App template. 203 | */ 204 | 205 | var app = [ 206 | '' 207 | , '/**' 208 | , ' * Module dependencies.' 209 | , ' */' 210 | , '' 211 | , 'var express = require(\'express\')' 212 | , ' , routes = require(\'./routes\')' 213 | , ' , user = require(\'./routes/user\')' 214 | , ' , http = require(\'http\')' 215 | , ' , path = require(\'path\');' 216 | , '' 217 | , 'var app = express();' 218 | , '' 219 | , '// all environments' 220 | , 'app.set(\'port\', process.env.PORT || 3000);' 221 | , 'app.set(\'views\', __dirname + \'/views\');' 222 | , 'app.set(\'view engine\', \':TEMPLATE\');' 223 | , 'app.use(express.favicon());' 224 | , 'app.use(express.logger(\'dev\'));' 225 | , 'app.use(express.bodyParser());' 226 | , 'app.use(express.methodOverride());{sess}' 227 | , 'app.use(app.router);{css}' 228 | , 'app.use(express.static(path.join(__dirname, \'public\')));' 229 | , '' 230 | , '// development only' 231 | , 'if (\'development\' == app.get(\'env\')) {' 232 | , ' app.use(express.errorHandler());' 233 | , '}' 234 | , '' 235 | , 'app.get(\'/\', routes.index);' 236 | , 'app.get(\'/users\', user.list);' 237 | , '' 238 | , 'http.createServer(app).listen(app.get(\'port\'), function(){' 239 | , ' console.log(\'Express server listening on port \' + app.get(\'port\'));' 240 | , '});' 241 | , '' 242 | ].join(eol); 243 | 244 | // Generate application 245 | 246 | (function createApplication(path) { 247 | emptyDirectory(path, function(empty){ 248 | if (empty || program.force) { 249 | createApplicationAt(path); 250 | } else { 251 | program.confirm('destination is not empty, continue? ', function(ok){ 252 | if (ok) { 253 | process.stdin.destroy(); 254 | createApplicationAt(path); 255 | } else { 256 | abort('aborting'); 257 | } 258 | }); 259 | } 260 | }); 261 | })(path); 262 | 263 | /** 264 | * Create application at the given directory `path`. 265 | * 266 | * @param {String} path 267 | */ 268 | 269 | function createApplicationAt(path) { 270 | console.log(); 271 | process.on('exit', function(){ 272 | console.log(); 273 | console.log(' install dependencies:'); 274 | console.log(' $ cd %s && npm install', path); 275 | console.log(); 276 | console.log(' run the app:'); 277 | console.log(' $ node app'); 278 | console.log(); 279 | }); 280 | 281 | mkdir(path, function(){ 282 | mkdir(path + '/public'); 283 | mkdir(path + '/public/javascripts'); 284 | mkdir(path + '/public/images'); 285 | mkdir(path + '/public/stylesheets', function(){ 286 | switch (program.css) { 287 | case 'less': 288 | write(path + '/public/stylesheets/style.less', less); 289 | break; 290 | case 'stylus': 291 | write(path + '/public/stylesheets/style.styl', stylus); 292 | break; 293 | default: 294 | write(path + '/public/stylesheets/style.css', css); 295 | } 296 | }); 297 | 298 | mkdir(path + '/routes', function(){ 299 | write(path + '/routes/index.js', index); 300 | write(path + '/routes/user.js', users); 301 | }); 302 | 303 | mkdir(path + '/views', function(){ 304 | switch (program.template) { 305 | case 'ejs': 306 | write(path + '/views/index.ejs', ejsIndex); 307 | break; 308 | case 'jade': 309 | write(path + '/views/layout.jade', jadeLayout); 310 | write(path + '/views/index.jade', jadeIndex); 311 | break; 312 | case 'jshtml': 313 | write(path + '/views/layout.jshtml', jshtmlLayout); 314 | write(path + '/views/index.jshtml', jshtmlIndex); 315 | break; 316 | case 'hjs': 317 | write(path + '/views/index.hjs', hoganIndex); 318 | break; 319 | 320 | } 321 | }); 322 | 323 | // CSS Engine support 324 | switch (program.css) { 325 | case 'less': 326 | app = app.replace('{css}', eol + 'app.use(require(\'less-middleware\')({ src: __dirname + \'/public\' }));'); 327 | break; 328 | case 'stylus': 329 | app = app.replace('{css}', eol + 'app.use(require(\'stylus\').middleware(__dirname + \'/public\'));'); 330 | break; 331 | default: 332 | app = app.replace('{css}', ''); 333 | } 334 | 335 | // Session support 336 | app = app.replace('{sess}', program.sessions 337 | ? eol + 'app.use(express.cookieParser(\'your secret here\'));' + eol + 'app.use(express.session());' 338 | : ''); 339 | 340 | // Template support 341 | app = app.replace(':TEMPLATE', program.template); 342 | 343 | // package.json 344 | var pkg = { 345 | name: 'application-name' 346 | , version: '0.0.1' 347 | , private: true 348 | , scripts: { start: 'node app.js' } 349 | , dependencies: { 350 | express: version 351 | } 352 | } 353 | 354 | if (program.template) pkg.dependencies[program.template] = '*'; 355 | 356 | // CSS Engine support 357 | switch (program.css) { 358 | case 'less': 359 | pkg.dependencies['less-middleware'] = '*'; 360 | break; 361 | default: 362 | if (program.css) { 363 | pkg.dependencies[program.css] = '*'; 364 | } 365 | } 366 | 367 | write(path + '/package.json', JSON.stringify(pkg, null, 2)); 368 | write(path + '/app.js', app); 369 | }); 370 | } 371 | 372 | /** 373 | * Check if the given directory `path` is empty. 374 | * 375 | * @param {String} path 376 | * @param {Function} fn 377 | */ 378 | 379 | function emptyDirectory(path, fn) { 380 | fs.readdir(path, function(err, files){ 381 | if (err && 'ENOENT' != err.code) throw err; 382 | fn(!files || !files.length); 383 | }); 384 | } 385 | 386 | /** 387 | * echo str > path. 388 | * 389 | * @param {String} path 390 | * @param {String} str 391 | */ 392 | 393 | function write(path, str) { 394 | fs.writeFile(path, str); 395 | console.log(' \x1b[36mcreate\x1b[0m : ' + path); 396 | } 397 | 398 | /** 399 | * Mkdir -p. 400 | * 401 | * @param {String} path 402 | * @param {Function} fn 403 | */ 404 | 405 | function mkdir(path, fn) { 406 | mkdirp(path, 0755, function(err){ 407 | if (err) throw err; 408 | console.log(' \033[36mcreate\033[0m : ' + path); 409 | fn && fn(); 410 | }); 411 | } 412 | 413 | /** 414 | * Exit with the given `str`. 415 | * 416 | * @param {String} str 417 | */ 418 | 419 | function abort(str) { 420 | console.error(str); 421 | process.exit(1); 422 | } 423 | -------------------------------------------------------------------------------- /node_modules/express/index.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = process.env.EXPRESS_COV 3 | ? require('./lib-cov/express') 4 | : require('./lib/express'); -------------------------------------------------------------------------------- /node_modules/express/lib/express.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var connect = require('connect') 6 | , proto = require('./application') 7 | , Route = require('./router/route') 8 | , Router = require('./router') 9 | , req = require('./request') 10 | , res = require('./response') 11 | , utils = connect.utils; 12 | 13 | /** 14 | * Expose `createApplication()`. 15 | */ 16 | 17 | exports = module.exports = createApplication; 18 | 19 | /** 20 | * Expose mime. 21 | */ 22 | 23 | exports.mime = connect.mime; 24 | 25 | /** 26 | * Create an express application. 27 | * 28 | * @return {Function} 29 | * @api public 30 | */ 31 | 32 | function createApplication() { 33 | var app = connect(); 34 | utils.merge(app, proto); 35 | app.request = { __proto__: req, app: app }; 36 | app.response = { __proto__: res, app: app }; 37 | app.init(); 38 | return app; 39 | } 40 | 41 | /** 42 | * Expose connect.middleware as express.* 43 | * for example `express.logger` etc. 44 | */ 45 | 46 | for (var key in connect.middleware) { 47 | Object.defineProperty( 48 | exports 49 | , key 50 | , Object.getOwnPropertyDescriptor(connect.middleware, key)); 51 | } 52 | 53 | /** 54 | * Error on createServer(). 55 | */ 56 | 57 | exports.createServer = function(){ 58 | console.warn('Warning: express.createServer() is deprecated, express'); 59 | console.warn('applications no longer inherit from http.Server,'); 60 | console.warn('please use:'); 61 | console.warn(''); 62 | console.warn(' var express = require("express");'); 63 | console.warn(' var app = express();'); 64 | console.warn(''); 65 | return createApplication(); 66 | }; 67 | 68 | /** 69 | * Expose the prototypes. 70 | */ 71 | 72 | exports.application = proto; 73 | exports.request = req; 74 | exports.response = res; 75 | 76 | /** 77 | * Expose constructors. 78 | */ 79 | 80 | exports.Route = Route; 81 | exports.Router = Router; 82 | 83 | // Error handler title 84 | 85 | exports.errorHandler.title = 'Express'; 86 | 87 | -------------------------------------------------------------------------------- /node_modules/express/lib/request.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var http = require('http') 7 | , utils = require('./utils') 8 | , connect = require('connect') 9 | , fresh = require('fresh') 10 | , parseRange = require('range-parser') 11 | , parse = connect.utils.parseUrl 12 | , mime = connect.mime; 13 | 14 | /** 15 | * Request prototype. 16 | */ 17 | 18 | var req = exports = module.exports = { 19 | __proto__: http.IncomingMessage.prototype 20 | }; 21 | 22 | /** 23 | * Return request header. 24 | * 25 | * The `Referrer` header field is special-cased, 26 | * both `Referrer` and `Referer` are interchangeable. 27 | * 28 | * Examples: 29 | * 30 | * req.get('Content-Type'); 31 | * // => "text/plain" 32 | * 33 | * req.get('content-type'); 34 | * // => "text/plain" 35 | * 36 | * req.get('Something'); 37 | * // => undefined 38 | * 39 | * Aliased as `req.header()`. 40 | * 41 | * @param {String} name 42 | * @return {String} 43 | * @api public 44 | */ 45 | 46 | req.get = 47 | req.header = function(name){ 48 | switch (name = name.toLowerCase()) { 49 | case 'referer': 50 | case 'referrer': 51 | return this.headers.referrer 52 | || this.headers.referer; 53 | default: 54 | return this.headers[name]; 55 | } 56 | }; 57 | 58 | /** 59 | * Check if the given `type(s)` is acceptable, returning 60 | * the best match when true, otherwise `undefined`, in which 61 | * case you should respond with 406 "Not Acceptable". 62 | * 63 | * The `type` value may be a single mime type string 64 | * such as "application/json", the extension name 65 | * such as "json", a comma-delimted list such as "json, html, text/plain", 66 | * or an array `["json", "html", "text/plain"]`. When a list 67 | * or array is given the _best_ match, if any is returned. 68 | * 69 | * Examples: 70 | * 71 | * // Accept: text/html 72 | * req.accepts('html'); 73 | * // => "html" 74 | * 75 | * // Accept: text/*, application/json 76 | * req.accepts('html'); 77 | * // => "html" 78 | * req.accepts('text/html'); 79 | * // => "text/html" 80 | * req.accepts('json, text'); 81 | * // => "json" 82 | * req.accepts('application/json'); 83 | * // => "application/json" 84 | * 85 | * // Accept: text/*, application/json 86 | * req.accepts('image/png'); 87 | * req.accepts('png'); 88 | * // => undefined 89 | * 90 | * // Accept: text/*;q=.5, application/json 91 | * req.accepts(['html', 'json']); 92 | * req.accepts('html, json'); 93 | * // => "json" 94 | * 95 | * @param {String|Array} type(s) 96 | * @return {String} 97 | * @api public 98 | */ 99 | 100 | req.accepts = function(type){ 101 | return utils.accepts(type, this.get('Accept')); 102 | }; 103 | 104 | /** 105 | * Check if the given `encoding` is accepted. 106 | * 107 | * @param {String} encoding 108 | * @return {Boolean} 109 | * @api public 110 | */ 111 | 112 | req.acceptsEncoding = function(encoding){ 113 | return !! ~this.acceptedEncodings.indexOf(encoding); 114 | }; 115 | 116 | /** 117 | * Check if the given `charset` is acceptable, 118 | * otherwise you should respond with 406 "Not Acceptable". 119 | * 120 | * @param {String} charset 121 | * @return {Boolean} 122 | * @api public 123 | */ 124 | 125 | req.acceptsCharset = function(charset){ 126 | var accepted = this.acceptedCharsets; 127 | return accepted.length 128 | ? !! ~accepted.indexOf(charset) 129 | : true; 130 | }; 131 | 132 | /** 133 | * Check if the given `lang` is acceptable, 134 | * otherwise you should respond with 406 "Not Acceptable". 135 | * 136 | * @param {String} lang 137 | * @return {Boolean} 138 | * @api public 139 | */ 140 | 141 | req.acceptsLanguage = function(lang){ 142 | var accepted = this.acceptedLanguages; 143 | return accepted.length 144 | ? !! ~accepted.indexOf(lang) 145 | : true; 146 | }; 147 | 148 | /** 149 | * Parse Range header field, 150 | * capping to the given `size`. 151 | * 152 | * Unspecified ranges such as "0-" require 153 | * knowledge of your resource length. In 154 | * the case of a byte range this is of course 155 | * the total number of bytes. If the Range 156 | * header field is not given `null` is returned, 157 | * `-1` when unsatisfiable, `-2` when syntactically invalid. 158 | * 159 | * NOTE: remember that ranges are inclusive, so 160 | * for example "Range: users=0-3" should respond 161 | * with 4 users when available, not 3. 162 | * 163 | * @param {Number} size 164 | * @return {Array} 165 | * @api public 166 | */ 167 | 168 | req.range = function(size){ 169 | var range = this.get('Range'); 170 | if (!range) return; 171 | return parseRange(size, range); 172 | }; 173 | 174 | /** 175 | * Return an array of encodings. 176 | * 177 | * Examples: 178 | * 179 | * ['gzip', 'deflate'] 180 | * 181 | * @return {Array} 182 | * @api public 183 | */ 184 | 185 | req.__defineGetter__('acceptedEncodings', function(){ 186 | var accept = this.get('Accept-Encoding'); 187 | return accept 188 | ? accept.trim().split(/ *, */) 189 | : []; 190 | }); 191 | 192 | /** 193 | * Return an array of Accepted media types 194 | * ordered from highest quality to lowest. 195 | * 196 | * Examples: 197 | * 198 | * [ { value: 'application/json', 199 | * quality: 1, 200 | * type: 'application', 201 | * subtype: 'json' }, 202 | * { value: 'text/html', 203 | * quality: 0.5, 204 | * type: 'text', 205 | * subtype: 'html' } ] 206 | * 207 | * @return {Array} 208 | * @api public 209 | */ 210 | 211 | req.__defineGetter__('accepted', function(){ 212 | var accept = this.get('Accept'); 213 | return accept 214 | ? utils.parseAccept(accept) 215 | : []; 216 | }); 217 | 218 | /** 219 | * Return an array of Accepted languages 220 | * ordered from highest quality to lowest. 221 | * 222 | * Examples: 223 | * 224 | * Accept-Language: en;q=.5, en-us 225 | * ['en-us', 'en'] 226 | * 227 | * @return {Array} 228 | * @api public 229 | */ 230 | 231 | req.__defineGetter__('acceptedLanguages', function(){ 232 | var accept = this.get('Accept-Language'); 233 | return accept 234 | ? utils 235 | .parseParams(accept) 236 | .map(function(obj){ 237 | return obj.value; 238 | }) 239 | : []; 240 | }); 241 | 242 | /** 243 | * Return an array of Accepted charsets 244 | * ordered from highest quality to lowest. 245 | * 246 | * Examples: 247 | * 248 | * Accept-Charset: iso-8859-5;q=.2, unicode-1-1;q=0.8 249 | * ['unicode-1-1', 'iso-8859-5'] 250 | * 251 | * @return {Array} 252 | * @api public 253 | */ 254 | 255 | req.__defineGetter__('acceptedCharsets', function(){ 256 | var accept = this.get('Accept-Charset'); 257 | return accept 258 | ? utils 259 | .parseParams(accept) 260 | .map(function(obj){ 261 | return obj.value; 262 | }) 263 | : []; 264 | }); 265 | 266 | /** 267 | * Return the value of param `name` when present or `defaultValue`. 268 | * 269 | * - Checks route placeholders, ex: _/user/:id_ 270 | * - Checks body params, ex: id=12, {"id":12} 271 | * - Checks query string params, ex: ?id=12 272 | * 273 | * To utilize request bodies, `req.body` 274 | * should be an object. This can be done by using 275 | * the `connect.bodyParser()` middleware. 276 | * 277 | * @param {String} name 278 | * @param {Mixed} [defaultValue] 279 | * @return {String} 280 | * @api public 281 | */ 282 | 283 | req.param = function(name, defaultValue){ 284 | var params = this.params || {}; 285 | var body = this.body || {}; 286 | var query = this.query || {}; 287 | if (null != params[name] && params.hasOwnProperty(name)) return params[name]; 288 | if (null != body[name]) return body[name]; 289 | if (null != query[name]) return query[name]; 290 | return defaultValue; 291 | }; 292 | 293 | /** 294 | * Check if the incoming request contains the "Content-Type" 295 | * header field, and it contains the give mime `type`. 296 | * 297 | * Examples: 298 | * 299 | * // With Content-Type: text/html; charset=utf-8 300 | * req.is('html'); 301 | * req.is('text/html'); 302 | * req.is('text/*'); 303 | * // => true 304 | * 305 | * // When Content-Type is application/json 306 | * req.is('json'); 307 | * req.is('application/json'); 308 | * req.is('application/*'); 309 | * // => true 310 | * 311 | * req.is('html'); 312 | * // => false 313 | * 314 | * @param {String} type 315 | * @return {Boolean} 316 | * @api public 317 | */ 318 | 319 | req.is = function(type){ 320 | var ct = this.get('Content-Type'); 321 | if (!ct) return false; 322 | ct = ct.split(';')[0]; 323 | if (!~type.indexOf('/')) type = mime.lookup(type); 324 | if (~type.indexOf('*')) { 325 | type = type.split('/'); 326 | ct = ct.split('/'); 327 | if ('*' == type[0] && type[1] == ct[1]) return true; 328 | if ('*' == type[1] && type[0] == ct[0]) return true; 329 | return false; 330 | } 331 | return !! ~ct.indexOf(type); 332 | }; 333 | 334 | /** 335 | * Return the protocol string "http" or "https" 336 | * when requested with TLS. When the "trust proxy" 337 | * setting is enabled the "X-Forwarded-Proto" header 338 | * field will be trusted. If you're running behind 339 | * a reverse proxy that supplies https for you this 340 | * may be enabled. 341 | * 342 | * @return {String} 343 | * @api public 344 | */ 345 | 346 | req.__defineGetter__('protocol', function(){ 347 | var trustProxy = this.app.get('trust proxy'); 348 | if (this.connection.encrypted) return 'https'; 349 | if (!trustProxy) return 'http'; 350 | var proto = this.get('X-Forwarded-Proto') || 'http'; 351 | return proto.split(/\s*,\s*/)[0]; 352 | }); 353 | 354 | /** 355 | * Short-hand for: 356 | * 357 | * req.protocol == 'https' 358 | * 359 | * @return {Boolean} 360 | * @api public 361 | */ 362 | 363 | req.__defineGetter__('secure', function(){ 364 | return 'https' == this.protocol; 365 | }); 366 | 367 | /** 368 | * Return the remote address, or when 369 | * "trust proxy" is `true` return 370 | * the upstream addr. 371 | * 372 | * @return {String} 373 | * @api public 374 | */ 375 | 376 | req.__defineGetter__('ip', function(){ 377 | return this.ips[0] || this.connection.remoteAddress; 378 | }); 379 | 380 | /** 381 | * When "trust proxy" is `true`, parse 382 | * the "X-Forwarded-For" ip address list. 383 | * 384 | * For example if the value were "client, proxy1, proxy2" 385 | * you would receive the array `["client", "proxy1", "proxy2"]` 386 | * where "proxy2" is the furthest down-stream. 387 | * 388 | * @return {Array} 389 | * @api public 390 | */ 391 | 392 | req.__defineGetter__('ips', function(){ 393 | var trustProxy = this.app.get('trust proxy'); 394 | var val = this.get('X-Forwarded-For'); 395 | return trustProxy && val 396 | ? val.split(/ *, */) 397 | : []; 398 | }); 399 | 400 | /** 401 | * Return basic auth credentials. 402 | * 403 | * Examples: 404 | * 405 | * // http://tobi:hello@example.com 406 | * req.auth 407 | * // => { username: 'tobi', password: 'hello' } 408 | * 409 | * @return {Object} or undefined 410 | * @api public 411 | */ 412 | 413 | req.__defineGetter__('auth', function(){ 414 | // missing 415 | var auth = this.get('Authorization'); 416 | if (!auth) return; 417 | 418 | // malformed 419 | var parts = auth.split(' '); 420 | if ('basic' != parts[0].toLowerCase()) return; 421 | if (!parts[1]) return; 422 | auth = parts[1]; 423 | 424 | // credentials 425 | auth = new Buffer(auth, 'base64').toString().match(/^([^:]*):(.*)$/); 426 | if (!auth) return; 427 | return { username: auth[1], password: auth[2] }; 428 | }); 429 | 430 | /** 431 | * Return subdomains as an array. 432 | * 433 | * Subdomains are the dot-separated parts of the host before the main domain of 434 | * the app. By default, the domain of the app is assumed to be the last two 435 | * parts of the host. This can be changed by setting "subdomain offset". 436 | * 437 | * For example, if the domain is "tobi.ferrets.example.com": 438 | * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`. 439 | * If "subdomain offset" is 3, req.subdomains is `["tobi"]`. 440 | * 441 | * @return {Array} 442 | * @api public 443 | */ 444 | 445 | req.__defineGetter__('subdomains', function(){ 446 | var offset = this.app.get('subdomain offset'); 447 | return (this.host || '') 448 | .split('.') 449 | .reverse() 450 | .slice(offset); 451 | }); 452 | 453 | /** 454 | * Short-hand for `url.parse(req.url).pathname`. 455 | * 456 | * @return {String} 457 | * @api public 458 | */ 459 | 460 | req.__defineGetter__('path', function(){ 461 | return parse(this).pathname; 462 | }); 463 | 464 | /** 465 | * Parse the "Host" header field hostname. 466 | * 467 | * @return {String} 468 | * @api public 469 | */ 470 | 471 | req.__defineGetter__('host', function(){ 472 | var trustProxy = this.app.get('trust proxy'); 473 | var host = trustProxy && this.get('X-Forwarded-Host'); 474 | host = host || this.get('Host'); 475 | if (!host) return; 476 | return host.split(':')[0]; 477 | }); 478 | 479 | /** 480 | * Check if the request is fresh, aka 481 | * Last-Modified and/or the ETag 482 | * still match. 483 | * 484 | * @return {Boolean} 485 | * @api public 486 | */ 487 | 488 | req.__defineGetter__('fresh', function(){ 489 | var method = this.method; 490 | var s = this.res.statusCode; 491 | 492 | // GET or HEAD for weak freshness validation only 493 | if ('GET' != method && 'HEAD' != method) return false; 494 | 495 | // 2xx or 304 as per rfc2616 14.26 496 | if ((s >= 200 && s < 300) || 304 == s) { 497 | return fresh(this.headers, this.res._headers); 498 | } 499 | 500 | return false; 501 | }); 502 | 503 | /** 504 | * Check if the request is stale, aka 505 | * "Last-Modified" and / or the "ETag" for the 506 | * resource has changed. 507 | * 508 | * @return {Boolean} 509 | * @api public 510 | */ 511 | 512 | req.__defineGetter__('stale', function(){ 513 | return !this.fresh; 514 | }); 515 | 516 | /** 517 | * Check if the request was an _XMLHttpRequest_. 518 | * 519 | * @return {Boolean} 520 | * @api public 521 | */ 522 | 523 | req.__defineGetter__('xhr', function(){ 524 | var val = this.get('X-Requested-With') || ''; 525 | return 'xmlhttprequest' == val.toLowerCase(); 526 | }); 527 | -------------------------------------------------------------------------------- /node_modules/express/lib/response.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var http = require('http') 6 | , path = require('path') 7 | , connect = require('connect') 8 | , utils = connect.utils 9 | , sign = require('cookie-signature').sign 10 | , normalizeType = require('./utils').normalizeType 11 | , normalizeTypes = require('./utils').normalizeTypes 12 | , etag = require('./utils').etag 13 | , statusCodes = http.STATUS_CODES 14 | , cookie = require('cookie') 15 | , send = require('send') 16 | , mime = connect.mime 17 | , basename = path.basename 18 | , extname = path.extname 19 | , join = path.join; 20 | 21 | /** 22 | * Response prototype. 23 | */ 24 | 25 | var res = module.exports = { 26 | __proto__: http.ServerResponse.prototype 27 | }; 28 | 29 | /** 30 | * Set status `code`. 31 | * 32 | * @param {Number} code 33 | * @return {ServerResponse} 34 | * @api public 35 | */ 36 | 37 | res.status = function(code){ 38 | this.statusCode = code; 39 | return this; 40 | }; 41 | 42 | /** 43 | * Set Link header field with the given `links`. 44 | * 45 | * Examples: 46 | * 47 | * res.links({ 48 | * next: 'http://api.example.com/users?page=2', 49 | * last: 'http://api.example.com/users?page=5' 50 | * }); 51 | * 52 | * @param {Object} links 53 | * @return {ServerResponse} 54 | * @api public 55 | */ 56 | 57 | res.links = function(links){ 58 | return this.set('Link', Object.keys(links).map(function(rel){ 59 | return '<' + links[rel] + '>; rel="' + rel + '"'; 60 | }).join(', ')); 61 | }; 62 | 63 | /** 64 | * Send a response. 65 | * 66 | * Examples: 67 | * 68 | * res.send(new Buffer('wahoo')); 69 | * res.send({ some: 'json' }); 70 | * res.send('

some html

'); 71 | * res.send(404, 'Sorry, cant find that'); 72 | * res.send(404); 73 | * 74 | * @param {Mixed} body or status 75 | * @param {Mixed} body 76 | * @return {ServerResponse} 77 | * @api public 78 | */ 79 | 80 | res.send = function(body){ 81 | var req = this.req; 82 | var head = 'HEAD' == req.method; 83 | var len; 84 | 85 | // allow status / body 86 | if (2 == arguments.length) { 87 | // res.send(body, status) backwards compat 88 | if ('number' != typeof body && 'number' == typeof arguments[1]) { 89 | this.statusCode = arguments[1]; 90 | } else { 91 | this.statusCode = body; 92 | body = arguments[1]; 93 | } 94 | } 95 | 96 | switch (typeof body) { 97 | // response status 98 | case 'number': 99 | this.get('Content-Type') || this.type('txt'); 100 | this.statusCode = body; 101 | body = http.STATUS_CODES[body]; 102 | break; 103 | // string defaulting to html 104 | case 'string': 105 | if (!this.get('Content-Type')) { 106 | this.charset = this.charset || 'utf-8'; 107 | this.type('html'); 108 | } 109 | break; 110 | case 'boolean': 111 | case 'object': 112 | if (null == body) { 113 | body = ''; 114 | } else if (Buffer.isBuffer(body)) { 115 | this.get('Content-Type') || this.type('bin'); 116 | } else { 117 | return this.json(body); 118 | } 119 | break; 120 | } 121 | 122 | // populate Content-Length 123 | if (undefined !== body && !this.get('Content-Length')) { 124 | this.set('Content-Length', len = Buffer.isBuffer(body) 125 | ? body.length 126 | : Buffer.byteLength(body)); 127 | } 128 | 129 | // ETag support 130 | // TODO: W/ support 131 | if (len > 1024 && 'GET' == req.method) { 132 | if (!this.get('ETag')) { 133 | this.set('ETag', etag(body)); 134 | } 135 | } 136 | 137 | // freshness 138 | if (req.fresh) this.statusCode = 304; 139 | 140 | // strip irrelevant headers 141 | if (204 == this.statusCode || 304 == this.statusCode) { 142 | this.removeHeader('Content-Type'); 143 | this.removeHeader('Content-Length'); 144 | this.removeHeader('Transfer-Encoding'); 145 | body = ''; 146 | } 147 | 148 | // respond 149 | this.end(head ? null : body); 150 | return this; 151 | }; 152 | 153 | /** 154 | * Send JSON response. 155 | * 156 | * Examples: 157 | * 158 | * res.json(null); 159 | * res.json({ user: 'tj' }); 160 | * res.json(500, 'oh noes!'); 161 | * res.json(404, 'I dont have that'); 162 | * 163 | * @param {Mixed} obj or status 164 | * @param {Mixed} obj 165 | * @return {ServerResponse} 166 | * @api public 167 | */ 168 | 169 | res.json = function(obj){ 170 | // allow status / body 171 | if (2 == arguments.length) { 172 | // res.json(body, status) backwards compat 173 | if ('number' == typeof arguments[1]) { 174 | this.statusCode = arguments[1]; 175 | } else { 176 | this.statusCode = obj; 177 | obj = arguments[1]; 178 | } 179 | } 180 | 181 | // settings 182 | var app = this.app; 183 | var replacer = app.get('json replacer'); 184 | var spaces = app.get('json spaces'); 185 | var body = JSON.stringify(obj, replacer, spaces); 186 | 187 | // content-type 188 | this.get('Content-Type') || this.set('Content-Type', 'application/json'); 189 | 190 | return this.send(body); 191 | }; 192 | 193 | /** 194 | * Send JSON response with JSONP callback support. 195 | * 196 | * Examples: 197 | * 198 | * res.jsonp(null); 199 | * res.jsonp({ user: 'tj' }); 200 | * res.jsonp(500, 'oh noes!'); 201 | * res.jsonp(404, 'I dont have that'); 202 | * 203 | * @param {Mixed} obj or status 204 | * @param {Mixed} obj 205 | * @return {ServerResponse} 206 | * @api public 207 | */ 208 | 209 | res.jsonp = function(obj){ 210 | // allow status / body 211 | if (2 == arguments.length) { 212 | // res.json(body, status) backwards compat 213 | if ('number' == typeof arguments[1]) { 214 | this.statusCode = arguments[1]; 215 | } else { 216 | this.statusCode = obj; 217 | obj = arguments[1]; 218 | } 219 | } 220 | 221 | // settings 222 | var app = this.app; 223 | var replacer = app.get('json replacer'); 224 | var spaces = app.get('json spaces'); 225 | var body = JSON.stringify(obj, replacer, spaces) 226 | .replace(/\u2028/g, '\\u2028') 227 | .replace(/\u2029/g, '\\u2029'); 228 | var callback = this.req.query[app.get('jsonp callback name')]; 229 | 230 | // content-type 231 | this.charset = this.charset || 'utf-8'; 232 | this.set('Content-Type', 'application/json'); 233 | 234 | // jsonp 235 | if (callback) { 236 | if (callback instanceof Array) callback = callback[0]; 237 | this.set('Content-Type', 'text/javascript'); 238 | var cb = callback.replace(/[^\[\]\w$.]/g, ''); 239 | body = cb + ' && ' + cb + '(' + body + ');'; 240 | } 241 | 242 | return this.send(body); 243 | }; 244 | 245 | /** 246 | * Transfer the file at the given `path`. 247 | * 248 | * Automatically sets the _Content-Type_ response header field. 249 | * The callback `fn(err)` is invoked when the transfer is complete 250 | * or when an error occurs. Be sure to check `res.sentHeader` 251 | * if you wish to attempt responding, as the header and some data 252 | * may have already been transferred. 253 | * 254 | * Options: 255 | * 256 | * - `maxAge` defaulting to 0 257 | * - `root` root directory for relative filenames 258 | * 259 | * Examples: 260 | * 261 | * The following example illustrates how `res.sendfile()` may 262 | * be used as an alternative for the `static()` middleware for 263 | * dynamic situations. The code backing `res.sendfile()` is actually 264 | * the same code, so HTTP cache support etc is identical. 265 | * 266 | * app.get('/user/:uid/photos/:file', function(req, res){ 267 | * var uid = req.params.uid 268 | * , file = req.params.file; 269 | * 270 | * req.user.mayViewFilesFrom(uid, function(yes){ 271 | * if (yes) { 272 | * res.sendfile('/uploads/' + uid + '/' + file); 273 | * } else { 274 | * res.send(403, 'Sorry! you cant see that.'); 275 | * } 276 | * }); 277 | * }); 278 | * 279 | * @param {String} path 280 | * @param {Object|Function} options or fn 281 | * @param {Function} fn 282 | * @api public 283 | */ 284 | 285 | res.sendfile = function(path, options, fn){ 286 | var self = this 287 | , req = self.req 288 | , next = this.req.next 289 | , options = options || {} 290 | , done; 291 | 292 | // support function as second arg 293 | if ('function' == typeof options) { 294 | fn = options; 295 | options = {}; 296 | } 297 | 298 | // socket errors 299 | req.socket.on('error', error); 300 | 301 | // errors 302 | function error(err) { 303 | if (done) return; 304 | done = true; 305 | 306 | // clean up 307 | cleanup(); 308 | if (!self.headerSent) self.removeHeader('Content-Disposition'); 309 | 310 | // callback available 311 | if (fn) return fn(err); 312 | 313 | // list in limbo if there's no callback 314 | if (self.headerSent) return; 315 | 316 | // delegate 317 | next(err); 318 | } 319 | 320 | // streaming 321 | function stream() { 322 | if (done) return; 323 | cleanup(); 324 | if (fn) self.on('finish', fn); 325 | } 326 | 327 | // cleanup 328 | function cleanup() { 329 | req.socket.removeListener('error', error); 330 | } 331 | 332 | // transfer 333 | var file = send(req, path); 334 | if (options.root) file.root(options.root); 335 | file.maxage(options.maxAge || 0); 336 | file.on('error', error); 337 | file.on('directory', next); 338 | file.on('stream', stream); 339 | file.pipe(this); 340 | this.on('finish', cleanup); 341 | }; 342 | 343 | /** 344 | * Transfer the file at the given `path` as an attachment. 345 | * 346 | * Optionally providing an alternate attachment `filename`, 347 | * and optional callback `fn(err)`. The callback is invoked 348 | * when the data transfer is complete, or when an error has 349 | * ocurred. Be sure to check `res.headerSent` if you plan to respond. 350 | * 351 | * This method uses `res.sendfile()`. 352 | * 353 | * @param {String} path 354 | * @param {String|Function} filename or fn 355 | * @param {Function} fn 356 | * @api public 357 | */ 358 | 359 | res.download = function(path, filename, fn){ 360 | // support function as second arg 361 | if ('function' == typeof filename) { 362 | fn = filename; 363 | filename = null; 364 | } 365 | 366 | filename = filename || path; 367 | this.set('Content-Disposition', 'attachment; filename="' + basename(filename) + '"'); 368 | return this.sendfile(path, fn); 369 | }; 370 | 371 | /** 372 | * Set _Content-Type_ response header with `type` through `mime.lookup()` 373 | * when it does not contain "/", or set the Content-Type to `type` otherwise. 374 | * 375 | * Examples: 376 | * 377 | * res.type('.html'); 378 | * res.type('html'); 379 | * res.type('json'); 380 | * res.type('application/json'); 381 | * res.type('png'); 382 | * 383 | * @param {String} type 384 | * @return {ServerResponse} for chaining 385 | * @api public 386 | */ 387 | 388 | res.contentType = 389 | res.type = function(type){ 390 | return this.set('Content-Type', ~type.indexOf('/') 391 | ? type 392 | : mime.lookup(type)); 393 | }; 394 | 395 | /** 396 | * Respond to the Acceptable formats using an `obj` 397 | * of mime-type callbacks. 398 | * 399 | * This method uses `req.accepted`, an array of 400 | * acceptable types ordered by their quality values. 401 | * When "Accept" is not present the _first_ callback 402 | * is invoked, otherwise the first match is used. When 403 | * no match is performed the server responds with 404 | * 406 "Not Acceptable". 405 | * 406 | * Content-Type is set for you, however if you choose 407 | * you may alter this within the callback using `res.type()` 408 | * or `res.set('Content-Type', ...)`. 409 | * 410 | * res.format({ 411 | * 'text/plain': function(){ 412 | * res.send('hey'); 413 | * }, 414 | * 415 | * 'text/html': function(){ 416 | * res.send('

hey

'); 417 | * }, 418 | * 419 | * 'appliation/json': function(){ 420 | * res.send({ message: 'hey' }); 421 | * } 422 | * }); 423 | * 424 | * In addition to canonicalized MIME types you may 425 | * also use extnames mapped to these types: 426 | * 427 | * res.format({ 428 | * text: function(){ 429 | * res.send('hey'); 430 | * }, 431 | * 432 | * html: function(){ 433 | * res.send('

hey

'); 434 | * }, 435 | * 436 | * json: function(){ 437 | * res.send({ message: 'hey' }); 438 | * } 439 | * }); 440 | * 441 | * By default Express passes an `Error` 442 | * with a `.status` of 406 to `next(err)` 443 | * if a match is not made. If you provide 444 | * a `.default` callback it will be invoked 445 | * instead. 446 | * 447 | * @param {Object} obj 448 | * @return {ServerResponse} for chaining 449 | * @api public 450 | */ 451 | 452 | res.format = function(obj){ 453 | var req = this.req 454 | , next = req.next; 455 | 456 | var fn = obj.default; 457 | if (fn) delete obj.default; 458 | var keys = Object.keys(obj); 459 | 460 | var key = req.accepts(keys); 461 | 462 | this.set('Vary', 'Accept'); 463 | 464 | if (key) { 465 | this.set('Content-Type', normalizeType(key).value); 466 | obj[key](req, this, next); 467 | } else if (fn) { 468 | fn(); 469 | } else { 470 | var err = new Error('Not Acceptable'); 471 | err.status = 406; 472 | err.types = normalizeTypes(keys).map(function(o){ return o.value }); 473 | next(err); 474 | } 475 | 476 | return this; 477 | }; 478 | 479 | /** 480 | * Set _Content-Disposition_ header to _attachment_ with optional `filename`. 481 | * 482 | * @param {String} filename 483 | * @return {ServerResponse} 484 | * @api public 485 | */ 486 | 487 | res.attachment = function(filename){ 488 | if (filename) this.type(extname(filename)); 489 | this.set('Content-Disposition', filename 490 | ? 'attachment; filename="' + basename(filename) + '"' 491 | : 'attachment'); 492 | return this; 493 | }; 494 | 495 | /** 496 | * Set header `field` to `val`, or pass 497 | * an object of header fields. 498 | * 499 | * Examples: 500 | * 501 | * res.set('Foo', ['bar', 'baz']); 502 | * res.set('Accept', 'application/json'); 503 | * res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' }); 504 | * 505 | * Aliased as `res.header()`. 506 | * 507 | * @param {String|Object|Array} field 508 | * @param {String} val 509 | * @return {ServerResponse} for chaining 510 | * @api public 511 | */ 512 | 513 | res.set = 514 | res.header = function(field, val){ 515 | if (2 == arguments.length) { 516 | if (Array.isArray(val)) val = val.map(String); 517 | else val = String(val); 518 | this.setHeader(field, val); 519 | } else { 520 | for (var key in field) { 521 | this.set(key, field[key]); 522 | } 523 | } 524 | return this; 525 | }; 526 | 527 | /** 528 | * Get value for header `field`. 529 | * 530 | * @param {String} field 531 | * @return {String} 532 | * @api public 533 | */ 534 | 535 | res.get = function(field){ 536 | return this.getHeader(field); 537 | }; 538 | 539 | /** 540 | * Clear cookie `name`. 541 | * 542 | * @param {String} name 543 | * @param {Object} options 544 | * @param {ServerResponse} for chaining 545 | * @api public 546 | */ 547 | 548 | res.clearCookie = function(name, options){ 549 | var opts = { expires: new Date(1), path: '/' }; 550 | return this.cookie(name, '', options 551 | ? utils.merge(opts, options) 552 | : opts); 553 | }; 554 | 555 | /** 556 | * Set cookie `name` to `val`, with the given `options`. 557 | * 558 | * Options: 559 | * 560 | * - `maxAge` max-age in milliseconds, converted to `expires` 561 | * - `signed` sign the cookie 562 | * - `path` defaults to "/" 563 | * 564 | * Examples: 565 | * 566 | * // "Remember Me" for 15 minutes 567 | * res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true }); 568 | * 569 | * // save as above 570 | * res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true }) 571 | * 572 | * @param {String} name 573 | * @param {String|Object} val 574 | * @param {Options} options 575 | * @api public 576 | */ 577 | 578 | res.cookie = function(name, val, options){ 579 | options = utils.merge({}, options); 580 | var secret = this.req.secret; 581 | var signed = options.signed; 582 | if (signed && !secret) throw new Error('connect.cookieParser("secret") required for signed cookies'); 583 | if ('number' == typeof val) val = val.toString(); 584 | if ('object' == typeof val) val = 'j:' + JSON.stringify(val); 585 | if (signed) val = 's:' + sign(val, secret); 586 | if ('maxAge' in options) { 587 | options.expires = new Date(Date.now() + options.maxAge); 588 | options.maxAge /= 1000; 589 | } 590 | if (null == options.path) options.path = '/'; 591 | this.set('Set-Cookie', cookie.serialize(name, String(val), options)); 592 | return this; 593 | }; 594 | 595 | 596 | /** 597 | * Set the location header to `url`. 598 | * 599 | * The given `url` can also be the name of a mapped url, for 600 | * example by default express supports "back" which redirects 601 | * to the _Referrer_ or _Referer_ headers or "/". 602 | * 603 | * Examples: 604 | * 605 | * res.location('/foo/bar').; 606 | * res.location('http://example.com'); 607 | * res.location('../login'); // /blog/post/1 -> /blog/login 608 | * 609 | * Mounting: 610 | * 611 | * When an application is mounted and `res.location()` 612 | * is given a path that does _not_ lead with "/" it becomes 613 | * relative to the mount-point. For example if the application 614 | * is mounted at "/blog", the following would become "/blog/login". 615 | * 616 | * res.location('login'); 617 | * 618 | * While the leading slash would result in a location of "/login": 619 | * 620 | * res.location('/login'); 621 | * 622 | * @param {String} url 623 | * @api public 624 | */ 625 | 626 | res.location = function(url){ 627 | var app = this.app 628 | , req = this.req; 629 | 630 | // setup redirect map 631 | var map = { back: req.get('Referrer') || '/' }; 632 | 633 | // perform redirect 634 | url = map[url] || url; 635 | 636 | // relative 637 | if (!~url.indexOf('://') && 0 != url.indexOf('//')) { 638 | var path 639 | 640 | // relative to path 641 | if ('.' == url[0]) { 642 | path = req.originalUrl.split('?')[0] 643 | url = path + ('/' == path[path.length - 1] ? '' : '/') + url; 644 | // relative to mount-point 645 | } else if ('/' != url[0]) { 646 | path = app.path(); 647 | url = path + '/' + url; 648 | } 649 | } 650 | 651 | // Respond 652 | this.set('Location', url); 653 | return this; 654 | }; 655 | 656 | /** 657 | * Redirect to the given `url` with optional response `status` 658 | * defaulting to 302. 659 | * 660 | * The resulting `url` is determined by `res.location()`, so 661 | * it will play nicely with mounted apps, relative paths, 662 | * `"back"` etc. 663 | * 664 | * Examples: 665 | * 666 | * res.redirect('/foo/bar'); 667 | * res.redirect('http://example.com'); 668 | * res.redirect(301, 'http://example.com'); 669 | * res.redirect('http://example.com', 301); 670 | * res.redirect('../login'); // /blog/post/1 -> /blog/login 671 | * 672 | * @param {String} url 673 | * @param {Number} code 674 | * @api public 675 | */ 676 | 677 | res.redirect = function(url){ 678 | var app = this.app 679 | , head = 'HEAD' == this.req.method 680 | , status = 302 681 | , body; 682 | 683 | // allow status / url 684 | if (2 == arguments.length) { 685 | if ('number' == typeof url) { 686 | status = url; 687 | url = arguments[1]; 688 | } else { 689 | status = arguments[1]; 690 | } 691 | } 692 | 693 | // Set location header 694 | this.location(url); 695 | url = this.get('Location'); 696 | 697 | // Support text/{plain,html} by default 698 | this.format({ 699 | text: function(){ 700 | body = statusCodes[status] + '. Redirecting to ' + encodeURI(url); 701 | }, 702 | 703 | html: function(){ 704 | var u = utils.escape(url); 705 | body = '

' + statusCodes[status] + '. Redirecting to ' + u + '

'; 706 | }, 707 | 708 | default: function(){ 709 | body = ''; 710 | } 711 | }); 712 | 713 | // Respond 714 | this.statusCode = status; 715 | this.set('Content-Length', Buffer.byteLength(body)); 716 | this.end(head ? null : body); 717 | }; 718 | 719 | /** 720 | * Render `view` with the given `options` and optional callback `fn`. 721 | * When a callback function is given a response will _not_ be made 722 | * automatically, otherwise a response of _200_ and _text/html_ is given. 723 | * 724 | * Options: 725 | * 726 | * - `cache` boolean hinting to the engine it should cache 727 | * - `filename` filename of the view being rendered 728 | * 729 | * @param {String} view 730 | * @param {Object|Function} options or callback function 731 | * @param {Function} fn 732 | * @api public 733 | */ 734 | 735 | res.render = function(view, options, fn){ 736 | var self = this 737 | , options = options || {} 738 | , req = this.req 739 | , app = req.app; 740 | 741 | // support callback function as second arg 742 | if ('function' == typeof options) { 743 | fn = options, options = {}; 744 | } 745 | 746 | // merge res.locals 747 | options._locals = self.locals; 748 | 749 | // default callback to respond 750 | fn = fn || function(err, str){ 751 | if (err) return req.next(err); 752 | self.send(str); 753 | }; 754 | 755 | // render 756 | app.render(view, options, fn); 757 | }; 758 | -------------------------------------------------------------------------------- /node_modules/express/lib/router/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Route = require('./route') 6 | , utils = require('../utils') 7 | , methods = require('methods') 8 | , debug = require('debug')('express:router') 9 | , parse = require('connect').utils.parseUrl; 10 | 11 | /** 12 | * Expose `Router` constructor. 13 | */ 14 | 15 | exports = module.exports = Router; 16 | 17 | /** 18 | * Initialize a new `Router` with the given `options`. 19 | * 20 | * @param {Object} options 21 | * @api private 22 | */ 23 | 24 | function Router(options) { 25 | options = options || {}; 26 | var self = this; 27 | this.map = {}; 28 | this.params = {}; 29 | this._params = []; 30 | this.caseSensitive = options.caseSensitive; 31 | this.strict = options.strict; 32 | this.middleware = function router(req, res, next){ 33 | self._dispatch(req, res, next); 34 | }; 35 | } 36 | 37 | /** 38 | * Register a param callback `fn` for the given `name`. 39 | * 40 | * @param {String|Function} name 41 | * @param {Function} fn 42 | * @return {Router} for chaining 43 | * @api public 44 | */ 45 | 46 | Router.prototype.param = function(name, fn){ 47 | // param logic 48 | if ('function' == typeof name) { 49 | this._params.push(name); 50 | return; 51 | } 52 | 53 | // apply param functions 54 | var params = this._params 55 | , len = params.length 56 | , ret; 57 | 58 | for (var i = 0; i < len; ++i) { 59 | if (ret = params[i](name, fn)) { 60 | fn = ret; 61 | } 62 | } 63 | 64 | // ensure we end up with a 65 | // middleware function 66 | if ('function' != typeof fn) { 67 | throw new Error('invalid param() call for ' + name + ', got ' + fn); 68 | } 69 | 70 | (this.params[name] = this.params[name] || []).push(fn); 71 | return this; 72 | }; 73 | 74 | /** 75 | * Route dispatcher aka the route "middleware". 76 | * 77 | * @param {IncomingMessage} req 78 | * @param {ServerResponse} res 79 | * @param {Function} next 80 | * @api private 81 | */ 82 | 83 | Router.prototype._dispatch = function(req, res, next){ 84 | var params = this.params 85 | , self = this; 86 | 87 | debug('dispatching %s %s (%s)', req.method, req.url, req.originalUrl); 88 | 89 | // route dispatch 90 | (function pass(i, err){ 91 | var paramCallbacks 92 | , paramIndex = 0 93 | , paramVal 94 | , route 95 | , keys 96 | , key; 97 | 98 | // match next route 99 | function nextRoute(err) { 100 | pass(req._route_index + 1, err); 101 | } 102 | 103 | // match route 104 | req.route = route = self.matchRequest(req, i); 105 | 106 | // no route 107 | if (!route) return next(err); 108 | debug('matched %s %s', route.method, route.path); 109 | 110 | // we have a route 111 | // start at param 0 112 | req.params = route.params; 113 | keys = route.keys; 114 | i = 0; 115 | 116 | // param callbacks 117 | function param(err) { 118 | paramIndex = 0; 119 | key = keys[i++]; 120 | paramVal = key && req.params[key.name]; 121 | paramCallbacks = key && params[key.name]; 122 | 123 | try { 124 | if ('route' == err) { 125 | nextRoute(); 126 | } else if (err) { 127 | i = 0; 128 | callbacks(err); 129 | } else if (paramCallbacks && undefined !== paramVal) { 130 | paramCallback(); 131 | } else if (key) { 132 | param(); 133 | } else { 134 | i = 0; 135 | callbacks(); 136 | } 137 | } catch (err) { 138 | param(err); 139 | } 140 | }; 141 | 142 | param(err); 143 | 144 | // single param callbacks 145 | function paramCallback(err) { 146 | var fn = paramCallbacks[paramIndex++]; 147 | if (err || !fn) return param(err); 148 | fn(req, res, paramCallback, paramVal, key.name); 149 | } 150 | 151 | // invoke route callbacks 152 | function callbacks(err) { 153 | var fn = route.callbacks[i++]; 154 | try { 155 | if ('route' == err) { 156 | nextRoute(); 157 | } else if (err && fn) { 158 | if (fn.length < 4) return callbacks(err); 159 | fn(err, req, res, callbacks); 160 | } else if (fn) { 161 | if (fn.length < 4) return fn(req, res, callbacks); 162 | callbacks(); 163 | } else { 164 | nextRoute(err); 165 | } 166 | } catch (err) { 167 | callbacks(err); 168 | } 169 | } 170 | })(0); 171 | }; 172 | 173 | /** 174 | * Attempt to match a route for `req` 175 | * with optional starting index of `i` 176 | * defaulting to 0. 177 | * 178 | * @param {IncomingMessage} req 179 | * @param {Number} i 180 | * @return {Route} 181 | * @api private 182 | */ 183 | 184 | Router.prototype.matchRequest = function(req, i, head){ 185 | var method = req.method.toLowerCase() 186 | , url = parse(req) 187 | , path = url.pathname 188 | , routes = this.map 189 | , i = i || 0 190 | , route; 191 | 192 | // HEAD support 193 | if (!head && 'head' == method) { 194 | route = this.matchRequest(req, i, true); 195 | if (route) return route; 196 | method = 'get'; 197 | } 198 | 199 | // routes for this method 200 | if (routes = routes[method]) { 201 | 202 | // matching routes 203 | for (var len = routes.length; i < len; ++i) { 204 | route = routes[i]; 205 | if (route.match(path)) { 206 | req._route_index = i; 207 | return route; 208 | } 209 | } 210 | } 211 | }; 212 | 213 | /** 214 | * Attempt to match a route for `method` 215 | * and `url` with optional starting 216 | * index of `i` defaulting to 0. 217 | * 218 | * @param {String} method 219 | * @param {String} url 220 | * @param {Number} i 221 | * @return {Route} 222 | * @api private 223 | */ 224 | 225 | Router.prototype.match = function(method, url, i, head){ 226 | var req = { method: method, url: url }; 227 | return this.matchRequest(req, i, head); 228 | }; 229 | 230 | /** 231 | * Route `method`, `path`, and one or more callbacks. 232 | * 233 | * @param {String} method 234 | * @param {String} path 235 | * @param {Function} callback... 236 | * @return {Router} for chaining 237 | * @api private 238 | */ 239 | 240 | Router.prototype.route = function(method, path, callbacks){ 241 | var method = method.toLowerCase() 242 | , callbacks = utils.flatten([].slice.call(arguments, 2)); 243 | 244 | // ensure path was given 245 | if (!path) throw new Error('Router#' + method + '() requires a path'); 246 | 247 | // ensure all callbacks are functions 248 | callbacks.forEach(function(fn, i){ 249 | if ('function' == typeof fn) return; 250 | var type = {}.toString.call(fn); 251 | var msg = '.' + method + '() requires callback functions but got a ' + type; 252 | throw new Error(msg); 253 | }); 254 | 255 | // create the route 256 | debug('defined %s %s', method, path); 257 | var route = new Route(method, path, callbacks, { 258 | sensitive: this.caseSensitive, 259 | strict: this.strict 260 | }); 261 | 262 | // add it 263 | (this.map[method] = this.map[method] || []).push(route); 264 | return this; 265 | }; 266 | 267 | methods.forEach(function(method){ 268 | Router.prototype[method] = function(path){ 269 | var args = [method].concat([].slice.call(arguments)); 270 | this.route.apply(this, args); 271 | return this; 272 | }; 273 | }); 274 | -------------------------------------------------------------------------------- /node_modules/express/lib/router/route.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var utils = require('../utils'); 7 | 8 | /** 9 | * Expose `Route`. 10 | */ 11 | 12 | module.exports = Route; 13 | 14 | /** 15 | * Initialize `Route` with the given HTTP `method`, `path`, 16 | * and an array of `callbacks` and `options`. 17 | * 18 | * Options: 19 | * 20 | * - `sensitive` enable case-sensitive routes 21 | * - `strict` enable strict matching for trailing slashes 22 | * 23 | * @param {String} method 24 | * @param {String} path 25 | * @param {Array} callbacks 26 | * @param {Object} options. 27 | * @api private 28 | */ 29 | 30 | function Route(method, path, callbacks, options) { 31 | options = options || {}; 32 | this.path = path; 33 | this.method = method; 34 | this.callbacks = callbacks; 35 | this.regexp = utils.pathRegexp(path 36 | , this.keys = [] 37 | , options.sensitive 38 | , options.strict); 39 | } 40 | 41 | /** 42 | * Check if this route matches `path`, if so 43 | * populate `.params`. 44 | * 45 | * @param {String} path 46 | * @return {Boolean} 47 | * @api private 48 | */ 49 | 50 | Route.prototype.match = function(path){ 51 | var keys = this.keys 52 | , params = this.params = [] 53 | , m = this.regexp.exec(path); 54 | 55 | if (!m) return false; 56 | 57 | for (var i = 1, len = m.length; i < len; ++i) { 58 | var key = keys[i - 1]; 59 | 60 | var val = 'string' == typeof m[i] 61 | ? decodeURIComponent(m[i]) 62 | : m[i]; 63 | 64 | if (key) { 65 | params[key.name] = val; 66 | } else { 67 | params.push(val); 68 | } 69 | } 70 | 71 | return true; 72 | }; 73 | -------------------------------------------------------------------------------- /node_modules/express/lib/utils.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var mime = require('connect').mime 7 | , crc32 = require('buffer-crc32'); 8 | 9 | /** 10 | * toString ref. 11 | */ 12 | 13 | var toString = {}.toString; 14 | 15 | /** 16 | * Return ETag for `body`. 17 | * 18 | * @param {String|Buffer} body 19 | * @return {String} 20 | * @api private 21 | */ 22 | 23 | exports.etag = function(body){ 24 | return '"' + crc32.signed(body) + '"'; 25 | }; 26 | 27 | /** 28 | * Make `locals()` bound to the given `obj`. 29 | * 30 | * This is used for `app.locals` and `res.locals`. 31 | * 32 | * @param {Object} obj 33 | * @return {Function} 34 | * @api private 35 | */ 36 | 37 | exports.locals = function(obj){ 38 | function locals(obj){ 39 | for (var key in obj) locals[key] = obj[key]; 40 | return obj; 41 | }; 42 | 43 | return locals; 44 | }; 45 | 46 | /** 47 | * Check if `path` looks absolute. 48 | * 49 | * @param {String} path 50 | * @return {Boolean} 51 | * @api private 52 | */ 53 | 54 | exports.isAbsolute = function(path){ 55 | if ('/' == path[0]) return true; 56 | if (':' == path[1] && '\\' == path[2]) return true; 57 | }; 58 | 59 | /** 60 | * Flatten the given `arr`. 61 | * 62 | * @param {Array} arr 63 | * @return {Array} 64 | * @api private 65 | */ 66 | 67 | exports.flatten = function(arr, ret){ 68 | var ret = ret || [] 69 | , len = arr.length; 70 | for (var i = 0; i < len; ++i) { 71 | if (Array.isArray(arr[i])) { 72 | exports.flatten(arr[i], ret); 73 | } else { 74 | ret.push(arr[i]); 75 | } 76 | } 77 | return ret; 78 | }; 79 | 80 | /** 81 | * Normalize the given `type`, for example "html" becomes "text/html". 82 | * 83 | * @param {String} type 84 | * @return {Object} 85 | * @api private 86 | */ 87 | 88 | exports.normalizeType = function(type){ 89 | return ~type.indexOf('/') 90 | ? acceptParams(type) 91 | : { value: mime.lookup(type), params: {} }; 92 | }; 93 | 94 | /** 95 | * Normalize `types`, for example "html" becomes "text/html". 96 | * 97 | * @param {Array} types 98 | * @return {Array} 99 | * @api private 100 | */ 101 | 102 | exports.normalizeTypes = function(types){ 103 | var ret = []; 104 | 105 | for (var i = 0; i < types.length; ++i) { 106 | ret.push(exports.normalizeType(types[i])); 107 | } 108 | 109 | return ret; 110 | }; 111 | 112 | /** 113 | * Return the acceptable type in `types`, if any. 114 | * 115 | * @param {Array} types 116 | * @param {String} str 117 | * @return {String} 118 | * @api private 119 | */ 120 | 121 | exports.acceptsArray = function(types, str){ 122 | // accept anything when Accept is not present 123 | if (!str) return types[0]; 124 | 125 | // parse 126 | var accepted = exports.parseAccept(str) 127 | , normalized = exports.normalizeTypes(types) 128 | , len = accepted.length; 129 | 130 | for (var i = 0; i < len; ++i) { 131 | for (var j = 0, jlen = types.length; j < jlen; ++j) { 132 | if (exports.accept(normalized[j], accepted[i])) { 133 | return types[j]; 134 | } 135 | } 136 | } 137 | }; 138 | 139 | /** 140 | * Check if `type(s)` are acceptable based on 141 | * the given `str`. 142 | * 143 | * @param {String|Array} type(s) 144 | * @param {String} str 145 | * @return {Boolean|String} 146 | * @api private 147 | */ 148 | 149 | exports.accepts = function(type, str){ 150 | if ('string' == typeof type) type = type.split(/ *, */); 151 | return exports.acceptsArray(type, str); 152 | }; 153 | 154 | /** 155 | * Check if `type` array is acceptable for `other`. 156 | * 157 | * @param {Object} type 158 | * @param {Object} other 159 | * @return {Boolean} 160 | * @api private 161 | */ 162 | 163 | exports.accept = function(type, other){ 164 | var t = type.value.split('/'); 165 | return (t[0] == other.type || '*' == other.type) 166 | && (t[1] == other.subtype || '*' == other.subtype) 167 | && paramsEqual(type.params, other.params); 168 | }; 169 | 170 | /** 171 | * Check if accept params are equal. 172 | * 173 | * @param {Object} a 174 | * @param {Object} b 175 | * @return {Boolean} 176 | * @api private 177 | */ 178 | 179 | function paramsEqual(a, b){ 180 | return !Object.keys(a).some(function(k) { 181 | return a[k] != b[k]; 182 | }); 183 | } 184 | 185 | /** 186 | * Parse accept `str`, returning 187 | * an array objects containing 188 | * `.type` and `.subtype` along 189 | * with the values provided by 190 | * `parseQuality()`. 191 | * 192 | * @param {Type} name 193 | * @return {Type} 194 | * @api private 195 | */ 196 | 197 | exports.parseAccept = function(str){ 198 | return exports 199 | .parseParams(str) 200 | .map(function(obj){ 201 | var parts = obj.value.split('/'); 202 | obj.type = parts[0]; 203 | obj.subtype = parts[1]; 204 | return obj; 205 | }); 206 | }; 207 | 208 | /** 209 | * Parse quality `str`, returning an 210 | * array of objects with `.value`, 211 | * `.quality` and optional `.params` 212 | * 213 | * @param {String} str 214 | * @return {Array} 215 | * @api private 216 | */ 217 | 218 | exports.parseParams = function(str){ 219 | return str 220 | .split(/ *, */) 221 | .map(acceptParams) 222 | .filter(function(obj){ 223 | return obj.quality; 224 | }) 225 | .sort(function(a, b){ 226 | if (a.quality === b.quality) { 227 | return a.originalIndex - b.originalIndex; 228 | } else { 229 | return b.quality - a.quality; 230 | } 231 | }); 232 | }; 233 | 234 | /** 235 | * Parse accept params `str` returning an 236 | * object with `.value`, `.quality` and `.params`. 237 | * also includes `.originalIndex` for stable sorting 238 | * 239 | * @param {String} str 240 | * @return {Object} 241 | * @api private 242 | */ 243 | 244 | function acceptParams(str, index) { 245 | var parts = str.split(/ *; */); 246 | var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index }; 247 | 248 | for (var i = 1; i < parts.length; ++i) { 249 | var pms = parts[i].split(/ *= */); 250 | if ('q' == pms[0]) { 251 | ret.quality = parseFloat(pms[1]); 252 | } else { 253 | ret.params[pms[0]] = pms[1]; 254 | } 255 | } 256 | 257 | return ret; 258 | } 259 | 260 | /** 261 | * Escape special characters in the given string of html. 262 | * 263 | * @param {String} html 264 | * @return {String} 265 | * @api private 266 | */ 267 | 268 | exports.escape = function(html) { 269 | return String(html) 270 | .replace(/&/g, '&') 271 | .replace(/"/g, '"') 272 | .replace(//g, '>'); 274 | }; 275 | 276 | /** 277 | * Normalize the given path string, 278 | * returning a regular expression. 279 | * 280 | * An empty array should be passed, 281 | * which will contain the placeholder 282 | * key names. For example "/user/:id" will 283 | * then contain ["id"]. 284 | * 285 | * @param {String|RegExp|Array} path 286 | * @param {Array} keys 287 | * @param {Boolean} sensitive 288 | * @param {Boolean} strict 289 | * @return {RegExp} 290 | * @api private 291 | */ 292 | 293 | exports.pathRegexp = function(path, keys, sensitive, strict) { 294 | if (toString.call(path) == '[object RegExp]') return path; 295 | if (Array.isArray(path)) path = '(' + path.join('|') + ')'; 296 | path = path 297 | .concat(strict ? '' : '/?') 298 | .replace(/\/\(/g, '(?:/') 299 | .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g, function(_, slash, format, key, capture, optional, star){ 300 | keys.push({ name: key, optional: !! optional }); 301 | slash = slash || ''; 302 | return '' 303 | + (optional ? '' : slash) 304 | + '(?:' 305 | + (optional ? slash : '') 306 | + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')' 307 | + (optional || '') 308 | + (star ? '(/*)?' : ''); 309 | }) 310 | .replace(/([\/.])/g, '\\$1') 311 | .replace(/\*/g, '(.*)'); 312 | return new RegExp('^' + path + '$', sensitive ? '' : 'i'); 313 | } 314 | -------------------------------------------------------------------------------- /node_modules/express/lib/view.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var path = require('path') 6 | , fs = require('fs') 7 | , utils = require('./utils') 8 | , dirname = path.dirname 9 | , basename = path.basename 10 | , extname = path.extname 11 | , exists = fs.existsSync || path.existsSync 12 | , join = path.join; 13 | 14 | /** 15 | * Expose `View`. 16 | */ 17 | 18 | module.exports = View; 19 | 20 | /** 21 | * Initialize a new `View` with the given `name`. 22 | * 23 | * Options: 24 | * 25 | * - `defaultEngine` the default template engine name 26 | * - `engines` template engine require() cache 27 | * - `root` root path for view lookup 28 | * 29 | * @param {String} name 30 | * @param {Object} options 31 | * @api private 32 | */ 33 | 34 | function View(name, options) { 35 | options = options || {}; 36 | this.name = name; 37 | this.root = options.root; 38 | var engines = options.engines; 39 | this.defaultEngine = options.defaultEngine; 40 | var ext = this.ext = extname(name); 41 | if (!ext && !this.defaultEngine) throw new Error('No default engine was specified and no extension was provided.'); 42 | if (!ext) name += (ext = this.ext = ('.' != this.defaultEngine[0] ? '.' : '') + this.defaultEngine); 43 | this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express); 44 | this.path = this.lookup(name); 45 | } 46 | 47 | /** 48 | * Lookup view by the given `path` 49 | * 50 | * @param {String} path 51 | * @return {String} 52 | * @api private 53 | */ 54 | 55 | View.prototype.lookup = function(path){ 56 | var ext = this.ext; 57 | 58 | // . 59 | if (!utils.isAbsolute(path)) path = join(this.root, path); 60 | if (exists(path)) return path; 61 | 62 | // /index. 63 | path = join(dirname(path), basename(path, ext), 'index' + ext); 64 | if (exists(path)) return path; 65 | }; 66 | 67 | /** 68 | * Render with the given `options` and callback `fn(err, str)`. 69 | * 70 | * @param {Object} options 71 | * @param {Function} fn 72 | * @api private 73 | */ 74 | 75 | View.prototype.render = function(options, fn){ 76 | this.engine(this.path, options, fn); 77 | }; 78 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/.npmignore: -------------------------------------------------------------------------------- 1 | *.markdown 2 | *.md 3 | .git* 4 | Makefile 5 | benchmarks/ 6 | docs/ 7 | examples/ 8 | install.sh 9 | support/ 10 | test/ 11 | .DS_Store 12 | coverage.html 13 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2010 Sencha Inc. 4 | Copyright (c) 2011 LearnBoost 5 | Copyright (c) 2011 TJ Holowaychuk 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining 8 | a copy of this software and associated documentation files (the 9 | 'Software'), to deal in the Software without restriction, including 10 | without limitation the rights to use, copy, modify, merge, publish, 11 | distribute, sublicense, and/or sell copies of the Software, and to 12 | permit persons to whom the Software is furnished to do so, subject to 13 | the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/index.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = process.env.CONNECT_COV 3 | ? require('./lib-cov/connect') 4 | : require('./lib/connect'); -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/connect.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Connect 3 | * Copyright(c) 2010 Sencha Inc. 4 | * Copyright(c) 2011 TJ Holowaychuk 5 | * MIT Licensed 6 | */ 7 | 8 | /** 9 | * Module dependencies. 10 | */ 11 | 12 | var EventEmitter = require('events').EventEmitter 13 | , proto = require('./proto') 14 | , utils = require('./utils') 15 | , path = require('path') 16 | , basename = path.basename 17 | , fs = require('fs'); 18 | 19 | // node patches 20 | 21 | require('./patch'); 22 | 23 | // expose createServer() as the module 24 | 25 | exports = module.exports = createServer; 26 | 27 | /** 28 | * Framework version. 29 | */ 30 | 31 | exports.version = '2.7.11'; 32 | 33 | /** 34 | * Expose mime module. 35 | */ 36 | 37 | exports.mime = require('./middleware/static').mime; 38 | 39 | /** 40 | * Expose the prototype. 41 | */ 42 | 43 | exports.proto = proto; 44 | 45 | /** 46 | * Auto-load middleware getters. 47 | */ 48 | 49 | exports.middleware = {}; 50 | 51 | /** 52 | * Expose utilities. 53 | */ 54 | 55 | exports.utils = utils; 56 | 57 | /** 58 | * Create a new connect server. 59 | * 60 | * @return {Function} 61 | * @api public 62 | */ 63 | 64 | function createServer() { 65 | function app(req, res, next){ app.handle(req, res, next); } 66 | utils.merge(app, proto); 67 | utils.merge(app, EventEmitter.prototype); 68 | app.route = '/'; 69 | app.stack = []; 70 | for (var i = 0; i < arguments.length; ++i) { 71 | app.use(arguments[i]); 72 | } 73 | return app; 74 | }; 75 | 76 | /** 77 | * Support old `.createServer()` method. 78 | */ 79 | 80 | createServer.createServer = createServer; 81 | 82 | /** 83 | * Auto-load bundled middleware with getters. 84 | */ 85 | 86 | fs.readdirSync(__dirname + '/middleware').forEach(function(filename){ 87 | if (!/\.js$/.test(filename)) return; 88 | var name = basename(filename, '.js'); 89 | function load(){ return require('./middleware/' + name); } 90 | exports.middleware.__defineGetter__(name, load); 91 | exports.__defineGetter__(name, load); 92 | }); 93 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/index.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Connect is a middleware framework for node, 4 | * shipping with over 18 bundled middleware and a rich selection of 5 | * 3rd-party middleware. 6 | * 7 | * var app = connect() 8 | * .use(connect.logger('dev')) 9 | * .use(connect.static('public')) 10 | * .use(function(req, res){ 11 | * res.end('hello world\n'); 12 | * }) 13 | * .listen(3000); 14 | * 15 | * Installation: 16 | * 17 | * $ npm install connect 18 | * 19 | * Middleware: 20 | * 21 | * - [logger](logger.html) request logger with custom format support 22 | * - [csrf](csrf.html) Cross-site request forgery protection 23 | * - [compress](compress.html) Gzip compression middleware 24 | * - [basicAuth](basicAuth.html) basic http authentication 25 | * - [bodyParser](bodyParser.html) extensible request body parser 26 | * - [json](json.html) application/json parser 27 | * - [urlencoded](urlencoded.html) application/x-www-form-urlencoded parser 28 | * - [multipart](multipart.html) multipart/form-data parser 29 | * - [timeout](timeout.html) request timeouts 30 | * - [cookieParser](cookieParser.html) cookie parser 31 | * - [session](session.html) session management support with bundled MemoryStore 32 | * - [cookieSession](cookieSession.html) cookie-based session support 33 | * - [methodOverride](methodOverride.html) faux HTTP method support 34 | * - [responseTime](responseTime.html) calculates response-time and exposes via X-Response-Time 35 | * - [staticCache](staticCache.html) memory cache layer for the static() middleware 36 | * - [static](static.html) streaming static file server supporting `Range` and more 37 | * - [directory](directory.html) directory listing middleware 38 | * - [vhost](vhost.html) virtual host sub-domain mapping middleware 39 | * - [favicon](favicon.html) efficient favicon server (with default icon) 40 | * - [limit](limit.html) limit the bytesize of request bodies 41 | * - [query](query.html) automatic querystring parser, populating `req.query` 42 | * - [errorHandler](errorHandler.html) flexible error handler 43 | * 44 | * Links: 45 | * 46 | * - list of [3rd-party](https://github.com/senchalabs/connect/wiki) middleware 47 | * - GitHub [repository](http://github.com/senchalabs/connect) 48 | * - [test documentation](https://github.com/senchalabs/connect/blob/gh-pages/tests.md) 49 | * 50 | */ -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/basicAuth.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * Connect - basicAuth 4 | * Copyright(c) 2010 Sencha Inc. 5 | * Copyright(c) 2011 TJ Holowaychuk 6 | * MIT Licensed 7 | */ 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | 13 | var utils = require('../utils') 14 | , unauthorized = utils.unauthorized; 15 | 16 | /** 17 | * Basic Auth: 18 | * 19 | * Enfore basic authentication by providing a `callback(user, pass)`, 20 | * which must return `true` in order to gain access. Alternatively an async 21 | * method is provided as well, invoking `callback(user, pass, callback)`. Populates 22 | * `req.user`. The final alternative is simply passing username / password 23 | * strings. 24 | * 25 | * Simple username and password 26 | * 27 | * connect(connect.basicAuth('username', 'password')); 28 | * 29 | * Callback verification 30 | * 31 | * connect() 32 | * .use(connect.basicAuth(function(user, pass){ 33 | * return 'tj' == user & 'wahoo' == pass; 34 | * })) 35 | * 36 | * Async callback verification, accepting `fn(err, user)`. 37 | * 38 | * connect() 39 | * .use(connect.basicAuth(function(user, pass, fn){ 40 | * User.authenticate({ user: user, pass: pass }, fn); 41 | * })) 42 | * 43 | * @param {Function|String} callback or username 44 | * @param {String} realm 45 | * @api public 46 | */ 47 | 48 | module.exports = function basicAuth(callback, realm) { 49 | var username, password; 50 | 51 | // user / pass strings 52 | if ('string' == typeof callback) { 53 | username = callback; 54 | password = realm; 55 | if ('string' != typeof password) throw new Error('password argument required'); 56 | realm = arguments[2]; 57 | callback = function(user, pass){ 58 | return user == username && pass == password; 59 | } 60 | } 61 | 62 | realm = realm || 'Authorization Required'; 63 | 64 | return function(req, res, next) { 65 | var authorization = req.headers.authorization; 66 | 67 | if (req.user) return next(); 68 | if (!authorization) return unauthorized(res, realm); 69 | 70 | var parts = authorization.split(' '); 71 | 72 | if (parts.length !== 2) return next(utils.error(400)); 73 | 74 | var scheme = parts[0] 75 | , credentials = new Buffer(parts[1], 'base64').toString() 76 | , index = credentials.indexOf(':'); 77 | 78 | if ('Basic' != scheme || index < 0) return next(utils.error(400)); 79 | 80 | var user = credentials.slice(0, index) 81 | , pass = credentials.slice(index + 1); 82 | 83 | // async 84 | if (callback.length >= 3) { 85 | var pause = utils.pause(req); 86 | callback(user, pass, function(err, user){ 87 | if (err || !user) return unauthorized(res, realm); 88 | req.user = req.remoteUser = user; 89 | next(); 90 | pause.resume(); 91 | }); 92 | // sync 93 | } else { 94 | if (callback(user, pass)) { 95 | req.user = req.remoteUser = user; 96 | next(); 97 | } else { 98 | unauthorized(res, realm); 99 | } 100 | } 101 | } 102 | }; 103 | 104 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/bodyParser.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * Connect - bodyParser 4 | * Copyright(c) 2010 Sencha Inc. 5 | * Copyright(c) 2011 TJ Holowaychuk 6 | * MIT Licensed 7 | */ 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | 13 | var multipart = require('./multipart') 14 | , urlencoded = require('./urlencoded') 15 | , json = require('./json'); 16 | 17 | /** 18 | * Body parser: 19 | * 20 | * Parse request bodies, supports _application/json_, 21 | * _application/x-www-form-urlencoded_, and _multipart/form-data_. 22 | * 23 | * This is equivalent to: 24 | * 25 | * app.use(connect.json()); 26 | * app.use(connect.urlencoded()); 27 | * app.use(connect.multipart()); 28 | * 29 | * Examples: 30 | * 31 | * connect() 32 | * .use(connect.bodyParser()) 33 | * .use(function(req, res) { 34 | * res.end('viewing user ' + req.body.user.name); 35 | * }); 36 | * 37 | * $ curl -d 'user[name]=tj' http://local/ 38 | * $ curl -d '{"user":{"name":"tj"}}' -H "Content-Type: application/json" http://local/ 39 | * 40 | * View [json](json.html), [urlencoded](urlencoded.html), and [multipart](multipart.html) for more info. 41 | * 42 | * @param {Object} options 43 | * @return {Function} 44 | * @api public 45 | */ 46 | 47 | exports = module.exports = function bodyParser(options){ 48 | var _urlencoded = urlencoded(options) 49 | , _multipart = multipart(options) 50 | , _json = json(options); 51 | 52 | return function bodyParser(req, res, next) { 53 | _json(req, res, function(err){ 54 | if (err) return next(err); 55 | _urlencoded(req, res, function(err){ 56 | if (err) return next(err); 57 | _multipart(req, res, next); 58 | }); 59 | }); 60 | } 61 | }; -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/cookieParser.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * Connect - cookieParser 4 | * Copyright(c) 2010 Sencha Inc. 5 | * Copyright(c) 2011 TJ Holowaychuk 6 | * MIT Licensed 7 | */ 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | 13 | var utils = require('./../utils') 14 | , cookie = require('cookie'); 15 | 16 | /** 17 | * Cookie parser: 18 | * 19 | * Parse _Cookie_ header and populate `req.cookies` 20 | * with an object keyed by the cookie names. Optionally 21 | * you may enabled signed cookie support by passing 22 | * a `secret` string, which assigns `req.secret` so 23 | * it may be used by other middleware. 24 | * 25 | * Examples: 26 | * 27 | * connect() 28 | * .use(connect.cookieParser('optional secret string')) 29 | * .use(function(req, res, next){ 30 | * res.end(JSON.stringify(req.cookies)); 31 | * }) 32 | * 33 | * @param {String} secret 34 | * @return {Function} 35 | * @api public 36 | */ 37 | 38 | module.exports = function cookieParser(secret){ 39 | return function cookieParser(req, res, next) { 40 | if (req.cookies) return next(); 41 | var cookies = req.headers.cookie; 42 | 43 | req.secret = secret; 44 | req.cookies = {}; 45 | req.signedCookies = {}; 46 | 47 | if (cookies) { 48 | try { 49 | req.cookies = cookie.parse(cookies); 50 | if (secret) { 51 | req.signedCookies = utils.parseSignedCookies(req.cookies, secret); 52 | req.signedCookies = utils.parseJSONCookies(req.signedCookies); 53 | } 54 | req.cookies = utils.parseJSONCookies(req.cookies); 55 | } catch (err) { 56 | err.status = 400; 57 | return next(err); 58 | } 59 | } 60 | next(); 61 | }; 62 | }; 63 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/errorHandler.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Connect - errorHandler 3 | * Copyright(c) 2010 Sencha Inc. 4 | * Copyright(c) 2011 TJ Holowaychuk 5 | * MIT Licensed 6 | */ 7 | 8 | /** 9 | * Module dependencies. 10 | */ 11 | 12 | var utils = require('../utils') 13 | , fs = require('fs'); 14 | 15 | // environment 16 | 17 | var env = process.env.NODE_ENV || 'development'; 18 | 19 | /** 20 | * Error handler: 21 | * 22 | * Development error handler, providing stack traces 23 | * and error message responses for requests accepting text, html, 24 | * or json. 25 | * 26 | * Text: 27 | * 28 | * By default, and when _text/plain_ is accepted a simple stack trace 29 | * or error message will be returned. 30 | * 31 | * JSON: 32 | * 33 | * When _application/json_ is accepted, connect will respond with 34 | * an object in the form of `{ "error": error }`. 35 | * 36 | * HTML: 37 | * 38 | * When accepted connect will output a nice html stack trace. 39 | * 40 | * @return {Function} 41 | * @api public 42 | */ 43 | 44 | exports = module.exports = function errorHandler(){ 45 | return function errorHandler(err, req, res, next){ 46 | if (err.status) res.statusCode = err.status; 47 | if (res.statusCode < 400) res.statusCode = 500; 48 | if ('test' != env) console.error(err.stack); 49 | var accept = req.headers.accept || ''; 50 | // html 51 | if (~accept.indexOf('html')) { 52 | fs.readFile(__dirname + '/../public/style.css', 'utf8', function(e, style){ 53 | fs.readFile(__dirname + '/../public/error.html', 'utf8', function(e, html){ 54 | var stack = (err.stack || '') 55 | .split('\n').slice(1) 56 | .map(function(v){ return '
  • ' + v + '
  • '; }).join(''); 57 | html = html 58 | .replace('{style}', style) 59 | .replace('{stack}', stack) 60 | .replace('{title}', exports.title) 61 | .replace('{statusCode}', res.statusCode) 62 | .replace(/\{error\}/g, utils.escape(err.toString())); 63 | res.setHeader('Content-Type', 'text/html; charset=utf-8'); 64 | res.end(html); 65 | }); 66 | }); 67 | // json 68 | } else if (~accept.indexOf('json')) { 69 | var error = { message: err.message, stack: err.stack }; 70 | for (var prop in err) error[prop] = err[prop]; 71 | var json = JSON.stringify({ error: error }); 72 | res.setHeader('Content-Type', 'application/json'); 73 | res.end(json); 74 | // plain text 75 | } else { 76 | res.writeHead(res.statusCode, { 'Content-Type': 'text/plain' }); 77 | res.end(err.stack); 78 | } 79 | }; 80 | }; 81 | 82 | /** 83 | * Template title, framework authors may override this value. 84 | */ 85 | 86 | exports.title = 'Connect'; 87 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/favicon.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Connect - favicon 3 | * Copyright(c) 2010 Sencha Inc. 4 | * Copyright(c) 2011 TJ Holowaychuk 5 | * MIT Licensed 6 | */ 7 | 8 | /** 9 | * Module dependencies. 10 | */ 11 | 12 | var fs = require('fs') 13 | , utils = require('../utils'); 14 | 15 | /** 16 | * Favicon: 17 | * 18 | * By default serves the connect favicon, or the favicon 19 | * located by the given `path`. 20 | * 21 | * Options: 22 | * 23 | * - `maxAge` cache-control max-age directive, defaulting to 1 day 24 | * 25 | * Examples: 26 | * 27 | * Serve default favicon: 28 | * 29 | * connect() 30 | * .use(connect.favicon()) 31 | * 32 | * Serve favicon before logging for brevity: 33 | * 34 | * connect() 35 | * .use(connect.favicon()) 36 | * .use(connect.logger('dev')) 37 | * 38 | * Serve custom favicon: 39 | * 40 | * connect() 41 | * .use(connect.favicon('public/favicon.ico')) 42 | * 43 | * @param {String} path 44 | * @param {Object} options 45 | * @return {Function} 46 | * @api public 47 | */ 48 | 49 | module.exports = function favicon(path, options){ 50 | var options = options || {} 51 | , path = path || __dirname + '/../public/favicon.ico' 52 | , maxAge = options.maxAge || 86400000 53 | , icon; // favicon cache 54 | 55 | return function favicon(req, res, next){ 56 | if ('/favicon.ico' == req.url) { 57 | if (icon) { 58 | res.writeHead(200, icon.headers); 59 | res.end(icon.body); 60 | } else { 61 | fs.readFile(path, function(err, buf){ 62 | if (err) return next(err); 63 | icon = { 64 | headers: { 65 | 'Content-Type': 'image/x-icon' 66 | , 'Content-Length': buf.length 67 | , 'ETag': '"' + utils.md5(buf) + '"' 68 | , 'Cache-Control': 'public, max-age=' + (maxAge / 1000) 69 | }, 70 | body: buf 71 | }; 72 | res.writeHead(200, icon.headers); 73 | res.end(icon.body); 74 | }); 75 | } 76 | } else { 77 | next(); 78 | } 79 | }; 80 | }; 81 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/limit.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * Connect - limit 4 | * Copyright(c) 2011 TJ Holowaychuk 5 | * MIT Licensed 6 | */ 7 | 8 | /** 9 | * Module dependencies. 10 | */ 11 | 12 | var utils = require('../utils'), 13 | brokenPause = utils.brokenPause; 14 | 15 | /** 16 | * Limit: 17 | * 18 | * Limit request bodies to the given size in `bytes`. 19 | * 20 | * A string representation of the bytesize may also be passed, 21 | * for example "5mb", "200kb", "1gb", etc. 22 | * 23 | * connect() 24 | * .use(connect.limit('5.5mb')) 25 | * .use(handleImageUpload) 26 | * 27 | * @param {Number|String} bytes 28 | * @return {Function} 29 | * @api public 30 | */ 31 | 32 | module.exports = function limit(bytes){ 33 | if ('string' == typeof bytes) bytes = utils.parseBytes(bytes); 34 | if ('number' != typeof bytes) throw new Error('limit() bytes required'); 35 | return function limit(req, res, next){ 36 | var received = 0 37 | , len = req.headers['content-length'] 38 | ? parseInt(req.headers['content-length'], 10) 39 | : null; 40 | 41 | // self-awareness 42 | if (req._limit) return next(); 43 | req._limit = true; 44 | 45 | // limit by content-length 46 | if (len && len > bytes) return next(utils.error(413)); 47 | 48 | // limit 49 | if (brokenPause) { 50 | listen(); 51 | } else { 52 | req.on('newListener', function handler(event) { 53 | if (event !== 'data') return; 54 | 55 | req.removeListener('newListener', handler); 56 | // Start listening at the end of the current loop 57 | // otherwise the request will be consumed too early. 58 | // Sideaffect is `limit` will miss the first chunk, 59 | // but that's not a big deal. 60 | // Unfortunately, the tests don't have large enough 61 | // request bodies to test this. 62 | process.nextTick(listen); 63 | }); 64 | }; 65 | 66 | next(); 67 | 68 | function listen() { 69 | req.on('data', function(chunk) { 70 | received += Buffer.isBuffer(chunk) 71 | ? chunk.length : 72 | Buffer.byteLength(chunk); 73 | 74 | if (received > bytes) req.destroy(); 75 | }); 76 | }; 77 | }; 78 | }; -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/logger.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Connect - logger 3 | * Copyright(c) 2010 Sencha Inc. 4 | * Copyright(c) 2011 TJ Holowaychuk 5 | * MIT Licensed 6 | */ 7 | 8 | /** 9 | * Module dependencies. 10 | */ 11 | 12 | var bytes = require('bytes'); 13 | 14 | /*! 15 | * Log buffer. 16 | */ 17 | 18 | var buf = []; 19 | 20 | /*! 21 | * Default log buffer duration. 22 | */ 23 | 24 | var defaultBufferDuration = 1000; 25 | 26 | /** 27 | * Logger: 28 | * 29 | * Log requests with the given `options` or a `format` string. 30 | * 31 | * Options: 32 | * 33 | * - `format` Format string, see below for tokens 34 | * - `stream` Output stream, defaults to _stdout_ 35 | * - `buffer` Buffer duration, defaults to 1000ms when _true_ 36 | * - `immediate` Write log line on request instead of response (for response times) 37 | * 38 | * Tokens: 39 | * 40 | * - `:req[header]` ex: `:req[Accept]` 41 | * - `:res[header]` ex: `:res[Content-Length]` 42 | * - `:http-version` 43 | * - `:response-time` 44 | * - `:remote-addr` 45 | * - `:date` 46 | * - `:method` 47 | * - `:url` 48 | * - `:referrer` 49 | * - `:user-agent` 50 | * - `:status` 51 | * 52 | * Formats: 53 | * 54 | * Pre-defined formats that ship with connect: 55 | * 56 | * - `default` ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"' 57 | * - `short` ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms' 58 | * - `tiny` ':method :url :status :res[content-length] - :response-time ms' 59 | * - `dev` concise output colored by response status for development use 60 | * 61 | * Examples: 62 | * 63 | * connect.logger() // default 64 | * connect.logger('short') 65 | * connect.logger('tiny') 66 | * connect.logger({ immediate: true, format: 'dev' }) 67 | * connect.logger(':method :url - :referrer') 68 | * connect.logger(':req[content-type] -> :res[content-type]') 69 | * connect.logger(function(tokens, req, res){ return 'some format string' }) 70 | * 71 | * Defining Tokens: 72 | * 73 | * To define a token, simply invoke `connect.logger.token()` with the 74 | * name and a callback function. The value returned is then available 75 | * as ":type" in this case. 76 | * 77 | * connect.logger.token('type', function(req, res){ return req.headers['content-type']; }) 78 | * 79 | * Defining Formats: 80 | * 81 | * All default formats are defined this way, however it's public API as well: 82 | * 83 | * connect.logger.format('name', 'string or function') 84 | * 85 | * @param {String|Function|Object} format or options 86 | * @return {Function} 87 | * @api public 88 | */ 89 | 90 | exports = module.exports = function logger(options) { 91 | if ('object' == typeof options) { 92 | options = options || {}; 93 | } else if (options) { 94 | options = { format: options }; 95 | } else { 96 | options = {}; 97 | } 98 | 99 | // output on request instead of response 100 | var immediate = options.immediate; 101 | 102 | // format name 103 | var fmt = exports[options.format] || options.format || exports.default; 104 | 105 | // compile format 106 | if ('function' != typeof fmt) fmt = compile(fmt); 107 | 108 | // options 109 | var stream = options.stream || process.stdout 110 | , buffer = options.buffer; 111 | 112 | // buffering support 113 | if (buffer) { 114 | var realStream = stream 115 | , interval = 'number' == typeof buffer 116 | ? buffer 117 | : defaultBufferDuration; 118 | 119 | // flush interval 120 | setInterval(function(){ 121 | if (buf.length) { 122 | realStream.write(buf.join('')); 123 | buf.length = 0; 124 | } 125 | }, interval); 126 | 127 | // swap the stream 128 | stream = { 129 | write: function(str){ 130 | buf.push(str); 131 | } 132 | }; 133 | } 134 | 135 | return function logger(req, res, next) { 136 | req._startTime = new Date; 137 | 138 | // immediate 139 | if (immediate) { 140 | var line = fmt(exports, req, res); 141 | if (null == line) return; 142 | stream.write(line + '\n'); 143 | // proxy end to output logging 144 | } else { 145 | var end = res.end; 146 | res.end = function(chunk, encoding){ 147 | res.end = end; 148 | res.end(chunk, encoding); 149 | var line = fmt(exports, req, res); 150 | if (null == line) return; 151 | stream.write(line + '\n'); 152 | }; 153 | } 154 | 155 | 156 | next(); 157 | }; 158 | }; 159 | 160 | /** 161 | * Compile `fmt` into a function. 162 | * 163 | * @param {String} fmt 164 | * @return {Function} 165 | * @api private 166 | */ 167 | 168 | function compile(fmt) { 169 | fmt = fmt.replace(/"/g, '\\"'); 170 | var js = ' return "' + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function(_, name, arg){ 171 | return '"\n + (tokens["' + name + '"](req, res, "' + arg + '") || "-") + "'; 172 | }) + '";' 173 | return new Function('tokens, req, res', js); 174 | }; 175 | 176 | /** 177 | * Define a token function with the given `name`, 178 | * and callback `fn(req, res)`. 179 | * 180 | * @param {String} name 181 | * @param {Function} fn 182 | * @return {Object} exports for chaining 183 | * @api public 184 | */ 185 | 186 | exports.token = function(name, fn) { 187 | exports[name] = fn; 188 | return this; 189 | }; 190 | 191 | /** 192 | * Define a `fmt` with the given `name`. 193 | * 194 | * @param {String} name 195 | * @param {String|Function} fmt 196 | * @return {Object} exports for chaining 197 | * @api public 198 | */ 199 | 200 | exports.format = function(name, str){ 201 | exports[name] = str; 202 | return this; 203 | }; 204 | 205 | /** 206 | * Default format. 207 | */ 208 | 209 | exports.format('default', ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"'); 210 | 211 | /** 212 | * Short format. 213 | */ 214 | 215 | exports.format('short', ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms'); 216 | 217 | /** 218 | * Tiny format. 219 | */ 220 | 221 | exports.format('tiny', ':method :url :status :res[content-length] - :response-time ms'); 222 | 223 | /** 224 | * dev (colored) 225 | */ 226 | 227 | exports.format('dev', function(tokens, req, res){ 228 | var status = res.statusCode 229 | , len = parseInt(res.getHeader('Content-Length'), 10) 230 | , color = 32; 231 | 232 | if (status >= 500) color = 31 233 | else if (status >= 400) color = 33 234 | else if (status >= 300) color = 36; 235 | 236 | len = isNaN(len) 237 | ? '' 238 | : len = ' - ' + bytes(len); 239 | 240 | return '\x1b[90m' + req.method 241 | + ' ' + req.originalUrl + ' ' 242 | + '\x1b[' + color + 'm' + res.statusCode 243 | + ' \x1b[90m' 244 | + (new Date - req._startTime) 245 | + 'ms' + len 246 | + '\x1b[0m'; 247 | }); 248 | 249 | /** 250 | * request url 251 | */ 252 | 253 | exports.token('url', function(req){ 254 | return req.originalUrl || req.url; 255 | }); 256 | 257 | /** 258 | * request method 259 | */ 260 | 261 | exports.token('method', function(req){ 262 | return req.method; 263 | }); 264 | 265 | /** 266 | * response time in milliseconds 267 | */ 268 | 269 | exports.token('response-time', function(req){ 270 | return new Date - req._startTime; 271 | }); 272 | 273 | /** 274 | * UTC date 275 | */ 276 | 277 | exports.token('date', function(){ 278 | return new Date().toUTCString(); 279 | }); 280 | 281 | /** 282 | * response status code 283 | */ 284 | 285 | exports.token('status', function(req, res){ 286 | return res.statusCode; 287 | }); 288 | 289 | /** 290 | * normalized referrer 291 | */ 292 | 293 | exports.token('referrer', function(req){ 294 | return req.headers['referer'] || req.headers['referrer']; 295 | }); 296 | 297 | /** 298 | * remote address 299 | */ 300 | 301 | exports.token('remote-addr', function(req){ 302 | if (req.ip) return req.ip; 303 | var sock = req.socket; 304 | if (sock.socket) return sock.socket.remoteAddress; 305 | return sock.remoteAddress; 306 | }); 307 | 308 | /** 309 | * HTTP version 310 | */ 311 | 312 | exports.token('http-version', function(req){ 313 | return req.httpVersionMajor + '.' + req.httpVersionMinor; 314 | }); 315 | 316 | /** 317 | * UA string 318 | */ 319 | 320 | exports.token('user-agent', function(req){ 321 | return req.headers['user-agent']; 322 | }); 323 | 324 | /** 325 | * request header 326 | */ 327 | 328 | exports.token('req', function(req, res, field){ 329 | return req.headers[field.toLowerCase()]; 330 | }); 331 | 332 | /** 333 | * response header 334 | */ 335 | 336 | exports.token('res', function(req, res, field){ 337 | return (res._headers || {})[field.toLowerCase()]; 338 | }); 339 | 340 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/methodOverride.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * Connect - methodOverride 4 | * Copyright(c) 2010 Sencha Inc. 5 | * Copyright(c) 2011 TJ Holowaychuk 6 | * MIT Licensed 7 | */ 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | 13 | var methods = require('methods'); 14 | 15 | /** 16 | * Method Override: 17 | * 18 | * Provides faux HTTP method support. 19 | * 20 | * Pass an optional `key` to use when checking for 21 | * a method override, othewise defaults to _\_method_. 22 | * The original method is available via `req.originalMethod`. 23 | * 24 | * @param {String} key 25 | * @return {Function} 26 | * @api public 27 | */ 28 | 29 | module.exports = function methodOverride(key){ 30 | key = key || "_method"; 31 | return function methodOverride(req, res, next) { 32 | var method; 33 | req.originalMethod = req.originalMethod || req.method; 34 | 35 | // req.body 36 | if (req.body && key in req.body) { 37 | method = req.body[key].toLowerCase(); 38 | delete req.body[key]; 39 | } 40 | 41 | // check X-HTTP-Method-Override 42 | if (req.headers['x-http-method-override']) { 43 | method = req.headers['x-http-method-override'].toLowerCase(); 44 | } 45 | 46 | // replace 47 | if (supports(method)) req.method = method.toUpperCase(); 48 | 49 | next(); 50 | }; 51 | }; 52 | 53 | /** 54 | * Check if node supports `method`. 55 | */ 56 | 57 | function supports(method) { 58 | return ~methods.indexOf(method); 59 | } 60 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/responseTime.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * Connect - responseTime 4 | * Copyright(c) 2011 TJ Holowaychuk 5 | * MIT Licensed 6 | */ 7 | 8 | /** 9 | * Reponse time: 10 | * 11 | * Adds the `X-Response-Time` header displaying the response 12 | * duration in milliseconds. 13 | * 14 | * @return {Function} 15 | * @api public 16 | */ 17 | 18 | module.exports = function responseTime(){ 19 | return function(req, res, next){ 20 | var start = new Date; 21 | 22 | if (res._responseTime) return next(); 23 | res._responseTime = true; 24 | 25 | res.on('header', function(){ 26 | var duration = new Date - start; 27 | res.setHeader('X-Response-Time', duration + 'ms'); 28 | }); 29 | 30 | next(); 31 | }; 32 | }; 33 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/session.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Connect - session 3 | * Copyright(c) 2010 Sencha Inc. 4 | * Copyright(c) 2011 TJ Holowaychuk 5 | * MIT Licensed 6 | */ 7 | 8 | /** 9 | * Module dependencies. 10 | */ 11 | 12 | var Session = require('./session/session') 13 | , debug = require('debug')('connect:session') 14 | , MemoryStore = require('./session/memory') 15 | , signature = require('cookie-signature') 16 | , Cookie = require('./session/cookie') 17 | , Store = require('./session/store') 18 | , utils = require('./../utils') 19 | , uid = require('uid2') 20 | , parse = utils.parseUrl 21 | , crc32 = require('buffer-crc32'); 22 | 23 | // environment 24 | 25 | var env = process.env.NODE_ENV; 26 | 27 | /** 28 | * Expose the middleware. 29 | */ 30 | 31 | exports = module.exports = session; 32 | 33 | /** 34 | * Expose constructors. 35 | */ 36 | 37 | exports.Store = Store; 38 | exports.Cookie = Cookie; 39 | exports.Session = Session; 40 | exports.MemoryStore = MemoryStore; 41 | 42 | /** 43 | * Warning message for `MemoryStore` usage in production. 44 | */ 45 | 46 | var warning = 'Warning: connection.session() MemoryStore is not\n' 47 | + 'designed for a production environment, as it will leak\n' 48 | + 'memory, and will not scale past a single process.'; 49 | 50 | /** 51 | * Session: 52 | * 53 | * Setup session store with the given `options`. 54 | * 55 | * Session data is _not_ saved in the cookie itself, however 56 | * cookies are used, so we must use the [cookieParser()](cookieParser.html) 57 | * middleware _before_ `session()`. 58 | * 59 | * Examples: 60 | * 61 | * connect() 62 | * .use(connect.cookieParser()) 63 | * .use(connect.session({ secret: 'keyboard cat', key: 'sid', cookie: { secure: true }})) 64 | * 65 | * Options: 66 | * 67 | * - `key` cookie name defaulting to `connect.sid` 68 | * - `store` session store instance 69 | * - `secret` session cookie is signed with this secret to prevent tampering 70 | * - `cookie` session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: null }` 71 | * - `proxy` trust the reverse proxy when setting secure cookies (via "x-forwarded-proto") 72 | * 73 | * Cookie option: 74 | * 75 | * By default `cookie.maxAge` is `null`, meaning no "expires" parameter is set 76 | * so the cookie becomes a browser-session cookie. When the user closes the 77 | * browser the cookie (and session) will be removed. 78 | * 79 | * ## req.session 80 | * 81 | * To store or access session data, simply use the request property `req.session`, 82 | * which is (generally) serialized as JSON by the store, so nested objects 83 | * are typically fine. For example below is a user-specific view counter: 84 | * 85 | * connect() 86 | * .use(connect.favicon()) 87 | * .use(connect.cookieParser()) 88 | * .use(connect.session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }})) 89 | * .use(function(req, res, next){ 90 | * var sess = req.session; 91 | * if (sess.views) { 92 | * res.setHeader('Content-Type', 'text/html'); 93 | * res.write('

    views: ' + sess.views + '

    '); 94 | * res.write('

    expires in: ' + (sess.cookie.maxAge / 1000) + 's

    '); 95 | * res.end(); 96 | * sess.views++; 97 | * } else { 98 | * sess.views = 1; 99 | * res.end('welcome to the session demo. refresh!'); 100 | * } 101 | * } 102 | * )).listen(3000); 103 | * 104 | * ## Session#regenerate() 105 | * 106 | * To regenerate the session simply invoke the method, once complete 107 | * a new SID and `Session` instance will be initialized at `req.session`. 108 | * 109 | * req.session.regenerate(function(err){ 110 | * // will have a new session here 111 | * }); 112 | * 113 | * ## Session#destroy() 114 | * 115 | * Destroys the session, removing `req.session`, will be re-generated next request. 116 | * 117 | * req.session.destroy(function(err){ 118 | * // cannot access session here 119 | * }); 120 | * 121 | * ## Session#reload() 122 | * 123 | * Reloads the session data. 124 | * 125 | * req.session.reload(function(err){ 126 | * // session updated 127 | * }); 128 | * 129 | * ## Session#save() 130 | * 131 | * Save the session. 132 | * 133 | * req.session.save(function(err){ 134 | * // session saved 135 | * }); 136 | * 137 | * ## Session#touch() 138 | * 139 | * Updates the `.maxAge` property. Typically this is 140 | * not necessary to call, as the session middleware does this for you. 141 | * 142 | * ## Session#cookie 143 | * 144 | * Each session has a unique cookie object accompany it. This allows 145 | * you to alter the session cookie per visitor. For example we can 146 | * set `req.session.cookie.expires` to `false` to enable the cookie 147 | * to remain for only the duration of the user-agent. 148 | * 149 | * ## Session#maxAge 150 | * 151 | * Alternatively `req.session.cookie.maxAge` will return the time 152 | * remaining in milliseconds, which we may also re-assign a new value 153 | * to adjust the `.expires` property appropriately. The following 154 | * are essentially equivalent 155 | * 156 | * var hour = 3600000; 157 | * req.session.cookie.expires = new Date(Date.now() + hour); 158 | * req.session.cookie.maxAge = hour; 159 | * 160 | * For example when `maxAge` is set to `60000` (one minute), and 30 seconds 161 | * has elapsed it will return `30000` until the current request has completed, 162 | * at which time `req.session.touch()` is called to reset `req.session.maxAge` 163 | * to its original value. 164 | * 165 | * req.session.cookie.maxAge; 166 | * // => 30000 167 | * 168 | * Session Store Implementation: 169 | * 170 | * Every session store _must_ implement the following methods 171 | * 172 | * - `.get(sid, callback)` 173 | * - `.set(sid, session, callback)` 174 | * - `.destroy(sid, callback)` 175 | * 176 | * Recommended methods include, but are not limited to: 177 | * 178 | * - `.length(callback)` 179 | * - `.clear(callback)` 180 | * 181 | * For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo. 182 | * 183 | * @param {Object} options 184 | * @return {Function} 185 | * @api public 186 | */ 187 | 188 | function session(options){ 189 | var options = options || {} 190 | , key = options.key || 'connect.sid' 191 | , store = options.store || new MemoryStore 192 | , cookie = options.cookie || {} 193 | , trustProxy = options.proxy 194 | , storeReady = true; 195 | 196 | // notify user that this store is not 197 | // meant for a production environment 198 | if ('production' == env && store instanceof MemoryStore) { 199 | console.warn(warning); 200 | } 201 | 202 | // generates the new session 203 | store.generate = function(req){ 204 | req.sessionID = uid(24); 205 | req.session = new Session(req); 206 | req.session.cookie = new Cookie(cookie); 207 | }; 208 | 209 | store.on('disconnect', function(){ storeReady = false; }); 210 | store.on('connect', function(){ storeReady = true; }); 211 | 212 | return function session(req, res, next) { 213 | // self-awareness 214 | if (req.session) return next(); 215 | 216 | // Handle connection as if there is no session if 217 | // the store has temporarily disconnected etc 218 | if (!storeReady) return debug('store is disconnected'), next(); 219 | 220 | // pathname mismatch 221 | if (0 != req.originalUrl.indexOf(cookie.path || '/')) return next(); 222 | 223 | // backwards compatibility for signed cookies 224 | // req.secret is passed from the cookie parser middleware 225 | var secret = options.secret || req.secret; 226 | 227 | // ensure secret is available or bail 228 | if (!secret) throw new Error('`secret` option required for sessions'); 229 | 230 | // parse url 231 | var originalHash 232 | , originalId; 233 | 234 | // expose store 235 | req.sessionStore = store; 236 | 237 | // grab the session cookie value and check the signature 238 | var rawCookie = req.cookies[key]; 239 | 240 | // get signedCookies for backwards compat with signed cookies 241 | var unsignedCookie = req.signedCookies[key]; 242 | 243 | if (!unsignedCookie && rawCookie) { 244 | unsignedCookie = utils.parseSignedCookie(rawCookie, secret); 245 | } 246 | 247 | // set-cookie 248 | res.on('header', function(){ 249 | if (!req.session) return; 250 | var cookie = req.session.cookie 251 | , proto = (req.headers['x-forwarded-proto'] || '').split(',')[0].toLowerCase().trim() 252 | , tls = req.connection.encrypted || (trustProxy && 'https' == proto) 253 | , isNew = unsignedCookie != req.sessionID; 254 | 255 | // only send secure cookies via https 256 | if (cookie.secure && !tls) return debug('not secured'); 257 | 258 | // long expires, handle expiry server-side 259 | if (!isNew && cookie.hasLongExpires) return debug('already set cookie'); 260 | 261 | // browser-session length cookie 262 | if (null == cookie.expires) { 263 | if (!isNew) return debug('already set browser-session cookie'); 264 | // compare hashes and ids 265 | } else if (originalHash == hash(req.session) && originalId == req.session.id) { 266 | return debug('unmodified session'); 267 | } 268 | 269 | var val = 's:' + signature.sign(req.sessionID, secret); 270 | val = cookie.serialize(key, val); 271 | debug('set-cookie %s', val); 272 | res.setHeader('Set-Cookie', val); 273 | }); 274 | 275 | // proxy end() to commit the session 276 | var end = res.end; 277 | res.end = function(data, encoding){ 278 | res.end = end; 279 | if (!req.session) return res.end(data, encoding); 280 | debug('saving'); 281 | req.session.resetMaxAge(); 282 | req.session.save(function(err){ 283 | if (err) console.error(err.stack); 284 | debug('saved'); 285 | res.end(data, encoding); 286 | }); 287 | }; 288 | 289 | // generate the session 290 | function generate() { 291 | store.generate(req); 292 | } 293 | 294 | // get the sessionID from the cookie 295 | req.sessionID = unsignedCookie; 296 | 297 | // generate a session if the browser doesn't send a sessionID 298 | if (!req.sessionID) { 299 | debug('no SID sent, generating session'); 300 | generate(); 301 | next(); 302 | return; 303 | } 304 | 305 | // generate the session object 306 | var pause = utils.pause(req); 307 | debug('fetching %s', req.sessionID); 308 | store.get(req.sessionID, function(err, sess){ 309 | // proxy to resume() events 310 | var _next = next; 311 | next = function(err){ 312 | _next(err); 313 | pause.resume(); 314 | }; 315 | 316 | // error handling 317 | if (err) { 318 | debug('error %j', err); 319 | if ('ENOENT' == err.code) { 320 | generate(); 321 | next(); 322 | } else { 323 | next(err); 324 | } 325 | // no session 326 | } else if (!sess) { 327 | debug('no session found'); 328 | generate(); 329 | next(); 330 | // populate req.session 331 | } else { 332 | debug('session found'); 333 | store.createSession(req, sess); 334 | originalId = req.sessionID; 335 | originalHash = hash(sess); 336 | next(); 337 | } 338 | }); 339 | }; 340 | }; 341 | 342 | /** 343 | * Hash the given `sess` object omitting changes 344 | * to `.cookie`. 345 | * 346 | * @param {Object} sess 347 | * @return {String} 348 | * @api private 349 | */ 350 | 351 | function hash(sess) { 352 | return crc32.signed(JSON.stringify(sess, function(key, val){ 353 | if ('cookie' != key) return val; 354 | })); 355 | } 356 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/session/cookie.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * Connect - session - Cookie 4 | * Copyright(c) 2010 Sencha Inc. 5 | * Copyright(c) 2011 TJ Holowaychuk 6 | * MIT Licensed 7 | */ 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | 13 | var utils = require('../../utils') 14 | , cookie = require('cookie'); 15 | 16 | /** 17 | * Initialize a new `Cookie` with the given `options`. 18 | * 19 | * @param {IncomingMessage} req 20 | * @param {Object} options 21 | * @api private 22 | */ 23 | 24 | var Cookie = module.exports = function Cookie(options) { 25 | this.path = '/'; 26 | this.maxAge = null; 27 | this.httpOnly = true; 28 | if (options) utils.merge(this, options); 29 | this.originalMaxAge = undefined == this.originalMaxAge 30 | ? this.maxAge 31 | : this.originalMaxAge; 32 | }; 33 | 34 | /*! 35 | * Prototype. 36 | */ 37 | 38 | Cookie.prototype = { 39 | 40 | /** 41 | * Set expires `date`. 42 | * 43 | * @param {Date} date 44 | * @api public 45 | */ 46 | 47 | set expires(date) { 48 | this._expires = date; 49 | this.originalMaxAge = this.maxAge; 50 | }, 51 | 52 | /** 53 | * Get expires `date`. 54 | * 55 | * @return {Date} 56 | * @api public 57 | */ 58 | 59 | get expires() { 60 | return this._expires; 61 | }, 62 | 63 | /** 64 | * Set expires via max-age in `ms`. 65 | * 66 | * @param {Number} ms 67 | * @api public 68 | */ 69 | 70 | set maxAge(ms) { 71 | this.expires = 'number' == typeof ms 72 | ? new Date(Date.now() + ms) 73 | : ms; 74 | }, 75 | 76 | /** 77 | * Get expires max-age in `ms`. 78 | * 79 | * @return {Number} 80 | * @api public 81 | */ 82 | 83 | get maxAge() { 84 | return this.expires instanceof Date 85 | ? this.expires.valueOf() - Date.now() 86 | : this.expires; 87 | }, 88 | 89 | /** 90 | * Return cookie data object. 91 | * 92 | * @return {Object} 93 | * @api private 94 | */ 95 | 96 | get data() { 97 | return { 98 | originalMaxAge: this.originalMaxAge 99 | , expires: this._expires 100 | , secure: this.secure 101 | , httpOnly: this.httpOnly 102 | , domain: this.domain 103 | , path: this.path 104 | } 105 | }, 106 | 107 | /** 108 | * Check if the cookie has a reasonably large max-age. 109 | * 110 | * @return {Boolean} 111 | * @api private 112 | */ 113 | 114 | get hasLongExpires() { 115 | var week = 604800000; 116 | return this.maxAge > (4 * week); 117 | }, 118 | 119 | /** 120 | * Return a serialized cookie string. 121 | * 122 | * @return {String} 123 | * @api public 124 | */ 125 | 126 | serialize: function(name, val){ 127 | return cookie.serialize(name, val, this.data); 128 | }, 129 | 130 | /** 131 | * Return JSON representation of this cookie. 132 | * 133 | * @return {Object} 134 | * @api private 135 | */ 136 | 137 | toJSON: function(){ 138 | return this.data; 139 | } 140 | }; 141 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/session/memory.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * Connect - session - MemoryStore 4 | * Copyright(c) 2010 Sencha Inc. 5 | * Copyright(c) 2011 TJ Holowaychuk 6 | * MIT Licensed 7 | */ 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | 13 | var Store = require('./store'); 14 | 15 | /** 16 | * Initialize a new `MemoryStore`. 17 | * 18 | * @api public 19 | */ 20 | 21 | var MemoryStore = module.exports = function MemoryStore() { 22 | this.sessions = {}; 23 | }; 24 | 25 | /** 26 | * Inherit from `Store.prototype`. 27 | */ 28 | 29 | MemoryStore.prototype.__proto__ = Store.prototype; 30 | 31 | /** 32 | * Attempt to fetch session by the given `sid`. 33 | * 34 | * @param {String} sid 35 | * @param {Function} fn 36 | * @api public 37 | */ 38 | 39 | MemoryStore.prototype.get = function(sid, fn){ 40 | var self = this; 41 | process.nextTick(function(){ 42 | var expires 43 | , sess = self.sessions[sid]; 44 | if (sess) { 45 | sess = JSON.parse(sess); 46 | expires = 'string' == typeof sess.cookie.expires 47 | ? new Date(sess.cookie.expires) 48 | : sess.cookie.expires; 49 | if (!expires || new Date < expires) { 50 | fn(null, sess); 51 | } else { 52 | self.destroy(sid, fn); 53 | } 54 | } else { 55 | fn(); 56 | } 57 | }); 58 | }; 59 | 60 | /** 61 | * Commit the given `sess` object associated with the given `sid`. 62 | * 63 | * @param {String} sid 64 | * @param {Session} sess 65 | * @param {Function} fn 66 | * @api public 67 | */ 68 | 69 | MemoryStore.prototype.set = function(sid, sess, fn){ 70 | var self = this; 71 | process.nextTick(function(){ 72 | self.sessions[sid] = JSON.stringify(sess); 73 | fn && fn(); 74 | }); 75 | }; 76 | 77 | /** 78 | * Destroy the session associated with the given `sid`. 79 | * 80 | * @param {String} sid 81 | * @api public 82 | */ 83 | 84 | MemoryStore.prototype.destroy = function(sid, fn){ 85 | var self = this; 86 | process.nextTick(function(){ 87 | delete self.sessions[sid]; 88 | fn && fn(); 89 | }); 90 | }; 91 | 92 | /** 93 | * Invoke the given callback `fn` with all active sessions. 94 | * 95 | * @param {Function} fn 96 | * @api public 97 | */ 98 | 99 | MemoryStore.prototype.all = function(fn){ 100 | var arr = [] 101 | , keys = Object.keys(this.sessions); 102 | for (var i = 0, len = keys.length; i < len; ++i) { 103 | arr.push(this.sessions[keys[i]]); 104 | } 105 | fn(null, arr); 106 | }; 107 | 108 | /** 109 | * Clear all sessions. 110 | * 111 | * @param {Function} fn 112 | * @api public 113 | */ 114 | 115 | MemoryStore.prototype.clear = function(fn){ 116 | this.sessions = {}; 117 | fn && fn(); 118 | }; 119 | 120 | /** 121 | * Fetch number of sessions. 122 | * 123 | * @param {Function} fn 124 | * @api public 125 | */ 126 | 127 | MemoryStore.prototype.length = function(fn){ 128 | fn(null, Object.keys(this.sessions).length); 129 | }; 130 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/session/session.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * Connect - session - Session 4 | * Copyright(c) 2010 Sencha Inc. 5 | * Copyright(c) 2011 TJ Holowaychuk 6 | * MIT Licensed 7 | */ 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | 13 | var utils = require('../../utils'); 14 | 15 | /** 16 | * Create a new `Session` with the given request and `data`. 17 | * 18 | * @param {IncomingRequest} req 19 | * @param {Object} data 20 | * @api private 21 | */ 22 | 23 | var Session = module.exports = function Session(req, data) { 24 | Object.defineProperty(this, 'req', { value: req }); 25 | Object.defineProperty(this, 'id', { value: req.sessionID }); 26 | if ('object' == typeof data) utils.merge(this, data); 27 | }; 28 | 29 | /** 30 | * Update reset `.cookie.maxAge` to prevent 31 | * the cookie from expiring when the 32 | * session is still active. 33 | * 34 | * @return {Session} for chaining 35 | * @api public 36 | */ 37 | 38 | Session.prototype.touch = function(){ 39 | return this.resetMaxAge(); 40 | }; 41 | 42 | /** 43 | * Reset `.maxAge` to `.originalMaxAge`. 44 | * 45 | * @return {Session} for chaining 46 | * @api public 47 | */ 48 | 49 | Session.prototype.resetMaxAge = function(){ 50 | this.cookie.maxAge = this.cookie.originalMaxAge; 51 | return this; 52 | }; 53 | 54 | /** 55 | * Save the session data with optional callback `fn(err)`. 56 | * 57 | * @param {Function} fn 58 | * @return {Session} for chaining 59 | * @api public 60 | */ 61 | 62 | Session.prototype.save = function(fn){ 63 | this.req.sessionStore.set(this.id, this, fn || function(){}); 64 | return this; 65 | }; 66 | 67 | /** 68 | * Re-loads the session data _without_ altering 69 | * the maxAge properties. Invokes the callback `fn(err)`, 70 | * after which time if no exception has occurred the 71 | * `req.session` property will be a new `Session` object, 72 | * although representing the same session. 73 | * 74 | * @param {Function} fn 75 | * @return {Session} for chaining 76 | * @api public 77 | */ 78 | 79 | Session.prototype.reload = function(fn){ 80 | var req = this.req 81 | , store = this.req.sessionStore; 82 | store.get(this.id, function(err, sess){ 83 | if (err) return fn(err); 84 | if (!sess) return fn(new Error('failed to load session')); 85 | store.createSession(req, sess); 86 | fn(); 87 | }); 88 | return this; 89 | }; 90 | 91 | /** 92 | * Destroy `this` session. 93 | * 94 | * @param {Function} fn 95 | * @return {Session} for chaining 96 | * @api public 97 | */ 98 | 99 | Session.prototype.destroy = function(fn){ 100 | delete this.req.session; 101 | this.req.sessionStore.destroy(this.id, fn); 102 | return this; 103 | }; 104 | 105 | /** 106 | * Regenerate this request's session. 107 | * 108 | * @param {Function} fn 109 | * @return {Session} for chaining 110 | * @api public 111 | */ 112 | 113 | Session.prototype.regenerate = function(fn){ 114 | this.req.sessionStore.regenerate(this.req, fn); 115 | return this; 116 | }; 117 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/session/store.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * Connect - session - Store 4 | * Copyright(c) 2010 Sencha Inc. 5 | * Copyright(c) 2011 TJ Holowaychuk 6 | * MIT Licensed 7 | */ 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | 13 | var EventEmitter = require('events').EventEmitter 14 | , Session = require('./session') 15 | , Cookie = require('./cookie'); 16 | 17 | /** 18 | * Initialize abstract `Store`. 19 | * 20 | * @api private 21 | */ 22 | 23 | var Store = module.exports = function Store(options){}; 24 | 25 | /** 26 | * Inherit from `EventEmitter.prototype`. 27 | */ 28 | 29 | Store.prototype.__proto__ = EventEmitter.prototype; 30 | 31 | /** 32 | * Re-generate the given requests's session. 33 | * 34 | * @param {IncomingRequest} req 35 | * @return {Function} fn 36 | * @api public 37 | */ 38 | 39 | Store.prototype.regenerate = function(req, fn){ 40 | var self = this; 41 | this.destroy(req.sessionID, function(err){ 42 | self.generate(req); 43 | fn(err); 44 | }); 45 | }; 46 | 47 | /** 48 | * Load a `Session` instance via the given `sid` 49 | * and invoke the callback `fn(err, sess)`. 50 | * 51 | * @param {String} sid 52 | * @param {Function} fn 53 | * @api public 54 | */ 55 | 56 | Store.prototype.load = function(sid, fn){ 57 | var self = this; 58 | this.get(sid, function(err, sess){ 59 | if (err) return fn(err); 60 | if (!sess) return fn(); 61 | var req = { sessionID: sid, sessionStore: self }; 62 | sess = self.createSession(req, sess); 63 | fn(null, sess); 64 | }); 65 | }; 66 | 67 | /** 68 | * Create session from JSON `sess` data. 69 | * 70 | * @param {IncomingRequest} req 71 | * @param {Object} sess 72 | * @return {Session} 73 | * @api private 74 | */ 75 | 76 | Store.prototype.createSession = function(req, sess){ 77 | var expires = sess.cookie.expires 78 | , orig = sess.cookie.originalMaxAge; 79 | sess.cookie = new Cookie(sess.cookie); 80 | if ('string' == typeof expires) sess.cookie.expires = new Date(expires); 81 | sess.cookie.originalMaxAge = orig; 82 | req.session = new Session(req, sess); 83 | return req.session; 84 | }; 85 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/static.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Connect - static 3 | * Copyright(c) 2010 Sencha Inc. 4 | * Copyright(c) 2011 TJ Holowaychuk 5 | * MIT Licensed 6 | */ 7 | 8 | /** 9 | * Module dependencies. 10 | */ 11 | 12 | var send = require('send') 13 | , utils = require('../utils') 14 | , parse = utils.parseUrl 15 | , url = require('url'); 16 | 17 | /** 18 | * Static: 19 | * 20 | * Static file server with the given `root` path. 21 | * 22 | * Examples: 23 | * 24 | * var oneDay = 86400000; 25 | * 26 | * connect() 27 | * .use(connect.static(__dirname + '/public')) 28 | * 29 | * connect() 30 | * .use(connect.static(__dirname + '/public', { maxAge: oneDay })) 31 | * 32 | * Options: 33 | * 34 | * - `maxAge` Browser cache maxAge in milliseconds. defaults to 0 35 | * - `hidden` Allow transfer of hidden files. defaults to false 36 | * - `redirect` Redirect to trailing "/" when the pathname is a dir. defaults to true 37 | * - `index` Default file name, defaults to 'index.html' 38 | * 39 | * @param {String} root 40 | * @param {Object} options 41 | * @return {Function} 42 | * @api public 43 | */ 44 | 45 | exports = module.exports = function(root, options){ 46 | options = options || {}; 47 | 48 | // root required 49 | if (!root) throw new Error('static() root path required'); 50 | 51 | // default redirect 52 | var redirect = false !== options.redirect; 53 | 54 | return function staticMiddleware(req, res, next) { 55 | if ('GET' != req.method && 'HEAD' != req.method) return next(); 56 | var path = parse(req).pathname; 57 | var pause = utils.pause(req); 58 | 59 | function resume() { 60 | next(); 61 | pause.resume(); 62 | } 63 | 64 | function directory() { 65 | if (!redirect) return resume(); 66 | var pathname = url.parse(req.originalUrl).pathname; 67 | res.statusCode = 303; 68 | res.setHeader('Location', pathname + '/'); 69 | res.end('Redirecting to ' + utils.escape(pathname) + '/'); 70 | } 71 | 72 | function error(err) { 73 | if (404 == err.status) return resume(); 74 | next(err); 75 | } 76 | 77 | send(req, path) 78 | .maxage(options.maxAge || 0) 79 | .root(root) 80 | .index(options.index || 'index.html') 81 | .hidden(options.hidden) 82 | .on('error', error) 83 | .on('directory', directory) 84 | .pipe(res); 85 | }; 86 | }; 87 | 88 | /** 89 | * Expose mime module. 90 | * 91 | * If you wish to extend the mime table use this 92 | * reference to the "mime" module in the npm registry. 93 | */ 94 | 95 | exports.mime = send.mime; 96 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/middleware/vhost.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * Connect - vhost 4 | * Copyright(c) 2010 Sencha Inc. 5 | * Copyright(c) 2011 TJ Holowaychuk 6 | * MIT Licensed 7 | */ 8 | 9 | /** 10 | * Vhost: 11 | * 12 | * Setup vhost for the given `hostname` and `server`. 13 | * 14 | * connect() 15 | * .use(connect.vhost('foo.com', fooApp)) 16 | * .use(connect.vhost('bar.com', barApp)) 17 | * .use(connect.vhost('*.com', mainApp)) 18 | * 19 | * The `server` may be a Connect server or 20 | * a regular Node `http.Server`. 21 | * 22 | * @param {String} hostname 23 | * @param {Server} server 24 | * @return {Function} 25 | * @api public 26 | */ 27 | 28 | module.exports = function vhost(hostname, server){ 29 | if (!hostname) throw new Error('vhost hostname required'); 30 | if (!server) throw new Error('vhost server required'); 31 | var regexp = new RegExp('^' + hostname.replace(/[^*\w]/g, '\\$&').replace(/[*]/g, '(?:.*?)') + '$', 'i'); 32 | if (server.onvhost) server.onvhost(hostname); 33 | return function vhost(req, res, next){ 34 | if (!req.headers.host) return next(); 35 | var host = req.headers.host.split(':')[0]; 36 | if (!regexp.test(host)) return next(); 37 | if ('function' == typeof server) return server(req, res, next); 38 | server.emit('request', req, res); 39 | }; 40 | }; 41 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/patch.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * Connect 4 | * Copyright(c) 2011 TJ Holowaychuk 5 | * MIT Licensed 6 | */ 7 | 8 | /** 9 | * Module dependencies. 10 | */ 11 | 12 | var http = require('http') 13 | , res = http.ServerResponse.prototype 14 | , setHeader = res.setHeader 15 | , _renderHeaders = res._renderHeaders 16 | , writeHead = res.writeHead; 17 | 18 | // apply only once 19 | 20 | if (!res._hasConnectPatch) { 21 | 22 | /** 23 | * Provide a public "header sent" flag 24 | * until node does. 25 | * 26 | * @return {Boolean} 27 | * @api public 28 | */ 29 | 30 | res.__defineGetter__('headerSent', function(){ 31 | return this._header; 32 | }); 33 | 34 | /** 35 | * Set header `field` to `val`, special-casing 36 | * the `Set-Cookie` field for multiple support. 37 | * 38 | * @param {String} field 39 | * @param {String} val 40 | * @api public 41 | */ 42 | 43 | res.setHeader = function(field, val){ 44 | var key = field.toLowerCase() 45 | , prev; 46 | 47 | // special-case Set-Cookie 48 | if (this._headers && 'set-cookie' == key) { 49 | if (prev = this.getHeader(field)) { 50 | val = Array.isArray(prev) 51 | ? prev.concat(val) 52 | : [prev, val]; 53 | } 54 | // charset 55 | } else if ('content-type' == key && this.charset) { 56 | val += '; charset=' + this.charset; 57 | } 58 | 59 | return setHeader.call(this, field, val); 60 | }; 61 | 62 | /** 63 | * Proxy to emit "header" event. 64 | */ 65 | 66 | res._renderHeaders = function(){ 67 | if (!this._emittedHeader) this.emit('header'); 68 | this._emittedHeader = true; 69 | return _renderHeaders.call(this); 70 | }; 71 | 72 | res.writeHead = function(){ 73 | if (!this._emittedHeader) this.emit('header'); 74 | this._emittedHeader = true; 75 | return writeHead.apply(this, arguments); 76 | }; 77 | 78 | res._hasConnectPatch = true; 79 | } 80 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/public/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {error} 5 | 6 | 7 | 8 |
    9 |

    {title}

    10 |

    {statusCode} {error}

    11 |
      {stack}
    12 |
    13 | 14 | 15 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xjamundx/CollabPaintJS/f014285b98b247ebe5217e35dd35dc989346b99f/node_modules/express/node_modules/connect/lib/public/favicon.ico -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/public/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 80px 100px; 4 | font: 13px "Helvetica Neue", "Lucida Grande", "Arial"; 5 | background: #ECE9E9 -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9)); 6 | background: #ECE9E9 -moz-linear-gradient(top, #fff, #ECE9E9); 7 | background-repeat: no-repeat; 8 | color: #555; 9 | -webkit-font-smoothing: antialiased; 10 | } 11 | h1, h2, h3 { 12 | margin: 0; 13 | font-size: 22px; 14 | color: #343434; 15 | } 16 | h1 em, h2 em { 17 | padding: 0 5px; 18 | font-weight: normal; 19 | } 20 | h1 { 21 | font-size: 60px; 22 | } 23 | h2 { 24 | margin-top: 10px; 25 | } 26 | h3 { 27 | margin: 5px 0 10px 0; 28 | padding-bottom: 5px; 29 | border-bottom: 1px solid #eee; 30 | font-size: 18px; 31 | } 32 | ul { 33 | margin: 0; 34 | padding: 0; 35 | } 36 | ul li { 37 | margin: 5px 0; 38 | padding: 3px 8px; 39 | list-style: none; 40 | } 41 | ul li:hover { 42 | cursor: pointer; 43 | color: #2e2e2e; 44 | } 45 | ul li .path { 46 | padding-left: 5px; 47 | font-weight: bold; 48 | } 49 | ul li .line { 50 | padding-right: 5px; 51 | font-style: italic; 52 | } 53 | ul li:first-child .path { 54 | padding-left: 0; 55 | } 56 | p { 57 | line-height: 1.5; 58 | } 59 | a { 60 | color: #555; 61 | text-decoration: none; 62 | } 63 | a:hover { 64 | color: #303030; 65 | } 66 | #stacktrace { 67 | margin-top: 15px; 68 | } 69 | .directory h1 { 70 | margin-bottom: 15px; 71 | font-size: 18px; 72 | } 73 | ul#files { 74 | width: 100%; 75 | height: 500px; 76 | } 77 | ul#files li { 78 | padding: 0; 79 | } 80 | ul#files li img { 81 | position: absolute; 82 | top: 5px; 83 | left: 5px; 84 | } 85 | ul#files li a { 86 | position: relative; 87 | display: block; 88 | margin: 1px; 89 | width: 30%; 90 | height: 25px; 91 | line-height: 25px; 92 | text-indent: 8px; 93 | float: left; 94 | border: 1px solid transparent; 95 | -webkit-border-radius: 5px; 96 | -moz-border-radius: 5px; 97 | border-radius: 5px; 98 | overflow: hidden; 99 | text-overflow: ellipsis; 100 | } 101 | ul#files li a.icon { 102 | text-indent: 25px; 103 | } 104 | ul#files li a:focus, 105 | ul#files li a:hover { 106 | outline: none; 107 | background: rgba(255,255,255,0.65); 108 | border: 1px solid #ececec; 109 | } 110 | ul#files li a.highlight { 111 | -webkit-transition: background .4s ease-in-out; 112 | background: #ffff4f; 113 | border-color: #E9DC51; 114 | } 115 | #search { 116 | display: block; 117 | position: fixed; 118 | top: 20px; 119 | right: 20px; 120 | width: 90px; 121 | -webkit-transition: width ease 0.2s, opacity ease 0.4s; 122 | -moz-transition: width ease 0.2s, opacity ease 0.4s; 123 | -webkit-border-radius: 32px; 124 | -moz-border-radius: 32px; 125 | -webkit-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03); 126 | -moz-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03); 127 | -webkit-font-smoothing: antialiased; 128 | text-align: left; 129 | font: 13px "Helvetica Neue", Arial, sans-serif; 130 | padding: 4px 10px; 131 | border: none; 132 | background: transparent; 133 | margin-bottom: 0; 134 | outline: none; 135 | opacity: 0.7; 136 | color: #888; 137 | } 138 | #search:focus { 139 | width: 120px; 140 | opacity: 1.0; 141 | } 142 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/lib/utils.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * Connect - utils 4 | * Copyright(c) 2010 Sencha Inc. 5 | * Copyright(c) 2011 TJ Holowaychuk 6 | * MIT Licensed 7 | */ 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | 13 | var http = require('http') 14 | , crypto = require('crypto') 15 | , parse = require('url').parse 16 | , signature = require('cookie-signature') 17 | , nodeVersion = process.versions.node.split('.'); 18 | 19 | // pause is broken in node < 0.10 20 | exports.brokenPause = parseInt(nodeVersion[0], 10) === 0 21 | && parseInt(nodeVersion[1], 10) < 10; 22 | 23 | /** 24 | * Return `true` if the request has a body, otherwise return `false`. 25 | * 26 | * @param {IncomingMessage} req 27 | * @return {Boolean} 28 | * @api private 29 | */ 30 | 31 | exports.hasBody = function(req) { 32 | var encoding = 'transfer-encoding' in req.headers; 33 | var length = 'content-length' in req.headers && req.headers['content-length'] !== '0'; 34 | return encoding || length; 35 | }; 36 | 37 | /** 38 | * Extract the mime type from the given request's 39 | * _Content-Type_ header. 40 | * 41 | * @param {IncomingMessage} req 42 | * @return {String} 43 | * @api private 44 | */ 45 | 46 | exports.mime = function(req) { 47 | var str = req.headers['content-type'] || ''; 48 | return str.split(';')[0]; 49 | }; 50 | 51 | /** 52 | * Generate an `Error` from the given status `code` 53 | * and optional `msg`. 54 | * 55 | * @param {Number} code 56 | * @param {String} msg 57 | * @return {Error} 58 | * @api private 59 | */ 60 | 61 | exports.error = function(code, msg){ 62 | var err = new Error(msg || http.STATUS_CODES[code]); 63 | err.status = code; 64 | return err; 65 | }; 66 | 67 | /** 68 | * Return md5 hash of the given string and optional encoding, 69 | * defaulting to hex. 70 | * 71 | * utils.md5('wahoo'); 72 | * // => "e493298061761236c96b02ea6aa8a2ad" 73 | * 74 | * @param {String} str 75 | * @param {String} encoding 76 | * @return {String} 77 | * @api private 78 | */ 79 | 80 | exports.md5 = function(str, encoding){ 81 | return crypto 82 | .createHash('md5') 83 | .update(str) 84 | .digest(encoding || 'hex'); 85 | }; 86 | 87 | /** 88 | * Merge object b with object a. 89 | * 90 | * var a = { foo: 'bar' } 91 | * , b = { bar: 'baz' }; 92 | * 93 | * utils.merge(a, b); 94 | * // => { foo: 'bar', bar: 'baz' } 95 | * 96 | * @param {Object} a 97 | * @param {Object} b 98 | * @return {Object} 99 | * @api private 100 | */ 101 | 102 | exports.merge = function(a, b){ 103 | if (a && b) { 104 | for (var key in b) { 105 | a[key] = b[key]; 106 | } 107 | } 108 | return a; 109 | }; 110 | 111 | /** 112 | * Escape the given string of `html`. 113 | * 114 | * @param {String} html 115 | * @return {String} 116 | * @api private 117 | */ 118 | 119 | exports.escape = function(html){ 120 | return String(html) 121 | .replace(/&(?!\w+;)/g, '&') 122 | .replace(//g, '>') 124 | .replace(/"/g, '"'); 125 | }; 126 | 127 | /** 128 | * Sign the given `val` with `secret`. 129 | * 130 | * @param {String} val 131 | * @param {String} secret 132 | * @return {String} 133 | * @api private 134 | */ 135 | 136 | exports.sign = function(val, secret){ 137 | console.warn('do not use utils.sign(), use https://github.com/visionmedia/node-cookie-signature') 138 | return val + '.' + crypto 139 | .createHmac('sha256', secret) 140 | .update(val) 141 | .digest('base64') 142 | .replace(/=+$/, ''); 143 | }; 144 | 145 | /** 146 | * Unsign and decode the given `val` with `secret`, 147 | * returning `false` if the signature is invalid. 148 | * 149 | * @param {String} val 150 | * @param {String} secret 151 | * @return {String|Boolean} 152 | * @api private 153 | */ 154 | 155 | exports.unsign = function(val, secret){ 156 | console.warn('do not use utils.unsign(), use https://github.com/visionmedia/node-cookie-signature') 157 | var str = val.slice(0, val.lastIndexOf('.')); 158 | return exports.sign(str, secret) == val 159 | ? str 160 | : false; 161 | }; 162 | 163 | /** 164 | * Parse signed cookies, returning an object 165 | * containing the decoded key/value pairs, 166 | * while removing the signed key from `obj`. 167 | * 168 | * @param {Object} obj 169 | * @return {Object} 170 | * @api private 171 | */ 172 | 173 | exports.parseSignedCookies = function(obj, secret){ 174 | var ret = {}; 175 | Object.keys(obj).forEach(function(key){ 176 | var val = obj[key]; 177 | if (0 == val.indexOf('s:')) { 178 | val = signature.unsign(val.slice(2), secret); 179 | if (val) { 180 | ret[key] = val; 181 | delete obj[key]; 182 | } 183 | } 184 | }); 185 | return ret; 186 | }; 187 | 188 | /** 189 | * Parse a signed cookie string, return the decoded value 190 | * 191 | * @param {String} str signed cookie string 192 | * @param {String} secret 193 | * @return {String} decoded value 194 | * @api private 195 | */ 196 | 197 | exports.parseSignedCookie = function(str, secret){ 198 | return 0 == str.indexOf('s:') 199 | ? signature.unsign(str.slice(2), secret) 200 | : str; 201 | }; 202 | 203 | /** 204 | * Parse JSON cookies. 205 | * 206 | * @param {Object} obj 207 | * @return {Object} 208 | * @api private 209 | */ 210 | 211 | exports.parseJSONCookies = function(obj){ 212 | Object.keys(obj).forEach(function(key){ 213 | var val = obj[key]; 214 | var res = exports.parseJSONCookie(val); 215 | if (res) obj[key] = res; 216 | }); 217 | return obj; 218 | }; 219 | 220 | /** 221 | * Parse JSON cookie string 222 | * 223 | * @param {String} str 224 | * @return {Object} Parsed object or null if not json cookie 225 | * @api private 226 | */ 227 | 228 | exports.parseJSONCookie = function(str) { 229 | if (0 == str.indexOf('j:')) { 230 | try { 231 | return JSON.parse(str.slice(2)); 232 | } catch (err) { 233 | // no op 234 | } 235 | } 236 | }; 237 | 238 | /** 239 | * Pause `data` and `end` events on the given `obj`. 240 | * Middleware performing async tasks _should_ utilize 241 | * this utility (or similar), to re-emit data once 242 | * the async operation has completed, otherwise these 243 | * events may be lost. Pause is only required for 244 | * node versions less than 10, and is replaced with 245 | * noop's otherwise. 246 | * 247 | * var pause = utils.pause(req); 248 | * fs.readFile(path, function(){ 249 | * next(); 250 | * pause.resume(); 251 | * }); 252 | * 253 | * @param {Object} obj 254 | * @return {Object} 255 | * @api private 256 | */ 257 | 258 | exports.pause = exports.brokenPause 259 | ? require('pause') 260 | : function () { 261 | return { 262 | end: noop, 263 | resume: noop 264 | } 265 | } 266 | 267 | /** 268 | * Strip `Content-*` headers from `res`. 269 | * 270 | * @param {ServerResponse} res 271 | * @api private 272 | */ 273 | 274 | exports.removeContentHeaders = function(res){ 275 | Object.keys(res._headers).forEach(function(field){ 276 | if (0 == field.indexOf('content')) { 277 | res.removeHeader(field); 278 | } 279 | }); 280 | }; 281 | 282 | /** 283 | * Check if `req` is a conditional GET request. 284 | * 285 | * @param {IncomingMessage} req 286 | * @return {Boolean} 287 | * @api private 288 | */ 289 | 290 | exports.conditionalGET = function(req) { 291 | return req.headers['if-modified-since'] 292 | || req.headers['if-none-match']; 293 | }; 294 | 295 | /** 296 | * Respond with 401 "Unauthorized". 297 | * 298 | * @param {ServerResponse} res 299 | * @param {String} realm 300 | * @api private 301 | */ 302 | 303 | exports.unauthorized = function(res, realm) { 304 | res.statusCode = 401; 305 | res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"'); 306 | res.end('Unauthorized'); 307 | }; 308 | 309 | /** 310 | * Respond with 304 "Not Modified". 311 | * 312 | * @param {ServerResponse} res 313 | * @param {Object} headers 314 | * @api private 315 | */ 316 | 317 | exports.notModified = function(res) { 318 | exports.removeContentHeaders(res); 319 | res.statusCode = 304; 320 | res.end(); 321 | }; 322 | 323 | /** 324 | * Return an ETag in the form of `"-"` 325 | * from the given `stat`. 326 | * 327 | * @param {Object} stat 328 | * @return {String} 329 | * @api private 330 | */ 331 | 332 | exports.etag = function(stat) { 333 | return '"' + stat.size + '-' + Number(stat.mtime) + '"'; 334 | }; 335 | 336 | /** 337 | * Parse the given Cache-Control `str`. 338 | * 339 | * @param {String} str 340 | * @return {Object} 341 | * @api private 342 | */ 343 | 344 | exports.parseCacheControl = function(str){ 345 | var directives = str.split(',') 346 | , obj = {}; 347 | 348 | for(var i = 0, len = directives.length; i < len; i++) { 349 | var parts = directives[i].split('=') 350 | , key = parts.shift().trim() 351 | , val = parseInt(parts.shift(), 10); 352 | 353 | obj[key] = isNaN(val) ? true : val; 354 | } 355 | 356 | return obj; 357 | }; 358 | 359 | /** 360 | * Parse the `req` url with memoization. 361 | * 362 | * @param {ServerRequest} req 363 | * @return {Object} 364 | * @api private 365 | */ 366 | 367 | exports.parseUrl = function(req){ 368 | var parsed = req._parsedUrl; 369 | if (parsed && parsed.href == req.url) { 370 | return parsed; 371 | } else { 372 | return req._parsedUrl = parse(req.url); 373 | } 374 | }; 375 | 376 | /** 377 | * Parse byte `size` string. 378 | * 379 | * @param {String} size 380 | * @return {Number} 381 | * @api private 382 | */ 383 | 384 | exports.parseBytes = require('bytes'); 385 | 386 | function noop() {} 387 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "connect", 3 | "version": "2.8.4", 4 | "description": "High performance middleware framework", 5 | "keywords": [ 6 | "framework", 7 | "web", 8 | "middleware", 9 | "connect", 10 | "rack" 11 | ], 12 | "repository": { 13 | "type": "git", 14 | "url": "git://github.com/senchalabs/connect.git" 15 | }, 16 | "author": { 17 | "name": "TJ Holowaychuk", 18 | "email": "tj@vision-media.ca", 19 | "url": "http://tjholowaychuk.com" 20 | }, 21 | "dependencies": { 22 | "qs": "0.6.5", 23 | "formidable": "1.0.14", 24 | "cookie-signature": "1.0.1", 25 | "buffer-crc32": "0.2.1", 26 | "cookie": "0.1.0", 27 | "send": "0.1.3", 28 | "bytes": "0.2.0", 29 | "fresh": "0.1.0", 30 | "pause": "0.0.1", 31 | "uid2": "0.0.2", 32 | "debug": "*", 33 | "methods": "0.0.1" 34 | }, 35 | "devDependencies": { 36 | "should": "*", 37 | "mocha": "*", 38 | "jade": "*", 39 | "dox": "*" 40 | }, 41 | "main": "index", 42 | "engines": { 43 | "node": ">= 0.8.0" 44 | }, 45 | "scripts": { 46 | "test": "make" 47 | }, 48 | "readme": "[![build status](https://secure.travis-ci.org/senchalabs/connect.png)](http://travis-ci.org/senchalabs/connect)\n# Connect\n\n Connect is an extensible HTTP server framework for [node](http://nodejs.org), providing high performance \"plugins\" known as _middleware_.\n\n Connect is bundled with over _20_ commonly used middleware, including\n a logger, session support, cookie parser, and [more](http://senchalabs.github.com/connect). Be sure to view the 2.x [documentation](http://senchalabs.github.com/connect/).\n\n```js\nvar connect = require('connect')\n , http = require('http');\n\nvar app = connect()\n .use(connect.favicon())\n .use(connect.logger('dev'))\n .use(connect.static('public'))\n .use(connect.directory('public'))\n .use(connect.cookieParser())\n .use(connect.session({ secret: 'my secret here' }))\n .use(function(req, res){\n res.end('Hello from Connect!\\n');\n });\n\nhttp.createServer(app).listen(3000);\n```\n\n## Middleware\n\n - [csrf](http://www.senchalabs.org/connect/csrf.html)\n - [basicAuth](http://www.senchalabs.org/connect/basicAuth.html)\n - [bodyParser](http://www.senchalabs.org/connect/bodyParser.html)\n - [json](http://www.senchalabs.org/connect/json.html)\n - [multipart](http://www.senchalabs.org/connect/multipart.html)\n - [urlencoded](http://www.senchalabs.org/connect/urlencoded.html)\n - [cookieParser](http://www.senchalabs.org/connect/cookieParser.html)\n - [directory](http://www.senchalabs.org/connect/directory.html)\n - [compress](http://www.senchalabs.org/connect/compress.html)\n - [errorHandler](http://www.senchalabs.org/connect/errorHandler.html)\n - [favicon](http://www.senchalabs.org/connect/favicon.html)\n - [limit](http://www.senchalabs.org/connect/limit.html)\n - [logger](http://www.senchalabs.org/connect/logger.html)\n - [methodOverride](http://www.senchalabs.org/connect/methodOverride.html)\n - [query](http://www.senchalabs.org/connect/query.html)\n - [responseTime](http://www.senchalabs.org/connect/responseTime.html)\n - [session](http://www.senchalabs.org/connect/session.html)\n - [static](http://www.senchalabs.org/connect/static.html)\n - [staticCache](http://www.senchalabs.org/connect/staticCache.html)\n - [vhost](http://www.senchalabs.org/connect/vhost.html)\n - [subdomains](http://www.senchalabs.org/connect/subdomains.html)\n - [cookieSession](http://www.senchalabs.org/connect/cookieSession.html)\n\n## Running Tests\n\nfirst:\n\n $ npm install -d\n\nthen:\n\n $ make test\n\n## Authors\n\n Below is the output from [git-summary](http://github.com/visionmedia/git-extras).\n\n\n project: connect\n commits: 2033\n active : 301 days\n files : 171\n authors: \n 1414\tTj Holowaychuk 69.6%\n 298\tvisionmedia 14.7%\n 191\tTim Caswell 9.4%\n 51\tTJ Holowaychuk 2.5%\n 10\tRyan Olds 0.5%\n 8\tAstro 0.4%\n 5\tNathan Rajlich 0.2%\n 5\tJakub Nešetřil 0.2%\n 3\tDaniel Dickison 0.1%\n 3\tDavid Rio Deiros 0.1%\n 3\tAlexander Simmerl 0.1%\n 3\tAndreas Lind Petersen 0.1%\n 2\tAaron Heckmann 0.1%\n 2\tJacques Crocker 0.1%\n 2\tFabian Jakobs 0.1%\n 2\tBrian J Brennan 0.1%\n 2\tAdam Malcontenti-Wilson 0.1%\n 2\tGlen Mailer 0.1%\n 2\tJames Campos 0.1%\n 1\tTrent Mick 0.0%\n 1\tTroy Kruthoff 0.0%\n 1\tWei Zhu 0.0%\n 1\tcomerc 0.0%\n 1\tdarobin 0.0%\n 1\tnateps 0.0%\n 1\tMarco Sanson 0.0%\n 1\tArthur Taylor 0.0%\n 1\tAseem Kishore 0.0%\n 1\tBart Teeuwisse 0.0%\n 1\tCameron Howey 0.0%\n 1\tChad Weider 0.0%\n 1\tCraig Barnes 0.0%\n 1\tEran Hammer-Lahav 0.0%\n 1\tGregory McWhirter 0.0%\n 1\tGuillermo Rauch 0.0%\n 1\tJae Kwon 0.0%\n 1\tJakub Nesetril 0.0%\n 1\tJoshua Peek 0.0%\n 1\tJxck 0.0%\n 1\tAJ ONeal 0.0%\n 1\tMichael Hemesath 0.0%\n 1\tMorten Siebuhr 0.0%\n 1\tSamori Gorse 0.0%\n 1\tTom Jensen 0.0%\n\n## Node Compatibility\n\n Connect `< 1.x` is compatible with node 0.2.x\n\n\n Connect `1.x` is compatible with node 0.4.x\n\n\n Connect (_master_) `2.x` is compatible with node 0.6.x\n\n## CLA\n\n [http://sencha.com/cla](http://sencha.com/cla)\n\n## License\n\nView the [LICENSE](https://github.com/senchalabs/connect/blob/master/LICENSE) file. The [Silk](http://www.famfamfam.com/lab/icons/silk/) icons used by the `directory` middleware created by/copyright of [FAMFAMFAM](http://www.famfamfam.com/).\n", 49 | "readmeFilename": "Readme.md", 50 | "_id": "connect@2.8.4", 51 | "_from": "connect@2.8.4" 52 | } 53 | -------------------------------------------------------------------------------- /node_modules/express/node_modules/connect/test.js: -------------------------------------------------------------------------------- 1 | var crypto = require('crypto') 2 | 3 | exports.uid = function(len) { 4 | return crypto.randomBytes(Math.ceil(len * 3 / 4)) 5 | .toString('hex') 6 | }; 7 | 8 | console.log(exports.uid(10)); 9 | -------------------------------------------------------------------------------- /node_modules/express/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express", 3 | "description": "Sinatra inspired web development framework", 4 | "version": "3.3.4", 5 | "author": { 6 | "name": "TJ Holowaychuk", 7 | "email": "tj@vision-media.ca" 8 | }, 9 | "contributors": [ 10 | { 11 | "name": "TJ Holowaychuk", 12 | "email": "tj@vision-media.ca" 13 | }, 14 | { 15 | "name": "Aaron Heckmann", 16 | "email": "aaron.heckmann+github@gmail.com" 17 | }, 18 | { 19 | "name": "Ciaran Jessup", 20 | "email": "ciaranj@gmail.com" 21 | }, 22 | { 23 | "name": "Guillermo Rauch", 24 | "email": "rauchg@gmail.com" 25 | } 26 | ], 27 | "dependencies": { 28 | "connect": "2.8.4", 29 | "commander": "1.2.0", 30 | "range-parser": "0.0.4", 31 | "mkdirp": "0.3.5", 32 | "cookie": "0.1.0", 33 | "buffer-crc32": "0.2.1", 34 | "fresh": "0.1.0", 35 | "methods": "0.0.1", 36 | "send": "0.1.3", 37 | "cookie-signature": "1.0.1", 38 | "debug": "*" 39 | }, 40 | "devDependencies": { 41 | "ejs": "*", 42 | "mocha": "*", 43 | "jade": "0.30.0", 44 | "hjs": "*", 45 | "stylus": "*", 46 | "should": "*", 47 | "connect-redis": "*", 48 | "marked": "*", 49 | "supertest": "0.6.0" 50 | }, 51 | "keywords": [ 52 | "express", 53 | "framework", 54 | "sinatra", 55 | "web", 56 | "rest", 57 | "restful", 58 | "router", 59 | "app", 60 | "api" 61 | ], 62 | "repository": { 63 | "type": "git", 64 | "url": "git://github.com/visionmedia/express" 65 | }, 66 | "main": "index", 67 | "bin": { 68 | "express": "./bin/express" 69 | }, 70 | "scripts": { 71 | "prepublish": "npm prune", 72 | "test": "make test" 73 | }, 74 | "engines": { 75 | "node": "*" 76 | }, 77 | "readme": "![express logo](http://f.cl.ly/items/0V2S1n0K1i3y1c122g04/Screen%20Shot%202012-04-11%20at%209.59.42%20AM.png)\n\n Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). [![Build Status](https://secure.travis-ci.org/visionmedia/express.png)](http://travis-ci.org/visionmedia/express) [![Dependency Status](https://gemnasium.com/visionmedia/express.png)](https://gemnasium.com/visionmedia/express)\n\n```js\nvar express = require('express');\nvar app = express();\n\napp.get('/', function(req, res){\n res.send('Hello World');\n});\n\napp.listen(3000);\n```\n\n## Installation\n\n $ npm install -g express\n\n## Quick Start\n\n The quickest way to get started with express is to utilize the executable `express(1)` to generate an application as shown below:\n\n Create the app:\n\n $ npm install -g express\n $ express /tmp/foo && cd /tmp/foo\n\n Install dependencies:\n\n $ npm install\n\n Start the server:\n\n $ node app\n\n## Features\n\n * Built on [Connect](http://github.com/senchalabs/connect)\n * Robust routing\n * HTTP helpers (redirection, caching, etc)\n * View system supporting 14+ template engines\n * Content negotiation\n * Focus on high performance\n * Environment based configuration\n * Executable for generating applications quickly\n * High test coverage\n\n## Philosophy\n\n The Express philosophy is to provide small, robust tooling for HTTP servers. Making\n it a great solution for single page applications, web sites, hybrids, or public\n HTTP APIs.\n\n Built on Connect you can use _only_ what you need, and nothing more, applications\n can be as big or as small as you like, even a single file. Express does\n not force you to use any specific ORM or template engine. With support for over\n 14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js)\n you can quickly craft your perfect framework.\n\n## More Information\n\n * Join #express on freenode\n * [Google Group](http://groups.google.com/group/express-js) for discussion\n * Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates\n * Visit the [Wiki](http://github.com/visionmedia/express/wiki)\n * [Русскоязычная документация](http://jsman.ru/express/)\n * Run express examples [online](https://runnable.com/express)\n\n## Viewing Examples\n\nClone the Express repo, then install the dev dependencies to install all the example / test suite deps:\n\n $ git clone git://github.com/visionmedia/express.git --depth 1\n $ cd express\n $ npm install\n\nthen run whichever tests you want:\n\n $ node examples/content-negotiation\n\n## Running Tests\n\nTo run the test suite first invoke the following command within the repo, installing the development dependencies:\n\n $ npm install\n\nthen run the tests:\n\n $ make test\n\n## Contributors\n\n```\nproject: express\ncommits: 3559\nactive : 468 days\nfiles : 237\nauthors:\n 1891\tTj Holowaychuk 53.1%\n 1285\tvisionmedia 36.1%\n 182\tTJ Holowaychuk 5.1%\n 54\tAaron Heckmann 1.5%\n 34\tcsausdev 1.0%\n 26\tciaranj 0.7%\n 21\tRobert Sköld 0.6%\n 6\tGuillermo Rauch 0.2%\n 3\tDav Glass 0.1%\n 3\tNick Poulden 0.1%\n 2\tRandy Merrill 0.1%\n 2\tBenny Wong 0.1%\n 2\tHunter Loftis 0.1%\n 2\tJake Gordon 0.1%\n 2\tBrian McKinney 0.1%\n 2\tRoman Shtylman 0.1%\n 2\tBen Weaver 0.1%\n 2\tDave Hoover 0.1%\n 2\tEivind Fjeldstad 0.1%\n 2\tDaniel Shaw 0.1%\n 1\tMatt Colyer 0.0%\n 1\tPau Ramon 0.0%\n 1\tPero Pejovic 0.0%\n 1\tPeter Rekdal Sunde 0.0%\n 1\tRaynos 0.0%\n 1\tTeng Siong Ong 0.0%\n 1\tViktor Kelemen 0.0%\n 1\tctide 0.0%\n 1\t8bitDesigner 0.0%\n 1\tisaacs 0.0%\n 1\tmgutz 0.0%\n 1\tpikeas 0.0%\n 1\tshuwatto 0.0%\n 1\ttstrimple 0.0%\n 1\tewoudj 0.0%\n 1\tAdam Sanderson 0.0%\n 1\tAndrii Kostenko 0.0%\n 1\tAndy Hiew 0.0%\n 1\tArpad Borsos 0.0%\n 1\tAshwin Purohit 0.0%\n 1\tBenjen 0.0%\n 1\tDarren Torpey 0.0%\n 1\tGreg Ritter 0.0%\n 1\tGregory Ritter 0.0%\n 1\tJames Herdman 0.0%\n 1\tJim Snodgrass 0.0%\n 1\tJoe McCann 0.0%\n 1\tJonathan Dumaine 0.0%\n 1\tJonathan Palardy 0.0%\n 1\tJonathan Zacsh 0.0%\n 1\tJustin Lilly 0.0%\n 1\tKen Sato 0.0%\n 1\tMaciej Małecki 0.0%\n 1\tMasahiro Hayashi 0.0%\n```\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2009-2012 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", 78 | "readmeFilename": "Readme.md", 79 | "_id": "express@3.3.4", 80 | "_from": "express" 81 | } 82 | -------------------------------------------------------------------------------- /node_modules/socket.io/History.md: -------------------------------------------------------------------------------- 1 | 2 | 0.9.16 / 2013-06-06 3 | =================== 4 | 5 | * transports: added tests for htmlfile escaping/unescaping 6 | 7 | 0.9.15 / 2013-06-06 8 | =================== 9 | 10 | * transports: added escaping to htmlfile (fixes #1251) 11 | 12 | 0.9.14 / 2013-03-29 13 | =================== 14 | 15 | * manager: fix memory leak with SSL [jpallen] 16 | 17 | 0.9.13 / 2012-12-13 18 | =================== 19 | 20 | * package: fixed `base64id` requirement 21 | 22 | 0.9.12 / 2012-12-13 23 | =================== 24 | 25 | * manager: fix for latest node which is returning a clone with `listeners` [viirya] 26 | 27 | 0.9.11 / 2012-11-02 28 | =================== 29 | 30 | * package: move redis to optionalDependenices [3rd-Eden] 31 | * bumped client 32 | 33 | 0.9.10 / 2012-08-10 34 | =================== 35 | 36 | * Don't lowercase log messages 37 | * Always set the HTTP response in case an error should be returned to the client 38 | * Create or destroy the flash policy server on configuration change 39 | * Honour configuration to disable flash policy server 40 | * Add express 3.0 instructions on Readme.md 41 | * Bump client 42 | 43 | 0.9.9 / 2012-08-01 44 | ================== 45 | 46 | * Fixed sync disconnect xhrs handling 47 | * Put license text in its own file (#965) 48 | * Add warning to .listen() to ease the migration to Express 3.x 49 | * Restored compatibility with node 0.4.x 50 | 51 | 0.9.8 / 2012-07-24 52 | ================== 53 | 54 | * Bumped client. 55 | 56 | 0.9.7 / 2012-07-24 57 | ================== 58 | 59 | * Prevent crash when socket leaves a room twice. 60 | * Corrects unsafe usage of for..in 61 | * Fix for node 0.8 with `gzip compression` [vadimi] 62 | * Update redis to support Node 0.8.x 63 | * Made ID generation securely random 64 | * Fix Redis Store race condition in manager onOpen unsubscribe callback 65 | * Fix for EventEmitters always reusing the same Array instance for listeners 66 | 67 | 0.9.6 / 2012-04-17 68 | ================== 69 | 70 | * Fixed XSS in jsonp-polling. 71 | 72 | 0.9.5 / 2012-04-05 73 | ================== 74 | 75 | * Added test for polling and socket close. 76 | * Ensure close upon request close. 77 | * Fix disconnection reason being lost for polling transports. 78 | * Ensure that polling transports work with Connection: close. 79 | * Log disconnection reason. 80 | 81 | 0.9.4 / 2012-04-01 82 | ================== 83 | 84 | * Disconnecting from namespace improvement (#795) [DanielBaulig] 85 | * Bumped client with polling reconnection loop (#438) 86 | 87 | 0.9.3 / 2012-03-28 88 | ================== 89 | 90 | * Fix "Syntax error" on FF Web Console with XHR Polling [mikito] 91 | 92 | 0.9.2 / 2012-03-13 93 | ================== 94 | 95 | * More sensible close `timeout default` (fixes disconnect issue) 96 | 97 | 0.9.1-1 / 2012-03-02 98 | ==================== 99 | 100 | * Bumped client with NPM dependency fix. 101 | 102 | 0.9.1 / 2012-03-02 103 | ================== 104 | 105 | * Changed heartbeat timeout and interval defaults (60 and 25 seconds) 106 | * Make tests work both on 0.4 and 0.6 107 | * Updated client (improvements + bug fixes). 108 | 109 | 0.9.0 / 2012-02-26 110 | ================== 111 | 112 | * Make it possible to use a regexp to match the socket.io resource URL. 113 | We need this because we have to prefix the socket.io URL with a variable ID. 114 | * Supplemental fix to gavinuhma/authfix, it looks like the same Access-Control-Origin logic is needed in the http and xhr-polling transports 115 | * Updated express dep for windows compatibility. 116 | * Combine two substr calls into one in decodePayload to improve performance 117 | * Minor documentation fix 118 | * Minor. Conform to style of other files. 119 | * Switching setting to 'match origin protocol' 120 | * Revert "Fixes leaking Redis subscriptions for #663. The local flag was not getting passed through onClientDisconnect()." 121 | * Revert "Handle leaked dispatch:[id] subscription." 122 | * Merge pull request #667 from dshaw/patch/redis-disconnect 123 | * Handle leaked dispatch:[id] subscription. 124 | * Fixes leaking Redis subscriptions for #663. The local flag was not getting passed through onClientDisconnect(). 125 | * Prevent memory leaking on uncompleted requests & add max post size limitation 126 | * Fix for testcase 127 | * Set Access-Control-Allow-Credentials true, regardless of cookie 128 | * Remove assertvarnish from package as it breaks on 0.6 129 | * Correct irc channel 130 | * Added proper return after reserved field error 131 | * Fixes manager.js failure to close connection after transport error has happened 132 | * Added implicit port 80 for origin checks. fixes #638 133 | * Fixed bug #432 in 0.8.7 134 | * Set Access-Control-Allow-Origin header to origin to enable withCredentials 135 | * Adding configuration variable matchOriginProtocol 136 | * Fixes location mismatch error in Safari. 137 | * Use tty to detect if we should add colors or not by default. 138 | * Updated the package location. 139 | 140 | 0.8.7 / 2011-11-05 141 | ================== 142 | 143 | * Fixed memory leaks in closed clients. 144 | * Fixed memory leaks in namespaces. 145 | * Fixed websocket handling for malformed requests from proxies. [einaros] 146 | * Node 0.6 compatibility. [einaros] [3rd-Eden] 147 | * Adapted tests and examples. 148 | 149 | 0.8.6 / 2011-10-27 150 | ================== 151 | 152 | * Added JSON decoding on jsonp-polling transport. 153 | * Fixed README example. 154 | * Major speed optimizations [3rd-Eden] [einaros] [visionmedia] 155 | * Added decode/encode benchmarks [visionmedia] 156 | * Added support for black-listing client sent events. 157 | * Fixed logging options, closes #540 [3rd-Eden] 158 | * Added vary header for gzip [3rd-Eden] 159 | * Properly cleaned up async websocket / flashsocket tests, after patching node-websocket-client 160 | * Patched to properly shut down when a finishClose call is made during connection establishment 161 | * Added support for socket.io version on url and far-future Expires [3rd-Eden] [getify] 162 | * Began IE10 compatibility [einaros] [tbranyen] 163 | * Misc WebSocket fixes [einaros] 164 | * Added UTF8 to respone headers for htmlfile [3rd-Eden] 165 | 166 | 0.8.5 / 2011-10-07 167 | ================== 168 | 169 | * Added websocket draft HyBi-16 support. [einaros] 170 | * Fixed websocket continuation bugs. [einaros] 171 | * Fixed flashsocket transport name. 172 | * Fixed websocket tests. 173 | * Ensured `parser#decodePayload` doesn't choke. 174 | * Added http referrer verification to manager verifyOrigin. 175 | * Added access control for cross domain xhr handshakes [3rd-Eden] 176 | * Added support for automatic generation of socket.io files [3rd-Eden] 177 | * Added websocket binary support [einaros] 178 | * Added gzip support for socket.io.js [3rd-Eden] 179 | * Expose socket.transport [3rd-Eden] 180 | * Updated client. 181 | 182 | 0.8.4 / 2011-09-06 183 | ================== 184 | 185 | * Client build 186 | 187 | 0.8.3 / 2011-09-03 188 | ================== 189 | 190 | * Fixed `\n` parsing for non-JSON packets (fixes #479). 191 | * Fixed parsing of certain unicode characters (fixes #451). 192 | * Fixed transport message packet logging. 193 | * Fixed emission of `error` event resulting in an uncaught exception if unhandled (fixes #476). 194 | * Fixed; allow for falsy values as the configuration value of `log level` (fixes #491). 195 | * Fixed repository URI in `package.json`. Fixes #504. 196 | * Added text/plain content-type to handshake responses [einaros] 197 | * Improved single byte writes [einaros] 198 | * Updated socket.io-flashsocket default port from 843 to 10843 [3rd-Eden] 199 | * Updated client. 200 | 201 | 0.8.2 / 2011-08-29 202 | ================== 203 | 204 | * Updated client. 205 | 206 | 0.8.1 / 2011-08-29 207 | ================== 208 | 209 | * Fixed utf8 bug in send framing in websocket [einaros] 210 | * Fixed typo in docs [Znarkus] 211 | * Fixed bug in send framing for over 64kB of data in websocket [einaros] 212 | * Corrected ping handling in websocket transport [einaros] 213 | 214 | 0.8.0 / 2011-08-28 215 | ================== 216 | 217 | * Updated to work with two-level websocket versioning. [einaros] 218 | * Added hybi07 support. [einaros] 219 | * Added hybi10 support. [einaros] 220 | * Added http referrer verification to manager.js verifyOrigin. [einaors] 221 | 222 | 0.7.11 / 2011-08-27 223 | =================== 224 | 225 | * Updated socket.io-client. 226 | 227 | 0.7.10 / 2011-08-27 228 | =================== 229 | 230 | * Updated socket.io-client. 231 | 232 | 0.7.9 / 2011-08-12 233 | ================== 234 | 235 | * Updated socket.io-client. 236 | * Make sure we only do garbage collection when the server we receive is actually run. 237 | 238 | 0.7.8 / 2011-08-08 239 | ================== 240 | 241 | * Changed; make sure sio#listen passes options to both HTTP server and socket.io manager. 242 | * Added docs for sio#listen. 243 | * Added options parameter support for Manager constructor. 244 | * Added memory leaks tests and test-leaks Makefile task. 245 | * Removed auto npm-linking from make test. 246 | * Make sure that you can disable heartbeats. [3rd-Eden] 247 | * Fixed rooms memory leak [3rd-Eden] 248 | * Send response once we got all POST data, not immediately [Pita] 249 | * Fixed onLeave behavior with missing clientsk [3rd-Eden] 250 | * Prevent duplicate references in rooms. 251 | * Added alias for `to` to `in` and `in` to `to`. 252 | * Fixed roomClients definition. 253 | * Removed dependency on redis for installation without npm [3rd-Eden] 254 | * Expose path and querystring in handshakeData [3rd-Eden] 255 | 256 | 0.7.7 / 2011-07-12 257 | ================== 258 | 259 | * Fixed double dispatch handling with emit to closed clients. 260 | * Added test for emitting to closed clients to prevent regression. 261 | * Fixed race condition in redis test. 262 | * Changed Transport#end instrumentation. 263 | * Leveraged $emit instead of emit internally. 264 | * Made tests faster. 265 | * Fixed double disconnect events. 266 | * Fixed disconnect logic 267 | * Simplified remote events handling in Socket. 268 | * Increased testcase timeout. 269 | * Fixed unknown room emitting (GH-291). [3rd-Eden] 270 | * Fixed `address` in handshakeData. [3rd-Eden] 271 | * Removed transports definition in chat example. 272 | * Fixed room cleanup 273 | * Fixed; make sure the client is cleaned up after booting. 274 | * Make sure to mark the client as non-open if the connection is closed. 275 | * Removed unneeded `buffer` declarations. 276 | * Fixed; make sure to clear socket handlers and subscriptions upon transport close. 277 | 278 | 0.7.6 / 2011-06-30 279 | ================== 280 | 281 | * Fixed general dispatching when a client has closed. 282 | 283 | 0.7.5 / 2011-06-30 284 | ================== 285 | 286 | * Fixed dispatching to clients that are disconnected. 287 | 288 | 0.7.4 / 2011-06-30 289 | ================== 290 | 291 | * Fixed; only clear handlers if they were set. [level09] 292 | 293 | 0.7.3 / 2011-06-30 294 | ================== 295 | 296 | * Exposed handshake data to clients. 297 | * Refactored dispatcher interface. 298 | * Changed; Moved id generation method into the manager. 299 | * Added sub-namespace authorization. [3rd-Eden] 300 | * Changed; normalized SocketNamespace local eventing [dvv] 301 | * Changed; Use packet.reason or default to 'packet' [3rd-Eden] 302 | * Changed console.error to console.log. 303 | * Fixed; bind both servers at the same time do that the test never times out. 304 | * Added 304 support. 305 | * Removed `Transport#name` for abstract interface. 306 | * Changed; lazily require http and https module only when needed. [3rd-Eden] 307 | 308 | 0.7.2 / 2011-06-22 309 | ================== 310 | 311 | * Make sure to write a packet (of type `noop`) when closing a poll. 312 | This solves a problem with cross-domain requests being flagged as aborted and 313 | reconnection being triggered. 314 | * Added `noop` message type. 315 | 316 | 0.7.1 / 2011-06-21 317 | ================== 318 | 319 | * Fixed cross-domain XHR. 320 | * Added CORS test to xhr-polling suite. 321 | 322 | 0.7.0 / 2010-06-21 323 | ================== 324 | 325 | * http://socket.io/announcement.html 326 | -------------------------------------------------------------------------------- /node_modules/socket.io/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ALL_TESTS = $(shell find test/ -name '*.test.js') 3 | ALL_BENCH = $(shell find benchmarks -name '*.bench.js') 4 | 5 | run-tests: 6 | @./node_modules/.bin/expresso \ 7 | -t 3000 \ 8 | -I support \ 9 | --serial \ 10 | $(TESTFLAGS) \ 11 | $(TESTS) 12 | 13 | test: 14 | @$(MAKE) NODE_PATH=lib TESTS="$(ALL_TESTS)" run-tests 15 | 16 | test-cov: 17 | @TESTFLAGS=--cov $(MAKE) test 18 | 19 | test-leaks: 20 | @ls test/leaks/* | xargs node --expose_debug_as=debug --expose_gc 21 | 22 | run-bench: 23 | @node $(PROFILEFLAGS) benchmarks/runner.js 24 | 25 | bench: 26 | @$(MAKE) BENCHMARKS="$(ALL_BENCH)" run-bench 27 | 28 | profile: 29 | @PROFILEFLAGS='--prof --trace-opt --trace-bailout --trace-deopt' $(MAKE) bench 30 | 31 | .PHONY: test bench profile 32 | -------------------------------------------------------------------------------- /node_modules/socket.io/README.md: -------------------------------------------------------------------------------- 1 | # Socket.IO 2 | 3 | Socket.IO is a Node.JS project that makes WebSockets and realtime possible in 4 | all browsers. It also enhances WebSockets by providing built-in multiplexing, 5 | horizontal scalability, automatic JSON encoding/decoding, and more. 6 | 7 | ## How to Install 8 | 9 | ```bash 10 | npm install socket.io 11 | ``` 12 | 13 | ## How to use 14 | 15 | First, require `socket.io`: 16 | 17 | ```js 18 | var io = require('socket.io'); 19 | ``` 20 | 21 | Next, attach it to a HTTP/HTTPS server. If you're using the fantastic `express` 22 | web framework: 23 | 24 | #### Express 3.x 25 | 26 | ```js 27 | var app = express() 28 | , server = require('http').createServer(app) 29 | , io = io.listen(server); 30 | 31 | server.listen(80); 32 | 33 | io.sockets.on('connection', function (socket) { 34 | socket.emit('news', { hello: 'world' }); 35 | socket.on('my other event', function (data) { 36 | console.log(data); 37 | }); 38 | }); 39 | ``` 40 | 41 | #### Express 2.x 42 | 43 | ```js 44 | var app = express.createServer() 45 | , io = io.listen(app); 46 | 47 | app.listen(80); 48 | 49 | io.sockets.on('connection', function (socket) { 50 | socket.emit('news', { hello: 'world' }); 51 | socket.on('my other event', function (data) { 52 | console.log(data); 53 | }); 54 | }); 55 | ``` 56 | 57 | Finally, load it from the client side code: 58 | 59 | ```html 60 | 61 | 68 | ``` 69 | 70 | For more thorough examples, look at the `examples/` directory. 71 | 72 | ## Short recipes 73 | 74 | ### Sending and receiving events. 75 | 76 | Socket.IO allows you to emit and receive custom events. 77 | Besides `connect`, `message` and `disconnect`, you can emit custom events: 78 | 79 | ```js 80 | // note, io.listen() will create a http server for you 81 | var io = require('socket.io').listen(80); 82 | 83 | io.sockets.on('connection', function (socket) { 84 | io.sockets.emit('this', { will: 'be received by everyone' }); 85 | 86 | socket.on('private message', function (from, msg) { 87 | console.log('I received a private message by ', from, ' saying ', msg); 88 | }); 89 | 90 | socket.on('disconnect', function () { 91 | io.sockets.emit('user disconnected'); 92 | }); 93 | }); 94 | ``` 95 | 96 | ### Storing data associated to a client 97 | 98 | Sometimes it's necessary to store data associated with a client that's 99 | necessary for the duration of the session. 100 | 101 | #### Server side 102 | 103 | ```js 104 | var io = require('socket.io').listen(80); 105 | 106 | io.sockets.on('connection', function (socket) { 107 | socket.on('set nickname', function (name) { 108 | socket.set('nickname', name, function () { socket.emit('ready'); }); 109 | }); 110 | 111 | socket.on('msg', function () { 112 | socket.get('nickname', function (err, name) { 113 | console.log('Chat message by ', name); 114 | }); 115 | }); 116 | }); 117 | ``` 118 | 119 | #### Client side 120 | 121 | ```html 122 | 133 | ``` 134 | 135 | ### Restricting yourself to a namespace 136 | 137 | If you have control over all the messages and events emitted for a particular 138 | application, using the default `/` namespace works. 139 | 140 | If you want to leverage 3rd-party code, or produce code to share with others, 141 | socket.io provides a way of namespacing a `socket`. 142 | 143 | This has the benefit of `multiplexing` a single connection. Instead of 144 | socket.io using two `WebSocket` connections, it'll use one. 145 | 146 | The following example defines a socket that listens on '/chat' and one for 147 | '/news': 148 | 149 | #### Server side 150 | 151 | ```js 152 | var io = require('socket.io').listen(80); 153 | 154 | var chat = io 155 | .of('/chat') 156 | .on('connection', function (socket) { 157 | socket.emit('a message', { that: 'only', '/chat': 'will get' }); 158 | chat.emit('a message', { everyone: 'in', '/chat': 'will get' }); 159 | }); 160 | 161 | var news = io 162 | .of('/news'); 163 | .on('connection', function (socket) { 164 | socket.emit('item', { news: 'item' }); 165 | }); 166 | ``` 167 | 168 | #### Client side: 169 | 170 | ```html 171 | 183 | ``` 184 | 185 | ### Sending volatile messages. 186 | 187 | Sometimes certain messages can be dropped. Let's say you have an app that 188 | shows realtime tweets for the keyword `bieber`. 189 | 190 | If a certain client is not ready to receive messages (because of network slowness 191 | or other issues, or because he's connected through long polling and is in the 192 | middle of a request-response cycle), if he doesn't receive ALL the tweets related 193 | to bieber your application won't suffer. 194 | 195 | In that case, you might want to send those messages as volatile messages. 196 | 197 | #### Server side 198 | 199 | ```js 200 | var io = require('socket.io').listen(80); 201 | 202 | io.sockets.on('connection', function (socket) { 203 | var tweets = setInterval(function () { 204 | getBieberTweet(function (tweet) { 205 | socket.volatile.emit('bieber tweet', tweet); 206 | }); 207 | }, 100); 208 | 209 | socket.on('disconnect', function () { 210 | clearInterval(tweets); 211 | }); 212 | }); 213 | ``` 214 | 215 | #### Client side 216 | 217 | In the client side, messages are received the same way whether they're volatile 218 | or not. 219 | 220 | ### Getting acknowledgements 221 | 222 | Sometimes, you might want to get a callback when the client confirmed the message 223 | reception. 224 | 225 | To do this, simply pass a function as the last parameter of `.send` or `.emit`. 226 | What's more, when you use `.emit`, the acknowledgement is done by you, which 227 | means you can also pass data along: 228 | 229 | #### Server side 230 | 231 | ```js 232 | var io = require('socket.io').listen(80); 233 | 234 | io.sockets.on('connection', function (socket) { 235 | socket.on('ferret', function (name, fn) { 236 | fn('woot'); 237 | }); 238 | }); 239 | ``` 240 | 241 | #### Client side 242 | 243 | ```html 244 | 252 | ``` 253 | 254 | ### Broadcasting messages 255 | 256 | To broadcast, simply add a `broadcast` flag to `emit` and `send` method calls. 257 | Broadcasting means sending a message to everyone else except for the socket 258 | that starts it. 259 | 260 | #### Server side 261 | 262 | ```js 263 | var io = require('socket.io').listen(80); 264 | 265 | io.sockets.on('connection', function (socket) { 266 | socket.broadcast.emit('user connected'); 267 | socket.broadcast.json.send({ a: 'message' }); 268 | }); 269 | ``` 270 | 271 | ### Rooms 272 | 273 | Sometimes you want to put certain sockets in the same room, so that it's easy 274 | to broadcast to all of them together. 275 | 276 | Think of this as built-in channels for sockets. Sockets `join` and `leave` 277 | rooms in each socket. 278 | 279 | #### Server side 280 | 281 | ```js 282 | var io = require('socket.io').listen(80); 283 | 284 | io.sockets.on('connection', function (socket) { 285 | socket.join('justin bieber fans'); 286 | socket.broadcast.to('justin bieber fans').emit('new fan'); 287 | io.sockets.in('rammstein fans').emit('new non-fan'); 288 | }); 289 | ``` 290 | 291 | ### Using it just as a cross-browser WebSocket 292 | 293 | If you just want the WebSocket semantics, you can do that too. 294 | Simply leverage `send` and listen on the `message` event: 295 | 296 | #### Server side 297 | 298 | ```js 299 | var io = require('socket.io').listen(80); 300 | 301 | io.sockets.on('connection', function (socket) { 302 | socket.on('message', function () { }); 303 | socket.on('disconnect', function () { }); 304 | }); 305 | ``` 306 | 307 | #### Client side 308 | 309 | ```html 310 | 320 | ``` 321 | 322 | ### Changing configuration 323 | 324 | Configuration in socket.io is TJ-style: 325 | 326 | #### Server side 327 | 328 | ```js 329 | var io = require('socket.io').listen(80); 330 | 331 | io.configure(function () { 332 | io.set('transports', ['websocket', 'flashsocket', 'xhr-polling']); 333 | }); 334 | 335 | io.configure('development', function () { 336 | io.set('transports', ['websocket', 'xhr-polling']); 337 | io.enable('log'); 338 | }); 339 | ``` 340 | 341 | ## License 342 | 343 | (The MIT License) 344 | 345 | Copyright (c) 2011 Guillermo Rauch <guillermo@learnboost.com> 346 | 347 | Permission is hereby granted, free of charge, to any person obtaining 348 | a copy of this software and associated documentation files (the 349 | 'Software'), to deal in the Software without restriction, including 350 | without limitation the rights to use, copy, modify, merge, publish, 351 | distribute, sublicense, and/or sell copies of the Software, and to 352 | permit persons to whom the Software is furnished to do so, subject to 353 | the following conditions: 354 | 355 | The above copyright notice and this permission notice shall be 356 | included in all copies or substantial portions of the Software. 357 | 358 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 359 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 360 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 361 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 362 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 363 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 364 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 365 | -------------------------------------------------------------------------------- /node_modules/socket.io/index.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * socket.io-node 4 | * Copyright(c) 2011 LearnBoost 5 | * MIT Licensed 6 | */ 7 | 8 | module.exports = require('./lib/socket.io'); 9 | -------------------------------------------------------------------------------- /node_modules/socket.io/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "socket.io", 3 | "version": "0.9.16", 4 | "description": "Real-time apps made cross-browser & easy with a WebSocket-like API", 5 | "homepage": "http://socket.io", 6 | "keywords": [ 7 | "websocket", 8 | "socket", 9 | "realtime", 10 | "socket.io", 11 | "comet", 12 | "ajax" 13 | ], 14 | "author": { 15 | "name": "Guillermo Rauch", 16 | "email": "guillermo@learnboost.com" 17 | }, 18 | "contributors": [ 19 | { 20 | "name": "Guillermo Rauch", 21 | "email": "rauchg@gmail.com" 22 | }, 23 | { 24 | "name": "Arnout Kazemier", 25 | "email": "info@3rd-eden.com" 26 | }, 27 | { 28 | "name": "Vladimir Dronnikov", 29 | "email": "dronnikov@gmail.com" 30 | }, 31 | { 32 | "name": "Einar Otto Stangvik", 33 | "email": "einaros@gmail.com" 34 | } 35 | ], 36 | "repository": { 37 | "type": "git", 38 | "url": "https://github.com/LearnBoost/socket.io.git" 39 | }, 40 | "dependencies": { 41 | "socket.io-client": "0.9.16", 42 | "policyfile": "0.0.4", 43 | "base64id": "0.1.0", 44 | "redis": "0.7.3" 45 | }, 46 | "devDependencies": { 47 | "expresso": "0.9.2", 48 | "should": "*", 49 | "benchmark": "0.2.2", 50 | "microtime": "0.1.3-1", 51 | "colors": "0.5.1" 52 | }, 53 | "optionalDependencies": { 54 | "redis": "0.7.3" 55 | }, 56 | "main": "index", 57 | "engines": { 58 | "node": ">= 0.4.0" 59 | }, 60 | "scripts": { 61 | "test": "make test" 62 | }, 63 | "readme": "# Socket.IO\n\nSocket.IO is a Node.JS project that makes WebSockets and realtime possible in\nall browsers. It also enhances WebSockets by providing built-in multiplexing,\nhorizontal scalability, automatic JSON encoding/decoding, and more.\n\n## How to Install\n\n```bash\nnpm install socket.io\n```\n\n## How to use\n\nFirst, require `socket.io`:\n\n```js\nvar io = require('socket.io');\n```\n\nNext, attach it to a HTTP/HTTPS server. If you're using the fantastic `express`\nweb framework:\n\n#### Express 3.x\n\n```js\nvar app = express()\n , server = require('http').createServer(app)\n , io = io.listen(server);\n\nserver.listen(80);\n\nio.sockets.on('connection', function (socket) {\n socket.emit('news', { hello: 'world' });\n socket.on('my other event', function (data) {\n console.log(data);\n });\n});\n```\n\n#### Express 2.x\n\n```js\nvar app = express.createServer()\n , io = io.listen(app);\n\napp.listen(80);\n\nio.sockets.on('connection', function (socket) {\n socket.emit('news', { hello: 'world' });\n socket.on('my other event', function (data) {\n console.log(data);\n });\n});\n```\n\nFinally, load it from the client side code:\n\n```html\n\n\n```\n\nFor more thorough examples, look at the `examples/` directory.\n\n## Short recipes\n\n### Sending and receiving events.\n\nSocket.IO allows you to emit and receive custom events.\nBesides `connect`, `message` and `disconnect`, you can emit custom events:\n\n```js\n// note, io.listen() will create a http server for you\nvar io = require('socket.io').listen(80);\n\nio.sockets.on('connection', function (socket) {\n io.sockets.emit('this', { will: 'be received by everyone' });\n\n socket.on('private message', function (from, msg) {\n console.log('I received a private message by ', from, ' saying ', msg);\n });\n\n socket.on('disconnect', function () {\n io.sockets.emit('user disconnected');\n });\n});\n```\n\n### Storing data associated to a client\n\nSometimes it's necessary to store data associated with a client that's\nnecessary for the duration of the session.\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nio.sockets.on('connection', function (socket) {\n socket.on('set nickname', function (name) {\n socket.set('nickname', name, function () { socket.emit('ready'); });\n });\n\n socket.on('msg', function () {\n socket.get('nickname', function (err, name) {\n console.log('Chat message by ', name);\n });\n });\n});\n```\n\n#### Client side\n\n```html\n\n```\n\n### Restricting yourself to a namespace\n\nIf you have control over all the messages and events emitted for a particular\napplication, using the default `/` namespace works.\n\nIf you want to leverage 3rd-party code, or produce code to share with others,\nsocket.io provides a way of namespacing a `socket`.\n\nThis has the benefit of `multiplexing` a single connection. Instead of\nsocket.io using two `WebSocket` connections, it'll use one.\n\nThe following example defines a socket that listens on '/chat' and one for\n'/news':\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nvar chat = io\n .of('/chat')\n .on('connection', function (socket) {\n socket.emit('a message', { that: 'only', '/chat': 'will get' });\n chat.emit('a message', { everyone: 'in', '/chat': 'will get' });\n });\n\nvar news = io\n .of('/news');\n .on('connection', function (socket) {\n socket.emit('item', { news: 'item' });\n });\n```\n\n#### Client side:\n\n```html\n\n```\n\n### Sending volatile messages.\n\nSometimes certain messages can be dropped. Let's say you have an app that\nshows realtime tweets for the keyword `bieber`. \n\nIf a certain client is not ready to receive messages (because of network slowness\nor other issues, or because he's connected through long polling and is in the\nmiddle of a request-response cycle), if he doesn't receive ALL the tweets related\nto bieber your application won't suffer.\n\nIn that case, you might want to send those messages as volatile messages.\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nio.sockets.on('connection', function (socket) {\n var tweets = setInterval(function () {\n getBieberTweet(function (tweet) {\n socket.volatile.emit('bieber tweet', tweet);\n });\n }, 100);\n\n socket.on('disconnect', function () {\n clearInterval(tweets);\n });\n});\n```\n\n#### Client side\n\nIn the client side, messages are received the same way whether they're volatile\nor not.\n\n### Getting acknowledgements\n\nSometimes, you might want to get a callback when the client confirmed the message\nreception.\n\nTo do this, simply pass a function as the last parameter of `.send` or `.emit`.\nWhat's more, when you use `.emit`, the acknowledgement is done by you, which\nmeans you can also pass data along:\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nio.sockets.on('connection', function (socket) {\n socket.on('ferret', function (name, fn) {\n fn('woot');\n });\n});\n```\n\n#### Client side\n\n```html\n\n```\n\n### Broadcasting messages\n\nTo broadcast, simply add a `broadcast` flag to `emit` and `send` method calls.\nBroadcasting means sending a message to everyone else except for the socket\nthat starts it.\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nio.sockets.on('connection', function (socket) {\n socket.broadcast.emit('user connected');\n socket.broadcast.json.send({ a: 'message' });\n});\n```\n\n### Rooms\n\nSometimes you want to put certain sockets in the same room, so that it's easy\nto broadcast to all of them together.\n\nThink of this as built-in channels for sockets. Sockets `join` and `leave`\nrooms in each socket.\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nio.sockets.on('connection', function (socket) {\n socket.join('justin bieber fans');\n socket.broadcast.to('justin bieber fans').emit('new fan');\n io.sockets.in('rammstein fans').emit('new non-fan');\n});\n```\n\n### Using it just as a cross-browser WebSocket\n\nIf you just want the WebSocket semantics, you can do that too.\nSimply leverage `send` and listen on the `message` event:\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nio.sockets.on('connection', function (socket) {\n socket.on('message', function () { });\n socket.on('disconnect', function () { });\n});\n```\n\n#### Client side\n\n```html\n\n```\n\n### Changing configuration\n\nConfiguration in socket.io is TJ-style:\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nio.configure(function () {\n io.set('transports', ['websocket', 'flashsocket', 'xhr-polling']);\n});\n\nio.configure('development', function () {\n io.set('transports', ['websocket', 'xhr-polling']);\n io.enable('log');\n});\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 Guillermo Rauch <guillermo@learnboost.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", 64 | "readmeFilename": "Readme.md", 65 | "_id": "socket.io@0.9.16", 66 | "_from": "socket.io" 67 | } 68 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Collaborative painting app with socket.io", 3 | "version": "0.0.1-1", 4 | "homepage": "http://xjamundx.no.de", 5 | "engines": { 6 | "node": "0.8.x" 7 | }, 8 | "dependencies": { 9 | "express": "~3.3.4", 10 | "socket.io": "~0.9.16" 11 | }, 12 | "scripts": { 13 | "start": "server.js" 14 | }, 15 | "name": "paint", 16 | "subdomain": "xpaintx" 17 | } -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xjamundx/CollabPaintJS/f014285b98b247ebe5217e35dd35dc989346b99f/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | CollabPaintJS 7 | 8 | 9 | 10 |

    CollabPaintJS

    11 |
    12 | 13 |
    14 | 15 | 25 | 26 | 41 | Current Users: 1 42 | 43 |
    44 |
    45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /public/paint.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var last = []; 4 | var ctx, touchdown, socket, i, color, size, width, height; 5 | 6 | socket = new io.connect(); 7 | socket.on('paint', paint); 8 | socket.on('message', message); 9 | socket.on('reset', reset); 10 | socket.on('clear', clearScreen); 11 | 12 | // locals 13 | var body = document.body 14 | , $canvas = document.getElementById('canvas') 15 | , $size = document.getElementById('size') 16 | , $color = document.getElementById('color') 17 | , $clear = document.getElementById('clear') 18 | , $game = document.getElementById('game') 19 | , $count = document.getElementById('count'); 20 | 21 | // globals 22 | ctx = $canvas.getContext('2d'); 23 | width = $canvas.getAttribute('width'); 24 | height = $canvas.getAttribute('height'); 25 | 26 | // get the starting size 27 | size = $size.options[$size.selectedIndex].value; 28 | color = $color.options[$color.selectedIndex].value.toLowerCase(); 29 | 30 | // typical draw event for desktop 31 | $canvas.onmousemove = function(e) { 32 | move(e); 33 | }; 34 | 35 | $size.addEventListener('change', function(e) { 36 | size = $size.options[$size.selectedIndex].value 37 | touchdown = false 38 | }, false) 39 | 40 | $color.addEventListener('change', function(e) { 41 | color = $color.options[$color.selectedIndex].value.toLowerCase() 42 | touchdown = false 43 | }, false) 44 | 45 | $clear.addEventListener('click', function(e) { 46 | clearScreen() 47 | socket.emit('clear'); 48 | touchdown = false 49 | clearLast() 50 | }, false) 51 | 52 | window.onmouseup = function(e) { 53 | touchdown = false 54 | clearLast() 55 | }; 56 | 57 | window.onmousedown = function(e) { 58 | touchdown = true; 59 | }; 60 | 61 | // iOS 62 | 63 | // hide the toolbar in iOS 64 | setTimeout(function() { 65 | window.scrollTo(0, 1); 66 | }, 100); 67 | 68 | // prevents dragging the page in iOS 69 | body.ontouchmove = function(e) { 70 | e.preventDefault(); 71 | }; 72 | 73 | $canvas.ontouchstart = function(e) { 74 | touchdown = false 75 | clearLast() 76 | } 77 | 78 | // iOS alternative to mouse move 79 | $canvas.ontouchmove = function(e) { 80 | move(e); 81 | }; 82 | 83 | function paint(msg) { 84 | drawCircle(msg.circle, msg.sessionId); 85 | } 86 | 87 | function message(msg) { 88 | 89 | if (msg.buffer) { 90 | msg.buffer.forEach(paint); 91 | } 92 | 93 | if (msg.count) { 94 | $count.innerHTML = 'Current Users: ' + msg.count 95 | } 96 | }; 97 | 98 | function reset(msg) { 99 | delete last[msg.sessionId]; 100 | } 101 | 102 | function clearScreen() { 103 | ctx.clearRect(0,0,width,height) 104 | } 105 | 106 | function clearLast() { 107 | delete last['me'] 108 | socket.emit('reset'); 109 | } 110 | 111 | function move(e) { 112 | 113 | var x, y 114 | 115 | if (!touchdown && !e.targetTouches) return 116 | 117 | if (touchdown) { 118 | x = e.clientX + window.scrollX 119 | y = e.clientY + window.scrollY 120 | } else { 121 | x = e.targetTouches[0].clientX 122 | y = e.targetTouches[0].clientY 123 | } 124 | 125 | x -= $game.offsetLeft 126 | y -= $game.offsetTop 127 | 128 | circle = { 129 | x: x, 130 | y: y, 131 | color: color, 132 | size: size 133 | } 134 | 135 | drawCircle(circle) 136 | socket.emit('paint', circle); 137 | 138 | }; 139 | 140 | function drawCircle(circle, sessionId) { 141 | 142 | sessionId = sessionId || 'me'; 143 | 144 | ctx.strokeStyle = circle.color 145 | ctx.fillStyle = circle.color; 146 | ctx.lineWidth = circle.size; 147 | ctx.lineCap = 'round'; 148 | 149 | ctx.beginPath() 150 | if (last[sessionId]) { 151 | ctx.moveTo(last[sessionId].x, last[sessionId].y) 152 | ctx.lineTo(circle.x, circle.y) 153 | ctx.stroke() 154 | } else { 155 | ctx.moveTo(circle.x, circle.y); 156 | ctx.arc(circle.x, circle.y, circle.size / 2, 0, Math.PI*2, true); 157 | ctx.fill(); 158 | } 159 | ctx.closePath(); 160 | 161 | last[sessionId] = circle; 162 | 163 | }; 164 | 165 | })(); 166 | -------------------------------------------------------------------------------- /public/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: black; 3 | text-align: center; 4 | font-family: Arial; 5 | } 6 | 7 | h1 { 8 | color: red; 9 | font-weight: bold; 10 | } 11 | 12 | #canvas { 13 | background-color: black; 14 | cursor: pointer; 15 | } 16 | 17 | #controls { 18 | color: white; 19 | top: 0; 20 | right: 0px; 21 | background: white; 22 | padding: 16px; 23 | position: absolute; 24 | border-radius: 0 0 0 16px; 25 | color: black; 26 | } 27 | 28 | #game { 29 | 30 | border: 2px solid white; 31 | 32 | width: 640px; 33 | margin: 0 auto; 34 | height: 480px; 35 | overflow: hidden; 36 | position: relative; 37 | } -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | // requires 2 | var express = require('express'); 3 | var app = express(); 4 | var io = require('socket.io'); 5 | var port = process.argv[2] || 8888; 6 | var server = require('http').createServer(app); 7 | var socket = io.listen(server); 8 | 9 | // setup static files directory 10 | app.use(express.static(__dirname + '/public')); 11 | 12 | // start server listening 13 | server.listen(port); 14 | 15 | // state 16 | var buffer = []; 17 | var count = 0; 18 | 19 | 20 | socket.on('connection', function(client) { 21 | 22 | count++; 23 | 24 | // each time a new person connects, send them the old stuff 25 | client.emit('message', { 26 | buffer: buffer, 27 | count: count 28 | }); 29 | 30 | // send a welcome 31 | client.broadcast.emit('message', {count: count, sessionId: client.sessionId}) 32 | 33 | // message 34 | client.on('paint', function(data) { 35 | 36 | var msg = { 37 | circle: data, 38 | session_id: data.sessionId 39 | } 40 | 41 | buffer.push(msg) 42 | 43 | if (buffer.length > 1024) buffer.shift(); 44 | 45 | client.broadcast.emit('paint', msg); 46 | 47 | }); 48 | 49 | client.on('reset', function() { 50 | client.broadcast.emit('reset'); 51 | }); 52 | 53 | client.on('clear', function() { 54 | buffer = []; 55 | client.broadcast.emit('clear'); 56 | }); 57 | 58 | client.on('disconnect', function(){ 59 | count--; 60 | client.broadcast.emit('message', {count: count, sessionId: client.sessionId}); 61 | }); 62 | 63 | }); 64 | --------------------------------------------------------------------------------