From 2afbcf4e7d000d99fdbc582d7113684ee00e80cc Mon Sep 17 00:00:00 2001 From: yo mama Date: Fri, 20 Mar 2015 17:33:43 -0700 Subject: first --- .gitignore | 1 + How to runs.txt | 21 + app.js | 31 + config.js | 4 + modules/webrtc.io/index.js | 1 + modules/webrtc.io/lib/webrtc.io.js | 286 + node_modules/.bin/express | 15 + node_modules/.bin/express.cmd | 5 + node_modules/.bin/wscat | 15 + node_modules/.bin/wscat.cmd | 5 + node_modules/ejs/.gitmodules | 0 node_modules/ejs/.npmignore | 4 + node_modules/ejs/.travis.yml | 7 + node_modules/ejs/History.md | 131 + node_modules/ejs/Makefile | 23 + node_modules/ejs/Readme.md | 188 + node_modules/ejs/benchmark.js | 14 + node_modules/ejs/ejs.js | 581 + node_modules/ejs/ejs.min.js | 1 + node_modules/ejs/examples/client.html | 24 + node_modules/ejs/examples/functions.ejs | 9 + node_modules/ejs/examples/functions.js | 22 + node_modules/ejs/examples/list.ejs | 7 + node_modules/ejs/examples/list.js | 14 + node_modules/ejs/index.js | 2 + node_modules/ejs/lib/ejs.js | 353 + node_modules/ejs/lib/filters.js | 198 + node_modules/ejs/lib/utils.js | 23 + node_modules/ejs/package.json | 33 + node_modules/ejs/support/compile.js | 176 + node_modules/ejs/test/ejs.js | 265 + node_modules/ejs/test/fixtures/backslash.ejs | 1 + node_modules/ejs/test/fixtures/backslash.html | 1 + node_modules/ejs/test/fixtures/comments.ejs | 5 + node_modules/ejs/test/fixtures/comments.html | 4 + node_modules/ejs/test/fixtures/double-quote.ejs | 1 + node_modules/ejs/test/fixtures/double-quote.html | 1 + node_modules/ejs/test/fixtures/error.ejs | 5 + node_modules/ejs/test/fixtures/error.out | 8 + node_modules/ejs/test/fixtures/fail.ejs | 1 + node_modules/ejs/test/fixtures/include.css.ejs | 1 + node_modules/ejs/test/fixtures/include.css.html | 3 + node_modules/ejs/test/fixtures/include.ejs | 5 + node_modules/ejs/test/fixtures/include.html | 9 + .../ejs/test/fixtures/includes/menu-item.ejs | 1 + .../ejs/test/fixtures/includes/menu/item.ejs | 1 + node_modules/ejs/test/fixtures/menu.ejs | 11 + node_modules/ejs/test/fixtures/menu.html | 3 + node_modules/ejs/test/fixtures/messed.ejs | 1 + node_modules/ejs/test/fixtures/messed.html | 1 + node_modules/ejs/test/fixtures/newlines.ejs | 5 + node_modules/ejs/test/fixtures/newlines.html | 9 + node_modules/ejs/test/fixtures/no.newlines.ejs | 5 + node_modules/ejs/test/fixtures/no.newlines.html | 5 + node_modules/ejs/test/fixtures/para.ejs | 1 + node_modules/ejs/test/fixtures/pet.ejs | 1 + node_modules/ejs/test/fixtures/single-quote.ejs | 1 + node_modules/ejs/test/fixtures/single-quote.html | 1 + node_modules/ejs/test/fixtures/style.css | 3 + node_modules/ejs/test/fixtures/user.ejs | 1 + node_modules/express/.npmignore | 9 + node_modules/express/.travis.yml | 4 + node_modules/express/History.md | 1183 ++ node_modules/express/LICENSE | 22 + node_modules/express/Makefile | 33 + node_modules/express/Readme.md | 179 + node_modules/express/bin/express | 422 + node_modules/express/index.js | 4 + node_modules/express/lib/application.js | 535 + node_modules/express/lib/express.js | 86 + node_modules/express/lib/middleware.js | 32 + node_modules/express/lib/request.js | 526 + node_modules/express/lib/response.js | 757 ++ node_modules/express/lib/router/index.js | 273 + node_modules/express/lib/router/route.js | 72 + node_modules/express/lib/utils.js | 313 + node_modules/express/lib/view.js | 77 + .../express/node_modules/buffer-crc32/.npmignore | 1 + .../express/node_modules/buffer-crc32/.travis.yml | 8 + .../express/node_modules/buffer-crc32/README.md | 47 + .../express/node_modules/buffer-crc32/index.js | 88 + .../express/node_modules/buffer-crc32/package.json | 43 + .../node_modules/buffer-crc32/tests/crc.test.js | 89 + .../express/node_modules/commander/History.md | 158 + .../express/node_modules/commander/Readme.md | 276 + .../express/node_modules/commander/index.js | 1152 ++ .../commander/node_modules/keypress/README.md | 101 + .../commander/node_modules/keypress/index.js | 346 + .../commander/node_modules/keypress/package.json | 35 + .../commander/node_modules/keypress/test.js | 28 + .../express/node_modules/commander/package.json | 44 + .../express/node_modules/connect/.npmignore | 12 + .../express/node_modules/connect/.travis.yml | 4 + node_modules/express/node_modules/connect/LICENSE | 24 + .../express/node_modules/connect/Readme.md | 133 + node_modules/express/node_modules/connect/index.js | 4 + .../express/node_modules/connect/lib/cache.js | 81 + .../express/node_modules/connect/lib/connect.js | 92 + .../express/node_modules/connect/lib/index.js | 50 + .../connect/lib/middleware/basicAuth.js | 103 + .../connect/lib/middleware/bodyParser.js | 61 + .../connect/lib/middleware/compress.js | 189 + .../connect/lib/middleware/cookieParser.js | 62 + .../connect/lib/middleware/cookieSession.js | 115 + .../node_modules/connect/lib/middleware/csrf.js | 75 + .../connect/lib/middleware/directory.js | 229 + .../connect/lib/middleware/errorHandler.js | 86 + .../node_modules/connect/lib/middleware/favicon.js | 80 + .../node_modules/connect/lib/middleware/json.js | 89 + .../node_modules/connect/lib/middleware/limit.js | 78 + .../node_modules/connect/lib/middleware/logger.js | 339 + .../connect/lib/middleware/methodOverride.js | 59 + .../connect/lib/middleware/multipart.js | 133 + .../node_modules/connect/lib/middleware/query.js | 46 + .../connect/lib/middleware/responseTime.js | 32 + .../node_modules/connect/lib/middleware/session.js | 355 + .../connect/lib/middleware/session/cookie.js | 140 + .../connect/lib/middleware/session/memory.js | 129 + .../connect/lib/middleware/session/session.js | 116 + .../connect/lib/middleware/session/store.js | 84 + .../node_modules/connect/lib/middleware/static.js | 95 + .../connect/lib/middleware/staticCache.js | 231 + .../node_modules/connect/lib/middleware/timeout.js | 55 + .../connect/lib/middleware/urlencoded.js | 78 + .../node_modules/connect/lib/middleware/vhost.js | 40 + .../express/node_modules/connect/lib/patch.js | 79 + .../express/node_modules/connect/lib/proto.js | 230 + .../node_modules/connect/lib/public/directory.html | 81 + .../node_modules/connect/lib/public/error.html | 14 + .../node_modules/connect/lib/public/favicon.ico | Bin 0 -> 1406 bytes .../node_modules/connect/lib/public/icons/page.png | Bin 0 -> 635 bytes .../connect/lib/public/icons/page_add.png | Bin 0 -> 739 bytes .../connect/lib/public/icons/page_attach.png | Bin 0 -> 794 bytes .../connect/lib/public/icons/page_code.png | Bin 0 -> 818 bytes .../connect/lib/public/icons/page_copy.png | Bin 0 -> 663 bytes .../connect/lib/public/icons/page_delete.png | Bin 0 -> 740 bytes .../connect/lib/public/icons/page_edit.png | Bin 0 -> 807 bytes .../connect/lib/public/icons/page_error.png | Bin 0 -> 793 bytes .../connect/lib/public/icons/page_excel.png | Bin 0 -> 817 bytes .../connect/lib/public/icons/page_find.png | Bin 0 -> 879 bytes .../connect/lib/public/icons/page_gear.png | Bin 0 -> 833 bytes .../connect/lib/public/icons/page_go.png | Bin 0 -> 779 bytes .../connect/lib/public/icons/page_green.png | Bin 0 -> 621 bytes .../connect/lib/public/icons/page_key.png | Bin 0 -> 801 bytes .../connect/lib/public/icons/page_lightning.png | Bin 0 -> 839 bytes .../connect/lib/public/icons/page_link.png | Bin 0 -> 830 bytes .../connect/lib/public/icons/page_paintbrush.png | Bin 0 -> 813 bytes .../connect/lib/public/icons/page_paste.png | Bin 0 -> 703 bytes .../connect/lib/public/icons/page_red.png | Bin 0 -> 641 bytes .../connect/lib/public/icons/page_refresh.png | Bin 0 -> 858 bytes .../connect/lib/public/icons/page_save.png | Bin 0 -> 774 bytes .../connect/lib/public/icons/page_white.png | Bin 0 -> 294 bytes .../lib/public/icons/page_white_acrobat.png | Bin 0 -> 591 bytes .../lib/public/icons/page_white_actionscript.png | Bin 0 -> 664 bytes .../connect/lib/public/icons/page_white_add.png | Bin 0 -> 512 bytes .../connect/lib/public/icons/page_white_c.png | Bin 0 -> 587 bytes .../connect/lib/public/icons/page_white_camera.png | Bin 0 -> 656 bytes .../connect/lib/public/icons/page_white_cd.png | Bin 0 -> 666 bytes .../connect/lib/public/icons/page_white_code.png | Bin 0 -> 603 bytes .../lib/public/icons/page_white_code_red.png | Bin 0 -> 587 bytes .../lib/public/icons/page_white_coldfusion.png | Bin 0 -> 592 bytes .../lib/public/icons/page_white_compressed.png | Bin 0 -> 724 bytes .../connect/lib/public/icons/page_white_copy.png | Bin 0 -> 309 bytes .../lib/public/icons/page_white_cplusplus.png | Bin 0 -> 621 bytes .../connect/lib/public/icons/page_white_csharp.png | Bin 0 -> 700 bytes .../connect/lib/public/icons/page_white_cup.png | Bin 0 -> 639 bytes .../lib/public/icons/page_white_database.png | Bin 0 -> 579 bytes .../connect/lib/public/icons/page_white_delete.png | Bin 0 -> 536 bytes .../connect/lib/public/icons/page_white_dvd.png | Bin 0 -> 638 bytes .../connect/lib/public/icons/page_white_edit.png | Bin 0 -> 618 bytes .../connect/lib/public/icons/page_white_error.png | Bin 0 -> 623 bytes .../connect/lib/public/icons/page_white_excel.png | Bin 0 -> 663 bytes .../connect/lib/public/icons/page_white_find.png | Bin 0 -> 676 bytes .../connect/lib/public/icons/page_white_flash.png | Bin 0 -> 582 bytes .../lib/public/icons/page_white_freehand.png | Bin 0 -> 639 bytes .../connect/lib/public/icons/page_white_gear.png | Bin 0 -> 402 bytes .../connect/lib/public/icons/page_white_get.png | Bin 0 -> 516 bytes .../connect/lib/public/icons/page_white_go.png | Bin 0 -> 612 bytes .../connect/lib/public/icons/page_white_h.png | Bin 0 -> 603 bytes .../lib/public/icons/page_white_horizontal.png | Bin 0 -> 296 bytes .../connect/lib/public/icons/page_white_key.png | Bin 0 -> 616 bytes .../lib/public/icons/page_white_lightning.png | Bin 0 -> 669 bytes .../connect/lib/public/icons/page_white_link.png | Bin 0 -> 614 bytes .../lib/public/icons/page_white_magnify.png | Bin 0 -> 554 bytes .../connect/lib/public/icons/page_white_medal.png | Bin 0 -> 706 bytes .../connect/lib/public/icons/page_white_office.png | Bin 0 -> 779 bytes .../connect/lib/public/icons/page_white_paint.png | Bin 0 -> 688 bytes .../lib/public/icons/page_white_paintbrush.png | Bin 0 -> 618 bytes .../connect/lib/public/icons/page_white_paste.png | Bin 0 -> 620 bytes .../connect/lib/public/icons/page_white_php.png | Bin 0 -> 538 bytes .../lib/public/icons/page_white_picture.png | Bin 0 -> 650 bytes .../lib/public/icons/page_white_powerpoint.png | Bin 0 -> 588 bytes .../connect/lib/public/icons/page_white_put.png | Bin 0 -> 523 bytes .../connect/lib/public/icons/page_white_ruby.png | Bin 0 -> 626 bytes .../connect/lib/public/icons/page_white_stack.png | Bin 0 -> 317 bytes .../connect/lib/public/icons/page_white_star.png | Bin 0 -> 565 bytes .../connect/lib/public/icons/page_white_swoosh.png | Bin 0 -> 634 bytes .../connect/lib/public/icons/page_white_text.png | Bin 0 -> 342 bytes .../lib/public/icons/page_white_text_width.png | Bin 0 -> 315 bytes .../connect/lib/public/icons/page_white_tux.png | Bin 0 -> 668 bytes .../connect/lib/public/icons/page_white_vector.png | Bin 0 -> 644 bytes .../lib/public/icons/page_white_visualstudio.png | Bin 0 -> 702 bytes .../connect/lib/public/icons/page_white_width.png | Bin 0 -> 309 bytes .../connect/lib/public/icons/page_white_word.png | Bin 0 -> 651 bytes .../connect/lib/public/icons/page_white_world.png | Bin 0 -> 734 bytes .../connect/lib/public/icons/page_white_wrench.png | Bin 0 -> 613 bytes .../connect/lib/public/icons/page_white_zip.png | Bin 0 -> 386 bytes .../connect/lib/public/icons/page_word.png | Bin 0 -> 777 bytes .../connect/lib/public/icons/page_world.png | Bin 0 -> 903 bytes .../node_modules/connect/lib/public/style.css | 141 + .../express/node_modules/connect/lib/utils.js | 386 + .../connect/node_modules/bytes/.npmignore | 1 + .../connect/node_modules/bytes/History.md | 10 + .../connect/node_modules/bytes/Makefile | 7 + .../connect/node_modules/bytes/Readme.md | 51 + .../connect/node_modules/bytes/component.json | 7 + .../connect/node_modules/bytes/index.js | 39 + .../connect/node_modules/bytes/package.json | 24 + .../connect/node_modules/formidable/.npmignore | 4 + .../connect/node_modules/formidable/.travis.yml | 5 + .../connect/node_modules/formidable/LICENSE | 7 + .../connect/node_modules/formidable/Readme.md | 419 + .../formidable/benchmark/bench-multipart-parser.js | 71 + .../node_modules/formidable/example/json.js | 67 + .../node_modules/formidable/example/post.js | 43 + .../node_modules/formidable/example/upload.js | 48 + .../connect/node_modules/formidable/index.js | 1 + .../connect/node_modules/formidable/lib/file.js | 72 + .../node_modules/formidable/lib/incoming_form.js | 535 + .../connect/node_modules/formidable/lib/index.js | 3 + .../node_modules/formidable/lib/json_parser.js | 35 + .../formidable/lib/multipart_parser.js | 324 + .../node_modules/formidable/lib/octet_parser.js | 20 + .../formidable/lib/querystring_parser.js | 27 + .../connect/node_modules/formidable/package.json | 42 + .../connect/node_modules/formidable/test/common.js | 18 + .../test/fixture/file/beta-sticker-1.png | Bin 0 -> 1660 bytes .../formidable/test/fixture/file/binaryfile.tar.gz | Bin 0 -> 301 bytes .../formidable/test/fixture/file/blank.gif | Bin 0 -> 49 bytes .../formidable/test/fixture/file/funkyfilename.txt | 1 + .../test/fixture/file/menu_separator.png | Bin 0 -> 931 bytes .../formidable/test/fixture/file/plain.txt | 1 + .../fixture/http/special-chars-in-filename/info.md | 3 + .../formidable/test/fixture/js/encoding.js | 24 + .../formidable/test/fixture/js/misc.js | 6 + .../formidable/test/fixture/js/no-filename.js | 9 + .../formidable/test/fixture/js/preamble.js | 9 + .../test/fixture/js/special-chars-in-filename.js | 21 + .../formidable/test/fixture/js/workarounds.js | 8 + .../formidable/test/fixture/multipart.js | 72 + .../formidable/test/integration/test-fixtures.js | 96 + .../formidable/test/integration/test-json.js | 38 + .../test/integration/test-octet-stream.js | 45 + .../node_modules/formidable/test/legacy/common.js | 24 + .../legacy/integration/test-multipart-parser.js | 80 + .../formidable/test/legacy/simple/test-file.js | 104 + .../test/legacy/simple/test-incoming-form.js | 756 ++ .../test/legacy/simple/test-multipart-parser.js | 50 + .../test/legacy/simple/test-querystring-parser.js | 45 + .../test/legacy/system/test-multi-video-upload.js | 71 + .../connect/node_modules/formidable/test/run.js | 1 + .../test/standalone/test-connection-aborted.js | 27 + .../standalone/test-content-transfer-encoding.js | 48 + .../formidable/test/standalone/test-issue-46.js | 49 + .../node_modules/formidable/test/tools/base64.html | 67 + .../node_modules/formidable/test/unit/test-file.js | 33 + .../formidable/test/unit/test-incoming-form.js | 63 + .../connect/node_modules/formidable/tool/record.js | 47 + .../connect/node_modules/pause/.npmignore | 4 + .../connect/node_modules/pause/History.md | 5 + .../connect/node_modules/pause/Makefile | 7 + .../connect/node_modules/pause/Readme.md | 29 + .../connect/node_modules/pause/index.js | 29 + .../connect/node_modules/pause/package.json | 24 + .../connect/node_modules/qs/.gitmodules | 6 + .../connect/node_modules/qs/.npmignore | 7 + .../node_modules/connect/node_modules/qs/Readme.md | 58 + .../node_modules/connect/node_modules/qs/index.js | 387 + .../connect/node_modules/qs/package.json | 41 + .../connect/node_modules/uid2/index.js | 49 + .../connect/node_modules/uid2/package.json | 16 + .../express/node_modules/connect/package.json | 59 + node_modules/express/node_modules/connect/test.js | 8 + .../node_modules/cookie-signature/.npmignore | 4 + .../node_modules/cookie-signature/History.md | 11 + .../express/node_modules/cookie-signature/Makefile | 7 + .../node_modules/cookie-signature/Readme.md | 42 + .../express/node_modules/cookie-signature/index.js | 42 + .../node_modules/cookie-signature/package.json | 28 + .../express/node_modules/cookie/.npmignore | 1 + .../express/node_modules/cookie/.travis.yml | 5 + node_modules/express/node_modules/cookie/LICENSE | 9 + node_modules/express/node_modules/cookie/README.md | 44 + node_modules/express/node_modules/cookie/index.js | 70 + .../express/node_modules/cookie/package.json | 40 + .../express/node_modules/cookie/test/mocha.opts | 1 + .../express/node_modules/cookie/test/parse.js | 44 + .../express/node_modules/cookie/test/serialize.js | 64 + node_modules/express/node_modules/debug/.npmignore | 4 + node_modules/express/node_modules/debug/History.md | 62 + node_modules/express/node_modules/debug/Readme.md | 115 + .../express/node_modules/debug/component.json | 9 + node_modules/express/node_modules/debug/debug.js | 124 + .../express/node_modules/debug/example/app.js | 19 + .../node_modules/debug/example/browser.html | 24 + .../node_modules/debug/example/wildcards.js | 10 + .../express/node_modules/debug/example/worker.js | 22 + node_modules/express/node_modules/debug/index.js | 5 + .../express/node_modules/debug/lib/debug.js | 134 + .../express/node_modules/debug/package.json | 44 + node_modules/express/node_modules/fresh/.npmignore | 1 + node_modules/express/node_modules/fresh/Makefile | 7 + node_modules/express/node_modules/fresh/Readme.md | 32 + node_modules/express/node_modules/fresh/index.js | 49 + .../express/node_modules/fresh/package.json | 24 + node_modules/express/node_modules/methods/index.js | 26 + .../express/node_modules/methods/package.json | 24 + .../express/node_modules/mkdirp/.npmignore | 2 + .../express/node_modules/mkdirp/.travis.yml | 5 + node_modules/express/node_modules/mkdirp/LICENSE | 21 + .../express/node_modules/mkdirp/examples/pow.js | 6 + node_modules/express/node_modules/mkdirp/index.js | 82 + .../express/node_modules/mkdirp/package.json | 37 + .../express/node_modules/mkdirp/readme.markdown | 63 + .../express/node_modules/mkdirp/test/chmod.js | 38 + .../express/node_modules/mkdirp/test/clobber.js | 37 + .../express/node_modules/mkdirp/test/mkdirp.js | 28 + .../express/node_modules/mkdirp/test/perm.js | 32 + .../express/node_modules/mkdirp/test/perm_sync.js | 39 + .../express/node_modules/mkdirp/test/race.js | 41 + .../express/node_modules/mkdirp/test/rel.js | 32 + .../express/node_modules/mkdirp/test/return.js | 25 + .../node_modules/mkdirp/test/return_sync.js | 24 + .../express/node_modules/mkdirp/test/root.js | 18 + .../express/node_modules/mkdirp/test/sync.js | 32 + .../express/node_modules/mkdirp/test/umask.js | 28 + .../express/node_modules/mkdirp/test/umask_sync.js | 32 + .../express/node_modules/range-parser/.npmignore | 1 + .../express/node_modules/range-parser/History.md | 15 + .../express/node_modules/range-parser/Makefile | 7 + .../express/node_modules/range-parser/Readme.md | 28 + .../express/node_modules/range-parser/index.js | 49 + .../express/node_modules/range-parser/package.json | 24 + node_modules/express/node_modules/send/.npmignore | 4 + node_modules/express/node_modules/send/History.md | 35 + node_modules/express/node_modules/send/Makefile | 8 + node_modules/express/node_modules/send/Readme.md | 128 + node_modules/express/node_modules/send/index.js | 2 + node_modules/express/node_modules/send/lib/send.js | 474 + .../express/node_modules/send/lib/utils.js | 47 + .../node_modules/send/node_modules/mime/LICENSE | 19 + .../node_modules/send/node_modules/mime/README.md | 66 + .../node_modules/send/node_modules/mime/mime.js | 114 + .../send/node_modules/mime/package.json | 39 + .../node_modules/send/node_modules/mime/test.js | 84 + .../send/node_modules/mime/types/mime.types | 1588 +++ .../send/node_modules/mime/types/node.types | 77 + .../express/node_modules/send/package.json | 45 + node_modules/express/package.json | 88 + node_modules/express/test.js | 17 + node_modules/ws/.npmignore | 6 + node_modules/ws/.travis.yml | 6 + node_modules/ws/History.md | 260 + node_modules/ws/Makefile | 38 + node_modules/ws/README.md | 159 + node_modules/ws/bench/parser.benchmark.js | 115 + node_modules/ws/bench/sender.benchmark.js | 66 + node_modules/ws/bench/speed.js | 105 + node_modules/ws/bench/util.js | 105 + node_modules/ws/bin/wscat | 190 + node_modules/ws/binding.gyp | 14 + node_modules/ws/builderror.log | 11 + node_modules/ws/doc/ws.md | 179 + node_modules/ws/examples/fileapi/.npmignore | 1 + node_modules/ws/examples/fileapi/package.json | 18 + node_modules/ws/examples/fileapi/public/app.js | 39 + node_modules/ws/examples/fileapi/public/index.html | 22 + .../ws/examples/fileapi/public/uploader.js | 55 + node_modules/ws/examples/fileapi/server.js | 103 + .../ws/examples/serverstats-express_3/package.json | 17 + .../serverstats-express_3/public/index.html | 33 + .../ws/examples/serverstats-express_3/server.js | 21 + node_modules/ws/examples/serverstats/package.json | 17 + .../ws/examples/serverstats/public/index.html | 33 + node_modules/ws/examples/serverstats/server.js | 19 + node_modules/ws/examples/ssl.js | 59 + node_modules/ws/index.js | 26 + node_modules/ws/lib/BufferPool.js | 59 + node_modules/ws/lib/BufferUtil.fallback.js | 47 + node_modules/ws/lib/BufferUtil.js | 16 + node_modules/ws/lib/ErrorCodes.js | 24 + node_modules/ws/lib/Receiver.hixie.js | 180 + node_modules/ws/lib/Receiver.js | 591 + node_modules/ws/lib/Sender.hixie.js | 123 + node_modules/ws/lib/Sender.js | 226 + node_modules/ws/lib/Validation.fallback.js | 12 + node_modules/ws/lib/Validation.js | 16 + node_modules/ws/lib/WebSocket.js | 766 ++ node_modules/ws/lib/WebSocketServer.js | 460 + node_modules/ws/lib/browser.js | 5 + node_modules/ws/node_modules/commander/.npmignore | 4 + node_modules/ws/node_modules/commander/.travis.yml | 4 + node_modules/ws/node_modules/commander/History.md | 107 + node_modules/ws/node_modules/commander/Makefile | 7 + node_modules/ws/node_modules/commander/Readme.md | 262 + node_modules/ws/node_modules/commander/index.js | 2 + .../ws/node_modules/commander/lib/commander.js | 1026 ++ .../ws/node_modules/commander/package.json | 42 + node_modules/ws/node_modules/options/.npmignore | 5 + node_modules/ws/node_modules/options/Makefile | 12 + node_modules/ws/node_modules/options/README.md | 28 + .../ws/node_modules/options/lib/options.js | 86 + node_modules/ws/node_modules/options/package.json | 36 + .../node_modules/options/test/fixtures/test.conf | 4 + .../ws/node_modules/options/test/options.test.js | 140 + node_modules/ws/node_modules/tinycolor/.npmignore | 5 + node_modules/ws/node_modules/tinycolor/README.md | 3 + node_modules/ws/node_modules/tinycolor/example.js | 3 + .../ws/node_modules/tinycolor/package.json | 31 + .../ws/node_modules/tinycolor/tinycolor.js | 31 + node_modules/ws/package.json | 48 + node_modules/ws/src/bufferutil.cc | 115 + node_modules/ws/src/validation.cc | 143 + node_modules/ws/test/BufferPool.test.js | 63 + node_modules/ws/test/Receiver.hixie.test.js | 158 + node_modules/ws/test/Receiver.test.js | 255 + node_modules/ws/test/Sender.hixie.test.js | 134 + node_modules/ws/test/Sender.test.js | 24 + node_modules/ws/test/Validation.test.js | 23 + node_modules/ws/test/WebSocket.integration.js | 42 + node_modules/ws/test/WebSocket.test.js | 1609 +++ node_modules/ws/test/WebSocketServer.test.js | 1103 ++ node_modules/ws/test/autobahn-server.js | 29 + node_modules/ws/test/autobahn.js | 52 + node_modules/ws/test/fixtures/agent1-cert.pem | 16 + node_modules/ws/test/fixtures/agent1-key.pem | 15 + node_modules/ws/test/fixtures/ca1-cert.pem | 15 + node_modules/ws/test/fixtures/ca1-key.pem | 17 + node_modules/ws/test/fixtures/certificate.pem | 13 + node_modules/ws/test/fixtures/key.pem | 15 + node_modules/ws/test/fixtures/request.pem | 11 + node_modules/ws/test/fixtures/textfile | 9 + node_modules/ws/test/hybi-common.js | 99 + node_modules/ws/test/testserver.js | 180 + npm-debug.log | 62 + package.json | 13 + public/css/styles.css | 154 + public/images/capture.png | Bin 0 -> 3693 bytes public/images/login_bg.jpg | Bin 0 -> 165881 bytes public/images/loginbt.png | Bin 0 -> 4944 bytes public/images/offline.png | Bin 0 -> 1467 bytes public/images/online.png | Bin 0 -> 3838 bytes public/images/user.png | Bin 0 -> 4054 bytes public/javascripts/client.js | 249 + public/javascripts/easyloader.js | 192 + public/javascripts/file-utils.js | 296 + public/javascripts/jquery.easyui.min.js | 11839 +++++++++++++++++++ public/javascripts/jquery.min.js | 6 + public/javascripts/rtc-io.js | 411 + public/javascripts/themes/black/accordion.css | 41 + public/javascripts/themes/black/calendar.css | 190 + public/javascripts/themes/black/combo.css | 58 + public/javascripts/themes/black/combobox.css | 14 + public/javascripts/themes/black/datagrid.css | 259 + public/javascripts/themes/black/datebox.css | 42 + public/javascripts/themes/black/dialog.css | 30 + public/javascripts/themes/black/easyui.css | 2297 ++++ public/javascripts/themes/black/images/Thumbs.db | Bin 0 -> 35328 bytes .../themes/black/images/accordion_arrows.png | Bin 0 -> 122 bytes public/javascripts/themes/black/images/blank.gif | Bin 0 -> 43 bytes .../themes/black/images/calendar_arrows.png | Bin 0 -> 173 bytes .../themes/black/images/combo_arrow.png | Bin 0 -> 100 bytes .../themes/black/images/datagrid_icons.png | Bin 0 -> 210 bytes .../themes/black/images/datebox_arrow.png | Bin 0 -> 626 bytes .../themes/black/images/layout_arrows.png | Bin 0 -> 179 bytes .../themes/black/images/linkbutton_bg.png | Bin 0 -> 1274 bytes public/javascripts/themes/black/images/loading.gif | Bin 0 -> 1737 bytes .../themes/black/images/menu_arrows.png | Bin 0 -> 134 bytes .../themes/black/images/messager_icons.png | Bin 0 -> 6116 bytes .../themes/black/images/pagination_icons.png | Bin 0 -> 364 bytes .../themes/black/images/panel_tools.png | Bin 0 -> 184 bytes .../themes/black/images/searchbox_button.png | Bin 0 -> 813 bytes .../themes/black/images/slider_handle.png | Bin 0 -> 863 bytes .../themes/black/images/spinner_arrows.png | Bin 0 -> 112 bytes .../javascripts/themes/black/images/tabs_icons.png | Bin 0 -> 144 bytes .../javascripts/themes/black/images/tree_icons.png | Bin 0 -> 3086 bytes .../themes/black/images/validatebox_warning.png | Bin 0 -> 921 bytes public/javascripts/themes/black/layout.css | 91 + public/javascripts/themes/black/linkbutton.css | 151 + public/javascripts/themes/black/menu.css | 109 + public/javascripts/themes/black/menubutton.css | 31 + public/javascripts/themes/black/messager.css | 37 + public/javascripts/themes/black/pagination.css | 66 + public/javascripts/themes/black/panel.css | 125 + public/javascripts/themes/black/progressbar.css | 31 + public/javascripts/themes/black/propertygrid.css | 28 + public/javascripts/themes/black/searchbox.css | 79 + public/javascripts/themes/black/slider.css | 100 + public/javascripts/themes/black/spinner.css | 59 + public/javascripts/themes/black/splitbutton.css | 43 + public/javascripts/themes/black/tabs.css | 363 + public/javascripts/themes/black/tooltip.css | 98 + public/javascripts/themes/black/tree.css | 157 + public/javascripts/themes/black/validatebox.css | 8 + public/javascripts/themes/black/window.css | 87 + public/javascripts/themes/bootstrap/accordion.css | 41 + public/javascripts/themes/bootstrap/calendar.css | 190 + public/javascripts/themes/bootstrap/combo.css | 58 + public/javascripts/themes/bootstrap/combobox.css | 14 + public/javascripts/themes/bootstrap/datagrid.css | 259 + public/javascripts/themes/bootstrap/datebox.css | 42 + public/javascripts/themes/bootstrap/dialog.css | 30 + public/javascripts/themes/bootstrap/easyui.css | 2316 ++++ .../javascripts/themes/bootstrap/images/Thumbs.db | Bin 0 -> 35328 bytes .../themes/bootstrap/images/accordion_arrows.png | Bin 0 -> 184 bytes .../javascripts/themes/bootstrap/images/blank.gif | Bin 0 -> 43 bytes .../themes/bootstrap/images/calendar_arrows.png | Bin 0 -> 173 bytes .../themes/bootstrap/images/combo_arrow.png | Bin 0 -> 117 bytes .../themes/bootstrap/images/datagrid_icons.png | Bin 0 -> 220 bytes .../themes/bootstrap/images/datebox_arrow.png | Bin 0 -> 626 bytes .../themes/bootstrap/images/layout_arrows.png | Bin 0 -> 319 bytes .../themes/bootstrap/images/linkbutton_bg.png | Bin 0 -> 1274 bytes .../themes/bootstrap/images/loading.gif | Bin 0 -> 1737 bytes .../themes/bootstrap/images/menu_arrows.png | Bin 0 -> 160 bytes .../themes/bootstrap/images/messager_icons.png | Bin 0 -> 6116 bytes .../themes/bootstrap/images/pagination_icons.png | Bin 0 -> 651 bytes .../themes/bootstrap/images/panel_tools.png | Bin 0 -> 194 bytes .../themes/bootstrap/images/searchbox_button.png | Bin 0 -> 813 bytes .../themes/bootstrap/images/slider_handle.png | Bin 0 -> 863 bytes .../themes/bootstrap/images/spinner_arrows.png | Bin 0 -> 115 bytes .../themes/bootstrap/images/tabs_icons.png | Bin 0 -> 150 bytes .../themes/bootstrap/images/tree_icons.png | Bin 0 -> 3115 bytes .../bootstrap/images/validatebox_warning.png | Bin 0 -> 921 bytes public/javascripts/themes/bootstrap/layout.css | 91 + public/javascripts/themes/bootstrap/linkbutton.css | 151 + public/javascripts/themes/bootstrap/menu.css | 109 + public/javascripts/themes/bootstrap/menubutton.css | 31 + public/javascripts/themes/bootstrap/messager.css | 37 + public/javascripts/themes/bootstrap/pagination.css | 66 + public/javascripts/themes/bootstrap/panel.css | 125 + .../javascripts/themes/bootstrap/progressbar.css | 31 + .../javascripts/themes/bootstrap/propertygrid.css | 28 + public/javascripts/themes/bootstrap/searchbox.css | 79 + public/javascripts/themes/bootstrap/slider.css | 100 + public/javascripts/themes/bootstrap/spinner.css | 59 + .../javascripts/themes/bootstrap/splitbutton.css | 43 + public/javascripts/themes/bootstrap/tabs.css | 363 + public/javascripts/themes/bootstrap/tooltip.css | 98 + public/javascripts/themes/bootstrap/tree.css | 157 + .../javascripts/themes/bootstrap/validatebox.css | 8 + public/javascripts/themes/bootstrap/window.css | 87 + public/javascripts/themes/default/accordion.css | 41 + public/javascripts/themes/default/calendar.css | 190 + public/javascripts/themes/default/combo.css | 58 + public/javascripts/themes/default/combobox.css | 14 + public/javascripts/themes/default/datagrid.css | 259 + public/javascripts/themes/default/datebox.css | 42 + public/javascripts/themes/default/dialog.css | 30 + public/javascripts/themes/default/easyui.css | 2269 ++++ public/javascripts/themes/default/images/Thumbs.db | Bin 0 -> 35328 bytes .../themes/default/images/accordion_arrows.png | Bin 0 -> 184 bytes public/javascripts/themes/default/images/blank.gif | Bin 0 -> 43 bytes .../themes/default/images/calendar_arrows.png | Bin 0 -> 173 bytes .../themes/default/images/combo_arrow.png | Bin 0 -> 117 bytes .../themes/default/images/datagrid_icons.png | Bin 0 -> 220 bytes .../themes/default/images/datebox_arrow.png | Bin 0 -> 626 bytes .../themes/default/images/layout_arrows.png | Bin 0 -> 319 bytes .../themes/default/images/linkbutton_bg.png | Bin 0 -> 1274 bytes .../javascripts/themes/default/images/loading.gif | Bin 0 -> 1737 bytes .../themes/default/images/menu_arrows.png | Bin 0 -> 160 bytes .../themes/default/images/messager_icons.png | Bin 0 -> 6116 bytes .../themes/default/images/pagination_icons.png | Bin 0 -> 651 bytes .../themes/default/images/panel_tools.png | Bin 0 -> 852 bytes .../themes/default/images/searchbox_button.png | Bin 0 -> 813 bytes .../themes/default/images/slider_handle.png | Bin 0 -> 863 bytes .../themes/default/images/spinner_arrows.png | Bin 0 -> 115 bytes .../themes/default/images/tabs_icons.png | Bin 0 -> 150 bytes .../themes/default/images/tree_icons.png | Bin 0 -> 3115 bytes .../themes/default/images/validatebox_warning.png | Bin 0 -> 921 bytes public/javascripts/themes/default/layout.css | 91 + public/javascripts/themes/default/linkbutton.css | 123 + public/javascripts/themes/default/menu.css | 109 + public/javascripts/themes/default/menubutton.css | 31 + public/javascripts/themes/default/messager.css | 37 + public/javascripts/themes/default/pagination.css | 66 + public/javascripts/themes/default/panel.css | 125 + public/javascripts/themes/default/progressbar.css | 31 + public/javascripts/themes/default/propertygrid.css | 28 + public/javascripts/themes/default/searchbox.css | 79 + public/javascripts/themes/default/slider.css | 100 + public/javascripts/themes/default/spinner.css | 59 + public/javascripts/themes/default/splitbutton.css | 43 + public/javascripts/themes/default/tabs.css | 363 + public/javascripts/themes/default/tooltip.css | 98 + public/javascripts/themes/default/tree.css | 157 + public/javascripts/themes/default/validatebox.css | 8 + public/javascripts/themes/default/window.css | 87 + public/javascripts/themes/gray/accordion.css | 41 + public/javascripts/themes/gray/calendar.css | 190 + public/javascripts/themes/gray/combo.css | 58 + public/javascripts/themes/gray/combobox.css | 14 + public/javascripts/themes/gray/datagrid.css | 259 + public/javascripts/themes/gray/datebox.css | 42 + public/javascripts/themes/gray/dialog.css | 30 + public/javascripts/themes/gray/easyui.css | 2269 ++++ public/javascripts/themes/gray/images/Thumbs.db | Bin 0 -> 35328 bytes .../themes/gray/images/accordion_arrows.png | Bin 0 -> 125 bytes public/javascripts/themes/gray/images/blank.gif | Bin 0 -> 43 bytes .../themes/gray/images/calendar_arrows.png | Bin 0 -> 173 bytes .../javascripts/themes/gray/images/combo_arrow.png | Bin 0 -> 103 bytes .../themes/gray/images/datagrid_icons.png | Bin 0 -> 243 bytes .../themes/gray/images/datebox_arrow.png | Bin 0 -> 626 bytes .../themes/gray/images/layout_arrows.png | Bin 0 -> 181 bytes .../themes/gray/images/linkbutton_bg.png | Bin 0 -> 1274 bytes public/javascripts/themes/gray/images/loading.gif | Bin 0 -> 1737 bytes .../javascripts/themes/gray/images/menu_arrows.png | Bin 0 -> 160 bytes .../themes/gray/images/messager_icons.png | Bin 0 -> 6116 bytes .../themes/gray/images/pagination_icons.png | Bin 0 -> 492 bytes .../javascripts/themes/gray/images/panel_tools.png | Bin 0 -> 191 bytes .../themes/gray/images/searchbox_button.png | Bin 0 -> 813 bytes .../themes/gray/images/slider_handle.png | Bin 0 -> 863 bytes .../themes/gray/images/spinner_arrows.png | Bin 0 -> 141 bytes .../javascripts/themes/gray/images/tabs_icons.png | Bin 0 -> 144 bytes .../javascripts/themes/gray/images/tree_icons.png | Bin 0 -> 3115 bytes .../themes/gray/images/validatebox_warning.png | Bin 0 -> 921 bytes public/javascripts/themes/gray/layout.css | 91 + public/javascripts/themes/gray/linkbutton.css | 123 + public/javascripts/themes/gray/menu.css | 109 + public/javascripts/themes/gray/menubutton.css | 31 + public/javascripts/themes/gray/messager.css | 37 + public/javascripts/themes/gray/pagination.css | 66 + public/javascripts/themes/gray/panel.css | 125 + public/javascripts/themes/gray/progressbar.css | 31 + public/javascripts/themes/gray/propertygrid.css | 28 + public/javascripts/themes/gray/searchbox.css | 79 + public/javascripts/themes/gray/slider.css | 100 + public/javascripts/themes/gray/spinner.css | 59 + public/javascripts/themes/gray/splitbutton.css | 43 + public/javascripts/themes/gray/tabs.css | 363 + public/javascripts/themes/gray/tooltip.css | 98 + public/javascripts/themes/gray/tree.css | 157 + public/javascripts/themes/gray/validatebox.css | 8 + public/javascripts/themes/gray/window.css | 87 + public/javascripts/themes/icon.css | 64 + public/javascripts/themes/icons/back.png | Bin 0 -> 912 bytes public/javascripts/themes/icons/blank.gif | Bin 0 -> 43 bytes public/javascripts/themes/icons/cancel.png | Bin 0 -> 1133 bytes public/javascripts/themes/icons/cut.png | Bin 0 -> 1024 bytes public/javascripts/themes/icons/edit_add.png | Bin 0 -> 1088 bytes public/javascripts/themes/icons/edit_remove.png | Bin 0 -> 625 bytes public/javascripts/themes/icons/filesave.png | Bin 0 -> 898 bytes public/javascripts/themes/icons/help.png | Bin 0 -> 1187 bytes public/javascripts/themes/icons/mini_add.png | Bin 0 -> 244 bytes public/javascripts/themes/icons/mini_edit.png | Bin 0 -> 161 bytes public/javascripts/themes/icons/mini_refresh.png | Bin 0 -> 160 bytes public/javascripts/themes/icons/no.png | Bin 0 -> 922 bytes public/javascripts/themes/icons/ok.png | Bin 0 -> 883 bytes public/javascripts/themes/icons/pencil.png | Bin 0 -> 713 bytes public/javascripts/themes/icons/print.png | Bin 0 -> 1057 bytes public/javascripts/themes/icons/redo.png | Bin 0 -> 708 bytes public/javascripts/themes/icons/reload.png | Bin 0 -> 1045 bytes public/javascripts/themes/icons/search.png | Bin 0 -> 813 bytes public/javascripts/themes/icons/sum.png | Bin 0 -> 289 bytes public/javascripts/themes/icons/tip.png | Bin 0 -> 743 bytes public/javascripts/themes/icons/undo.png | Bin 0 -> 707 bytes public/javascripts/themes/metro/accordion.css | 41 + public/javascripts/themes/metro/calendar.css | 190 + public/javascripts/themes/metro/combo.css | 58 + public/javascripts/themes/metro/combobox.css | 14 + public/javascripts/themes/metro/datagrid.css | 253 + public/javascripts/themes/metro/datebox.css | 42 + public/javascripts/themes/metro/dialog.css | 30 + public/javascripts/themes/metro/easyui.css | 2243 ++++ public/javascripts/themes/metro/images/Thumbs.db | Bin 0 -> 35328 bytes .../themes/metro/images/accordion_arrows.png | Bin 0 -> 184 bytes public/javascripts/themes/metro/images/blank.gif | Bin 0 -> 43 bytes .../themes/metro/images/calendar_arrows.png | Bin 0 -> 173 bytes .../themes/metro/images/combo_arrow.png | Bin 0 -> 117 bytes .../themes/metro/images/datagrid_icons.png | Bin 0 -> 220 bytes .../themes/metro/images/datebox_arrow.png | Bin 0 -> 626 bytes .../themes/metro/images/layout_arrows.png | Bin 0 -> 319 bytes .../themes/metro/images/linkbutton_bg.png | Bin 0 -> 1274 bytes public/javascripts/themes/metro/images/loading.gif | Bin 0 -> 1737 bytes .../themes/metro/images/menu_arrows.png | Bin 0 -> 160 bytes .../themes/metro/images/messager_icons.png | Bin 0 -> 6116 bytes .../themes/metro/images/pagination_icons.png | Bin 0 -> 651 bytes .../themes/metro/images/panel_tools.png | Bin 0 -> 194 bytes .../themes/metro/images/searchbox_button.png | Bin 0 -> 813 bytes .../themes/metro/images/slider_handle.png | Bin 0 -> 863 bytes .../themes/metro/images/spinner_arrows.png | Bin 0 -> 115 bytes .../javascripts/themes/metro/images/tabs_icons.png | Bin 0 -> 150 bytes .../javascripts/themes/metro/images/tree_icons.png | Bin 0 -> 3115 bytes .../themes/metro/images/validatebox_warning.png | Bin 0 -> 921 bytes public/javascripts/themes/metro/layout.css | 91 + public/javascripts/themes/metro/linkbutton.css | 151 + public/javascripts/themes/metro/menu.css | 109 + public/javascripts/themes/metro/menubutton.css | 31 + public/javascripts/themes/metro/messager.css | 37 + public/javascripts/themes/metro/pagination.css | 66 + public/javascripts/themes/metro/panel.css | 119 + public/javascripts/themes/metro/progressbar.css | 31 + public/javascripts/themes/metro/propertygrid.css | 28 + public/javascripts/themes/metro/searchbox.css | 79 + public/javascripts/themes/metro/slider.css | 100 + public/javascripts/themes/metro/spinner.css | 59 + public/javascripts/themes/metro/splitbutton.css | 43 + public/javascripts/themes/metro/tabs.css | 327 + public/javascripts/themes/metro/tooltip.css | 98 + public/javascripts/themes/metro/tree.css | 157 + public/javascripts/themes/metro/validatebox.css | 8 + public/javascripts/themes/metro/window.css | 81 + routes/index.js | 20 + routes/main.js | 26 + uploads/pepper.png | Bin 0 -> 30200 bytes views/index.html | 47 + views/main.html | 64 + 716 files changed, 69542 insertions(+) create mode 100644 .gitignore create mode 100644 How to runs.txt create mode 100644 app.js create mode 100644 config.js create mode 100644 modules/webrtc.io/index.js create mode 100644 modules/webrtc.io/lib/webrtc.io.js create mode 100644 node_modules/.bin/express create mode 100644 node_modules/.bin/express.cmd create mode 100644 node_modules/.bin/wscat create mode 100644 node_modules/.bin/wscat.cmd create mode 100644 node_modules/ejs/.gitmodules create mode 100644 node_modules/ejs/.npmignore create mode 100644 node_modules/ejs/.travis.yml create mode 100644 node_modules/ejs/History.md create mode 100644 node_modules/ejs/Makefile create mode 100644 node_modules/ejs/Readme.md create mode 100644 node_modules/ejs/benchmark.js create mode 100644 node_modules/ejs/ejs.js create mode 100644 node_modules/ejs/ejs.min.js create mode 100644 node_modules/ejs/examples/client.html create mode 100644 node_modules/ejs/examples/functions.ejs create mode 100644 node_modules/ejs/examples/functions.js create mode 100644 node_modules/ejs/examples/list.ejs create mode 100644 node_modules/ejs/examples/list.js create mode 100644 node_modules/ejs/index.js create mode 100644 node_modules/ejs/lib/ejs.js create mode 100644 node_modules/ejs/lib/filters.js create mode 100644 node_modules/ejs/lib/utils.js create mode 100644 node_modules/ejs/package.json create mode 100644 node_modules/ejs/support/compile.js create mode 100644 node_modules/ejs/test/ejs.js create mode 100644 node_modules/ejs/test/fixtures/backslash.ejs create mode 100644 node_modules/ejs/test/fixtures/backslash.html create mode 100644 node_modules/ejs/test/fixtures/comments.ejs create mode 100644 node_modules/ejs/test/fixtures/comments.html create mode 100644 node_modules/ejs/test/fixtures/double-quote.ejs create mode 100644 node_modules/ejs/test/fixtures/double-quote.html create mode 100644 node_modules/ejs/test/fixtures/error.ejs create mode 100644 node_modules/ejs/test/fixtures/error.out create mode 100644 node_modules/ejs/test/fixtures/fail.ejs create mode 100644 node_modules/ejs/test/fixtures/include.css.ejs create mode 100644 node_modules/ejs/test/fixtures/include.css.html create mode 100644 node_modules/ejs/test/fixtures/include.ejs create mode 100644 node_modules/ejs/test/fixtures/include.html create mode 100644 node_modules/ejs/test/fixtures/includes/menu-item.ejs create mode 100644 node_modules/ejs/test/fixtures/includes/menu/item.ejs create mode 100644 node_modules/ejs/test/fixtures/menu.ejs create mode 100644 node_modules/ejs/test/fixtures/menu.html create mode 100644 node_modules/ejs/test/fixtures/messed.ejs create mode 100644 node_modules/ejs/test/fixtures/messed.html create mode 100644 node_modules/ejs/test/fixtures/newlines.ejs create mode 100644 node_modules/ejs/test/fixtures/newlines.html create mode 100644 node_modules/ejs/test/fixtures/no.newlines.ejs create mode 100644 node_modules/ejs/test/fixtures/no.newlines.html create mode 100644 node_modules/ejs/test/fixtures/para.ejs create mode 100644 node_modules/ejs/test/fixtures/pet.ejs create mode 100644 node_modules/ejs/test/fixtures/single-quote.ejs create mode 100644 node_modules/ejs/test/fixtures/single-quote.html create mode 100644 node_modules/ejs/test/fixtures/style.css create mode 100644 node_modules/ejs/test/fixtures/user.ejs create mode 100644 node_modules/express/.npmignore create mode 100644 node_modules/express/.travis.yml create mode 100644 node_modules/express/History.md create mode 100644 node_modules/express/LICENSE create mode 100644 node_modules/express/Makefile create mode 100644 node_modules/express/Readme.md create mode 100644 node_modules/express/bin/express create mode 100644 node_modules/express/index.js create mode 100644 node_modules/express/lib/application.js create mode 100644 node_modules/express/lib/express.js create mode 100644 node_modules/express/lib/middleware.js create mode 100644 node_modules/express/lib/request.js create mode 100644 node_modules/express/lib/response.js create mode 100644 node_modules/express/lib/router/index.js create mode 100644 node_modules/express/lib/router/route.js create mode 100644 node_modules/express/lib/utils.js create mode 100644 node_modules/express/lib/view.js create mode 100644 node_modules/express/node_modules/buffer-crc32/.npmignore create mode 100644 node_modules/express/node_modules/buffer-crc32/.travis.yml create mode 100644 node_modules/express/node_modules/buffer-crc32/README.md create mode 100644 node_modules/express/node_modules/buffer-crc32/index.js create mode 100644 node_modules/express/node_modules/buffer-crc32/package.json create mode 100644 node_modules/express/node_modules/buffer-crc32/tests/crc.test.js create mode 100644 node_modules/express/node_modules/commander/History.md create mode 100644 node_modules/express/node_modules/commander/Readme.md create mode 100644 node_modules/express/node_modules/commander/index.js create mode 100644 node_modules/express/node_modules/commander/node_modules/keypress/README.md create mode 100644 node_modules/express/node_modules/commander/node_modules/keypress/index.js create mode 100644 node_modules/express/node_modules/commander/node_modules/keypress/package.json create mode 100644 node_modules/express/node_modules/commander/node_modules/keypress/test.js create mode 100644 node_modules/express/node_modules/commander/package.json create mode 100644 node_modules/express/node_modules/connect/.npmignore create mode 100644 node_modules/express/node_modules/connect/.travis.yml create mode 100644 node_modules/express/node_modules/connect/LICENSE create mode 100644 node_modules/express/node_modules/connect/Readme.md create mode 100644 node_modules/express/node_modules/connect/index.js create mode 100644 node_modules/express/node_modules/connect/lib/cache.js create mode 100644 node_modules/express/node_modules/connect/lib/connect.js create mode 100644 node_modules/express/node_modules/connect/lib/index.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/basicAuth.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/bodyParser.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/compress.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/cookieParser.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/cookieSession.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/csrf.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/directory.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/errorHandler.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/favicon.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/json.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/limit.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/logger.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/methodOverride.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/multipart.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/query.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/responseTime.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/session.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/session/cookie.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/session/memory.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/session/session.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/session/store.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/static.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/staticCache.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/timeout.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/urlencoded.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/vhost.js create mode 100644 node_modules/express/node_modules/connect/lib/patch.js create mode 100644 node_modules/express/node_modules/connect/lib/proto.js create mode 100644 node_modules/express/node_modules/connect/lib/public/directory.html create mode 100644 node_modules/express/node_modules/connect/lib/public/error.html create mode 100644 node_modules/express/node_modules/connect/lib/public/favicon.ico create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_add.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_attach.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_code.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_copy.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_delete.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_edit.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_error.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_excel.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_find.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_gear.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_go.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_green.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_key.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_lightning.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_link.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_paintbrush.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_paste.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_red.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_refresh.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_save.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_acrobat.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_actionscript.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_add.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_c.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_camera.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_cd.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_code.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_code_red.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_coldfusion.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_compressed.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_copy.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_cplusplus.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_csharp.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_cup.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_database.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_delete.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_dvd.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_edit.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_error.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_excel.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_find.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_flash.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_freehand.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_gear.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_get.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_go.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_h.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_horizontal.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_key.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_lightning.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_link.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_magnify.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_medal.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_office.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_paint.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_paintbrush.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_paste.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_php.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_picture.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_powerpoint.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_put.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_ruby.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_stack.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_star.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_swoosh.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_text.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_text_width.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_tux.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_vector.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_visualstudio.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_width.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_word.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_world.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_wrench.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_zip.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_word.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_world.png create mode 100644 node_modules/express/node_modules/connect/lib/public/style.css create mode 100644 node_modules/express/node_modules/connect/lib/utils.js create mode 100644 node_modules/express/node_modules/connect/node_modules/bytes/.npmignore create mode 100644 node_modules/express/node_modules/connect/node_modules/bytes/History.md create mode 100644 node_modules/express/node_modules/connect/node_modules/bytes/Makefile create mode 100644 node_modules/express/node_modules/connect/node_modules/bytes/Readme.md create mode 100644 node_modules/express/node_modules/connect/node_modules/bytes/component.json create mode 100644 node_modules/express/node_modules/connect/node_modules/bytes/index.js create mode 100644 node_modules/express/node_modules/connect/node_modules/bytes/package.json create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/.npmignore create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/LICENSE create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/Readme.md create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/example/json.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/example/post.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/index.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/lib/json_parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/lib/octet_parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/package.json create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/common.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/beta-sticker-1.png create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/binaryfile.tar.gz create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/blank.gif create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/menu_separator.png create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/encoding.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/misc.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/preamble.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/workarounds.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-json.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-octet-stream.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/run.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-connection-aborted.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-content-transfer-encoding.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-issue-46.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/tools/base64.html create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-file.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js create mode 100644 node_modules/express/node_modules/connect/node_modules/pause/.npmignore create mode 100644 node_modules/express/node_modules/connect/node_modules/pause/History.md create mode 100644 node_modules/express/node_modules/connect/node_modules/pause/Makefile create mode 100644 node_modules/express/node_modules/connect/node_modules/pause/Readme.md create mode 100644 node_modules/express/node_modules/connect/node_modules/pause/index.js create mode 100644 node_modules/express/node_modules/connect/node_modules/pause/package.json create mode 100644 node_modules/express/node_modules/connect/node_modules/qs/.gitmodules create mode 100644 node_modules/express/node_modules/connect/node_modules/qs/.npmignore create mode 100644 node_modules/express/node_modules/connect/node_modules/qs/Readme.md create mode 100644 node_modules/express/node_modules/connect/node_modules/qs/index.js create mode 100644 node_modules/express/node_modules/connect/node_modules/qs/package.json create mode 100644 node_modules/express/node_modules/connect/node_modules/uid2/index.js create mode 100644 node_modules/express/node_modules/connect/node_modules/uid2/package.json create mode 100644 node_modules/express/node_modules/connect/package.json create mode 100644 node_modules/express/node_modules/connect/test.js create mode 100644 node_modules/express/node_modules/cookie-signature/.npmignore create mode 100644 node_modules/express/node_modules/cookie-signature/History.md create mode 100644 node_modules/express/node_modules/cookie-signature/Makefile create mode 100644 node_modules/express/node_modules/cookie-signature/Readme.md create mode 100644 node_modules/express/node_modules/cookie-signature/index.js create mode 100644 node_modules/express/node_modules/cookie-signature/package.json create mode 100644 node_modules/express/node_modules/cookie/.npmignore create mode 100644 node_modules/express/node_modules/cookie/.travis.yml create mode 100644 node_modules/express/node_modules/cookie/LICENSE create mode 100644 node_modules/express/node_modules/cookie/README.md create mode 100644 node_modules/express/node_modules/cookie/index.js create mode 100644 node_modules/express/node_modules/cookie/package.json create mode 100644 node_modules/express/node_modules/cookie/test/mocha.opts create mode 100644 node_modules/express/node_modules/cookie/test/parse.js create mode 100644 node_modules/express/node_modules/cookie/test/serialize.js create mode 100644 node_modules/express/node_modules/debug/.npmignore create mode 100644 node_modules/express/node_modules/debug/History.md create mode 100644 node_modules/express/node_modules/debug/Readme.md create mode 100644 node_modules/express/node_modules/debug/component.json create mode 100644 node_modules/express/node_modules/debug/debug.js create mode 100644 node_modules/express/node_modules/debug/example/app.js create mode 100644 node_modules/express/node_modules/debug/example/browser.html create mode 100644 node_modules/express/node_modules/debug/example/wildcards.js create mode 100644 node_modules/express/node_modules/debug/example/worker.js create mode 100644 node_modules/express/node_modules/debug/index.js create mode 100644 node_modules/express/node_modules/debug/lib/debug.js create mode 100644 node_modules/express/node_modules/debug/package.json create mode 100644 node_modules/express/node_modules/fresh/.npmignore create mode 100644 node_modules/express/node_modules/fresh/Makefile create mode 100644 node_modules/express/node_modules/fresh/Readme.md create mode 100644 node_modules/express/node_modules/fresh/index.js create mode 100644 node_modules/express/node_modules/fresh/package.json create mode 100644 node_modules/express/node_modules/methods/index.js create mode 100644 node_modules/express/node_modules/methods/package.json create mode 100644 node_modules/express/node_modules/mkdirp/.npmignore create mode 100644 node_modules/express/node_modules/mkdirp/.travis.yml create mode 100644 node_modules/express/node_modules/mkdirp/LICENSE create mode 100644 node_modules/express/node_modules/mkdirp/examples/pow.js create mode 100644 node_modules/express/node_modules/mkdirp/index.js create mode 100644 node_modules/express/node_modules/mkdirp/package.json create mode 100644 node_modules/express/node_modules/mkdirp/readme.markdown create mode 100644 node_modules/express/node_modules/mkdirp/test/chmod.js create mode 100644 node_modules/express/node_modules/mkdirp/test/clobber.js create mode 100644 node_modules/express/node_modules/mkdirp/test/mkdirp.js create mode 100644 node_modules/express/node_modules/mkdirp/test/perm.js create mode 100644 node_modules/express/node_modules/mkdirp/test/perm_sync.js create mode 100644 node_modules/express/node_modules/mkdirp/test/race.js create mode 100644 node_modules/express/node_modules/mkdirp/test/rel.js create mode 100644 node_modules/express/node_modules/mkdirp/test/return.js create mode 100644 node_modules/express/node_modules/mkdirp/test/return_sync.js create mode 100644 node_modules/express/node_modules/mkdirp/test/root.js create mode 100644 node_modules/express/node_modules/mkdirp/test/sync.js create mode 100644 node_modules/express/node_modules/mkdirp/test/umask.js create mode 100644 node_modules/express/node_modules/mkdirp/test/umask_sync.js create mode 100644 node_modules/express/node_modules/range-parser/.npmignore create mode 100644 node_modules/express/node_modules/range-parser/History.md create mode 100644 node_modules/express/node_modules/range-parser/Makefile create mode 100644 node_modules/express/node_modules/range-parser/Readme.md create mode 100644 node_modules/express/node_modules/range-parser/index.js create mode 100644 node_modules/express/node_modules/range-parser/package.json create mode 100644 node_modules/express/node_modules/send/.npmignore create mode 100644 node_modules/express/node_modules/send/History.md create mode 100644 node_modules/express/node_modules/send/Makefile create mode 100644 node_modules/express/node_modules/send/Readme.md create mode 100644 node_modules/express/node_modules/send/index.js create mode 100644 node_modules/express/node_modules/send/lib/send.js create mode 100644 node_modules/express/node_modules/send/lib/utils.js create mode 100644 node_modules/express/node_modules/send/node_modules/mime/LICENSE create mode 100644 node_modules/express/node_modules/send/node_modules/mime/README.md create mode 100644 node_modules/express/node_modules/send/node_modules/mime/mime.js create mode 100644 node_modules/express/node_modules/send/node_modules/mime/package.json create mode 100644 node_modules/express/node_modules/send/node_modules/mime/test.js create mode 100644 node_modules/express/node_modules/send/node_modules/mime/types/mime.types create mode 100644 node_modules/express/node_modules/send/node_modules/mime/types/node.types create mode 100644 node_modules/express/node_modules/send/package.json create mode 100644 node_modules/express/package.json create mode 100644 node_modules/express/test.js create mode 100644 node_modules/ws/.npmignore create mode 100644 node_modules/ws/.travis.yml create mode 100644 node_modules/ws/History.md create mode 100644 node_modules/ws/Makefile create mode 100644 node_modules/ws/README.md create mode 100644 node_modules/ws/bench/parser.benchmark.js create mode 100644 node_modules/ws/bench/sender.benchmark.js create mode 100644 node_modules/ws/bench/speed.js create mode 100644 node_modules/ws/bench/util.js create mode 100644 node_modules/ws/bin/wscat create mode 100644 node_modules/ws/binding.gyp create mode 100644 node_modules/ws/builderror.log create mode 100644 node_modules/ws/doc/ws.md create mode 100644 node_modules/ws/examples/fileapi/.npmignore create mode 100644 node_modules/ws/examples/fileapi/package.json create mode 100644 node_modules/ws/examples/fileapi/public/app.js create mode 100644 node_modules/ws/examples/fileapi/public/index.html create mode 100644 node_modules/ws/examples/fileapi/public/uploader.js create mode 100644 node_modules/ws/examples/fileapi/server.js create mode 100644 node_modules/ws/examples/serverstats-express_3/package.json create mode 100644 node_modules/ws/examples/serverstats-express_3/public/index.html create mode 100644 node_modules/ws/examples/serverstats-express_3/server.js create mode 100644 node_modules/ws/examples/serverstats/package.json create mode 100644 node_modules/ws/examples/serverstats/public/index.html create mode 100644 node_modules/ws/examples/serverstats/server.js create mode 100644 node_modules/ws/examples/ssl.js create mode 100644 node_modules/ws/index.js create mode 100644 node_modules/ws/lib/BufferPool.js create mode 100644 node_modules/ws/lib/BufferUtil.fallback.js create mode 100644 node_modules/ws/lib/BufferUtil.js create mode 100644 node_modules/ws/lib/ErrorCodes.js create mode 100644 node_modules/ws/lib/Receiver.hixie.js create mode 100644 node_modules/ws/lib/Receiver.js create mode 100644 node_modules/ws/lib/Sender.hixie.js create mode 100644 node_modules/ws/lib/Sender.js create mode 100644 node_modules/ws/lib/Validation.fallback.js create mode 100644 node_modules/ws/lib/Validation.js create mode 100644 node_modules/ws/lib/WebSocket.js create mode 100644 node_modules/ws/lib/WebSocketServer.js create mode 100644 node_modules/ws/lib/browser.js create mode 100644 node_modules/ws/node_modules/commander/.npmignore create mode 100644 node_modules/ws/node_modules/commander/.travis.yml create mode 100644 node_modules/ws/node_modules/commander/History.md create mode 100644 node_modules/ws/node_modules/commander/Makefile create mode 100644 node_modules/ws/node_modules/commander/Readme.md create mode 100644 node_modules/ws/node_modules/commander/index.js create mode 100644 node_modules/ws/node_modules/commander/lib/commander.js create mode 100644 node_modules/ws/node_modules/commander/package.json create mode 100644 node_modules/ws/node_modules/options/.npmignore create mode 100644 node_modules/ws/node_modules/options/Makefile create mode 100644 node_modules/ws/node_modules/options/README.md create mode 100644 node_modules/ws/node_modules/options/lib/options.js create mode 100644 node_modules/ws/node_modules/options/package.json create mode 100644 node_modules/ws/node_modules/options/test/fixtures/test.conf create mode 100644 node_modules/ws/node_modules/options/test/options.test.js create mode 100644 node_modules/ws/node_modules/tinycolor/.npmignore create mode 100644 node_modules/ws/node_modules/tinycolor/README.md create mode 100644 node_modules/ws/node_modules/tinycolor/example.js create mode 100644 node_modules/ws/node_modules/tinycolor/package.json create mode 100644 node_modules/ws/node_modules/tinycolor/tinycolor.js create mode 100644 node_modules/ws/package.json create mode 100644 node_modules/ws/src/bufferutil.cc create mode 100644 node_modules/ws/src/validation.cc create mode 100644 node_modules/ws/test/BufferPool.test.js create mode 100644 node_modules/ws/test/Receiver.hixie.test.js create mode 100644 node_modules/ws/test/Receiver.test.js create mode 100644 node_modules/ws/test/Sender.hixie.test.js create mode 100644 node_modules/ws/test/Sender.test.js create mode 100644 node_modules/ws/test/Validation.test.js create mode 100644 node_modules/ws/test/WebSocket.integration.js create mode 100644 node_modules/ws/test/WebSocket.test.js create mode 100644 node_modules/ws/test/WebSocketServer.test.js create mode 100644 node_modules/ws/test/autobahn-server.js create mode 100644 node_modules/ws/test/autobahn.js create mode 100644 node_modules/ws/test/fixtures/agent1-cert.pem create mode 100644 node_modules/ws/test/fixtures/agent1-key.pem create mode 100644 node_modules/ws/test/fixtures/ca1-cert.pem create mode 100644 node_modules/ws/test/fixtures/ca1-key.pem create mode 100644 node_modules/ws/test/fixtures/certificate.pem create mode 100644 node_modules/ws/test/fixtures/key.pem create mode 100644 node_modules/ws/test/fixtures/request.pem create mode 100644 node_modules/ws/test/fixtures/textfile create mode 100644 node_modules/ws/test/hybi-common.js create mode 100644 node_modules/ws/test/testserver.js create mode 100644 npm-debug.log create mode 100644 package.json create mode 100644 public/css/styles.css create mode 100644 public/images/capture.png create mode 100644 public/images/login_bg.jpg create mode 100644 public/images/loginbt.png create mode 100644 public/images/offline.png create mode 100644 public/images/online.png create mode 100644 public/images/user.png create mode 100644 public/javascripts/client.js create mode 100644 public/javascripts/easyloader.js create mode 100644 public/javascripts/file-utils.js create mode 100644 public/javascripts/jquery.easyui.min.js create mode 100644 public/javascripts/jquery.min.js create mode 100644 public/javascripts/rtc-io.js create mode 100644 public/javascripts/themes/black/accordion.css create mode 100644 public/javascripts/themes/black/calendar.css create mode 100644 public/javascripts/themes/black/combo.css create mode 100644 public/javascripts/themes/black/combobox.css create mode 100644 public/javascripts/themes/black/datagrid.css create mode 100644 public/javascripts/themes/black/datebox.css create mode 100644 public/javascripts/themes/black/dialog.css create mode 100644 public/javascripts/themes/black/easyui.css create mode 100644 public/javascripts/themes/black/images/Thumbs.db create mode 100644 public/javascripts/themes/black/images/accordion_arrows.png create mode 100644 public/javascripts/themes/black/images/blank.gif create mode 100644 public/javascripts/themes/black/images/calendar_arrows.png create mode 100644 public/javascripts/themes/black/images/combo_arrow.png create mode 100644 public/javascripts/themes/black/images/datagrid_icons.png create mode 100644 public/javascripts/themes/black/images/datebox_arrow.png create mode 100644 public/javascripts/themes/black/images/layout_arrows.png create mode 100644 public/javascripts/themes/black/images/linkbutton_bg.png create mode 100644 public/javascripts/themes/black/images/loading.gif create mode 100644 public/javascripts/themes/black/images/menu_arrows.png create mode 100644 public/javascripts/themes/black/images/messager_icons.png create mode 100644 public/javascripts/themes/black/images/pagination_icons.png create mode 100644 public/javascripts/themes/black/images/panel_tools.png create mode 100644 public/javascripts/themes/black/images/searchbox_button.png create mode 100644 public/javascripts/themes/black/images/slider_handle.png create mode 100644 public/javascripts/themes/black/images/spinner_arrows.png create mode 100644 public/javascripts/themes/black/images/tabs_icons.png create mode 100644 public/javascripts/themes/black/images/tree_icons.png create mode 100644 public/javascripts/themes/black/images/validatebox_warning.png create mode 100644 public/javascripts/themes/black/layout.css create mode 100644 public/javascripts/themes/black/linkbutton.css create mode 100644 public/javascripts/themes/black/menu.css create mode 100644 public/javascripts/themes/black/menubutton.css create mode 100644 public/javascripts/themes/black/messager.css create mode 100644 public/javascripts/themes/black/pagination.css create mode 100644 public/javascripts/themes/black/panel.css create mode 100644 public/javascripts/themes/black/progressbar.css create mode 100644 public/javascripts/themes/black/propertygrid.css create mode 100644 public/javascripts/themes/black/searchbox.css create mode 100644 public/javascripts/themes/black/slider.css create mode 100644 public/javascripts/themes/black/spinner.css create mode 100644 public/javascripts/themes/black/splitbutton.css create mode 100644 public/javascripts/themes/black/tabs.css create mode 100644 public/javascripts/themes/black/tooltip.css create mode 100644 public/javascripts/themes/black/tree.css create mode 100644 public/javascripts/themes/black/validatebox.css create mode 100644 public/javascripts/themes/black/window.css create mode 100644 public/javascripts/themes/bootstrap/accordion.css create mode 100644 public/javascripts/themes/bootstrap/calendar.css create mode 100644 public/javascripts/themes/bootstrap/combo.css create mode 100644 public/javascripts/themes/bootstrap/combobox.css create mode 100644 public/javascripts/themes/bootstrap/datagrid.css create mode 100644 public/javascripts/themes/bootstrap/datebox.css create mode 100644 public/javascripts/themes/bootstrap/dialog.css create mode 100644 public/javascripts/themes/bootstrap/easyui.css create mode 100644 public/javascripts/themes/bootstrap/images/Thumbs.db create mode 100644 public/javascripts/themes/bootstrap/images/accordion_arrows.png create mode 100644 public/javascripts/themes/bootstrap/images/blank.gif create mode 100644 public/javascripts/themes/bootstrap/images/calendar_arrows.png create mode 100644 public/javascripts/themes/bootstrap/images/combo_arrow.png create mode 100644 public/javascripts/themes/bootstrap/images/datagrid_icons.png create mode 100644 public/javascripts/themes/bootstrap/images/datebox_arrow.png create mode 100644 public/javascripts/themes/bootstrap/images/layout_arrows.png create mode 100644 public/javascripts/themes/bootstrap/images/linkbutton_bg.png create mode 100644 public/javascripts/themes/bootstrap/images/loading.gif create mode 100644 public/javascripts/themes/bootstrap/images/menu_arrows.png create mode 100644 public/javascripts/themes/bootstrap/images/messager_icons.png create mode 100644 public/javascripts/themes/bootstrap/images/pagination_icons.png create mode 100644 public/javascripts/themes/bootstrap/images/panel_tools.png create mode 100644 public/javascripts/themes/bootstrap/images/searchbox_button.png create mode 100644 public/javascripts/themes/bootstrap/images/slider_handle.png create mode 100644 public/javascripts/themes/bootstrap/images/spinner_arrows.png create mode 100644 public/javascripts/themes/bootstrap/images/tabs_icons.png create mode 100644 public/javascripts/themes/bootstrap/images/tree_icons.png create mode 100644 public/javascripts/themes/bootstrap/images/validatebox_warning.png create mode 100644 public/javascripts/themes/bootstrap/layout.css create mode 100644 public/javascripts/themes/bootstrap/linkbutton.css create mode 100644 public/javascripts/themes/bootstrap/menu.css create mode 100644 public/javascripts/themes/bootstrap/menubutton.css create mode 100644 public/javascripts/themes/bootstrap/messager.css create mode 100644 public/javascripts/themes/bootstrap/pagination.css create mode 100644 public/javascripts/themes/bootstrap/panel.css create mode 100644 public/javascripts/themes/bootstrap/progressbar.css create mode 100644 public/javascripts/themes/bootstrap/propertygrid.css create mode 100644 public/javascripts/themes/bootstrap/searchbox.css create mode 100644 public/javascripts/themes/bootstrap/slider.css create mode 100644 public/javascripts/themes/bootstrap/spinner.css create mode 100644 public/javascripts/themes/bootstrap/splitbutton.css create mode 100644 public/javascripts/themes/bootstrap/tabs.css create mode 100644 public/javascripts/themes/bootstrap/tooltip.css create mode 100644 public/javascripts/themes/bootstrap/tree.css create mode 100644 public/javascripts/themes/bootstrap/validatebox.css create mode 100644 public/javascripts/themes/bootstrap/window.css create mode 100644 public/javascripts/themes/default/accordion.css create mode 100644 public/javascripts/themes/default/calendar.css create mode 100644 public/javascripts/themes/default/combo.css create mode 100644 public/javascripts/themes/default/combobox.css create mode 100644 public/javascripts/themes/default/datagrid.css create mode 100644 public/javascripts/themes/default/datebox.css create mode 100644 public/javascripts/themes/default/dialog.css create mode 100644 public/javascripts/themes/default/easyui.css create mode 100644 public/javascripts/themes/default/images/Thumbs.db create mode 100644 public/javascripts/themes/default/images/accordion_arrows.png create mode 100644 public/javascripts/themes/default/images/blank.gif create mode 100644 public/javascripts/themes/default/images/calendar_arrows.png create mode 100644 public/javascripts/themes/default/images/combo_arrow.png create mode 100644 public/javascripts/themes/default/images/datagrid_icons.png create mode 100644 public/javascripts/themes/default/images/datebox_arrow.png create mode 100644 public/javascripts/themes/default/images/layout_arrows.png create mode 100644 public/javascripts/themes/default/images/linkbutton_bg.png create mode 100644 public/javascripts/themes/default/images/loading.gif create mode 100644 public/javascripts/themes/default/images/menu_arrows.png create mode 100644 public/javascripts/themes/default/images/messager_icons.png create mode 100644 public/javascripts/themes/default/images/pagination_icons.png create mode 100644 public/javascripts/themes/default/images/panel_tools.png create mode 100644 public/javascripts/themes/default/images/searchbox_button.png create mode 100644 public/javascripts/themes/default/images/slider_handle.png create mode 100644 public/javascripts/themes/default/images/spinner_arrows.png create mode 100644 public/javascripts/themes/default/images/tabs_icons.png create mode 100644 public/javascripts/themes/default/images/tree_icons.png create mode 100644 public/javascripts/themes/default/images/validatebox_warning.png create mode 100644 public/javascripts/themes/default/layout.css create mode 100644 public/javascripts/themes/default/linkbutton.css create mode 100644 public/javascripts/themes/default/menu.css create mode 100644 public/javascripts/themes/default/menubutton.css create mode 100644 public/javascripts/themes/default/messager.css create mode 100644 public/javascripts/themes/default/pagination.css create mode 100644 public/javascripts/themes/default/panel.css create mode 100644 public/javascripts/themes/default/progressbar.css create mode 100644 public/javascripts/themes/default/propertygrid.css create mode 100644 public/javascripts/themes/default/searchbox.css create mode 100644 public/javascripts/themes/default/slider.css create mode 100644 public/javascripts/themes/default/spinner.css create mode 100644 public/javascripts/themes/default/splitbutton.css create mode 100644 public/javascripts/themes/default/tabs.css create mode 100644 public/javascripts/themes/default/tooltip.css create mode 100644 public/javascripts/themes/default/tree.css create mode 100644 public/javascripts/themes/default/validatebox.css create mode 100644 public/javascripts/themes/default/window.css create mode 100644 public/javascripts/themes/gray/accordion.css create mode 100644 public/javascripts/themes/gray/calendar.css create mode 100644 public/javascripts/themes/gray/combo.css create mode 100644 public/javascripts/themes/gray/combobox.css create mode 100644 public/javascripts/themes/gray/datagrid.css create mode 100644 public/javascripts/themes/gray/datebox.css create mode 100644 public/javascripts/themes/gray/dialog.css create mode 100644 public/javascripts/themes/gray/easyui.css create mode 100644 public/javascripts/themes/gray/images/Thumbs.db create mode 100644 public/javascripts/themes/gray/images/accordion_arrows.png create mode 100644 public/javascripts/themes/gray/images/blank.gif create mode 100644 public/javascripts/themes/gray/images/calendar_arrows.png create mode 100644 public/javascripts/themes/gray/images/combo_arrow.png create mode 100644 public/javascripts/themes/gray/images/datagrid_icons.png create mode 100644 public/javascripts/themes/gray/images/datebox_arrow.png create mode 100644 public/javascripts/themes/gray/images/layout_arrows.png create mode 100644 public/javascripts/themes/gray/images/linkbutton_bg.png create mode 100644 public/javascripts/themes/gray/images/loading.gif create mode 100644 public/javascripts/themes/gray/images/menu_arrows.png create mode 100644 public/javascripts/themes/gray/images/messager_icons.png create mode 100644 public/javascripts/themes/gray/images/pagination_icons.png create mode 100644 public/javascripts/themes/gray/images/panel_tools.png create mode 100644 public/javascripts/themes/gray/images/searchbox_button.png create mode 100644 public/javascripts/themes/gray/images/slider_handle.png create mode 100644 public/javascripts/themes/gray/images/spinner_arrows.png create mode 100644 public/javascripts/themes/gray/images/tabs_icons.png create mode 100644 public/javascripts/themes/gray/images/tree_icons.png create mode 100644 public/javascripts/themes/gray/images/validatebox_warning.png create mode 100644 public/javascripts/themes/gray/layout.css create mode 100644 public/javascripts/themes/gray/linkbutton.css create mode 100644 public/javascripts/themes/gray/menu.css create mode 100644 public/javascripts/themes/gray/menubutton.css create mode 100644 public/javascripts/themes/gray/messager.css create mode 100644 public/javascripts/themes/gray/pagination.css create mode 100644 public/javascripts/themes/gray/panel.css create mode 100644 public/javascripts/themes/gray/progressbar.css create mode 100644 public/javascripts/themes/gray/propertygrid.css create mode 100644 public/javascripts/themes/gray/searchbox.css create mode 100644 public/javascripts/themes/gray/slider.css create mode 100644 public/javascripts/themes/gray/spinner.css create mode 100644 public/javascripts/themes/gray/splitbutton.css create mode 100644 public/javascripts/themes/gray/tabs.css create mode 100644 public/javascripts/themes/gray/tooltip.css create mode 100644 public/javascripts/themes/gray/tree.css create mode 100644 public/javascripts/themes/gray/validatebox.css create mode 100644 public/javascripts/themes/gray/window.css create mode 100644 public/javascripts/themes/icon.css create mode 100644 public/javascripts/themes/icons/back.png create mode 100644 public/javascripts/themes/icons/blank.gif create mode 100644 public/javascripts/themes/icons/cancel.png create mode 100644 public/javascripts/themes/icons/cut.png create mode 100644 public/javascripts/themes/icons/edit_add.png create mode 100644 public/javascripts/themes/icons/edit_remove.png create mode 100644 public/javascripts/themes/icons/filesave.png create mode 100644 public/javascripts/themes/icons/help.png create mode 100644 public/javascripts/themes/icons/mini_add.png create mode 100644 public/javascripts/themes/icons/mini_edit.png create mode 100644 public/javascripts/themes/icons/mini_refresh.png create mode 100644 public/javascripts/themes/icons/no.png create mode 100644 public/javascripts/themes/icons/ok.png create mode 100644 public/javascripts/themes/icons/pencil.png create mode 100644 public/javascripts/themes/icons/print.png create mode 100644 public/javascripts/themes/icons/redo.png create mode 100644 public/javascripts/themes/icons/reload.png create mode 100644 public/javascripts/themes/icons/search.png create mode 100644 public/javascripts/themes/icons/sum.png create mode 100644 public/javascripts/themes/icons/tip.png create mode 100644 public/javascripts/themes/icons/undo.png create mode 100644 public/javascripts/themes/metro/accordion.css create mode 100644 public/javascripts/themes/metro/calendar.css create mode 100644 public/javascripts/themes/metro/combo.css create mode 100644 public/javascripts/themes/metro/combobox.css create mode 100644 public/javascripts/themes/metro/datagrid.css create mode 100644 public/javascripts/themes/metro/datebox.css create mode 100644 public/javascripts/themes/metro/dialog.css create mode 100644 public/javascripts/themes/metro/easyui.css create mode 100644 public/javascripts/themes/metro/images/Thumbs.db create mode 100644 public/javascripts/themes/metro/images/accordion_arrows.png create mode 100644 public/javascripts/themes/metro/images/blank.gif create mode 100644 public/javascripts/themes/metro/images/calendar_arrows.png create mode 100644 public/javascripts/themes/metro/images/combo_arrow.png create mode 100644 public/javascripts/themes/metro/images/datagrid_icons.png create mode 100644 public/javascripts/themes/metro/images/datebox_arrow.png create mode 100644 public/javascripts/themes/metro/images/layout_arrows.png create mode 100644 public/javascripts/themes/metro/images/linkbutton_bg.png create mode 100644 public/javascripts/themes/metro/images/loading.gif create mode 100644 public/javascripts/themes/metro/images/menu_arrows.png create mode 100644 public/javascripts/themes/metro/images/messager_icons.png create mode 100644 public/javascripts/themes/metro/images/pagination_icons.png create mode 100644 public/javascripts/themes/metro/images/panel_tools.png create mode 100644 public/javascripts/themes/metro/images/searchbox_button.png create mode 100644 public/javascripts/themes/metro/images/slider_handle.png create mode 100644 public/javascripts/themes/metro/images/spinner_arrows.png create mode 100644 public/javascripts/themes/metro/images/tabs_icons.png create mode 100644 public/javascripts/themes/metro/images/tree_icons.png create mode 100644 public/javascripts/themes/metro/images/validatebox_warning.png create mode 100644 public/javascripts/themes/metro/layout.css create mode 100644 public/javascripts/themes/metro/linkbutton.css create mode 100644 public/javascripts/themes/metro/menu.css create mode 100644 public/javascripts/themes/metro/menubutton.css create mode 100644 public/javascripts/themes/metro/messager.css create mode 100644 public/javascripts/themes/metro/pagination.css create mode 100644 public/javascripts/themes/metro/panel.css create mode 100644 public/javascripts/themes/metro/progressbar.css create mode 100644 public/javascripts/themes/metro/propertygrid.css create mode 100644 public/javascripts/themes/metro/searchbox.css create mode 100644 public/javascripts/themes/metro/slider.css create mode 100644 public/javascripts/themes/metro/spinner.css create mode 100644 public/javascripts/themes/metro/splitbutton.css create mode 100644 public/javascripts/themes/metro/tabs.css create mode 100644 public/javascripts/themes/metro/tooltip.css create mode 100644 public/javascripts/themes/metro/tree.css create mode 100644 public/javascripts/themes/metro/validatebox.css create mode 100644 public/javascripts/themes/metro/window.css create mode 100644 routes/index.js create mode 100644 routes/main.js create mode 100644 uploads/pepper.png create mode 100644 views/index.html create mode 100644 views/main.html diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1ee84da --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.sw* diff --git a/How to runs.txt b/How to runs.txt new file mode 100644 index 0000000..5d73f16 --- /dev/null +++ b/How to runs.txt @@ -0,0 +1,21 @@ +This project is made with NodeJs. That's why it needs the environment to run this project. +1) Donwload NodeJs installer from http://nodejs.org and Install it. +2) Extract the source file and run the command prompt + (For LinuxOS, terminal app.) +3) Run the following command in the source directory + -> node app + +The server port is 9000. + +Open the browser and type the url: http://localhost:9000 + +About the chat app. +1) Type the username and roomname. +2) Click Enter button. + (The user can enter the chat by clicking enter key in the roomname field.) + +Used Javascripts: + jQuery, jQueryEasyUI. + + + diff --git a/app.js b/app.js new file mode 100644 index 0000000..e5da84e --- /dev/null +++ b/app.js @@ -0,0 +1,31 @@ +var express = require('express'); +var app = express(); +var server = require('http').createServer(app); +var webRTC = require('./modules/webrtc.io').listen(server); +var env = require('./config.js').server_config; +var index = require('./routes/index'); +var chat_main = require('./routes/main'); + +server.listen(env.server_port); +console.log('Starting chat server on port ' + env.server_port); + +// ***** App Configuration +app.configure(function () { + app.set('views', __dirname + '/views'); + app.engine('.html', require('ejs').renderFile); + app.set('view engine', 'html'); + app.set('view options',{ layout:false}); + app.use( + express.static(__dirname + '/public') + ); + app.use(express.bodyParser()); + app.use(app.router); + app.use(express.methodOverride()); +}); + +// ***** App Routes +app.get('/', index.index); +app.get('/enter', chat_main.index); +app.post('/', index.login); +app.post('/enter', chat_main.index); +app.post('/upload', chat_main.upload); \ No newline at end of file diff --git a/config.js b/config.js new file mode 100644 index 0000000..9e0c76d --- /dev/null +++ b/config.js @@ -0,0 +1,4 @@ +exports.server_config = { + server_port:9000, + server_address:'localhost', +}; \ No newline at end of file diff --git a/modules/webrtc.io/index.js b/modules/webrtc.io/index.js new file mode 100644 index 0000000..8bdf9dc --- /dev/null +++ b/modules/webrtc.io/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/webrtc.io'); diff --git a/modules/webrtc.io/lib/webrtc.io.js b/modules/webrtc.io/lib/webrtc.io.js new file mode 100644 index 0000000..ada9d5c --- /dev/null +++ b/modules/webrtc.io/lib/webrtc.io.js @@ -0,0 +1,286 @@ +//SERVER +var WebSocketServer = require('ws').Server + +var iolog = function() {}; + +for (var i = 0; i < process.argv.length; i++) { + var arg = process.argv[i]; + if (arg === "-debug") { + iolog = function(msg) { + console.log(msg); + }; + console.log('Debug mode on!'); + } +} + + +// Used for callback publish and subscribe +if (typeof rtc === "undefined") { + var rtc = {}; +} +//Array to store connections +rtc.sockets = []; + +rtc.rooms = {}; +rtc.users = {}; +rtc.encryption = {}; +rtc.browser = {}; +rtc.browserVer = {}; + +// Holds callbacks for certain events. +rtc._events = {}; + +rtc.on = function(eventName, callback) { + rtc._events[eventName] = rtc._events[eventName] || []; + rtc._events[eventName].push(callback); +}; + +rtc.fire = function(eventName, _) { + var events = rtc._events[eventName]; + var args = Array.prototype.slice.call(arguments, 1); + + if (!events) { + return; + } + + for (var i = 0, len = events.length; i < len; i++) { + events[i].apply(null, args); + } +}; + +module.exports.listen = function(server) { + var manager; + if (typeof server === 'number') { + manager = new WebSocketServer({ + port: server + }); + } else { + manager = new WebSocketServer({ + server: server + }); + } + + manager.rtc = rtc; + attachEvents(manager); + return manager; +}; + +function attachEvents(manager) { + + manager.on('connection', function(socket) { + iolog('connect'); + + socket.id = id(); + iolog('new socket got id: ' + socket.id); + + rtc.sockets.push(socket); + + socket.on('message', function(msg) { + var json = JSON.parse(msg); + rtc.fire(json.eventName, json.data, socket); + }); + + socket.on('close', function() { + iolog('close'); + + // find socket to remove + var i = rtc.sockets.indexOf(socket); + // remove socket + rtc.sockets.splice(i, 1); + + // remove from rooms and send remove_peer_connected to all sockets in room + for (var key in rtc.rooms) { + + var room = rtc.rooms[key]; + var exist = room.indexOf(socket.id); + + if (exist !== -1) { + room.splice(room.indexOf(socket.id), 1); + for (var j = 0; j < room.length; j++) { + console.log(room[j]); + var soc = rtc.getSocket(room[j]); + soc.send(JSON.stringify({ + "eventName": "remove_peer_connected", + "data": { + "socketId": socket.id + } + }), function(error) { + if (error) { + console.log(error); + } + }); + } + + //also remove from username list + var userList = rtc.users[key]; + delete userList[socket.id]; + + break; + } + } + // we are leaved the room so lets notify about that + rtc.fire('room_leave', room, socket.id); + + // call the disconnect callback + rtc.fire('disconnect', rtc); + + }); + + + // call the connect callback + rtc.fire('connect', rtc); + + }); + + // manages the built-in room functionality + rtc.on('join_room', function(data, socket) { + iolog('join_room'); + + if (data.room == 0){ + return; + } + + var connectionsId = []; + var usersId = []; + var roomList = rtc.rooms[data.room] || []; + var userList = rtc.users[data.room] || {}; + + roomList.push(socket.id); + rtc.rooms[data.room] = roomList; + + userList[socket.id] = data.username; + rtc.users[data.room] = userList; + + for (var i = 0; i < roomList.length; i++) { + var id = roomList[i]; + + if (id == socket.id) { + continue; + } else { + + connectionsId.push(id); + var soc = rtc.getSocket(id); + + // inform the peers that they have a new peer + if (soc) { + soc.send(JSON.stringify({ + "eventName": "new_peer_connected", + "data":{ + "socketId": socket.id, + "username": data.username + } + }), function(error) { + if (error) { + console.log(error); + } + }); + } + } + } + // send new peer a list of all prior peers + socket.send(JSON.stringify({ + "eventName": "get_peers", + "data": { + "connections": connectionsId, + "usernames": userList, + "you": socket.id + } + }), function(error) { + if (error) { + console.log(error); + } + }); + }); + + //Receive ICE candidates and send to the correct socket + rtc.on('send_ice_candidate', function(data, socket) { + iolog('send_ice_candidate'); + var soc = rtc.getSocket(data.socketId); + + if (soc) { + soc.send(JSON.stringify({ + "eventName": "receive_ice_candidate", + "data": { + "label": data.label, + "candidate": data.candidate, + "socketId": socket.id + } + }), function(error) { + if (error) { + console.log(error); + } + }); + + // call the 'recieve ICE candidate' callback + rtc.fire('receive ice candidate', rtc); + } + }); + + //Receive offer and send to correct socket + rtc.on('send_offer', function(data, socket) { + iolog('send_offer'); + var soc = rtc.getSocket(data.socketId); + + if (soc) { + soc.send(JSON.stringify({ + "eventName": "receive_offer", + "data": { + "sdp": data.sdp, + "socketId": socket.id + } + }), function(error) { + if (error) { + console.log(error); + } + }); + } + // call the 'send offer' callback + rtc.fire('send offer', rtc); + }); + + //Receive answer and send to correct socket + rtc.on('send_answer', function(data, socket) { + iolog('send_answer'); + var soc = rtc.getSocket( data.socketId); + + if (soc) { + soc.send(JSON.stringify({ + "eventName": "receive_answer", + "data" : { + "sdp": data.sdp, + "socketId": socket.id + } + }), function(error) { + if (error) { + console.log(error); + } + }); + rtc.fire('send answer', rtc); + } + }); +} + +// generate a 4 digit hex code randomly +function S4() { + return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); +} + +// make a REALLY COMPLICATED AND RANDOM id, kudos to dennis +function id() { + return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()); +} + +rtc.getSocket = function(id) { + var connections = rtc.sockets; + if (!connections) { + // TODO: Or error, or customize + return; + } + + for (var i = 0; i < connections.length; i++) { + var socket = connections[i]; + if (id === socket.id) { + return socket; + } + } +}; diff --git a/node_modules/.bin/express b/node_modules/.bin/express new file mode 100644 index 0000000..cad5a1e --- /dev/null +++ b/node_modules/.bin/express @@ -0,0 +1,15 @@ +#!/bin/sh +basedir=`dirname "$0"` + +case `uname` in + *CYGWIN*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + "$basedir/node" "$basedir/../express/bin/express" "$@" + ret=$? +else + node "$basedir/../express/bin/express" "$@" + ret=$? +fi +exit $ret diff --git a/node_modules/.bin/express.cmd b/node_modules/.bin/express.cmd new file mode 100644 index 0000000..a17fbb0 --- /dev/null +++ b/node_modules/.bin/express.cmd @@ -0,0 +1,5 @@ +@IF EXIST "%~dp0\node.exe" ( + "%~dp0\node.exe" "%~dp0\..\express\bin\express" %* +) ELSE ( + node "%~dp0\..\express\bin\express" %* +) \ No newline at end of file diff --git a/node_modules/.bin/wscat b/node_modules/.bin/wscat new file mode 100644 index 0000000..1a710cf --- /dev/null +++ b/node_modules/.bin/wscat @@ -0,0 +1,15 @@ +#!/bin/sh +basedir=`dirname "$0"` + +case `uname` in + *CYGWIN*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + "$basedir/node" "$basedir/../ws/bin/wscat" "$@" + ret=$? +else + node "$basedir/../ws/bin/wscat" "$@" + ret=$? +fi +exit $ret diff --git a/node_modules/.bin/wscat.cmd b/node_modules/.bin/wscat.cmd new file mode 100644 index 0000000..aa44584 --- /dev/null +++ b/node_modules/.bin/wscat.cmd @@ -0,0 +1,5 @@ +@IF EXIST "%~dp0\node.exe" ( + "%~dp0\node.exe" "%~dp0\..\ws\bin\wscat" %* +) ELSE ( + node "%~dp0\..\ws\bin\wscat" %* +) \ No newline at end of file diff --git a/node_modules/ejs/.gitmodules b/node_modules/ejs/.gitmodules new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/ejs/.npmignore b/node_modules/ejs/.npmignore new file mode 100644 index 0000000..020ddac --- /dev/null +++ b/node_modules/ejs/.npmignore @@ -0,0 +1,4 @@ +# ignore any vim files: +*.sw[a-z] +vim/.netrwhist +node_modules diff --git a/node_modules/ejs/.travis.yml b/node_modules/ejs/.travis.yml new file mode 100644 index 0000000..1ccd299 --- /dev/null +++ b/node_modules/ejs/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - 0.11 + - 0.10 + - 0.9 + - 0.6 + - 0.8 diff --git a/node_modules/ejs/History.md b/node_modules/ejs/History.md new file mode 100644 index 0000000..c26f168 --- /dev/null +++ b/node_modules/ejs/History.md @@ -0,0 +1,131 @@ + +0.8.4 / 2013-05-08 +================== + + * fix support for colons in filter arguments + * fix double callback when the callback throws + * rename escape option + +0.8.3 / 2012-09-13 +================== + + * allow pre-compiling into a standalone function [seanmonstar] + +0.8.2 / 2012-08-16 +================== + + * fix include "open" / "close" options. Closes #64 + +0.8.1 / 2012-08-11 +================== + + * fix comments. Closes #62 [Nate Silva] + +0.8.0 / 2012-07-25 +================== + + * add `<% include file %>` support + * fix wrapping of custom require in build step. Closes #57 + +0.7.3 / 2012-04-25 +================== + + * Added repository to package.json [isaacs] + +0.7.1 / 2012-03-26 +================== + + * Fixed exception when using express in production caused by typo. [slaskis] + +0.7.0 / 2012-03-24 +================== + + * Added newline consumption support (`-%>`) [whoatemydomain] + +0.6.1 / 2011-12-09 +================== + + * Fixed `ejs.renderFile()` + +0.6.0 / 2011-12-09 +================== + + * Changed: you no longer need `{ locals: {} }` + +0.5.0 / 2011-11-20 +================== + + * Added express 3.x support + * Added ejs.renderFile() + * Added 'json' filter + * Fixed tests for 0.5.x + +0.4.3 / 2011-06-20 +================== + + * Fixed stacktraces line number when used multiline js expressions [Octave] + +0.4.2 / 2011-05-11 +================== + + * Added client side support + +0.4.1 / 2011-04-21 +================== + + * Fixed error context + +0.4.0 / 2011-04-21 +================== + + * Added; ported jade's error reporting to ejs. [slaskis] + +0.3.1 / 2011-02-23 +================== + + * Fixed optional `compile()` options + +0.3.0 / 2011-02-14 +================== + + * Added 'json' filter [Yuriy Bogdanov] + * Use exported version of parse function to allow monkey-patching [Anatoliy Chakkaev] + +0.2.1 / 2010-10-07 +================== + + * Added filter support + * Fixed _cache_ option. ~4x performance increase + +0.2.0 / 2010-08-05 +================== + + * Added support for global tag config + * Added custom tag support. Closes #5 + * Fixed whitespace bug. Closes #4 + +0.1.0 / 2010-08-04 +================== + + * Faster implementation [ashleydev] + +0.0.4 / 2010-08-02 +================== + + * Fixed single quotes for content outside of template tags. [aniero] + * Changed; `exports.compile()` now expects only "locals" + +0.0.3 / 2010-07-15 +================== + + * Fixed single quotes + +0.0.2 / 2010-07-09 +================== + + * Fixed newline preservation + +0.0.1 / 2010-07-09 +================== + + * Initial release diff --git a/node_modules/ejs/Makefile b/node_modules/ejs/Makefile new file mode 100644 index 0000000..a687a0a --- /dev/null +++ b/node_modules/ejs/Makefile @@ -0,0 +1,23 @@ + +SRC = $(shell find lib -name "*.js" -type f) +UGLIFY_FLAGS = --no-mangle + +all: ejs.min.js + +test: + @./node_modules/.bin/mocha \ + --reporter spec + +ejs.js: $(SRC) + @node support/compile.js $^ + +ejs.min.js: ejs.js + @uglifyjs $(UGLIFY_FLAGS) $< > $@ \ + && du ejs.min.js \ + && du ejs.js + +clean: + rm -f ejs.js + rm -f ejs.min.js + +.PHONY: test \ No newline at end of file diff --git a/node_modules/ejs/Readme.md b/node_modules/ejs/Readme.md new file mode 100644 index 0000000..ab0a3dd --- /dev/null +++ b/node_modules/ejs/Readme.md @@ -0,0 +1,188 @@ +# EJS + +Embedded JavaScript templates. + +[![Build Status](https://travis-ci.org/visionmedia/ejs.png)](https://travis-ci.org/visionmedia/ejs) + +## Installation + + $ npm install ejs + +## Features + + * Complies with the [Express](http://expressjs.com) view system + * Static caching of intermediate JavaScript + * Unbuffered code for conditionals etc `<% code %>` + * Escapes html by default with `<%= code %>` + * Unescaped buffering with `<%- code %>` + * Supports tag customization + * Filter support for designer-friendly templates + * Includes + * Client-side support + * Newline slurping with `<% code -%>` or `<% -%>` or `<%= code -%>` or `<%- code -%>` + +## Example + + <% if (user) { %> +

<%= user.name %>

+ <% } %> + +## Try out a live example now + + + +## Usage + + ejs.compile(str, options); + // => Function + + ejs.render(str, options); + // => str + +## Options + + - `cache` Compiled functions are cached, requires `filename` + - `filename` Used by `cache` to key caches + - `scope` Function execution context + - `debug` Output generated function body + - `compileDebug` When `false` no debug instrumentation is compiled + - `client` Returns standalone compiled function + - `open` Open tag, defaulting to "<%" + - `close` Closing tag, defaulting to "%>" + - * All others are template-local variables + +## Includes + + Includes are relative to the template with the `include` statement, + for example if you have "./views/users.ejs" and "./views/user/show.ejs" + you would use `<% include user/show %>`. The included file(s) are literally + included into the template, _no_ IO is performed after compilation, thus + local variables are available to these included templates. + +``` + +``` + +## Custom delimiters + +Custom delimiters can also be applied globally: + + var ejs = require('ejs'); + ejs.open = '{{'; + ejs.close = '}}'; + +Which would make the following a valid template: + +

{{= title }}

+ +## Filters + +EJS conditionally supports the concept of "filters". A "filter chain" +is a designer friendly api for manipulating data, without writing JavaScript. + +Filters can be applied by supplying the _:_ modifier, so for example if we wish to take the array `[{ name: 'tj' }, { name: 'mape' }, { name: 'guillermo' }]` and output a list of names we can do this simply with filters: + +Template: + +

<%=: users | map:'name' | join %>

+ +Output: + +

Tj, Mape, Guillermo

+ +Render call: + + ejs.render(str, { + users: [ + { name: 'tj' }, + { name: 'mape' }, + { name: 'guillermo' } + ] + }); + +Or perhaps capitalize the first user's name for display: + +

<%=: users | first | capitalize %>

+ +## Filter list + +Currently these filters are available: + + - first + - last + - capitalize + - downcase + - upcase + - sort + - sort_by:'prop' + - size + - length + - plus:n + - minus:n + - times:n + - divided_by:n + - join:'val' + - truncate:n + - truncate_words:n + - replace:pattern,substitution + - prepend:val + - append:val + - map:'prop' + - reverse + - get:'prop' + +## Adding filters + + To add a filter simply add a method to the `.filters` object: + +```js +ejs.filters.last = function(obj) { + return obj[obj.length - 1]; +}; +``` + +## Layouts + + Currently EJS has no notion of blocks, only compile-time `include`s, + however you may still utilize this feature to implement "layouts" by + simply including a header and footer like so: + +```html +<% include head %> +

Title

+

My page

+<% include foot %> +``` + +## client-side support + + include `./ejs.js` or `./ejs.min.js` and `require("ejs").compile(str)`. + +## License + +(The MIT License) + +Copyright (c) 2009-2010 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/ejs/benchmark.js b/node_modules/ejs/benchmark.js new file mode 100644 index 0000000..7b267e1 --- /dev/null +++ b/node_modules/ejs/benchmark.js @@ -0,0 +1,14 @@ + + +var ejs = require('./lib/ejs'), + str = '<% if (foo) { %>

<%= foo %>

<% } %>', + times = 50000; + +console.log('rendering ' + times + ' times'); + +var start = new Date; +while (times--) { + ejs.render(str, { cache: true, filename: 'test', locals: { foo: 'bar' }}); +} + +console.log('took ' + (new Date - start) + 'ms'); \ No newline at end of file diff --git a/node_modules/ejs/ejs.js b/node_modules/ejs/ejs.js new file mode 100644 index 0000000..d910f11 --- /dev/null +++ b/node_modules/ejs/ejs.js @@ -0,0 +1,581 @@ +ejs = (function(){ + +// CommonJS require() + +function require(p){ + if ('fs' == p) return {}; + var path = require.resolve(p) + , mod = require.modules[path]; + if (!mod) throw new Error('failed to require "' + p + '"'); + if (!mod.exports) { + mod.exports = {}; + mod.call(mod.exports, mod, mod.exports, require.relative(path)); + } + return mod.exports; + } + +require.modules = {}; + +require.resolve = function (path){ + var orig = path + , reg = path + '.js' + , index = path + '/index.js'; + return require.modules[reg] && reg + || require.modules[index] && index + || orig; + }; + +require.register = function (path, fn){ + require.modules[path] = fn; + }; + +require.relative = function (parent) { + return function(p){ + if ('.' != p.substr(0, 1)) return require(p); + + var path = parent.split('/') + , segs = p.split('/'); + path.pop(); + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if ('..' == seg) path.pop(); + else if ('.' != seg) path.push(seg); + } + + return require(path.join('/')); + }; + }; + + +require.register("ejs.js", function(module, exports, require){ + +/*! + * EJS + * Copyright(c) 2012 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('./utils') + , fs = require('fs'); + +/** + * Library version. + */ + +exports.version = '0.7.2'; + +/** + * Filters. + * + * @type Object + */ + +var filters = exports.filters = require('./filters'); + +/** + * Intermediate js cache. + * + * @type Object + */ + +var cache = {}; + +/** + * Clear intermediate js cache. + * + * @api public + */ + +exports.clearCache = function(){ + cache = {}; +}; + +/** + * Translate filtered code into function calls. + * + * @param {String} js + * @return {String} + * @api private + */ + +function filtered(js) { + return js.substr(1).split('|').reduce(function(js, filter){ + var parts = filter.split(':') + , name = parts.shift() + , args = parts.shift() || ''; + if (args) args = ', ' + args; + return 'filters.' + name + '(' + js + args + ')'; + }); +}; + +/** + * Re-throw the given `err` in context to the + * `str` of ejs, `filename`, and `lineno`. + * + * @param {Error} err + * @param {String} str + * @param {String} filename + * @param {String} lineno + * @api private + */ + +function rethrow(err, str, filename, lineno){ + var lines = str.split('\n') + , start = Math.max(lineno - 3, 0) + , end = Math.min(lines.length, lineno + 3); + + // Error context + var context = lines.slice(start, end).map(function(line, i){ + var curr = i + start + 1; + return (curr == lineno ? ' >> ' : ' ') + + curr + + '| ' + + line; + }).join('\n'); + + // Alter exception message + err.path = filename; + err.message = (filename || 'ejs') + ':' + + lineno + '\n' + + context + '\n\n' + + err.message; + + throw err; +} + +/** + * Parse the given `str` of ejs, returning the function body. + * + * @param {String} str + * @return {String} + * @api public + */ + +var parse = exports.parse = function(str, options){ + var options = options || {} + , open = options.open || exports.open || '<%' + , close = options.close || exports.close || '%>'; + + var buf = [ + "var buf = [];" + , "\nwith (locals) {" + , "\n buf.push('" + ]; + + var lineno = 1; + + var consumeEOL = false; + for (var i = 0, len = str.length; i < len; ++i) { + if (str.slice(i, open.length + i) == open) { + i += open.length + + var prefix, postfix, line = '__stack.lineno=' + lineno; + switch (str.substr(i, 1)) { + case '=': + prefix = "', escape((" + line + ', '; + postfix = ")), '"; + ++i; + break; + case '-': + prefix = "', (" + line + ', '; + postfix = "), '"; + ++i; + break; + default: + prefix = "');" + line + ';'; + postfix = "; buf.push('"; + } + + var end = str.indexOf(close, i) + , js = str.substring(i, end) + , start = i + , n = 0; + + if ('-' == js[js.length-1]){ + js = js.substring(0, js.length - 2); + consumeEOL = true; + } + + while (~(n = js.indexOf("\n", n))) n++, lineno++; + if (js.substr(0, 1) == ':') js = filtered(js); + buf.push(prefix, js, postfix); + i += end - start + close.length - 1; + + } else if (str.substr(i, 1) == "\\") { + buf.push("\\\\"); + } else if (str.substr(i, 1) == "'") { + buf.push("\\'"); + } else if (str.substr(i, 1) == "\r") { + buf.push(" "); + } else if (str.substr(i, 1) == "\n") { + if (consumeEOL) { + consumeEOL = false; + } else { + buf.push("\\n"); + lineno++; + } + } else { + buf.push(str.substr(i, 1)); + } + } + + buf.push("');\n}\nreturn buf.join('');"); + return buf.join(''); +}; + +/** + * Compile the given `str` of ejs into a `Function`. + * + * @param {String} str + * @param {Object} options + * @return {Function} + * @api public + */ + +var compile = exports.compile = function(str, options){ + options = options || {}; + + var input = JSON.stringify(str) + , filename = options.filename + ? JSON.stringify(options.filename) + : 'undefined'; + + // Adds the fancy stack trace meta info + str = [ + 'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };', + rethrow.toString(), + 'try {', + exports.parse(str, options), + '} catch (err) {', + ' rethrow(err, __stack.input, __stack.filename, __stack.lineno);', + '}' + ].join("\n"); + + if (options.debug) console.log(str); + var fn = new Function('locals, filters, escape', str); + return function(locals){ + return fn.call(this, locals, filters, utils.escape); + } +}; + +/** + * Render the given `str` of ejs. + * + * Options: + * + * - `locals` Local variables object + * - `cache` Compiled functions are cached, requires `filename` + * - `filename` Used by `cache` to key caches + * - `scope` Function execution context + * - `debug` Output generated function body + * - `open` Open tag, defaulting to "<%" + * - `close` Closing tag, defaulting to "%>" + * + * @param {String} str + * @param {Object} options + * @return {String} + * @api public + */ + +exports.render = function(str, options){ + var fn + , options = options || {}; + + if (options.cache) { + if (options.filename) { + fn = cache[options.filename] || (cache[options.filename] = compile(str, options)); + } else { + throw new Error('"cache" option requires "filename".'); + } + } else { + fn = compile(str, options); + } + + options.__proto__ = options.locals; + return fn.call(options.scope, options); +}; + +/** + * Render an EJS file at the given `path` and callback `fn(err, str)`. + * + * @param {String} path + * @param {Object|Function} options or callback + * @param {Function} fn + * @api public + */ + +exports.renderFile = function(path, options, fn){ + var key = path + ':string'; + + if ('function' == typeof options) { + fn = options, options = {}; + } + + options.filename = path; + + try { + var str = options.cache + ? cache[key] || (cache[key] = fs.readFileSync(path, 'utf8')) + : fs.readFileSync(path, 'utf8'); + + fn(null, exports.render(str, options)); + } catch (err) { + fn(err); + } +}; + +// express support + +exports.__express = exports.renderFile; + +/** + * Expose to require(). + */ + +if (require.extensions) { + require.extensions['.ejs'] = function(module, filename) { + source = require('fs').readFileSync(filename, 'utf-8'); + module._compile(compile(source, {}), filename); + }; +} else if (require.registerExtension) { + require.registerExtension('.ejs', function(src) { + return compile(src, {}); + }); +} + +}); // module: ejs.js + +require.register("filters.js", function(module, exports, require){ + +/*! + * EJS - Filters + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * First element of the target `obj`. + */ + +exports.first = function(obj) { + return obj[0]; +}; + +/** + * Last element of the target `obj`. + */ + +exports.last = function(obj) { + return obj[obj.length - 1]; +}; + +/** + * Capitalize the first letter of the target `str`. + */ + +exports.capitalize = function(str){ + str = String(str); + return str[0].toUpperCase() + str.substr(1, str.length); +}; + +/** + * Downcase the target `str`. + */ + +exports.downcase = function(str){ + return String(str).toLowerCase(); +}; + +/** + * Uppercase the target `str`. + */ + +exports.upcase = function(str){ + return String(str).toUpperCase(); +}; + +/** + * Sort the target `obj`. + */ + +exports.sort = function(obj){ + return Object.create(obj).sort(); +}; + +/** + * Sort the target `obj` by the given `prop` ascending. + */ + +exports.sort_by = function(obj, prop){ + return Object.create(obj).sort(function(a, b){ + a = a[prop], b = b[prop]; + if (a > b) return 1; + if (a < b) return -1; + return 0; + }); +}; + +/** + * Size or length of the target `obj`. + */ + +exports.size = exports.length = function(obj) { + return obj.length; +}; + +/** + * Add `a` and `b`. + */ + +exports.plus = function(a, b){ + return Number(a) + Number(b); +}; + +/** + * Subtract `b` from `a`. + */ + +exports.minus = function(a, b){ + return Number(a) - Number(b); +}; + +/** + * Multiply `a` by `b`. + */ + +exports.times = function(a, b){ + return Number(a) * Number(b); +}; + +/** + * Divide `a` by `b`. + */ + +exports.divided_by = function(a, b){ + return Number(a) / Number(b); +}; + +/** + * Join `obj` with the given `str`. + */ + +exports.join = function(obj, str){ + return obj.join(str || ', '); +}; + +/** + * Truncate `str` to `len`. + */ + +exports.truncate = function(str, len){ + str = String(str); + return str.substr(0, len); +}; + +/** + * Truncate `str` to `n` words. + */ + +exports.truncate_words = function(str, n){ + var str = String(str) + , words = str.split(/ +/); + return words.slice(0, n).join(' '); +}; + +/** + * Replace `pattern` with `substitution` in `str`. + */ + +exports.replace = function(str, pattern, substitution){ + return String(str).replace(pattern, substitution || ''); +}; + +/** + * Prepend `val` to `obj`. + */ + +exports.prepend = function(obj, val){ + return Array.isArray(obj) + ? [val].concat(obj) + : val + obj; +}; + +/** + * Append `val` to `obj`. + */ + +exports.append = function(obj, val){ + return Array.isArray(obj) + ? obj.concat(val) + : obj + val; +}; + +/** + * Map the given `prop`. + */ + +exports.map = function(arr, prop){ + return arr.map(function(obj){ + return obj[prop]; + }); +}; + +/** + * Reverse the given `obj`. + */ + +exports.reverse = function(obj){ + return Array.isArray(obj) + ? obj.reverse() + : String(obj).split('').reverse().join(''); +}; + +/** + * Get `prop` of the given `obj`. + */ + +exports.get = function(obj, prop){ + return obj[prop]; +}; + +/** + * Packs the given `obj` into json string + */ +exports.json = function(obj){ + return JSON.stringify(obj); +}; +}); // module: filters.js + +require.register("utils.js", function(module, exports, require){ + +/*! + * EJS + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + +}); // module: utils.js + + return require("ejs"); +})(); \ No newline at end of file diff --git a/node_modules/ejs/ejs.min.js b/node_modules/ejs/ejs.min.js new file mode 100644 index 0000000..611ee42 --- /dev/null +++ b/node_modules/ejs/ejs.min.js @@ -0,0 +1 @@ +ejs=function(){function require(p){if("fs"==p)return{};var path=require.resolve(p),mod=require.modules[path];if(!mod)throw new Error('failed to require "'+p+'"');return mod.exports||(mod.exports={},mod.call(mod.exports,mod,mod.exports,require.relative(path))),mod.exports}return require.modules={},require.resolve=function(path){var orig=path,reg=path+".js",index=path+"/index.js";return require.modules[reg]&®||require.modules[index]&&index||orig},require.register=function(path,fn){require.modules[path]=fn},require.relative=function(parent){return function(p){if("."!=p.substr(0,1))return require(p);var path=parent.split("/"),segs=p.split("/");path.pop();for(var i=0;i> ":" ")+curr+"| "+line}).join("\n");throw err.path=filename,err.message=(filename||"ejs")+":"+lineno+"\n"+context+"\n\n"+err.message,err}var parse=exports.parse=function(str,options){var options=options||{},open=options.open||exports.open||"<%",close=options.close||exports.close||"%>",buf=["var buf = [];","\nwith (locals) {","\n buf.push('"],lineno=1,consumeEOL=!1;for(var i=0,len=str.length;ib?1:a/g,">").replace(/"/g,""")}}),require("ejs")}(); \ No newline at end of file diff --git a/node_modules/ejs/examples/client.html b/node_modules/ejs/examples/client.html new file mode 100644 index 0000000..30dfea9 --- /dev/null +++ b/node_modules/ejs/examples/client.html @@ -0,0 +1,24 @@ + + + + + + + + + \ No newline at end of file diff --git a/node_modules/ejs/examples/functions.ejs b/node_modules/ejs/examples/functions.ejs new file mode 100644 index 0000000..bd5610e --- /dev/null +++ b/node_modules/ejs/examples/functions.ejs @@ -0,0 +1,9 @@ +

Users

+ +<% function user(user) { %> +
  • <%= user.name %> is a <%= user.age %> year old <%= user.species %>.
  • +<% } %> + +
      + <% users.map(user) %> +
    \ No newline at end of file diff --git a/node_modules/ejs/examples/functions.js b/node_modules/ejs/examples/functions.js new file mode 100644 index 0000000..607833f --- /dev/null +++ b/node_modules/ejs/examples/functions.js @@ -0,0 +1,22 @@ + +/** + * Module dependencies. + */ + +var ejs = require('../') + , fs = require('fs') + , path = __dirname + '/functions.ejs' + , str = fs.readFileSync(path, 'utf8'); + +var users = []; + +users.push({ name: 'Tobi', age: 2, species: 'ferret' }) +users.push({ name: 'Loki', age: 2, species: 'ferret' }) +users.push({ name: 'Jane', age: 6, species: 'ferret' }) + +var ret = ejs.render(str, { + users: users, + filename: path +}); + +console.log(ret); \ No newline at end of file diff --git a/node_modules/ejs/examples/list.ejs b/node_modules/ejs/examples/list.ejs new file mode 100644 index 0000000..d571330 --- /dev/null +++ b/node_modules/ejs/examples/list.ejs @@ -0,0 +1,7 @@ +<% if (names.length) { %> +
      + <% names.forEach(function(name){ %> +
    • <%= name %>
    • + <% }) %> +
    +<% } %> \ No newline at end of file diff --git a/node_modules/ejs/examples/list.js b/node_modules/ejs/examples/list.js new file mode 100644 index 0000000..ec614ed --- /dev/null +++ b/node_modules/ejs/examples/list.js @@ -0,0 +1,14 @@ + +/** + * Module dependencies. + */ + +var ejs = require('../') + , fs = require('fs') + , str = fs.readFileSync(__dirname + '/list.ejs', 'utf8'); + +var ret = ejs.render(str, { + names: ['foo', 'bar', 'baz'] +}); + +console.log(ret); \ No newline at end of file diff --git a/node_modules/ejs/index.js b/node_modules/ejs/index.js new file mode 100644 index 0000000..20bf71a --- /dev/null +++ b/node_modules/ejs/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/ejs'); \ No newline at end of file diff --git a/node_modules/ejs/lib/ejs.js b/node_modules/ejs/lib/ejs.js new file mode 100644 index 0000000..8601b10 --- /dev/null +++ b/node_modules/ejs/lib/ejs.js @@ -0,0 +1,353 @@ + +/*! + * EJS + * Copyright(c) 2012 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('./utils') + , path = require('path') + , basename = path.basename + , dirname = path.dirname + , extname = path.extname + , join = path.join + , fs = require('fs') + , read = fs.readFileSync; + +/** + * Filters. + * + * @type Object + */ + +var filters = exports.filters = require('./filters'); + +/** + * Intermediate js cache. + * + * @type Object + */ + +var cache = {}; + +/** + * Clear intermediate js cache. + * + * @api public + */ + +exports.clearCache = function(){ + cache = {}; +}; + +/** + * Translate filtered code into function calls. + * + * @param {String} js + * @return {String} + * @api private + */ + +function filtered(js) { + return js.substr(1).split('|').reduce(function(js, filter){ + var parts = filter.split(':') + , name = parts.shift() + , args = parts.join(':') || ''; + if (args) args = ', ' + args; + return 'filters.' + name + '(' + js + args + ')'; + }); +}; + +/** + * Re-throw the given `err` in context to the + * `str` of ejs, `filename`, and `lineno`. + * + * @param {Error} err + * @param {String} str + * @param {String} filename + * @param {String} lineno + * @api private + */ + +function rethrow(err, str, filename, lineno){ + var lines = str.split('\n') + , start = Math.max(lineno - 3, 0) + , end = Math.min(lines.length, lineno + 3); + + // Error context + var context = lines.slice(start, end).map(function(line, i){ + var curr = i + start + 1; + return (curr == lineno ? ' >> ' : ' ') + + curr + + '| ' + + line; + }).join('\n'); + + // Alter exception message + err.path = filename; + err.message = (filename || 'ejs') + ':' + + lineno + '\n' + + context + '\n\n' + + err.message; + + throw err; +} + +/** + * Parse the given `str` of ejs, returning the function body. + * + * @param {String} str + * @return {String} + * @api public + */ + +var parse = exports.parse = function(str, options){ + var options = options || {} + , open = options.open || exports.open || '<%' + , close = options.close || exports.close || '%>' + , filename = options.filename + , compileDebug = options.compileDebug !== false + , buf = []; + + buf.push('var buf = [];'); + if (false !== options._with) buf.push('\nwith (locals || {}) { (function(){ '); + buf.push('\n buf.push(\''); + + var lineno = 1; + + var consumeEOL = false; + for (var i = 0, len = str.length; i < len; ++i) { + if (str.slice(i, open.length + i) == open) { + i += open.length + + var prefix, postfix, line = (compileDebug ? '__stack.lineno=' : '') + lineno; + switch (str.substr(i, 1)) { + case '=': + prefix = "', escape((" + line + ', '; + postfix = ")), '"; + ++i; + break; + case '-': + prefix = "', (" + line + ', '; + postfix = "), '"; + ++i; + break; + default: + prefix = "');" + line + ';'; + postfix = "; buf.push('"; + } + + var end = str.indexOf(close, i) + , js = str.substring(i, end) + , start = i + , include = null + , n = 0; + + if ('-' == js[js.length-1]){ + js = js.substring(0, js.length - 2); + consumeEOL = true; + } + + if (0 == js.trim().indexOf('include')) { + var name = js.trim().slice(7).trim(); + if (!filename) throw new Error('filename option is required for includes'); + var path = resolveInclude(name, filename); + include = read(path, 'utf8'); + include = exports.parse(include, { filename: path, _with: false, open: open, close: close, compileDebug: compileDebug }); + buf.push("' + (function(){" + include + "})() + '"); + js = ''; + } + + while (~(n = js.indexOf("\n", n))) n++, lineno++; + if (js.substr(0, 1) == ':') js = filtered(js); + if (js) { + if (js.lastIndexOf('//') > js.lastIndexOf('\n')) js += '\n'; + buf.push(prefix, js, postfix); + } + i += end - start + close.length - 1; + + } else if (str.substr(i, 1) == "\\") { + buf.push("\\\\"); + } else if (str.substr(i, 1) == "'") { + buf.push("\\'"); + } else if (str.substr(i, 1) == "\r") { + // ignore + } else if (str.substr(i, 1) == "\n") { + if (consumeEOL) { + consumeEOL = false; + } else { + buf.push("\\n"); + lineno++; + } + } else { + buf.push(str.substr(i, 1)); + } + } + + if (false !== options._with) buf.push("'); })();\n} \nreturn buf.join('');") + else buf.push("');\nreturn buf.join('');"); + + return buf.join(''); +}; + +/** + * Compile the given `str` of ejs into a `Function`. + * + * @param {String} str + * @param {Object} options + * @return {Function} + * @api public + */ + +var compile = exports.compile = function(str, options){ + options = options || {}; + var escape = options.escape || utils.escape; + + var input = JSON.stringify(str) + , compileDebug = options.compileDebug !== false + , client = options.client + , filename = options.filename + ? JSON.stringify(options.filename) + : 'undefined'; + + if (compileDebug) { + // Adds the fancy stack trace meta info + str = [ + 'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };', + rethrow.toString(), + 'try {', + exports.parse(str, options), + '} catch (err) {', + ' rethrow(err, __stack.input, __stack.filename, __stack.lineno);', + '}' + ].join("\n"); + } else { + str = exports.parse(str, options); + } + + if (options.debug) console.log(str); + if (client) str = 'escape = escape || ' + escape.toString() + ';\n' + str; + + try { + var fn = new Function('locals, filters, escape', str); + } catch (err) { + if ('SyntaxError' == err.name) { + err.message += options.filename + ? ' in ' + filename + : ' while compiling ejs'; + } + throw err; + } + + if (client) return fn; + + return function(locals){ + return fn.call(this, locals, filters, escape); + } +}; + +/** + * Render the given `str` of ejs. + * + * Options: + * + * - `locals` Local variables object + * - `cache` Compiled functions are cached, requires `filename` + * - `filename` Used by `cache` to key caches + * - `scope` Function execution context + * - `debug` Output generated function body + * - `open` Open tag, defaulting to "<%" + * - `close` Closing tag, defaulting to "%>" + * + * @param {String} str + * @param {Object} options + * @return {String} + * @api public + */ + +exports.render = function(str, options){ + var fn + , options = options || {}; + + if (options.cache) { + if (options.filename) { + fn = cache[options.filename] || (cache[options.filename] = compile(str, options)); + } else { + throw new Error('"cache" option requires "filename".'); + } + } else { + fn = compile(str, options); + } + + options.__proto__ = options.locals; + return fn.call(options.scope, options); +}; + +/** + * Render an EJS file at the given `path` and callback `fn(err, str)`. + * + * @param {String} path + * @param {Object|Function} options or callback + * @param {Function} fn + * @api public + */ + +exports.renderFile = function(path, options, fn){ + var key = path + ':string'; + + if ('function' == typeof options) { + fn = options, options = {}; + } + + options.filename = path; + + var str; + try { + str = options.cache + ? cache[key] || (cache[key] = read(path, 'utf8')) + : read(path, 'utf8'); + } catch (err) { + fn(err); + return; + } + fn(null, exports.render(str, options)); +}; + +/** + * Resolve include `name` relative to `filename`. + * + * @param {String} name + * @param {String} filename + * @return {String} + * @api private + */ + +function resolveInclude(name, filename) { + var path = join(dirname(filename), name); + var ext = extname(name); + if (!ext) path += '.ejs'; + return path; +} + +// express support + +exports.__express = exports.renderFile; + +/** + * Expose to require(). + */ + +if (require.extensions) { + require.extensions['.ejs'] = function(module, filename) { + source = require('fs').readFileSync(filename, 'utf-8'); + module._compile(compile(source, {}), filename); + }; +} else if (require.registerExtension) { + require.registerExtension('.ejs', function(src) { + return compile(src, {}); + }); +} diff --git a/node_modules/ejs/lib/filters.js b/node_modules/ejs/lib/filters.js new file mode 100644 index 0000000..d425c8d --- /dev/null +++ b/node_modules/ejs/lib/filters.js @@ -0,0 +1,198 @@ + +/*! + * EJS - Filters + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * First element of the target `obj`. + */ + +exports.first = function(obj) { + return obj[0]; +}; + +/** + * Last element of the target `obj`. + */ + +exports.last = function(obj) { + return obj[obj.length - 1]; +}; + +/** + * Capitalize the first letter of the target `str`. + */ + +exports.capitalize = function(str){ + str = String(str); + return str[0].toUpperCase() + str.substr(1, str.length); +}; + +/** + * Downcase the target `str`. + */ + +exports.downcase = function(str){ + return String(str).toLowerCase(); +}; + +/** + * Uppercase the target `str`. + */ + +exports.upcase = function(str){ + return String(str).toUpperCase(); +}; + +/** + * Sort the target `obj`. + */ + +exports.sort = function(obj){ + return Object.create(obj).sort(); +}; + +/** + * Sort the target `obj` by the given `prop` ascending. + */ + +exports.sort_by = function(obj, prop){ + return Object.create(obj).sort(function(a, b){ + a = a[prop], b = b[prop]; + if (a > b) return 1; + if (a < b) return -1; + return 0; + }); +}; + +/** + * Size or length of the target `obj`. + */ + +exports.size = exports.length = function(obj) { + return obj.length; +}; + +/** + * Add `a` and `b`. + */ + +exports.plus = function(a, b){ + return Number(a) + Number(b); +}; + +/** + * Subtract `b` from `a`. + */ + +exports.minus = function(a, b){ + return Number(a) - Number(b); +}; + +/** + * Multiply `a` by `b`. + */ + +exports.times = function(a, b){ + return Number(a) * Number(b); +}; + +/** + * Divide `a` by `b`. + */ + +exports.divided_by = function(a, b){ + return Number(a) / Number(b); +}; + +/** + * Join `obj` with the given `str`. + */ + +exports.join = function(obj, str){ + return obj.join(str || ', '); +}; + +/** + * Truncate `str` to `len`. + */ + +exports.truncate = function(str, len){ + str = String(str); + return str.substr(0, len); +}; + +/** + * Truncate `str` to `n` words. + */ + +exports.truncate_words = function(str, n){ + var str = String(str) + , words = str.split(/ +/); + return words.slice(0, n).join(' '); +}; + +/** + * Replace `pattern` with `substitution` in `str`. + */ + +exports.replace = function(str, pattern, substitution){ + return String(str).replace(pattern, substitution || ''); +}; + +/** + * Prepend `val` to `obj`. + */ + +exports.prepend = function(obj, val){ + return Array.isArray(obj) + ? [val].concat(obj) + : val + obj; +}; + +/** + * Append `val` to `obj`. + */ + +exports.append = function(obj, val){ + return Array.isArray(obj) + ? obj.concat(val) + : obj + val; +}; + +/** + * Map the given `prop`. + */ + +exports.map = function(arr, prop){ + return arr.map(function(obj){ + return obj[prop]; + }); +}; + +/** + * Reverse the given `obj`. + */ + +exports.reverse = function(obj){ + return Array.isArray(obj) + ? obj.reverse() + : String(obj).split('').reverse().join(''); +}; + +/** + * Get `prop` of the given `obj`. + */ + +exports.get = function(obj, prop){ + return obj[prop]; +}; + +/** + * Packs the given `obj` into json string + */ +exports.json = function(obj){ + return JSON.stringify(obj); +}; \ No newline at end of file diff --git a/node_modules/ejs/lib/utils.js b/node_modules/ejs/lib/utils.js new file mode 100644 index 0000000..8d569d6 --- /dev/null +++ b/node_modules/ejs/lib/utils.js @@ -0,0 +1,23 @@ + +/*! + * EJS + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + \ No newline at end of file diff --git a/node_modules/ejs/package.json b/node_modules/ejs/package.json new file mode 100644 index 0000000..6cb631d --- /dev/null +++ b/node_modules/ejs/package.json @@ -0,0 +1,33 @@ +{ + "name": "ejs", + "description": "Embedded JavaScript templates", + "version": "0.8.4", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "keywords": [ + "template", + "engine", + "ejs" + ], + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "main": "./lib/ejs.js", + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/ejs.git" + }, + "scripts": { + "test": "mocha --require should --reporter spec" + }, + "readme": "# EJS\n\nEmbedded JavaScript templates.\n\n[![Build Status](https://travis-ci.org/visionmedia/ejs.png)](https://travis-ci.org/visionmedia/ejs)\n\n## Installation\n\n $ npm install ejs\n\n## Features\n\n * Complies with the [Express](http://expressjs.com) view system\n * Static caching of intermediate JavaScript\n * Unbuffered code for conditionals etc `<% code %>`\n * Escapes html by default with `<%= code %>`\n * Unescaped buffering with `<%- code %>`\n * Supports tag customization\n * Filter support for designer-friendly templates\n * Includes\n * Client-side support\n * Newline slurping with `<% code -%>` or `<% -%>` or `<%= code -%>` or `<%- code -%>`\n\n## Example\n\n <% if (user) { %>\n\t

    <%= user.name %>

    \n <% } %>\n \n## Try out a live example now\n\n\n\n## Usage\n\n ejs.compile(str, options);\n // => Function\n\n ejs.render(str, options);\n // => str\n\n## Options\n\n - `cache` Compiled functions are cached, requires `filename`\n - `filename` Used by `cache` to key caches\n - `scope` Function execution context\n - `debug` Output generated function body\n - `compileDebug` When `false` no debug instrumentation is compiled\n - `client` Returns standalone compiled function\n - `open` Open tag, defaulting to \"<%\"\n - `close` Closing tag, defaulting to \"%>\"\n - * All others are template-local variables\n\n## Includes\n\n Includes are relative to the template with the `include` statement,\n for example if you have \"./views/users.ejs\" and \"./views/user/show.ejs\"\n you would use `<% include user/show %>`. The included file(s) are literally\n included into the template, _no_ IO is performed after compilation, thus\n local variables are available to these included templates.\n\n```\n
      \n <% users.forEach(function(user){ %>\n <% include user/show %>\n <% }) %>\n
    \n```\n\n## Custom delimiters\n\nCustom delimiters can also be applied globally:\n\n var ejs = require('ejs');\n ejs.open = '{{';\n ejs.close = '}}';\n\nWhich would make the following a valid template:\n\n

    {{= title }}

    \n\n## Filters\n\nEJS conditionally supports the concept of \"filters\". A \"filter chain\"\nis a designer friendly api for manipulating data, without writing JavaScript.\n\nFilters can be applied by supplying the _:_ modifier, so for example if we wish to take the array `[{ name: 'tj' }, { name: 'mape' }, { name: 'guillermo' }]` and output a list of names we can do this simply with filters:\n\nTemplate:\n\n

    <%=: users | map:'name' | join %>

    \n\nOutput:\n\n

    Tj, Mape, Guillermo

    \n\nRender call:\n\n ejs.render(str, {\n users: [\n { name: 'tj' },\n { name: 'mape' },\n { name: 'guillermo' }\n ]\n });\n\nOr perhaps capitalize the first user's name for display:\n\n

    <%=: users | first | capitalize %>

    \n\n## Filter list\n\nCurrently these filters are available:\n\n - first\n - last\n - capitalize\n - downcase\n - upcase\n - sort\n - sort_by:'prop'\n - size\n - length\n - plus:n\n - minus:n\n - times:n\n - divided_by:n\n - join:'val'\n - truncate:n\n - truncate_words:n\n - replace:pattern,substitution\n - prepend:val\n - append:val\n - map:'prop'\n - reverse\n - get:'prop'\n\n## Adding filters\n\n To add a filter simply add a method to the `.filters` object:\n \n```js\nejs.filters.last = function(obj) {\n return obj[obj.length - 1];\n};\n```\n\n## Layouts\n\n Currently EJS has no notion of blocks, only compile-time `include`s,\n however you may still utilize this feature to implement \"layouts\" by\n simply including a header and footer like so:\n\n```html\n<% include head %>\n

    Title

    \n

    My page

    \n<% include foot %>\n```\n\n## client-side support\n\n include `./ejs.js` or `./ejs.min.js` and `require(\"ejs\").compile(str)`.\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2009-2010 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", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/visionmedia/ejs/issues" + }, + "_id": "ejs@0.8.4", + "_from": "ejs@" +} diff --git a/node_modules/ejs/support/compile.js b/node_modules/ejs/support/compile.js new file mode 100644 index 0000000..497a1bb --- /dev/null +++ b/node_modules/ejs/support/compile.js @@ -0,0 +1,176 @@ + +/** + * Module dependencies. + */ + +var fs = require('fs'); + +/** + * Arguments. + */ + +var args = process.argv.slice(2) + , pending = args.length + , files = {}; + +console.log(''); + +// parse arguments + +args.forEach(function(file){ + var mod = file.replace('lib/', ''); + fs.readFile(file, 'utf8', function(err, js){ + if (err) throw err; + console.log(' \033[90mcompile : \033[0m\033[36m%s\033[0m', file); + files[file] = parse(js); + --pending || compile(); + }); +}); + +/** + * Parse the given `js`. + */ + +function parse(js) { + return parseInheritance(parseConditionals(js)); +} + +/** + * Parse __proto__. + */ + +function parseInheritance(js) { + return js + .replace(/^ *(\w+)\.prototype\.__proto__ * = *(\w+)\.prototype *;?/gm, function(_, child, parent){ + return child + '.prototype = new ' + parent + ';\n' + + child + '.prototype.constructor = '+ child + ';\n'; + }); +} + +/** + * Parse the given `js`, currently supporting: + * + * 'if' ['node' | 'browser'] + * 'end' + * + */ + +function parseConditionals(js) { + var lines = js.split('\n') + , len = lines.length + , buffer = true + , browser = false + , buf = [] + , line + , cond; + + for (var i = 0; i < len; ++i) { + line = lines[i]; + if (/^ *\/\/ *if *(node|browser)/gm.exec(line)) { + cond = RegExp.$1; + buffer = browser = 'browser' == cond; + } else if (/^ *\/\/ *end/.test(line)) { + buffer = true; + browser = false; + } else if (browser) { + buf.push(line.replace(/^( *)\/\//, '$1')); + } else if (buffer) { + buf.push(line); + } + } + + return buf.join('\n'); +} + +/** + * Compile the files. + */ + +function compile() { + var buf = ''; + buf += 'ejs = (function(){\n'; + buf += '\n// CommonJS require()\n\n'; + buf += browser.require + '\n\n'; + buf += 'require.modules = {};\n\n'; + buf += 'require.resolve = ' + browser.resolve + ';\n\n'; + buf += 'require.register = ' + browser.register + ';\n\n'; + buf += 'require.relative = ' + browser.relative + ';\n\n'; + args.forEach(function(file){ + var js = files[file]; + file = file.replace('lib/', ''); + buf += '\nrequire.register("' + file + '", function(module, exports, require){\n'; + buf += js; + buf += '\n}); // module: ' + file + '\n'; + }); + buf += '\n return require("ejs");\n})();'; + fs.writeFile('ejs.js', buf, function(err){ + if (err) throw err; + console.log(' \033[90m create : \033[0m\033[36m%s\033[0m', 'ejs.js'); + console.log(); + }); +} + +// refactored version of weepy's +// https://github.com/weepy/brequire/blob/master/browser/brequire.js + +var browser = { + + /** + * Require a module. + */ + + require: function require(p){ + if ('fs' == p) return {}; + var path = require.resolve(p) + , mod = require.modules[path]; + if (!mod) throw new Error('failed to require "' + p + '"'); + if (!mod.exports) { + mod.exports = {}; + mod.call(mod.exports, mod, mod.exports, require.relative(path)); + } + return mod.exports; + }, + + /** + * Resolve module path. + */ + + resolve: function(path){ + var orig = path + , reg = path + '.js' + , index = path + '/index.js'; + return require.modules[reg] && reg + || require.modules[index] && index + || orig; + }, + + /** + * Return relative require(). + */ + + relative: function(parent) { + return function(p){ + if ('.' != p.substr(0, 1)) return require(p); + + var path = parent.split('/') + , segs = p.split('/'); + path.pop(); + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if ('..' == seg) path.pop(); + else if ('.' != seg) path.push(seg); + } + + return require(path.join('/')); + }; + }, + + /** + * Register a module. + */ + + register: function(path, fn){ + require.modules[path] = fn; + } +}; \ No newline at end of file diff --git a/node_modules/ejs/test/ejs.js b/node_modules/ejs/test/ejs.js new file mode 100644 index 0000000..1c58c1c --- /dev/null +++ b/node_modules/ejs/test/ejs.js @@ -0,0 +1,265 @@ +/** + * Module dependencies. + */ + +var ejs = require('..') + , fs = require('fs') + , read = fs.readFileSync + , assert = require('should'); + +/** + * Load fixture `name`. + */ + +function fixture(name) { + return read('test/fixtures/' + name, 'utf8').replace(/\r/g, ''); +} + +/** + * User fixtures. + */ + +var users = []; +users.push({ name: 'tobi' }); +users.push({ name: 'loki' }); +users.push({ name: 'jane' }); + +describe('ejs.compile(str, options)', function(){ + it('should compile to a function', function(){ + var fn = ejs.compile('

    yay

    '); + fn().should.equal('

    yay

    '); + }) + + it('should throw if there are syntax errors', function(){ + try { + ejs.compile(fixture('fail.ejs')); + } catch (err) { + err.message.should.include('compiling ejs'); + + try { + ejs.compile(fixture('fail.ejs'), { filename: 'fail.ejs' }); + } catch (err) { + err.message.should.include('fail.ejs'); + return; + } + } + + assert(false, 'compiling a file with invalid syntax should throw an exception'); + }) + + it('should allow customizing delimiters', function(){ + var fn = ejs.compile('

    {= name }

    ', { open: '{', close: '}' }); + fn({ name: 'tobi' }).should.equal('

    tobi

    '); + + var fn = ejs.compile('

    ::= name ::

    ', { open: '::', close: '::' }); + fn({ name: 'tobi' }).should.equal('

    tobi

    '); + + var fn = ejs.compile('

    (= name )

    ', { open: '(', close: ')' }); + fn({ name: 'tobi' }).should.equal('

    tobi

    '); + }) + + it('should default to using ejs.open and ejs.close', function(){ + ejs.open = '{'; + ejs.close = '}'; + var fn = ejs.compile('

    {= name }

    '); + fn({ name: 'tobi' }).should.equal('

    tobi

    '); + + var fn = ejs.compile('

    |= name |

    ', { open: '|', close: '|' }); + fn({ name: 'tobi' }).should.equal('

    tobi

    '); + delete ejs.open; + delete ejs.close; + }) + + it('should have a working client option', function(){ + var fn = ejs.compile('

    <%= foo %>

    ', { client: true }); + var str = fn.toString(); + eval('var preFn = ' + str); + preFn({ foo: 'bar' }).should.equal('

    bar

    '); + }) +}) + +describe('ejs.render(str, options)', function(){ + it('should render the template', function(){ + ejs.render('

    yay

    ') + .should.equal('

    yay

    '); + }) + + it('should accept locals', function(){ + ejs.render('

    <%= name %>

    ', { name: 'tobi' }) + .should.equal('

    tobi

    '); + }) +}) + +describe('ejs.renderFile(path, options, fn)', function(){ + it('should render a file', function(done){ + ejs.renderFile('test/fixtures/para.ejs', function(err, html){ + if (err) return done(err); + html.should.equal('

    hey

    '); + done(); + }); + }) + + it('should accept locals', function(done){ + var options = { name: 'tj', open: '{', close: '}' }; + ejs.renderFile('test/fixtures/user.ejs', options, function(err, html){ + if (err) return done(err); + html.should.equal('

    tj

    '); + done(); + }); + }) + + it('should not catch err threw by callback', function(done){ + var options = { name: 'tj', open: '{', close: '}' }; + var counter = 0; + try { + ejs.renderFile('test/fixtures/user.ejs', options, function(err, html){ + counter++; + if (err) { + err.message.should.not.equal('Exception in callback'); + return done(err); + } + throw new Error('Exception in callback'); + }); + } catch (err) { + counter.should.equal(1); + err.message.should.equal('Exception in callback'); + done(); + } + }) +}) + +describe('<%=', function(){ + it('should escape', function(){ + ejs.render('<%= name %>', { name: ' + + + +
    +

    {linked-path}

    + {files} +
    + + \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/lib/public/error.html b/node_modules/express/node_modules/connect/lib/public/error.html new file mode 100644 index 0000000..a6d3faf --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/public/error.html @@ -0,0 +1,14 @@ + + + + {error} + + + +
    +

    {title}

    +

    {statusCode} {error}

    +
      {stack}
    +
    + + diff --git a/node_modules/express/node_modules/connect/lib/public/favicon.ico b/node_modules/express/node_modules/connect/lib/public/favicon.ico new file mode 100644 index 0000000..895fc96 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/favicon.ico differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page.png b/node_modules/express/node_modules/connect/lib/public/icons/page.png new file mode 100644 index 0000000..03ddd79 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_add.png b/node_modules/express/node_modules/connect/lib/public/icons/page_add.png new file mode 100644 index 0000000..d5bfa07 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_add.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_attach.png b/node_modules/express/node_modules/connect/lib/public/icons/page_attach.png new file mode 100644 index 0000000..89ee2da Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_attach.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_code.png b/node_modules/express/node_modules/connect/lib/public/icons/page_code.png new file mode 100644 index 0000000..f7ea904 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_code.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_copy.png b/node_modules/express/node_modules/connect/lib/public/icons/page_copy.png new file mode 100644 index 0000000..195dc6d Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_copy.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_delete.png b/node_modules/express/node_modules/connect/lib/public/icons/page_delete.png new file mode 100644 index 0000000..3141467 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_delete.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_edit.png b/node_modules/express/node_modules/connect/lib/public/icons/page_edit.png new file mode 100644 index 0000000..046811e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_edit.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_error.png b/node_modules/express/node_modules/connect/lib/public/icons/page_error.png new file mode 100644 index 0000000..f07f449 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_error.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_excel.png b/node_modules/express/node_modules/connect/lib/public/icons/page_excel.png new file mode 100644 index 0000000..eb6158e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_excel.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_find.png b/node_modules/express/node_modules/connect/lib/public/icons/page_find.png new file mode 100644 index 0000000..2f19388 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_find.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_gear.png b/node_modules/express/node_modules/connect/lib/public/icons/page_gear.png new file mode 100644 index 0000000..8e83281 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_gear.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_go.png b/node_modules/express/node_modules/connect/lib/public/icons/page_go.png new file mode 100644 index 0000000..80fe1ed Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_go.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_green.png b/node_modules/express/node_modules/connect/lib/public/icons/page_green.png new file mode 100644 index 0000000..de8e003 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_green.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_key.png b/node_modules/express/node_modules/connect/lib/public/icons/page_key.png new file mode 100644 index 0000000..d6626cb Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_key.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_lightning.png b/node_modules/express/node_modules/connect/lib/public/icons/page_lightning.png new file mode 100644 index 0000000..7e56870 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_lightning.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_link.png b/node_modules/express/node_modules/connect/lib/public/icons/page_link.png new file mode 100644 index 0000000..312eab0 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_link.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_paintbrush.png b/node_modules/express/node_modules/connect/lib/public/icons/page_paintbrush.png new file mode 100644 index 0000000..246a2f0 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_paintbrush.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_paste.png b/node_modules/express/node_modules/connect/lib/public/icons/page_paste.png new file mode 100644 index 0000000..968f073 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_paste.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_red.png b/node_modules/express/node_modules/connect/lib/public/icons/page_red.png new file mode 100644 index 0000000..0b18247 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_red.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_refresh.png b/node_modules/express/node_modules/connect/lib/public/icons/page_refresh.png new file mode 100644 index 0000000..cf347c7 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_refresh.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_save.png b/node_modules/express/node_modules/connect/lib/public/icons/page_save.png new file mode 100644 index 0000000..caea546 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_save.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white.png new file mode 100644 index 0000000..8b8b1ca Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_acrobat.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_acrobat.png new file mode 100644 index 0000000..8f8095e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_acrobat.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_actionscript.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_actionscript.png new file mode 100644 index 0000000..159b240 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_actionscript.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_add.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_add.png new file mode 100644 index 0000000..aa23dde Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_add.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_c.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_c.png new file mode 100644 index 0000000..34a05cc Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_c.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_camera.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_camera.png new file mode 100644 index 0000000..f501a59 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_camera.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_cd.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_cd.png new file mode 100644 index 0000000..848bdaf Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_cd.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_code.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_code.png new file mode 100644 index 0000000..0c76bd1 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_code.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_code_red.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_code_red.png new file mode 100644 index 0000000..87a6914 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_code_red.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_coldfusion.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_coldfusion.png new file mode 100644 index 0000000..c66011f Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_coldfusion.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_compressed.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_compressed.png new file mode 100644 index 0000000..2b6b100 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_compressed.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_copy.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_copy.png new file mode 100644 index 0000000..a9f31a2 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_copy.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_cplusplus.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_cplusplus.png new file mode 100644 index 0000000..a87cf84 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_cplusplus.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_csharp.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_csharp.png new file mode 100644 index 0000000..ffb8fc9 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_csharp.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_cup.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_cup.png new file mode 100644 index 0000000..0a7d6f4 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_cup.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_database.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_database.png new file mode 100644 index 0000000..bddba1f Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_database.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_delete.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_delete.png new file mode 100644 index 0000000..af1ecaf Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_delete.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_dvd.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_dvd.png new file mode 100644 index 0000000..4cc537a Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_dvd.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_edit.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_edit.png new file mode 100644 index 0000000..b93e776 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_edit.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_error.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_error.png new file mode 100644 index 0000000..9fc5a0a Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_error.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_excel.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_excel.png new file mode 100644 index 0000000..b977d7e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_excel.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_find.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_find.png new file mode 100644 index 0000000..5818436 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_find.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_flash.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_flash.png new file mode 100644 index 0000000..5769120 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_flash.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_freehand.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_freehand.png new file mode 100644 index 0000000..8d719df Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_freehand.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_gear.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_gear.png new file mode 100644 index 0000000..106f5aa Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_gear.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_get.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_get.png new file mode 100644 index 0000000..e4a1ecb Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_get.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_go.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_go.png new file mode 100644 index 0000000..7e62a92 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_go.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_h.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_h.png new file mode 100644 index 0000000..e902abb Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_h.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_horizontal.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_horizontal.png new file mode 100644 index 0000000..1d2d0a4 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_horizontal.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_key.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_key.png new file mode 100644 index 0000000..d616484 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_key.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_lightning.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_lightning.png new file mode 100644 index 0000000..7215d1e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_lightning.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_link.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_link.png new file mode 100644 index 0000000..bf7bd1c Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_link.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_magnify.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_magnify.png new file mode 100644 index 0000000..f6b74cc Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_magnify.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_medal.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_medal.png new file mode 100644 index 0000000..d3fffb6 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_medal.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_office.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_office.png new file mode 100644 index 0000000..a65bcb3 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_office.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_paint.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_paint.png new file mode 100644 index 0000000..23a37b8 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_paint.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_paintbrush.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_paintbrush.png new file mode 100644 index 0000000..f907e44 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_paintbrush.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_paste.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_paste.png new file mode 100644 index 0000000..5b2cbb3 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_paste.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_php.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_php.png new file mode 100644 index 0000000..7868a25 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_php.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_picture.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_picture.png new file mode 100644 index 0000000..134b669 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_picture.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_powerpoint.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_powerpoint.png new file mode 100644 index 0000000..c4eff03 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_powerpoint.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_put.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_put.png new file mode 100644 index 0000000..884ffd6 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_put.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_ruby.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_ruby.png new file mode 100644 index 0000000..f59b7c4 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_ruby.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_stack.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_stack.png new file mode 100644 index 0000000..44084ad Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_stack.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_star.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_star.png new file mode 100644 index 0000000..3a1441c Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_star.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_swoosh.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_swoosh.png new file mode 100644 index 0000000..e770829 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_swoosh.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_text.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_text.png new file mode 100644 index 0000000..813f712 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_text.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_text_width.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_text_width.png new file mode 100644 index 0000000..d9cf132 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_text_width.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_tux.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_tux.png new file mode 100644 index 0000000..52699bf Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_tux.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_vector.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_vector.png new file mode 100644 index 0000000..4a05955 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_vector.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_visualstudio.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_visualstudio.png new file mode 100644 index 0000000..a0a433d Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_visualstudio.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_width.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_width.png new file mode 100644 index 0000000..1eb8809 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_width.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_word.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_word.png new file mode 100644 index 0000000..ae8ecbf Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_word.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_world.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_world.png new file mode 100644 index 0000000..6ed2490 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_world.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_wrench.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_wrench.png new file mode 100644 index 0000000..fecadd0 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_wrench.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_zip.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_zip.png new file mode 100644 index 0000000..fd4bbcc Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_zip.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_word.png b/node_modules/express/node_modules/connect/lib/public/icons/page_word.png new file mode 100644 index 0000000..834cdfa Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_word.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_world.png b/node_modules/express/node_modules/connect/lib/public/icons/page_world.png new file mode 100644 index 0000000..b8895dd Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_world.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/style.css b/node_modules/express/node_modules/connect/lib/public/style.css new file mode 100644 index 0000000..32b6507 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/public/style.css @@ -0,0 +1,141 @@ +body { + margin: 0; + padding: 80px 100px; + font: 13px "Helvetica Neue", "Lucida Grande", "Arial"; + background: #ECE9E9 -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9)); + background: #ECE9E9 -moz-linear-gradient(top, #fff, #ECE9E9); + background-repeat: no-repeat; + color: #555; + -webkit-font-smoothing: antialiased; +} +h1, h2, h3 { + margin: 0; + font-size: 22px; + color: #343434; +} +h1 em, h2 em { + padding: 0 5px; + font-weight: normal; +} +h1 { + font-size: 60px; +} +h2 { + margin-top: 10px; +} +h3 { + margin: 5px 0 10px 0; + padding-bottom: 5px; + border-bottom: 1px solid #eee; + font-size: 18px; +} +ul { + margin: 0; + padding: 0; +} +ul li { + margin: 5px 0; + padding: 3px 8px; + list-style: none; +} +ul li:hover { + cursor: pointer; + color: #2e2e2e; +} +ul li .path { + padding-left: 5px; + font-weight: bold; +} +ul li .line { + padding-right: 5px; + font-style: italic; +} +ul li:first-child .path { + padding-left: 0; +} +p { + line-height: 1.5; +} +a { + color: #555; + text-decoration: none; +} +a:hover { + color: #303030; +} +#stacktrace { + margin-top: 15px; +} +.directory h1 { + margin-bottom: 15px; + font-size: 18px; +} +ul#files { + width: 100%; + height: 500px; +} +ul#files li { + padding: 0; +} +ul#files li img { + position: absolute; + top: 5px; + left: 5px; +} +ul#files li a { + position: relative; + display: block; + margin: 1px; + width: 30%; + height: 25px; + line-height: 25px; + text-indent: 8px; + float: left; + border: 1px solid transparent; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + overflow: hidden; + text-overflow: ellipsis; +} +ul#files li a.icon { + text-indent: 25px; +} +ul#files li a:focus, +ul#files li a:hover { + outline: none; + background: rgba(255,255,255,0.65); + border: 1px solid #ececec; +} +ul#files li a.highlight { + -webkit-transition: background .4s ease-in-out; + background: #ffff4f; + border-color: #E9DC51; +} +#search { + display: block; + position: fixed; + top: 20px; + right: 20px; + width: 90px; + -webkit-transition: width ease 0.2s, opacity ease 0.4s; + -moz-transition: width ease 0.2s, opacity ease 0.4s; + -webkit-border-radius: 32px; + -moz-border-radius: 32px; + -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); + -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); + -webkit-font-smoothing: antialiased; + text-align: left; + font: 13px "Helvetica Neue", Arial, sans-serif; + padding: 4px 10px; + border: none; + background: transparent; + margin-bottom: 0; + outline: none; + opacity: 0.7; + color: #888; +} +#search:focus { + width: 120px; + opacity: 1.0; +} diff --git a/node_modules/express/node_modules/connect/lib/utils.js b/node_modules/express/node_modules/connect/lib/utils.js new file mode 100644 index 0000000..d52009a --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/utils.js @@ -0,0 +1,386 @@ + +/*! + * Connect - utils + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var http = require('http') + , crypto = require('crypto') + , parse = require('url').parse + , signature = require('cookie-signature') + , nodeVersion = process.versions.node.split('.'); + +// pause is broken in node < 0.10 +exports.brokenPause = parseInt(nodeVersion[0], 10) === 0 + && parseInt(nodeVersion[1], 10) < 10; + +/** + * Return `true` if the request has a body, otherwise return `false`. + * + * @param {IncomingMessage} req + * @return {Boolean} + * @api private + */ + +exports.hasBody = function(req) { + var encoding = 'transfer-encoding' in req.headers; + var length = 'content-length' in req.headers && req.headers['content-length'] !== '0'; + return encoding || length; +}; + +/** + * Extract the mime type from the given request's + * _Content-Type_ header. + * + * @param {IncomingMessage} req + * @return {String} + * @api private + */ + +exports.mime = function(req) { + var str = req.headers['content-type'] || ''; + return str.split(';')[0]; +}; + +/** + * Generate an `Error` from the given status `code` + * and optional `msg`. + * + * @param {Number} code + * @param {String} msg + * @return {Error} + * @api private + */ + +exports.error = function(code, msg){ + var err = new Error(msg || http.STATUS_CODES[code]); + err.status = code; + return err; +}; + +/** + * Return md5 hash of the given string and optional encoding, + * defaulting to hex. + * + * utils.md5('wahoo'); + * // => "e493298061761236c96b02ea6aa8a2ad" + * + * @param {String} str + * @param {String} encoding + * @return {String} + * @api private + */ + +exports.md5 = function(str, encoding){ + return crypto + .createHash('md5') + .update(str) + .digest(encoding || 'hex'); +}; + +/** + * Merge object b with object a. + * + * var a = { foo: 'bar' } + * , b = { bar: 'baz' }; + * + * utils.merge(a, b); + * // => { foo: 'bar', bar: 'baz' } + * + * @param {Object} a + * @param {Object} b + * @return {Object} + * @api private + */ + +exports.merge = function(a, b){ + if (a && b) { + for (var key in b) { + a[key] = b[key]; + } + } + return a; +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + +/** + * Sign the given `val` with `secret`. + * + * @param {String} val + * @param {String} secret + * @return {String} + * @api private + */ + +exports.sign = function(val, secret){ + console.warn('do not use utils.sign(), use https://github.com/visionmedia/node-cookie-signature') + return val + '.' + crypto + .createHmac('sha256', secret) + .update(val) + .digest('base64') + .replace(/=+$/, ''); +}; + +/** + * Unsign and decode the given `val` with `secret`, + * returning `false` if the signature is invalid. + * + * @param {String} val + * @param {String} secret + * @return {String|Boolean} + * @api private + */ + +exports.unsign = function(val, secret){ + console.warn('do not use utils.unsign(), use https://github.com/visionmedia/node-cookie-signature') + var str = val.slice(0, val.lastIndexOf('.')); + return exports.sign(str, secret) == val + ? str + : false; +}; + +/** + * Parse signed cookies, returning an object + * containing the decoded key/value pairs, + * while removing the signed key from `obj`. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +exports.parseSignedCookies = function(obj, secret){ + var ret = {}; + Object.keys(obj).forEach(function(key){ + var val = obj[key]; + if (0 == val.indexOf('s:')) { + val = signature.unsign(val.slice(2), secret); + if (val) { + ret[key] = val; + delete obj[key]; + } + } + }); + return ret; +}; + +/** + * Parse a signed cookie string, return the decoded value + * + * @param {String} str signed cookie string + * @param {String} secret + * @return {String} decoded value + * @api private + */ + +exports.parseSignedCookie = function(str, secret){ + return 0 == str.indexOf('s:') + ? signature.unsign(str.slice(2), secret) + : str; +}; + +/** + * Parse JSON cookies. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +exports.parseJSONCookies = function(obj){ + Object.keys(obj).forEach(function(key){ + var val = obj[key]; + var res = exports.parseJSONCookie(val); + if (res) obj[key] = res; + }); + return obj; +}; + +/** + * Parse JSON cookie string + * + * @param {String} str + * @return {Object} Parsed object or null if not json cookie + * @api private + */ + +exports.parseJSONCookie = function(str) { + if (0 == str.indexOf('j:')) { + try { + return JSON.parse(str.slice(2)); + } catch (err) { + // no op + } + } +}; + +/** + * Pause `data` and `end` events on the given `obj`. + * Middleware performing async tasks _should_ utilize + * this utility (or similar), to re-emit data once + * the async operation has completed, otherwise these + * events may be lost. Pause is only required for + * node versions less than 10, and is replaced with + * noop's otherwise. + * + * var pause = utils.pause(req); + * fs.readFile(path, function(){ + * next(); + * pause.resume(); + * }); + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +exports.pause = exports.brokenPause + ? require('pause') + : function () { + return { + end: noop, + resume: noop + } + } + +/** + * Strip `Content-*` headers from `res`. + * + * @param {ServerResponse} res + * @api private + */ + +exports.removeContentHeaders = function(res){ + Object.keys(res._headers).forEach(function(field){ + if (0 == field.indexOf('content')) { + res.removeHeader(field); + } + }); +}; + +/** + * Check if `req` is a conditional GET request. + * + * @param {IncomingMessage} req + * @return {Boolean} + * @api private + */ + +exports.conditionalGET = function(req) { + return req.headers['if-modified-since'] + || req.headers['if-none-match']; +}; + +/** + * Respond with 401 "Unauthorized". + * + * @param {ServerResponse} res + * @param {String} realm + * @api private + */ + +exports.unauthorized = function(res, realm) { + res.statusCode = 401; + res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"'); + res.end('Unauthorized'); +}; + +/** + * Respond with 304 "Not Modified". + * + * @param {ServerResponse} res + * @param {Object} headers + * @api private + */ + +exports.notModified = function(res) { + exports.removeContentHeaders(res); + res.statusCode = 304; + res.end(); +}; + +/** + * Return an ETag in the form of `"-"` + * from the given `stat`. + * + * @param {Object} stat + * @return {String} + * @api private + */ + +exports.etag = function(stat) { + return '"' + stat.size + '-' + Number(stat.mtime) + '"'; +}; + +/** + * Parse the given Cache-Control `str`. + * + * @param {String} str + * @return {Object} + * @api private + */ + +exports.parseCacheControl = function(str){ + var directives = str.split(',') + , obj = {}; + + for(var i = 0, len = directives.length; i < len; i++) { + var parts = directives[i].split('=') + , key = parts.shift().trim() + , val = parseInt(parts.shift(), 10); + + obj[key] = isNaN(val) ? true : val; + } + + return obj; +}; + +/** + * Parse the `req` url with memoization. + * + * @param {ServerRequest} req + * @return {Object} + * @api private + */ + +exports.parseUrl = function(req){ + var parsed = req._parsedUrl; + if (parsed && parsed.href == req.url) { + return parsed; + } else { + return req._parsedUrl = parse(req.url); + } +}; + +/** + * Parse byte `size` string. + * + * @param {String} size + * @return {Number} + * @api private + */ + +exports.parseBytes = require('bytes'); + +function noop() {} diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/.npmignore b/node_modules/express/node_modules/connect/node_modules/bytes/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/History.md b/node_modules/express/node_modules/connect/node_modules/bytes/History.md new file mode 100644 index 0000000..1332808 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/History.md @@ -0,0 +1,10 @@ + +0.2.0 / 2012-10-28 +================== + + * bytes(200).should.eql('200b') + +0.1.0 / 2012-07-04 +================== + + * add bytes to string conversion [yields] diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/Makefile b/node_modules/express/node_modules/connect/node_modules/bytes/Makefile new file mode 100644 index 0000000..8e8640f --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --reporter spec \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/Readme.md b/node_modules/express/node_modules/connect/node_modules/bytes/Readme.md new file mode 100644 index 0000000..9325d5b --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/Readme.md @@ -0,0 +1,51 @@ +# node-bytes + + Byte string parser / formatter. + +## Example: + +```js +bytes('1kb') +// => 1024 + +bytes('2mb') +// => 2097152 + +bytes('1gb') +// => 1073741824 + +bytes(1073741824) +// => 1gb +``` + +## Installation + +``` +$ npm install bytes +$ component install visionmedia/bytes.js +``` + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/component.json b/node_modules/express/node_modules/connect/node_modules/bytes/component.json new file mode 100644 index 0000000..76a6057 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/component.json @@ -0,0 +1,7 @@ +{ + "name": "bytes", + "description": "byte size string parser / serializer", + "keywords": ["bytes", "utility"], + "version": "0.1.0", + "scripts": ["index.js"] +} diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/index.js b/node_modules/express/node_modules/connect/node_modules/bytes/index.js new file mode 100644 index 0000000..70b2e01 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/index.js @@ -0,0 +1,39 @@ + +/** + * Parse byte `size` string. + * + * @param {String} size + * @return {Number} + * @api public + */ + +module.exports = function(size) { + if ('number' == typeof size) return convert(size); + var parts = size.match(/^(\d+(?:\.\d+)?) *(kb|mb|gb)$/) + , n = parseFloat(parts[1]) + , type = parts[2]; + + var map = { + kb: 1 << 10 + , mb: 1 << 20 + , gb: 1 << 30 + }; + + return map[type] * n; +}; + +/** + * convert bytes into string. + * + * @param {Number} b - bytes to convert + * @return {String} + * @api public + */ + +function convert (b) { + var gb = 1 << 30, mb = 1 << 20, kb = 1 << 10; + if (b >= gb) return (Math.round(b / gb * 100) / 100) + 'gb'; + if (b >= mb) return (Math.round(b / mb * 100) / 100) + 'mb'; + if (b >= kb) return (Math.round(b / kb * 100) / 100) + 'kb'; + return b + 'b'; +} diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/package.json b/node_modules/express/node_modules/connect/node_modules/bytes/package.json new file mode 100644 index 0000000..2f10433 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/package.json @@ -0,0 +1,24 @@ +{ + "name": "bytes", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "description": "byte size string parser / serializer", + "version": "0.2.0", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "readme": "# node-bytes\n\n Byte string parser / formatter.\n\n## Example:\n\n```js\nbytes('1kb')\n// => 1024\n\nbytes('2mb')\n// => 2097152\n\nbytes('1gb')\n// => 1073741824\n\nbytes(1073741824)\n// => 1gb\n```\n\n## Installation\n\n```\n$ npm install bytes\n$ component install visionmedia/bytes.js\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 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", + "readmeFilename": "Readme.md", + "_id": "bytes@0.2.0", + "dist": { + "shasum": "6455d77a156ca2aa32c3319bf9139cbcf45c892a" + }, + "_from": "bytes@0.2.0", + "_resolved": "https://registry.npmjs.org/bytes/-/bytes-0.2.0.tgz" +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore b/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore new file mode 100644 index 0000000..4fbabb3 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore @@ -0,0 +1,4 @@ +/test/tmp/ +*.upload +*.un~ +*.http diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml b/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml new file mode 100644 index 0000000..cb931cb --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.8 + - 0.9 + - "0.10" diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/LICENSE b/node_modules/express/node_modules/connect/node_modules/formidable/LICENSE new file mode 100644 index 0000000..38d3c9c --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/LICENSE @@ -0,0 +1,7 @@ +Copyright (C) 2011 Felix Geisendörfer + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md b/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md new file mode 100644 index 0000000..08e9eca --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md @@ -0,0 +1,419 @@ +# Formidable + +[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png?branch=master)](http://travis-ci.org/felixge/node-formidable) + +## Purpose + +A node.js module for parsing form data, especially file uploads. + +## Current status + +This module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading +and encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from +a large variety of clients and is considered production-ready. + +## Features + +* Fast (~500mb/sec), non-buffering multipart parser +* Automatically writing file uploads to disk +* Low memory footprint +* Graceful error handling +* Very high test coverage + +## Installation + +Via [npm](http://github.com/isaacs/npm): +``` +npm install formidable@latest +``` +Manually: +``` +git clone git://github.com/felixge/node-formidable.git formidable +vim my.js +# var formidable = require('./formidable'); +``` + +Note: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library. + +## Example + +Parse an incoming file upload. +```javascript +var formidable = require('formidable'), + http = require('http'), + util = require('util'); + +http.createServer(function(req, res) { + if (req.url == '/upload' && req.method.toLowerCase() == 'post') { + // parse a file upload + var form = new formidable.IncomingForm(); + + form.parse(req, function(err, fields, files) { + res.writeHead(200, {'content-type': 'text/plain'}); + res.write('received upload:\n\n'); + res.end(util.inspect({fields: fields, files: files})); + }); + + return; + } + + // show a file upload form + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '
    ' + ); +}).listen(8080); +``` +## API + +### Formidable.IncomingForm +```javascript +var form = new formidable.IncomingForm() +``` +Creates a new incoming form. + +```javascript +form.encoding = 'utf-8'; +``` +Sets encoding for incoming form fields. + +```javascript +form.uploadDir = process.env.TMP || process.env.TMPDIR || process.env.TEMP || '/tmp' || process.cwd(); +``` +The directory for placing file uploads in. You can move them later on using +`fs.rename()`. The default directory is picked at module load time depending on +the first existing directory from those listed above. + +```javascript +form.keepExtensions = false; +``` +If you want the files written to `form.uploadDir` to include the extensions of the original files, set this property to `true`. + +```javascript +form.type +``` +Either 'multipart' or 'urlencoded' depending on the incoming request. + +```javascript +form.maxFieldsSize = 2 * 1024 * 1024; +``` +Limits the amount of memory a field (not file) can allocate in bytes. +If this value is exceeded, an `'error'` event is emitted. The default +size is 2MB. + +```javascript +form.maxFields = 0; +``` +Limits the number of fields that the querystring parser will decode. Defaults +to 0 (unlimited). + +```javascript +form.hash = false; +``` +If you want checksums calculated for incoming files, set this to either `'sha1'` or `'md5'`. + +```javascript +form.bytesReceived +``` +The amount of bytes received for this form so far. + +```javascript +form.bytesExpected +``` +The expected number of bytes in this form. + +```javascript +form.parse(request, [cb]); +``` +Parses an incoming node.js `request` containing form data. If `cb` is provided, all fields an files are collected and passed to the callback: + + +```javascript +form.parse(req, function(err, fields, files) { + // ... +}); + +form.onPart(part); +``` +You may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events processing which would occur otherwise, making you fully responsible for handling the processing. + +```javascript +form.onPart = function(part) { + part.addListener('data', function() { + // ... + }); +} +``` +If you want to use formidable to only handle certain parts for you, you can do so: +```javascript +form.onPart = function(part) { + if (!part.filename) { + // let formidable handle all non-file parts + form.handlePart(part); + } +} +``` +Check the code in this method for further inspiration. + + +### Formidable.File +```javascript +file.size = 0 +``` +The size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet. +```javascript +file.path = null +``` +The path this file is being written to. You can modify this in the `'fileBegin'` event in +case you are unhappy with the way formidable generates a temporary path for your files. +```javascript +file.name = null +``` +The name this file had according to the uploading client. +```javascript +file.type = null +``` +The mime type of this file, according to the uploading client. +```javascript +file.lastModifiedDate = null +``` +A date object (or `null`) containing the time this file was last written to. Mostly +here for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/). +```javascript +file.hash = null +``` +If hash calculation was set, you can read the hex digest out of this var. + +#### Formidable.File#toJSON() + + This method returns a JSON-representation of the file, allowing you to + `JSON.stringify()` the file which is useful for logging and responding + to requests. + +### Events + + +#### 'progress' +```javascript +form.on('progress', function(bytesReceived, bytesExpected) { +}); +``` +Emitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar. + + + +#### 'field' +```javascript +form.on('field', function(name, value) { +}); +``` + +#### 'fileBegin' + +Emitted whenever a field / value pair has been received. +```javascript +form.on('fileBegin', function(name, file) { +}); +``` + +#### 'file' + +Emitted whenever a new file is detected in the upload stream. Use this even if +you want to stream the file to somewhere else while buffering the upload on +the file system. + +Emitted whenever a field / file pair has been received. `file` is an instance of `File`. +```javascript +form.on('file', function(name, file) { +}); +``` + +#### 'error' + +Emitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events. +```javascript +form.on('error', function(err) { +}); +``` + +#### 'aborted' + + +Emitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. In the future there will be a separate 'timeout' event (needs a change in the node core). +```javascript +form.on('aborted', function() { +}); +``` + +##### 'end' +```javascript +form.on('end', function() { +}); +``` +Emitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response. + + + +## Changelog + +### v1.0.14 + +* Add failing hash tests. (Ben Trask) +* Enable hash calculation again (Eugene Girshov) +* Test for immediate data events (Tim Smart) +* Re-arrange IncomingForm#parse (Tim Smart) + +### v1.0.13 + +* Only update hash if update method exists (Sven Lito) +* According to travis v0.10 needs to go quoted (Sven Lito) +* Bumping build node versions (Sven Lito) +* Additional fix for empty requests (Eugene Girshov) +* Change the default to 1000, to match the new Node behaviour. (OrangeDog) +* Add ability to control maxKeys in the querystring parser. (OrangeDog) +* Adjust test case to work with node 0.9.x (Eugene Girshov) +* Update package.json (Sven Lito) +* Path adjustment according to eb4468b (Markus Ast) + +### v1.0.12 + +* Emit error on aborted connections (Eugene Girshov) +* Add support for empty requests (Eugene Girshov) +* Fix name/filename handling in Content-Disposition (jesperp) +* Tolerate malformed closing boundary in multipart (Eugene Girshov) +* Ignore preamble in multipart messages (Eugene Girshov) +* Add support for application/json (Mike Frey, Carlos Rodriguez) +* Add support for Base64 encoding (Elmer Bulthuis) +* Add File#toJSON (TJ Holowaychuk) +* Remove support for Node.js 0.4 & 0.6 (Andrew Kelley) +* Documentation improvements (Sven Lito, Andre Azevedo) +* Add support for application/octet-stream (Ion Lupascu, Chris Scribner) +* Use os.tmpDir() to get tmp directory (Andrew Kelley) +* Improve package.json (Andrew Kelley, Sven Lito) +* Fix benchmark script (Andrew Kelley) +* Fix scope issue in incoming_forms (Sven Lito) +* Fix file handle leak on error (OrangeDog) + +### v1.0.11 + +* Calculate checksums for incoming files (sreuter) +* Add definition parameters to "IncomingForm" as an argument (Math-) + +### v1.0.10 + +* Make parts to be proper Streams (Matt Robenolt) + +### v1.0.9 + +* Emit progress when content length header parsed (Tim Koschützki) +* Fix Readme syntax due to GitHub changes (goob) +* Replace references to old 'sys' module in Readme with 'util' (Peter Sugihara) + +### v1.0.8 + +* Strip potentially unsafe characters when using `keepExtensions: true`. +* Switch to utest / urun for testing +* Add travis build + +### v1.0.7 + +* Remove file from package that was causing problems when installing on windows. (#102) +* Fix typos in Readme (Jason Davies). + +### v1.0.6 + +* Do not default to the default to the field name for file uploads where + filename="". + +### v1.0.5 + +* Support filename="" in multipart parts +* Explain unexpected end() errors in parser better + +**Note:** Starting with this version, formidable emits 'file' events for empty +file input fields. Previously those were incorrectly emitted as regular file +input fields with value = "". + +### v1.0.4 + +* Detect a good default tmp directory regardless of platform. (#88) + +### v1.0.3 + +* Fix problems with utf8 characters (#84) / semicolons in filenames (#58) +* Small performance improvements +* New test suite and fixture system + +### v1.0.2 + +* Exclude node\_modules folder from git +* Implement new `'aborted'` event +* Fix files in example folder to work with recent node versions +* Make gently a devDependency + +[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2) + +### v1.0.1 + +* Fix package.json to refer to proper main directory. (#68, Dean Landolt) + +[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1) + +### v1.0.0 + +* Add support for multipart boundaries that are quoted strings. (Jeff Craig) + +This marks the beginning of development on version 2.0 which will include +several architectural improvements. + +[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0) + +### v0.9.11 + +* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim Koschützki) +* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class + +**Important:** The old property names of the File class will be removed in a +future release. + +[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11) + +### Older releases + +These releases were done before starting to maintain the above Changelog: + +* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10) +* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9) +* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8) +* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7) +* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6) +* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5) +* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4) +* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3) +* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2) +* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0) + +## License + +Formidable is licensed under the MIT license. + +## Ports + +* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable + +## Credits + +* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js new file mode 100644 index 0000000..49abc43 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js @@ -0,0 +1,71 @@ +var assert = require('assert'); +require('../test/common'); +var multipartParser = require('../lib/multipart_parser'), + MultipartParser = multipartParser.MultipartParser, + parser = new MultipartParser(), + Buffer = require('buffer').Buffer, + boundary = '-----------------------------168072824752491622650073', + mb = 100, + buffer = createMultipartBuffer(boundary, mb * 1024 * 1024), + callbacks = + { partBegin: -1, + partEnd: -1, + headerField: -1, + headerValue: -1, + partData: -1, + end: -1, + }; + + +parser.initWithBoundary(boundary); +parser.onHeaderField = function() { + callbacks.headerField++; +}; + +parser.onHeaderValue = function() { + callbacks.headerValue++; +}; + +parser.onPartBegin = function() { + callbacks.partBegin++; +}; + +parser.onPartData = function() { + callbacks.partData++; +}; + +parser.onPartEnd = function() { + callbacks.partEnd++; +}; + +parser.onEnd = function() { + callbacks.end++; +}; + +var start = +new Date(), + nparsed = parser.write(buffer), + duration = +new Date - start, + mbPerSec = (mb / (duration / 1000)).toFixed(2); + +console.log(mbPerSec+' mb/sec'); + +assert.equal(nparsed, buffer.length); + +function createMultipartBuffer(boundary, size) { + var head = + '--'+boundary+'\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + '\r\n' + , tail = '\r\n--'+boundary+'--\r\n' + , buffer = new Buffer(size); + + buffer.write(head, 'ascii', 0); + buffer.write(tail, 'ascii', buffer.length - tail.length); + return buffer; +} + +process.on('exit', function() { + for (var k in callbacks) { + assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]); + } +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/example/json.js b/node_modules/express/node_modules/connect/node_modules/formidable/example/json.js new file mode 100644 index 0000000..eb8a724 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/example/json.js @@ -0,0 +1,67 @@ +var common = require('../test/common'), + http = require('http'), + util = require('util'), + formidable = common.formidable, + Buffer = require('buffer').Buffer, + port = common.port, + server; + +server = http.createServer(function(req, res) { + if (req.method !== 'POST') { + res.writeHead(200, {'content-type': 'text/plain'}) + res.end('Please POST a JSON payload to http://localhost:'+port+'/') + return; + } + + var form = new formidable.IncomingForm(), + fields = {}; + + form + .on('error', function(err) { + res.writeHead(500, {'content-type': 'text/plain'}); + res.end('error:\n\n'+util.inspect(err)); + console.error(err); + }) + .on('field', function(field, value) { + console.log(field, value); + fields[field] = value; + }) + .on('end', function() { + console.log('-> post done'); + res.writeHead(200, {'content-type': 'text/plain'}); + res.end('received fields:\n\n '+util.inspect(fields)); + }); + form.parse(req); +}); +server.listen(port); + +console.log('listening on http://localhost:'+port+'/'); + + +var request = http.request({ + host: 'localhost', + path: '/', + port: port, + method: 'POST', + headers: { 'content-type':'application/json', 'content-length':48 } +}, function(response) { + var data = ''; + console.log('\nServer responded with:'); + console.log('Status:', response.statusCode); + response.pipe(process.stdout); + response.on('end', function() { + console.log('\n') + process.exit(); + }); + // response.on('data', function(chunk) { + // data += chunk.toString('utf8'); + // }); + // response.on('end', function() { + // console.log('Response Data:') + // console.log(data); + // process.exit(); + // }); +}) + +request.write('{"numbers":[1,2,3,4,5],"nested":{"key":"value"}}'); +request.end(); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js b/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js new file mode 100644 index 0000000..f6c15a6 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js @@ -0,0 +1,43 @@ +require('../test/common'); +var http = require('http'), + util = require('util'), + formidable = require('formidable'), + server; + +server = http.createServer(function(req, res) { + if (req.url == '/') { + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '
    ' + ); + } else if (req.url == '/post') { + var form = new formidable.IncomingForm(), + fields = []; + + form + .on('error', function(err) { + res.writeHead(200, {'content-type': 'text/plain'}); + res.end('error:\n\n'+util.inspect(err)); + }) + .on('field', function(field, value) { + console.log(field, value); + fields.push([field, value]); + }) + .on('end', function() { + console.log('-> post done'); + res.writeHead(200, {'content-type': 'text/plain'}); + res.end('received fields:\n\n '+util.inspect(fields)); + }); + form.parse(req); + } else { + res.writeHead(404, {'content-type': 'text/plain'}); + res.end('404'); + } +}); +server.listen(TEST_PORT); + +console.log('listening on http://localhost:'+TEST_PORT+'/'); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js b/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js new file mode 100644 index 0000000..050cdd9 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js @@ -0,0 +1,48 @@ +require('../test/common'); +var http = require('http'), + util = require('util'), + formidable = require('formidable'), + server; + +server = http.createServer(function(req, res) { + if (req.url == '/') { + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '
    ' + ); + } else if (req.url == '/upload') { + var form = new formidable.IncomingForm(), + files = [], + fields = []; + + form.uploadDir = TEST_TMP; + + form + .on('field', function(field, value) { + console.log(field, value); + fields.push([field, value]); + }) + .on('file', function(field, file) { + console.log(field, file); + files.push([field, file]); + }) + .on('end', function() { + console.log('-> upload done'); + res.writeHead(200, {'content-type': 'text/plain'}); + res.write('received fields:\n\n '+util.inspect(fields)); + res.write('\n\n'); + res.end('received files:\n\n '+util.inspect(files)); + }); + form.parse(req); + } else { + res.writeHead(404, {'content-type': 'text/plain'}); + res.end('404'); + } +}); +server.listen(TEST_PORT); + +console.log('listening on http://localhost:'+TEST_PORT+'/'); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/index.js b/node_modules/express/node_modules/connect/node_modules/formidable/index.js new file mode 100644 index 0000000..4cc88b3 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/index.js @@ -0,0 +1 @@ +module.exports = require('./lib'); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js new file mode 100644 index 0000000..e34c10e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js @@ -0,0 +1,72 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +var util = require('util'), + WriteStream = require('fs').WriteStream, + EventEmitter = require('events').EventEmitter, + crypto = require('crypto'); + +function File(properties) { + EventEmitter.call(this); + + this.size = 0; + this.path = null; + this.name = null; + this.type = null; + this.hash = null; + this.lastModifiedDate = null; + + this._writeStream = null; + + for (var key in properties) { + this[key] = properties[key]; + } + + if(typeof this.hash === 'string') { + this.hash = crypto.createHash(properties.hash); + } else { + this.hash = null; + } +} +module.exports = File; +util.inherits(File, EventEmitter); + +File.prototype.open = function() { + this._writeStream = new WriteStream(this.path); +}; + +File.prototype.toJSON = function() { + return { + size: this.size, + path: this.path, + name: this.name, + type: this.type, + mtime: this.lastModifiedDate, + length: this.length, + filename: this.filename, + mime: this.mime + }; +}; + +File.prototype.write = function(buffer, cb) { + var self = this; + if (self.hash) { + self.hash.update(buffer); + } + this._writeStream.write(buffer, function() { + self.lastModifiedDate = new Date(); + self.size += buffer.length; + self.emit('progress', self.size); + cb(); + }); +}; + +File.prototype.end = function(cb) { + var self = this; + if (self.hash) { + self.hash = self.hash.digest('hex'); + } + this._writeStream.end(function() { + self.emit('end'); + cb(); + }); +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js new file mode 100644 index 0000000..c2eeaf8 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js @@ -0,0 +1,535 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +var fs = require('fs'); +var util = require('util'), + path = require('path'), + File = require('./file'), + MultipartParser = require('./multipart_parser').MultipartParser, + QuerystringParser = require('./querystring_parser').QuerystringParser, + OctetParser = require('./octet_parser').OctetParser, + JSONParser = require('./json_parser').JSONParser, + StringDecoder = require('string_decoder').StringDecoder, + EventEmitter = require('events').EventEmitter, + Stream = require('stream').Stream, + os = require('os'); + +function IncomingForm(opts) { + if (!(this instanceof IncomingForm)) return new IncomingForm(opts); + EventEmitter.call(this); + + opts=opts||{}; + + this.error = null; + this.ended = false; + + this.maxFields = opts.maxFields || 1000; + this.maxFieldsSize = opts.maxFieldsSize || 2 * 1024 * 1024; + this.keepExtensions = opts.keepExtensions || false; + this.uploadDir = opts.uploadDir || os.tmpDir(); + this.encoding = opts.encoding || 'utf-8'; + this.headers = null; + this.type = null; + this.hash = false; + + this.bytesReceived = null; + this.bytesExpected = null; + + this._parser = null; + this._flushing = 0; + this._fieldsSize = 0; + this.openedFiles = []; + + return this; +}; +util.inherits(IncomingForm, EventEmitter); +exports.IncomingForm = IncomingForm; + +IncomingForm.prototype.parse = function(req, cb) { + this.pause = function() { + try { + req.pause(); + } catch (err) { + // the stream was destroyed + if (!this.ended) { + // before it was completed, crash & burn + this._error(err); + } + return false; + } + return true; + }; + + this.resume = function() { + try { + req.resume(); + } catch (err) { + // the stream was destroyed + if (!this.ended) { + // before it was completed, crash & burn + this._error(err); + } + return false; + } + + return true; + }; + + // Setup callback first, so we don't miss anything from data events emitted + // immediately. + if (cb) { + var fields = {}, files = {}; + this + .on('field', function(name, value) { + fields[name] = value; + }) + .on('file', function(name, file) { + files[name] = file; + }) + .on('error', function(err) { + cb(err, fields, files); + }) + .on('end', function() { + cb(null, fields, files); + }); + } + + // Parse headers and setup the parser, ready to start listening for data. + this.writeHeaders(req.headers); + + // Start listening for data. + var self = this; + req + .on('error', function(err) { + self._error(err); + }) + .on('aborted', function() { + self.emit('aborted'); + self._error(new Error('Request aborted')); + }) + .on('data', function(buffer) { + self.write(buffer); + }) + .on('end', function() { + if (self.error) { + return; + } + + var err = self._parser.end(); + if (err) { + self._error(err); + } + }); + + return this; +}; + +IncomingForm.prototype.writeHeaders = function(headers) { + this.headers = headers; + this._parseContentLength(); + this._parseContentType(); +}; + +IncomingForm.prototype.write = function(buffer) { + if (!this._parser) { + this._error(new Error('unintialized parser')); + return; + } + + this.bytesReceived += buffer.length; + this.emit('progress', this.bytesReceived, this.bytesExpected); + + var bytesParsed = this._parser.write(buffer); + if (bytesParsed !== buffer.length) { + this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed')); + } + + return bytesParsed; +}; + +IncomingForm.prototype.pause = function() { + // this does nothing, unless overwritten in IncomingForm.parse + return false; +}; + +IncomingForm.prototype.resume = function() { + // this does nothing, unless overwritten in IncomingForm.parse + return false; +}; + +IncomingForm.prototype.onPart = function(part) { + // this method can be overwritten by the user + this.handlePart(part); +}; + +IncomingForm.prototype.handlePart = function(part) { + var self = this; + + if (part.filename === undefined) { + var value = '' + , decoder = new StringDecoder(this.encoding); + + part.on('data', function(buffer) { + self._fieldsSize += buffer.length; + if (self._fieldsSize > self.maxFieldsSize) { + self._error(new Error('maxFieldsSize exceeded, received '+self._fieldsSize+' bytes of field data')); + return; + } + value += decoder.write(buffer); + }); + + part.on('end', function() { + self.emit('field', part.name, value); + }); + return; + } + + this._flushing++; + + var file = new File({ + path: this._uploadPath(part.filename), + name: part.filename, + type: part.mime, + hash: self.hash + }); + + this.emit('fileBegin', part.name, file); + + file.open(); + this.openedFiles.push(file); + + part.on('data', function(buffer) { + self.pause(); + file.write(buffer, function() { + self.resume(); + }); + }); + + part.on('end', function() { + file.end(function() { + self._flushing--; + self.emit('file', part.name, file); + self._maybeEnd(); + }); + }); +}; + +function dummyParser(self) { + return { + end: function () { + self.ended = true; + self._maybeEnd(); + return null; + } + }; +} + +IncomingForm.prototype._parseContentType = function() { + if (this.bytesExpected === 0) { + this._parser = dummyParser(this); + return; + } + + if (!this.headers['content-type']) { + this._error(new Error('bad content-type header, no content-type')); + return; + } + + if (this.headers['content-type'].match(/octet-stream/i)) { + this._initOctetStream(); + return; + } + + if (this.headers['content-type'].match(/urlencoded/i)) { + this._initUrlencoded(); + return; + } + + if (this.headers['content-type'].match(/multipart/i)) { + var m; + if (m = this.headers['content-type'].match(/boundary=(?:"([^"]+)"|([^;]+))/i)) { + this._initMultipart(m[1] || m[2]); + } else { + this._error(new Error('bad content-type header, no multipart boundary')); + } + return; + } + + if (this.headers['content-type'].match(/json/i)) { + this._initJSONencoded(); + return; + } + + this._error(new Error('bad content-type header, unknown content-type: '+this.headers['content-type'])); +}; + +IncomingForm.prototype._error = function(err) { + if (this.error || this.ended) { + return; + } + + this.error = err; + this.pause(); + this.emit('error', err); + + if (Array.isArray(this.openedFiles)) { + this.openedFiles.forEach(function(file) { + file._writeStream.destroy(); + setTimeout(fs.unlink, 0, file.path); + }); + } +}; + +IncomingForm.prototype._parseContentLength = function() { + this.bytesReceived = 0; + if (this.headers['content-length']) { + this.bytesExpected = parseInt(this.headers['content-length'], 10); + } else if (this.headers['transfer-encoding'] === undefined) { + this.bytesExpected = 0; + } + + if (this.bytesExpected !== null) { + this.emit('progress', this.bytesReceived, this.bytesExpected); + } +}; + +IncomingForm.prototype._newParser = function() { + return new MultipartParser(); +}; + +IncomingForm.prototype._initMultipart = function(boundary) { + this.type = 'multipart'; + + var parser = new MultipartParser(), + self = this, + headerField, + headerValue, + part; + + parser.initWithBoundary(boundary); + + parser.onPartBegin = function() { + part = new Stream(); + part.readable = true; + part.headers = {}; + part.name = null; + part.filename = null; + part.mime = null; + + part.transferEncoding = 'binary'; + part.transferBuffer = ''; + + headerField = ''; + headerValue = ''; + }; + + parser.onHeaderField = function(b, start, end) { + headerField += b.toString(self.encoding, start, end); + }; + + parser.onHeaderValue = function(b, start, end) { + headerValue += b.toString(self.encoding, start, end); + }; + + parser.onHeaderEnd = function() { + headerField = headerField.toLowerCase(); + part.headers[headerField] = headerValue; + + var m; + if (headerField == 'content-disposition') { + if (m = headerValue.match(/\bname="([^"]+)"/i)) { + part.name = m[1]; + } + + part.filename = self._fileName(headerValue); + } else if (headerField == 'content-type') { + part.mime = headerValue; + } else if (headerField == 'content-transfer-encoding') { + part.transferEncoding = headerValue.toLowerCase(); + } + + headerField = ''; + headerValue = ''; + }; + + parser.onHeadersEnd = function() { + switch(part.transferEncoding){ + case 'binary': + case '7bit': + case '8bit': + parser.onPartData = function(b, start, end) { + part.emit('data', b.slice(start, end)); + }; + + parser.onPartEnd = function() { + part.emit('end'); + }; + break; + + case 'base64': + parser.onPartData = function(b, start, end) { + part.transferBuffer += b.slice(start, end).toString('ascii'); + + /* + four bytes (chars) in base64 converts to three bytes in binary + encoding. So we should always work with a number of bytes that + can be divided by 4, it will result in a number of buytes that + can be divided vy 3. + */ + var offset = parseInt(part.transferBuffer.length / 4) * 4; + part.emit('data', new Buffer(part.transferBuffer.substring(0, offset), 'base64')) + part.transferBuffer = part.transferBuffer.substring(offset); + }; + + parser.onPartEnd = function() { + part.emit('data', new Buffer(part.transferBuffer, 'base64')) + part.emit('end'); + }; + break; + + default: + return self._error(new Error('unknown transfer-encoding')); + } + + self.onPart(part); + }; + + + parser.onEnd = function() { + self.ended = true; + self._maybeEnd(); + }; + + this._parser = parser; +}; + +IncomingForm.prototype._fileName = function(headerValue) { + var m = headerValue.match(/\bfilename="(.*?)"($|; )/i); + if (!m) return; + + var filename = m[1].substr(m[1].lastIndexOf('\\') + 1); + filename = filename.replace(/%22/g, '"'); + filename = filename.replace(/&#([\d]{4});/g, function(m, code) { + return String.fromCharCode(code); + }); + return filename; +}; + +IncomingForm.prototype._initUrlencoded = function() { + this.type = 'urlencoded'; + + var parser = new QuerystringParser(this.maxFields) + , self = this; + + parser.onField = function(key, val) { + self.emit('field', key, val); + }; + + parser.onEnd = function() { + self.ended = true; + self._maybeEnd(); + }; + + this._parser = parser; +}; + +IncomingForm.prototype._initOctetStream = function() { + this.type = 'octet-stream'; + var filename = this.headers['x-file-name']; + var mime = this.headers['content-type']; + + var file = new File({ + path: this._uploadPath(filename), + name: filename, + type: mime + }); + + file.open(); + + this.emit('fileBegin', filename, file); + + this._flushing++; + + var self = this; + + self._parser = new OctetParser(); + + //Keep track of writes that haven't finished so we don't emit the file before it's done being written + var outstandingWrites = 0; + + self._parser.on('data', function(buffer){ + self.pause(); + outstandingWrites++; + + file.write(buffer, function() { + outstandingWrites--; + self.resume(); + + if(self.ended){ + self._parser.emit('doneWritingFile'); + } + }); + }); + + self._parser.on('end', function(){ + self._flushing--; + self.ended = true; + + var done = function(){ + self.emit('file', 'file', file); + self._maybeEnd(); + }; + + if(outstandingWrites === 0){ + done(); + } else { + self._parser.once('doneWritingFile', done); + } + }); +}; + +IncomingForm.prototype._initJSONencoded = function() { + this.type = 'json'; + + var parser = new JSONParser() + , self = this; + + if (this.bytesExpected) { + parser.initWithLength(this.bytesExpected); + } + + parser.onField = function(key, val) { + self.emit('field', key, val); + } + + parser.onEnd = function() { + self.ended = true; + self._maybeEnd(); + }; + + this._parser = parser; +}; + +IncomingForm.prototype._uploadPath = function(filename) { + var name = ''; + for (var i = 0; i < 32; i++) { + name += Math.floor(Math.random() * 16).toString(16); + } + + if (this.keepExtensions) { + var ext = path.extname(filename); + ext = ext.replace(/(\.[a-z0-9]+).*/, '$1'); + + name += ext; + } + + return path.join(this.uploadDir, name); +}; + +IncomingForm.prototype._maybeEnd = function() { + if (!this.ended || this._flushing || this.error) { + return; + } + + this.emit('end'); +}; + diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js new file mode 100644 index 0000000..7a6e3e1 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js @@ -0,0 +1,3 @@ +var IncomingForm = require('./incoming_form').IncomingForm; +IncomingForm.IncomingForm = IncomingForm; +module.exports = IncomingForm; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/json_parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/json_parser.js new file mode 100644 index 0000000..6ce966b --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/json_parser.js @@ -0,0 +1,35 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +var Buffer = require('buffer').Buffer + +function JSONParser() { + this.data = new Buffer(''); + this.bytesWritten = 0; +}; +exports.JSONParser = JSONParser; + +JSONParser.prototype.initWithLength = function(length) { + this.data = new Buffer(length); +} + +JSONParser.prototype.write = function(buffer) { + if (this.data.length >= this.bytesWritten + buffer.length) { + buffer.copy(this.data, this.bytesWritten); + } else { + this.data = Buffer.concat([this.data, buffer]); + } + this.bytesWritten += buffer.length; + return buffer.length; +} + +JSONParser.prototype.end = function() { + try { + var fields = JSON.parse(this.data.toString('utf8')) + for (var field in fields) { + this.onField(field, fields[field]); + } + } catch (e) {} + this.data = null; + + this.onEnd(); +} \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js new file mode 100644 index 0000000..98a6856 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js @@ -0,0 +1,324 @@ +var Buffer = require('buffer').Buffer, + s = 0, + S = + { PARSER_UNINITIALIZED: s++, + START: s++, + START_BOUNDARY: s++, + HEADER_FIELD_START: s++, + HEADER_FIELD: s++, + HEADER_VALUE_START: s++, + HEADER_VALUE: s++, + HEADER_VALUE_ALMOST_DONE: s++, + HEADERS_ALMOST_DONE: s++, + PART_DATA_START: s++, + PART_DATA: s++, + PART_END: s++, + END: s++ + }, + + f = 1, + F = + { PART_BOUNDARY: f, + LAST_BOUNDARY: f *= 2 + }, + + LF = 10, + CR = 13, + SPACE = 32, + HYPHEN = 45, + COLON = 58, + A = 97, + Z = 122, + + lower = function(c) { + return c | 0x20; + }; + +for (s in S) { + exports[s] = S[s]; +} + +function MultipartParser() { + this.boundary = null; + this.boundaryChars = null; + this.lookbehind = null; + this.state = S.PARSER_UNINITIALIZED; + + this.index = null; + this.flags = 0; +}; +exports.MultipartParser = MultipartParser; + +MultipartParser.stateToString = function(stateNumber) { + for (var state in S) { + var number = S[state]; + if (number === stateNumber) return state; + } +}; + +MultipartParser.prototype.initWithBoundary = function(str) { + this.boundary = new Buffer(str.length+4); + this.boundary.write('\r\n--', 'ascii', 0); + this.boundary.write(str, 'ascii', 4); + this.lookbehind = new Buffer(this.boundary.length+8); + this.state = S.START; + + this.boundaryChars = {}; + for (var i = 0; i < this.boundary.length; i++) { + this.boundaryChars[this.boundary[i]] = true; + } +}; + +MultipartParser.prototype.write = function(buffer) { + var self = this, + i = 0, + len = buffer.length, + prevIndex = this.index, + index = this.index, + state = this.state, + flags = this.flags, + lookbehind = this.lookbehind, + boundary = this.boundary, + boundaryChars = this.boundaryChars, + boundaryLength = this.boundary.length, + boundaryEnd = boundaryLength - 1, + bufferLength = buffer.length, + c, + cl, + + mark = function(name) { + self[name+'Mark'] = i; + }, + clear = function(name) { + delete self[name+'Mark']; + }, + callback = function(name, buffer, start, end) { + if (start !== undefined && start === end) { + return; + } + + var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1); + if (callbackSymbol in self) { + self[callbackSymbol](buffer, start, end); + } + }, + dataCallback = function(name, clear) { + var markSymbol = name+'Mark'; + if (!(markSymbol in self)) { + return; + } + + if (!clear) { + callback(name, buffer, self[markSymbol], buffer.length); + self[markSymbol] = 0; + } else { + callback(name, buffer, self[markSymbol], i); + delete self[markSymbol]; + } + }; + + for (i = 0; i < len; i++) { + c = buffer[i]; + switch (state) { + case S.PARSER_UNINITIALIZED: + return i; + case S.START: + index = 0; + state = S.START_BOUNDARY; + case S.START_BOUNDARY: + if (index == boundary.length - 2) { + if (c != CR) { + return i; + } + index++; + break; + } else if (index - 1 == boundary.length - 2) { + if (c != LF) { + return i; + } + index = 0; + callback('partBegin'); + state = S.HEADER_FIELD_START; + break; + } + + if (c != boundary[index+2]) { + index = -2; + } + if (c == boundary[index+2]) { + index++; + } + break; + case S.HEADER_FIELD_START: + state = S.HEADER_FIELD; + mark('headerField'); + index = 0; + case S.HEADER_FIELD: + if (c == CR) { + clear('headerField'); + state = S.HEADERS_ALMOST_DONE; + break; + } + + index++; + if (c == HYPHEN) { + break; + } + + if (c == COLON) { + if (index == 1) { + // empty header field + return i; + } + dataCallback('headerField', true); + state = S.HEADER_VALUE_START; + break; + } + + cl = lower(c); + if (cl < A || cl > Z) { + return i; + } + break; + case S.HEADER_VALUE_START: + if (c == SPACE) { + break; + } + + mark('headerValue'); + state = S.HEADER_VALUE; + case S.HEADER_VALUE: + if (c == CR) { + dataCallback('headerValue', true); + callback('headerEnd'); + state = S.HEADER_VALUE_ALMOST_DONE; + } + break; + case S.HEADER_VALUE_ALMOST_DONE: + if (c != LF) { + return i; + } + state = S.HEADER_FIELD_START; + break; + case S.HEADERS_ALMOST_DONE: + if (c != LF) { + return i; + } + + callback('headersEnd'); + state = S.PART_DATA_START; + break; + case S.PART_DATA_START: + state = S.PART_DATA; + mark('partData'); + case S.PART_DATA: + prevIndex = index; + + if (index == 0) { + // boyer-moore derrived algorithm to safely skip non-boundary data + i += boundaryEnd; + while (i < bufferLength && !(buffer[i] in boundaryChars)) { + i += boundaryLength; + } + i -= boundaryEnd; + c = buffer[i]; + } + + if (index < boundary.length) { + if (boundary[index] == c) { + if (index == 0) { + dataCallback('partData', true); + } + index++; + } else { + index = 0; + } + } else if (index == boundary.length) { + index++; + if (c == CR) { + // CR = part boundary + flags |= F.PART_BOUNDARY; + } else if (c == HYPHEN) { + // HYPHEN = end boundary + flags |= F.LAST_BOUNDARY; + } else { + index = 0; + } + } else if (index - 1 == boundary.length) { + if (flags & F.PART_BOUNDARY) { + index = 0; + if (c == LF) { + // unset the PART_BOUNDARY flag + flags &= ~F.PART_BOUNDARY; + callback('partEnd'); + callback('partBegin'); + state = S.HEADER_FIELD_START; + break; + } + } else if (flags & F.LAST_BOUNDARY) { + if (c == HYPHEN) { + callback('partEnd'); + callback('end'); + state = S.END; + } else { + index = 0; + } + } else { + index = 0; + } + } + + if (index > 0) { + // when matching a possible boundary, keep a lookbehind reference + // in case it turns out to be a false lead + lookbehind[index-1] = c; + } else if (prevIndex > 0) { + // if our boundary turned out to be rubbish, the captured lookbehind + // belongs to partData + callback('partData', lookbehind, 0, prevIndex); + prevIndex = 0; + mark('partData'); + + // reconsider the current character even so it interrupted the sequence + // it could be the beginning of a new sequence + i--; + } + + break; + case S.END: + break; + default: + return i; + } + } + + dataCallback('headerField'); + dataCallback('headerValue'); + dataCallback('partData'); + + this.index = index; + this.state = state; + this.flags = flags; + + return len; +}; + +MultipartParser.prototype.end = function() { + var callback = function(self, name) { + var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1); + if (callbackSymbol in self) { + self[callbackSymbol](); + } + }; + if ((this.state == S.HEADER_FIELD_START && this.index == 0) || + (this.state == S.PART_DATA && this.index == this.boundary.length)) { + callback(this, 'partEnd'); + callback(this, 'end'); + } else if (this.state != S.END) { + return new Error('MultipartParser.end(): stream ended unexpectedly: ' + this.explain()); + } +}; + +MultipartParser.prototype.explain = function() { + return 'state = ' + MultipartParser.stateToString(this.state); +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/octet_parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/octet_parser.js new file mode 100644 index 0000000..6e8b551 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/octet_parser.js @@ -0,0 +1,20 @@ +var EventEmitter = require('events').EventEmitter + , util = require('util'); + +function OctetParser(options){ + if(!(this instanceof OctetParser)) return new OctetParser(options); + EventEmitter.call(this); +} + +util.inherits(OctetParser, EventEmitter); + +exports.OctetParser = OctetParser; + +OctetParser.prototype.write = function(buffer) { + this.emit('data', buffer); + return buffer.length; +}; + +OctetParser.prototype.end = function() { + this.emit('end'); +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js new file mode 100644 index 0000000..320ce5a --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js @@ -0,0 +1,27 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +// This is a buffering parser, not quite as nice as the multipart one. +// If I find time I'll rewrite this to be fully streaming as well +var querystring = require('querystring'); + +function QuerystringParser(maxKeys) { + this.maxKeys = maxKeys; + this.buffer = ''; +}; +exports.QuerystringParser = QuerystringParser; + +QuerystringParser.prototype.write = function(buffer) { + this.buffer += buffer.toString('ascii'); + return buffer.length; +}; + +QuerystringParser.prototype.end = function() { + var fields = querystring.parse(this.buffer, '&', '=', { maxKeys: this.maxKeys }); + for (var field in fields) { + this.onField(field, fields[field]); + } + this.buffer = ''; + + this.onEnd(); +}; + diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/package.json b/node_modules/express/node_modules/connect/node_modules/formidable/package.json new file mode 100644 index 0000000..925a3de --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/package.json @@ -0,0 +1,42 @@ +{ + "name": "formidable", + "description": "A node.js module for parsing form data, especially file uploads.", + "homepage": "https://github.com/felixge/node-formidable", + "version": "1.0.14", + "devDependencies": { + "gently": "0.8.0", + "findit": "0.1.1", + "hashish": "0.0.4", + "urun": "~0.0.6", + "utest": "0.0.3", + "request": "~2.11.4" + }, + "directories": { + "lib": "./lib" + }, + "main": "./lib/index", + "scripts": { + "test": "node test/run.js", + "clean": "rm test/tmp/*" + }, + "engines": { + "node": ">=0.8.0" + }, + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-formidable.git" + }, + "bugs": { + "url": "http://github.com/felixge/node-formidable/issues" + }, + "optionalDependencies": {}, + "readme": "# Formidable\n\n[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png?branch=master)](http://travis-ci.org/felixge/node-formidable)\n\n## Purpose\n\nA node.js module for parsing form data, especially file uploads.\n\n## Current status\n\nThis module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading\nand encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from\na large variety of clients and is considered production-ready.\n\n## Features\n\n* Fast (~500mb/sec), non-buffering multipart parser\n* Automatically writing file uploads to disk\n* Low memory footprint\n* Graceful error handling\n* Very high test coverage\n\n## Installation\n\nVia [npm](http://github.com/isaacs/npm):\n```\nnpm install formidable@latest\n```\nManually:\n```\ngit clone git://github.com/felixge/node-formidable.git formidable\nvim my.js\n# var formidable = require('./formidable');\n```\n\nNote: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library.\n\n## Example\n\nParse an incoming file upload.\n```javascript\nvar formidable = require('formidable'),\n http = require('http'),\n util = require('util');\n\nhttp.createServer(function(req, res) {\n if (req.url == '/upload' && req.method.toLowerCase() == 'post') {\n // parse a file upload\n var form = new formidable.IncomingForm();\n\n form.parse(req, function(err, fields, files) {\n res.writeHead(200, {'content-type': 'text/plain'});\n res.write('received upload:\\n\\n');\n res.end(util.inspect({fields: fields, files: files}));\n });\n\n return;\n }\n\n // show a file upload form\n res.writeHead(200, {'content-type': 'text/html'});\n res.end(\n '
    '+\n '
    '+\n '
    '+\n ''+\n '
    '\n );\n}).listen(8080);\n```\n## API\n\n### Formidable.IncomingForm\n```javascript\nvar form = new formidable.IncomingForm()\n```\nCreates a new incoming form.\n\n```javascript\nform.encoding = 'utf-8';\n```\nSets encoding for incoming form fields.\n\n```javascript\nform.uploadDir = process.env.TMP || process.env.TMPDIR || process.env.TEMP || '/tmp' || process.cwd();\n```\nThe directory for placing file uploads in. You can move them later on using\n`fs.rename()`. The default directory is picked at module load time depending on\nthe first existing directory from those listed above.\n\n```javascript\nform.keepExtensions = false;\n```\nIf you want the files written to `form.uploadDir` to include the extensions of the original files, set this property to `true`.\n\n```javascript\nform.type\n```\nEither 'multipart' or 'urlencoded' depending on the incoming request.\n\n```javascript\nform.maxFieldsSize = 2 * 1024 * 1024;\n```\nLimits the amount of memory a field (not file) can allocate in bytes.\nIf this value is exceeded, an `'error'` event is emitted. The default\nsize is 2MB.\n\n```javascript\nform.maxFields = 0;\n```\nLimits the number of fields that the querystring parser will decode. Defaults\nto 0 (unlimited).\n\n```javascript\nform.hash = false;\n```\nIf you want checksums calculated for incoming files, set this to either `'sha1'` or `'md5'`.\n\n```javascript\nform.bytesReceived\n```\nThe amount of bytes received for this form so far.\n\n```javascript\nform.bytesExpected\n```\nThe expected number of bytes in this form.\n\n```javascript\nform.parse(request, [cb]);\n```\nParses an incoming node.js `request` containing form data. If `cb` is provided, all fields an files are collected and passed to the callback:\n\n\n```javascript\nform.parse(req, function(err, fields, files) {\n // ...\n});\n\nform.onPart(part);\n```\nYou may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events processing which would occur otherwise, making you fully responsible for handling the processing.\n\n```javascript\nform.onPart = function(part) {\n part.addListener('data', function() {\n // ...\n });\n}\n```\nIf you want to use formidable to only handle certain parts for you, you can do so:\n```javascript\nform.onPart = function(part) {\n if (!part.filename) {\n // let formidable handle all non-file parts\n form.handlePart(part);\n }\n}\n```\nCheck the code in this method for further inspiration.\n\n\n### Formidable.File\n```javascript\nfile.size = 0\n```\nThe size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet.\n```javascript\nfile.path = null\n```\nThe path this file is being written to. You can modify this in the `'fileBegin'` event in\ncase you are unhappy with the way formidable generates a temporary path for your files.\n```javascript\nfile.name = null\n```\nThe name this file had according to the uploading client.\n```javascript\nfile.type = null\n```\nThe mime type of this file, according to the uploading client.\n```javascript\nfile.lastModifiedDate = null\n```\nA date object (or `null`) containing the time this file was last written to. Mostly\nhere for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).\n```javascript\nfile.hash = null\n```\nIf hash calculation was set, you can read the hex digest out of this var.\n\n#### Formidable.File#toJSON()\n\n This method returns a JSON-representation of the file, allowing you to\n `JSON.stringify()` the file which is useful for logging and responding\n to requests.\n\n### Events\n\n\n#### 'progress'\n```javascript\nform.on('progress', function(bytesReceived, bytesExpected) {\n});\n```\nEmitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar.\n\n\n\n#### 'field'\n```javascript\nform.on('field', function(name, value) {\n});\n```\n\n#### 'fileBegin'\n\nEmitted whenever a field / value pair has been received.\n```javascript\nform.on('fileBegin', function(name, file) {\n});\n```\n\n#### 'file'\n\nEmitted whenever a new file is detected in the upload stream. Use this even if\nyou want to stream the file to somewhere else while buffering the upload on\nthe file system.\n\nEmitted whenever a field / file pair has been received. `file` is an instance of `File`.\n```javascript\nform.on('file', function(name, file) {\n});\n```\n\n#### 'error'\n\nEmitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events.\n```javascript\nform.on('error', function(err) {\n});\n```\n\n#### 'aborted'\n\n\nEmitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. In the future there will be a separate 'timeout' event (needs a change in the node core).\n```javascript\nform.on('aborted', function() {\n});\n```\n\n##### 'end'\n```javascript\nform.on('end', function() {\n});\n```\nEmitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response.\n\n\n\n## Changelog\n\n### v1.0.14\n\n* Add failing hash tests. (Ben Trask)\n* Enable hash calculation again (Eugene Girshov)\n* Test for immediate data events (Tim Smart)\n* Re-arrange IncomingForm#parse (Tim Smart)\n\n### v1.0.13\n\n* Only update hash if update method exists (Sven Lito)\n* According to travis v0.10 needs to go quoted (Sven Lito)\n* Bumping build node versions (Sven Lito)\n* Additional fix for empty requests (Eugene Girshov)\n* Change the default to 1000, to match the new Node behaviour. (OrangeDog)\n* Add ability to control maxKeys in the querystring parser. (OrangeDog)\n* Adjust test case to work with node 0.9.x (Eugene Girshov)\n* Update package.json (Sven Lito)\n* Path adjustment according to eb4468b (Markus Ast)\n\n### v1.0.12\n\n* Emit error on aborted connections (Eugene Girshov)\n* Add support for empty requests (Eugene Girshov)\n* Fix name/filename handling in Content-Disposition (jesperp)\n* Tolerate malformed closing boundary in multipart (Eugene Girshov)\n* Ignore preamble in multipart messages (Eugene Girshov)\n* Add support for application/json (Mike Frey, Carlos Rodriguez)\n* Add support for Base64 encoding (Elmer Bulthuis)\n* Add File#toJSON (TJ Holowaychuk)\n* Remove support for Node.js 0.4 & 0.6 (Andrew Kelley)\n* Documentation improvements (Sven Lito, Andre Azevedo)\n* Add support for application/octet-stream (Ion Lupascu, Chris Scribner)\n* Use os.tmpDir() to get tmp directory (Andrew Kelley)\n* Improve package.json (Andrew Kelley, Sven Lito)\n* Fix benchmark script (Andrew Kelley)\n* Fix scope issue in incoming_forms (Sven Lito)\n* Fix file handle leak on error (OrangeDog)\n\n### v1.0.11\n\n* Calculate checksums for incoming files (sreuter)\n* Add definition parameters to \"IncomingForm\" as an argument (Math-)\n\n### v1.0.10\n\n* Make parts to be proper Streams (Matt Robenolt)\n\n### v1.0.9\n\n* Emit progress when content length header parsed (Tim Koschützki)\n* Fix Readme syntax due to GitHub changes (goob)\n* Replace references to old 'sys' module in Readme with 'util' (Peter Sugihara)\n\n### v1.0.8\n\n* Strip potentially unsafe characters when using `keepExtensions: true`.\n* Switch to utest / urun for testing\n* Add travis build\n\n### v1.0.7\n\n* Remove file from package that was causing problems when installing on windows. (#102)\n* Fix typos in Readme (Jason Davies).\n\n### v1.0.6\n\n* Do not default to the default to the field name for file uploads where\n filename=\"\".\n\n### v1.0.5\n\n* Support filename=\"\" in multipart parts\n* Explain unexpected end() errors in parser better\n\n**Note:** Starting with this version, formidable emits 'file' events for empty\nfile input fields. Previously those were incorrectly emitted as regular file\ninput fields with value = \"\".\n\n### v1.0.4\n\n* Detect a good default tmp directory regardless of platform. (#88)\n\n### v1.0.3\n\n* Fix problems with utf8 characters (#84) / semicolons in filenames (#58)\n* Small performance improvements\n* New test suite and fixture system\n\n### v1.0.2\n\n* Exclude node\\_modules folder from git\n* Implement new `'aborted'` event\n* Fix files in example folder to work with recent node versions\n* Make gently a devDependency\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2)\n\n### v1.0.1\n\n* Fix package.json to refer to proper main directory. (#68, Dean Landolt)\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1)\n\n### v1.0.0\n\n* Add support for multipart boundaries that are quoted strings. (Jeff Craig)\n\nThis marks the beginning of development on version 2.0 which will include\nseveral architectural improvements.\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0)\n\n### v0.9.11\n\n* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim Koschützki)\n* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class\n\n**Important:** The old property names of the File class will be removed in a\nfuture release.\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11)\n\n### Older releases\n\nThese releases were done before starting to maintain the above Changelog:\n\n* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10)\n* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9)\n* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8)\n* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7)\n* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6)\n* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5)\n* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4)\n* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3)\n* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2)\n* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0)\n\n## License\n\nFormidable is licensed under the MIT license.\n\n## Ports\n\n* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable\n\n## Credits\n\n* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js\n", + "readmeFilename": "Readme.md", + "dependencies": {}, + "_id": "formidable@1.0.14", + "dist": { + "shasum": "73ba5aa6e343f96f25bc60620356adc1256c7897" + }, + "_from": "formidable@1.0.14", + "_resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.14.tgz" +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js new file mode 100644 index 0000000..6a94295 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js @@ -0,0 +1,18 @@ +var path = require('path'); + +var root = path.join(__dirname, '../'); +exports.dir = { + root : root, + lib : root + '/lib', + fixture : root + '/test/fixture', + tmp : root + '/test/tmp', +}; + +exports.port = 13532; + +exports.formidable = require('..'); +exports.assert = require('assert'); + +exports.require = function(lib) { + return require(exports.dir.lib + '/' + lib); +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/beta-sticker-1.png b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/beta-sticker-1.png new file mode 100644 index 0000000..20b1a7f Binary files /dev/null and b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/beta-sticker-1.png differ diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/binaryfile.tar.gz b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/binaryfile.tar.gz new file mode 100644 index 0000000..4a85af7 Binary files /dev/null and b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/binaryfile.tar.gz differ diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/blank.gif b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/blank.gif new file mode 100644 index 0000000..75b945d Binary files /dev/null and b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/blank.gif differ diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt new file mode 100644 index 0000000..e7a4785 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt @@ -0,0 +1 @@ +I am a text file with a funky name! diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/menu_separator.png b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/menu_separator.png new file mode 100644 index 0000000..1c16a71 Binary files /dev/null and b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/menu_separator.png differ diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt new file mode 100644 index 0000000..9b6903e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt @@ -0,0 +1 @@ +I am a plain text file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md new file mode 100644 index 0000000..3c9dbe3 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md @@ -0,0 +1,3 @@ +* Opera does not allow submitting this file, it shows a warning to the + user that the file could not be found instead. Tested in 9.8, 11.51 on OSX. + Reported to Opera on 08.09.2011 (tracking email DSK-346009@bugs.opera.com). diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/encoding.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/encoding.js new file mode 100644 index 0000000..fc22026 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/encoding.js @@ -0,0 +1,24 @@ +module.exports['menu_seperator.png.http'] = [ + {type: 'file', name: 'image', filename: 'menu_separator.png', fixture: 'menu_separator.png', + sha1: 'c845ca3ea794be298f2a1b79769b71939eaf4e54'} +]; + +module.exports['beta-sticker-1.png.http'] = [ + {type: 'file', name: 'sticker', filename: 'beta-sticker-1.png', fixture: 'beta-sticker-1.png', + sha1: '6abbcffd12b4ada5a6a084fe9e4584f846331bc4'} +]; + +module.exports['blank.gif.http'] = [ + {type: 'file', name: 'file', filename: 'blank.gif', fixture: 'blank.gif', + sha1: 'a1fdee122b95748d81cee426d717c05b5174fe96'} +]; + +module.exports['binaryfile.tar.gz.http'] = [ + {type: 'file', name: 'file', filename: 'binaryfile.tar.gz', fixture: 'binaryfile.tar.gz', + sha1: 'cfabe13b348e5e69287d677860880c52a69d2155'} +]; + +module.exports['plain.txt.http'] = [ + {type: 'file', name: 'file', filename: 'plain.txt', fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'} +]; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/misc.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/misc.js new file mode 100644 index 0000000..4489176 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/misc.js @@ -0,0 +1,6 @@ +module.exports = { + 'empty.http': [], + 'empty-urlencoded.http': [], + 'empty-multipart.http': [], + 'minimal.http': [], +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js new file mode 100644 index 0000000..f03b4f0 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js @@ -0,0 +1,9 @@ +module.exports['generic.http'] = [ + {type: 'file', name: 'upload', filename: '', fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, +]; + +module.exports['filename-name.http'] = [ + {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, +]; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/preamble.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/preamble.js new file mode 100644 index 0000000..d2e4cfd --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/preamble.js @@ -0,0 +1,9 @@ +module.exports['crlf.http'] = [ + {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, +]; + +module.exports['preamble.http'] = [ + {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, +]; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js new file mode 100644 index 0000000..eb76fdc --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js @@ -0,0 +1,21 @@ +var properFilename = 'funkyfilename.txt'; + +function expect(filename) { + return [ + {type: 'field', name: 'title', value: 'Weird filename'}, + {type: 'file', name: 'upload', filename: filename, fixture: properFilename}, + ]; +}; + +var webkit = " ? % * | \" < > . ? ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"; +var ffOrIe = " ? % * | \" < > . ☃ ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"; + +module.exports = { + 'osx-chrome-13.http' : expect(webkit), + 'osx-firefox-3.6.http' : expect(ffOrIe), + 'osx-safari-5.http' : expect(webkit), + 'xp-chrome-12.http' : expect(webkit), + 'xp-ie-7.http' : expect(ffOrIe), + 'xp-ie-8.http' : expect(ffOrIe), + 'xp-safari-5.http' : expect(webkit), +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/workarounds.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/workarounds.js new file mode 100644 index 0000000..e59c5b2 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/workarounds.js @@ -0,0 +1,8 @@ +module.exports['missing-hyphens1.http'] = [ + {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, +]; +module.exports['missing-hyphens2.http'] = [ + {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, +]; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js new file mode 100644 index 0000000..a476169 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js @@ -0,0 +1,72 @@ +exports['rfc1867'] = + { boundary: 'AaB03x', + raw: + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="field1"\r\n'+ + '\r\n'+ + 'Joe Blow\r\nalmost tricked you!\r\n'+ + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ + 'Content-Type: text/plain\r\n'+ + '\r\n'+ + '... contents of file1.txt ...\r\r\n'+ + '--AaB03x--\r\n', + parts: + [ { headers: { + 'content-disposition': 'form-data; name="field1"', + }, + data: 'Joe Blow\r\nalmost tricked you!', + }, + { headers: { + 'content-disposition': 'form-data; name="pics"; filename="file1.txt"', + 'Content-Type': 'text/plain', + }, + data: '... contents of file1.txt ...\r', + } + ] + }; + +exports['noTrailing\r\n'] = + { boundary: 'AaB03x', + raw: + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="field1"\r\n'+ + '\r\n'+ + 'Joe Blow\r\nalmost tricked you!\r\n'+ + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ + 'Content-Type: text/plain\r\n'+ + '\r\n'+ + '... contents of file1.txt ...\r\r\n'+ + '--AaB03x--', + parts: + [ { headers: { + 'content-disposition': 'form-data; name="field1"', + }, + data: 'Joe Blow\r\nalmost tricked you!', + }, + { headers: { + 'content-disposition': 'form-data; name="pics"; filename="file1.txt"', + 'Content-Type': 'text/plain', + }, + data: '... contents of file1.txt ...\r', + } + ] + }; + +exports['emptyHeader'] = + { boundary: 'AaB03x', + raw: + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="field1"\r\n'+ + ': foo\r\n'+ + '\r\n'+ + 'Joe Blow\r\nalmost tricked you!\r\n'+ + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ + 'Content-Type: text/plain\r\n'+ + '\r\n'+ + '... contents of file1.txt ...\r\r\n'+ + '--AaB03x--\r\n', + expectError: true, + }; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js new file mode 100644 index 0000000..8e10ac9 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js @@ -0,0 +1,96 @@ +var hashish = require('hashish'); +var fs = require('fs'); +var findit = require('findit'); +var path = require('path'); +var http = require('http'); +var net = require('net'); +var assert = require('assert'); + +var common = require('../common'); +var formidable = common.formidable; + +var server = http.createServer(); +server.listen(common.port, findFixtures); + +function findFixtures() { + var fixtures = []; + findit + .sync(common.dir.fixture + '/js') + .forEach(function(jsPath) { + if (!/\.js$/.test(jsPath)) return; + + var group = path.basename(jsPath, '.js'); + hashish.forEach(require(jsPath), function(fixture, name) { + fixtures.push({ + name : group + '/' + name, + fixture : fixture, + }); + }); + }); + + testNext(fixtures); +} + +function testNext(fixtures) { + var fixture = fixtures.shift(); + if (!fixture) return server.close(); + + var name = fixture.name; + var fixture = fixture.fixture; + + uploadFixture(name, function(err, parts) { + if (err) throw err; + + fixture.forEach(function(expectedPart, i) { + var parsedPart = parts[i]; + assert.equal(parsedPart.type, expectedPart.type); + assert.equal(parsedPart.name, expectedPart.name); + + if (parsedPart.type === 'file') { + var file = parsedPart.value; + assert.equal(file.name, expectedPart.filename); + if(expectedPart.sha1) assert.equal(file.hash, expectedPart.sha1); + } + }); + + testNext(fixtures); + }); +}; + +function uploadFixture(name, cb) { + server.once('request', function(req, res) { + var form = new formidable.IncomingForm(); + form.uploadDir = common.dir.tmp; + form.hash = "sha1"; + form.parse(req); + + function callback() { + var realCallback = cb; + cb = function() {}; + realCallback.apply(null, arguments); + } + + var parts = []; + form + .on('error', callback) + .on('fileBegin', function(name, value) { + parts.push({type: 'file', name: name, value: value}); + }) + .on('field', function(name, value) { + parts.push({type: 'field', name: name, value: value}); + }) + .on('end', function() { + res.end('OK'); + callback(null, parts); + }); + }); + + var socket = net.createConnection(common.port); + var file = fs.createReadStream(common.dir.fixture + '/http/' + name); + + file.pipe(socket, {end: false}); + socket.on('data', function () { + socket.end(); + }); + +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-json.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-json.js new file mode 100644 index 0000000..28e758e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-json.js @@ -0,0 +1,38 @@ +var common = require('../common'); +var formidable = common.formidable; +var http = require('http'); +var assert = require('assert'); + +var testData = { + numbers: [1, 2, 3, 4, 5], + nested: { key: 'value' } +}; + +var server = http.createServer(function(req, res) { + var form = new formidable.IncomingForm(); + + form.parse(req, function(err, fields, files) { + assert.deepEqual(fields, testData); + + res.end(); + server.close(); + }); +}); + +var port = common.port; + +server.listen(port, function(err){ + assert.equal(err, null); + + var request = http.request({ + port: port, + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + }); + + request.write(JSON.stringify(testData)); + request.end(); +}); + diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-octet-stream.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-octet-stream.js new file mode 100644 index 0000000..643d2c6 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-octet-stream.js @@ -0,0 +1,45 @@ +var common = require('../common'); +var formidable = common.formidable; +var http = require('http'); +var fs = require('fs'); +var path = require('path'); +var hashish = require('hashish'); +var assert = require('assert'); + +var testFilePath = path.join(__dirname, '../fixture/file/binaryfile.tar.gz'); + +var server = http.createServer(function(req, res) { + var form = new formidable.IncomingForm(); + + form.parse(req, function(err, fields, files) { + assert.equal(hashish(files).length, 1); + var file = files.file; + + assert.equal(file.size, 301); + + var uploaded = fs.readFileSync(file.path); + var original = fs.readFileSync(testFilePath); + + assert.deepEqual(uploaded, original); + + res.end(); + server.close(); + }); +}); + +var port = common.port; + +server.listen(port, function(err){ + assert.equal(err, null); + + var request = http.request({ + port: port, + method: 'POST', + headers: { + 'Content-Type': 'application/octet-stream' + } + }); + + fs.createReadStream(testFilePath).pipe(request); +}); + diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js new file mode 100644 index 0000000..2b98598 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js @@ -0,0 +1,24 @@ +var path = require('path'), + fs = require('fs'); + +try { + global.Gently = require('gently'); +} catch (e) { + throw new Error('this test suite requires node-gently'); +} + +exports.lib = path.join(__dirname, '../../lib'); + +global.GENTLY = new Gently(); + +global.assert = require('assert'); +global.TEST_PORT = 13532; +global.TEST_FIXTURES = path.join(__dirname, '../fixture'); +global.TEST_TMP = path.join(__dirname, '../tmp'); + +// Stupid new feature in node that complains about gently attaching too many +// listeners to process 'exit'. This is a workaround until I can think of a +// better way to deal with this. +if (process.setMaxListeners) { + process.setMaxListeners(10000); +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js new file mode 100644 index 0000000..75232aa --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js @@ -0,0 +1,80 @@ +var common = require('../common'); +var CHUNK_LENGTH = 10, + multipartParser = require(common.lib + '/multipart_parser'), + MultipartParser = multipartParser.MultipartParser, + parser = new MultipartParser(), + fixtures = require(TEST_FIXTURES + '/multipart'), + Buffer = require('buffer').Buffer; + +Object.keys(fixtures).forEach(function(name) { + var fixture = fixtures[name], + buffer = new Buffer(Buffer.byteLength(fixture.raw, 'binary')), + offset = 0, + chunk, + nparsed, + + parts = [], + part = null, + headerField, + headerValue, + endCalled = ''; + + parser.initWithBoundary(fixture.boundary); + parser.onPartBegin = function() { + part = {headers: {}, data: ''}; + parts.push(part); + headerField = ''; + headerValue = ''; + }; + + parser.onHeaderField = function(b, start, end) { + headerField += b.toString('ascii', start, end); + }; + + parser.onHeaderValue = function(b, start, end) { + headerValue += b.toString('ascii', start, end); + } + + parser.onHeaderEnd = function() { + part.headers[headerField] = headerValue; + headerField = ''; + headerValue = ''; + }; + + parser.onPartData = function(b, start, end) { + var str = b.toString('ascii', start, end); + part.data += b.slice(start, end); + } + + parser.onEnd = function() { + endCalled = true; + } + + buffer.write(fixture.raw, 'binary', 0); + + while (offset < buffer.length) { + if (offset + CHUNK_LENGTH < buffer.length) { + chunk = buffer.slice(offset, offset+CHUNK_LENGTH); + } else { + chunk = buffer.slice(offset, buffer.length); + } + offset = offset + CHUNK_LENGTH; + + nparsed = parser.write(chunk); + if (nparsed != chunk.length) { + if (fixture.expectError) { + return; + } + puts('-- ERROR --'); + p(chunk.toString('ascii')); + throw new Error(chunk.length+' bytes written, but only '+nparsed+' bytes parsed!'); + } + } + + if (fixture.expectError) { + throw new Error('expected parse error did not happen'); + } + + assert.ok(endCalled); + assert.deepEqual(parts, fixture.parts); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js new file mode 100644 index 0000000..52ceedb --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js @@ -0,0 +1,104 @@ +var common = require('../common'); +var WriteStreamStub = GENTLY.stub('fs', 'WriteStream'); + +var File = require(common.lib + '/file'), + EventEmitter = require('events').EventEmitter, + file, + gently; + +function test(test) { + gently = new Gently(); + file = new File(); + test(); + gently.verify(test.name); +} + +test(function constructor() { + assert.ok(file instanceof EventEmitter); + assert.strictEqual(file.size, 0); + assert.strictEqual(file.path, null); + assert.strictEqual(file.name, null); + assert.strictEqual(file.type, null); + assert.strictEqual(file.lastModifiedDate, null); + + assert.strictEqual(file._writeStream, null); + + (function testSetProperties() { + var file2 = new File({foo: 'bar'}); + assert.equal(file2.foo, 'bar'); + })(); +}); + +test(function open() { + var WRITE_STREAM; + file.path = '/foo'; + + gently.expect(WriteStreamStub, 'new', function (path) { + WRITE_STREAM = this; + assert.strictEqual(path, file.path); + }); + + file.open(); + assert.strictEqual(file._writeStream, WRITE_STREAM); +}); + +test(function write() { + var BUFFER = {length: 10}, + CB_STUB, + CB = function() { + CB_STUB.apply(this, arguments); + }; + + file._writeStream = {}; + + gently.expect(file._writeStream, 'write', function (buffer, cb) { + assert.strictEqual(buffer, BUFFER); + + gently.expect(file, 'emit', function (event, bytesWritten) { + assert.ok(file.lastModifiedDate instanceof Date); + assert.equal(event, 'progress'); + assert.equal(bytesWritten, file.size); + }); + + CB_STUB = gently.expect(function writeCb() { + assert.equal(file.size, 10); + }); + + cb(); + + gently.expect(file, 'emit', function (event, bytesWritten) { + assert.equal(event, 'progress'); + assert.equal(bytesWritten, file.size); + }); + + CB_STUB = gently.expect(function writeCb() { + assert.equal(file.size, 20); + }); + + cb(); + }); + + file.write(BUFFER, CB); +}); + +test(function end() { + var CB_STUB, + CB = function() { + CB_STUB.apply(this, arguments); + }; + + file._writeStream = {}; + + gently.expect(file._writeStream, 'end', function (cb) { + gently.expect(file, 'emit', function (event) { + assert.equal(event, 'end'); + }); + + CB_STUB = gently.expect(function endCb() { + }); + + cb(); + }); + + file.end(CB); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js new file mode 100644 index 0000000..25bd887 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js @@ -0,0 +1,756 @@ +var common = require('../common'); +var MultipartParserStub = GENTLY.stub('./multipart_parser', 'MultipartParser'), + QuerystringParserStub = GENTLY.stub('./querystring_parser', 'QuerystringParser'), + EventEmitterStub = GENTLY.stub('events', 'EventEmitter'), + StreamStub = GENTLY.stub('stream', 'Stream'), + FileStub = GENTLY.stub('./file'); + +var formidable = require(common.lib + '/index'), + IncomingForm = formidable.IncomingForm, + events = require('events'), + fs = require('fs'), + path = require('path'), + Buffer = require('buffer').Buffer, + fixtures = require(TEST_FIXTURES + '/multipart'), + form, + gently; + +function test(test) { + gently = new Gently(); + gently.expect(EventEmitterStub, 'call'); + form = new IncomingForm(); + test(); + gently.verify(test.name); +} + +test(function constructor() { + assert.strictEqual(form.error, null); + assert.strictEqual(form.ended, false); + assert.strictEqual(form.type, null); + assert.strictEqual(form.headers, null); + assert.strictEqual(form.keepExtensions, false); + // Can't assume dir === '/tmp' for portability + // assert.strictEqual(form.uploadDir, '/tmp'); + // Make sure it is a directory instead + assert.doesNotThrow(function () { + assert(fs.statSync(form.uploadDir).isDirectory()); + }); + assert.strictEqual(form.encoding, 'utf-8'); + assert.strictEqual(form.bytesReceived, null); + assert.strictEqual(form.bytesExpected, null); + assert.strictEqual(form.maxFieldsSize, 2 * 1024 * 1024); + assert.strictEqual(form._parser, null); + assert.strictEqual(form._flushing, 0); + assert.strictEqual(form._fieldsSize, 0); + assert.ok(form instanceof EventEmitterStub); + assert.equal(form.constructor.name, 'IncomingForm'); + + (function testSimpleConstructor() { + gently.expect(EventEmitterStub, 'call'); + var form = IncomingForm(); + assert.ok(form instanceof IncomingForm); + })(); + + (function testSimpleConstructorShortcut() { + gently.expect(EventEmitterStub, 'call'); + var form = formidable(); + assert.ok(form instanceof IncomingForm); + })(); +}); + +test(function parse() { + var REQ = {headers: {}} + , emit = {}; + + gently.expect(form, 'writeHeaders', function(headers) { + assert.strictEqual(headers, REQ.headers); + }); + + var EVENTS = ['error', 'aborted', 'data', 'end']; + gently.expect(REQ, 'on', EVENTS.length, function(event, fn) { + assert.equal(event, EVENTS.shift()); + emit[event] = fn; + return this; + }); + + form.parse(REQ); + + (function testPause() { + gently.expect(REQ, 'pause'); + assert.strictEqual(form.pause(), true); + })(); + + (function testPauseCriticalException() { + form.ended = false; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'pause', function() { + throw ERR; + }); + + gently.expect(form, '_error', function(err) { + assert.strictEqual(err, ERR); + }); + + assert.strictEqual(form.pause(), false); + })(); + + (function testPauseHarmlessException() { + form.ended = true; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'pause', function() { + throw ERR; + }); + + assert.strictEqual(form.pause(), false); + })(); + + (function testResume() { + gently.expect(REQ, 'resume'); + assert.strictEqual(form.resume(), true); + })(); + + (function testResumeCriticalException() { + form.ended = false; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'resume', function() { + throw ERR; + }); + + gently.expect(form, '_error', function(err) { + assert.strictEqual(err, ERR); + }); + + assert.strictEqual(form.resume(), false); + })(); + + (function testResumeHarmlessException() { + form.ended = true; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'resume', function() { + throw ERR; + }); + + assert.strictEqual(form.resume(), false); + })(); + + (function testEmitError() { + var ERR = new Error('something bad happened'); + gently.expect(form, '_error',function(err) { + assert.strictEqual(err, ERR); + }); + emit.error(ERR); + })(); + + (function testEmitAborted() { + gently.expect(form, 'emit',function(event) { + assert.equal(event, 'aborted'); + }); + gently.expect(form, '_error'); + + emit.aborted(); + })(); + + + (function testEmitData() { + var BUFFER = [1, 2, 3]; + gently.expect(form, 'write', function(buffer) { + assert.strictEqual(buffer, BUFFER); + }); + emit.data(BUFFER); + })(); + + (function testEmitEnd() { + form._parser = {}; + + (function testWithError() { + var ERR = new Error('haha'); + gently.expect(form._parser, 'end', function() { + return ERR; + }); + + gently.expect(form, '_error', function(err) { + assert.strictEqual(err, ERR); + }); + + emit.end(); + })(); + + (function testWithoutError() { + gently.expect(form._parser, 'end'); + emit.end(); + })(); + + (function testAfterError() { + form.error = true; + emit.end(); + })(); + })(); + + (function testWithCallback() { + gently.expect(EventEmitterStub, 'call'); + var form = new IncomingForm(), + REQ = {headers: {}}, + parseCalled = 0; + + gently.expect(form, 'on', 4, function(event, fn) { + if (event == 'field') { + fn('field1', 'foo'); + fn('field1', 'bar'); + fn('field2', 'nice'); + } + + if (event == 'file') { + fn('file1', '1'); + fn('file1', '2'); + fn('file2', '3'); + } + + if (event == 'end') { + fn(); + } + return this; + }); + + gently.expect(form, 'writeHeaders'); + + gently.expect(REQ, 'on', 4, function() { + return this; + }); + + var parseCbOk = function (err, fields, files) { + assert.deepEqual(fields, {field1: 'bar', field2: 'nice'}); + assert.deepEqual(files, {file1: '2', file2: '3'}); + }; + form.parse(REQ, parseCbOk); + + var ERR = new Error('test'); + gently.expect(form, 'on', 3, function(event, fn) { + if (event == 'field') { + fn('foo', 'bar'); + } + + if (event == 'error') { + fn(ERR); + gently.expect(form, 'on'); + gently.expect(form, 'writeHeaders'); + gently.expect(REQ, 'on', 4, function() { + return this; + }); + } + return this; + }); + + form.parse(REQ, function parseCbErr(err, fields, files) { + assert.strictEqual(err, ERR); + assert.deepEqual(fields, {foo: 'bar'}); + }); + })(); + + (function testWriteOrder() { + gently.expect(EventEmitterStub, 'call'); + var form = new IncomingForm(); + var REQ = new events.EventEmitter(); + var BUF = {}; + var DATACB = null; + + REQ.on('newListener', function(event, fn) { + if ('data' === event) fn(BUF); + }); + + gently.expect(form, 'writeHeaders'); + gently.expect(form, 'write', function(buf) { + assert.strictEqual(buf, BUF); + }); + + form.parse(REQ); + })(); +}); + +test(function pause() { + assert.strictEqual(form.pause(), false); +}); + +test(function resume() { + assert.strictEqual(form.resume(), false); +}); + + +test(function writeHeaders() { + var HEADERS = {}; + gently.expect(form, '_parseContentLength'); + gently.expect(form, '_parseContentType'); + + form.writeHeaders(HEADERS); + assert.strictEqual(form.headers, HEADERS); +}); + +test(function write() { + var parser = {}, + BUFFER = [1, 2, 3]; + + form._parser = parser; + form.bytesExpected = 523423; + + (function testBasic() { + gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { + assert.equal(event, 'progress'); + assert.equal(bytesReceived, BUFFER.length); + assert.equal(bytesExpected, form.bytesExpected); + }); + + gently.expect(parser, 'write', function(buffer) { + assert.strictEqual(buffer, BUFFER); + return buffer.length; + }); + + assert.equal(form.write(BUFFER), BUFFER.length); + assert.equal(form.bytesReceived, BUFFER.length); + })(); + + (function testParserError() { + gently.expect(form, 'emit'); + + gently.expect(parser, 'write', function(buffer) { + assert.strictEqual(buffer, BUFFER); + return buffer.length - 1; + }); + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/parser error/i)); + }); + + assert.equal(form.write(BUFFER), BUFFER.length - 1); + assert.equal(form.bytesReceived, BUFFER.length + BUFFER.length); + })(); + + (function testUninitialized() { + delete form._parser; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/unintialized parser/i)); + }); + form.write(BUFFER); + })(); +}); + +test(function parseContentType() { + var HEADERS = {}; + + form.headers = {'content-type': 'application/x-www-form-urlencoded'}; + gently.expect(form, '_initUrlencoded'); + form._parseContentType(); + + // accept anything that has 'urlencoded' in it + form.headers = {'content-type': 'broken-client/urlencoded-stupid'}; + gently.expect(form, '_initUrlencoded'); + form._parseContentType(); + + var BOUNDARY = '---------------------------57814261102167618332366269'; + form.headers = {'content-type': 'multipart/form-data; boundary='+BOUNDARY}; + + gently.expect(form, '_initMultipart', function(boundary) { + assert.equal(boundary, BOUNDARY); + }); + form._parseContentType(); + + (function testQuotedBoundary() { + form.headers = {'content-type': 'multipart/form-data; boundary="' + BOUNDARY + '"'}; + + gently.expect(form, '_initMultipart', function(boundary) { + assert.equal(boundary, BOUNDARY); + }); + form._parseContentType(); + })(); + + (function testNoBoundary() { + form.headers = {'content-type': 'multipart/form-data'}; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/no multipart boundary/i)); + }); + form._parseContentType(); + })(); + + (function testNoContentType() { + form.headers = {}; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/no content-type/i)); + }); + form._parseContentType(); + })(); + + (function testUnknownContentType() { + form.headers = {'content-type': 'invalid'}; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/unknown content-type/i)); + }); + form._parseContentType(); + })(); +}); + +test(function parseContentLength() { + var HEADERS = {}; + + form.headers = {}; + gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { + assert.equal(event, 'progress'); + assert.equal(bytesReceived, 0); + assert.equal(bytesExpected, 0); + }); + form._parseContentLength(); + + form.headers['content-length'] = '8'; + gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { + assert.equal(event, 'progress'); + assert.equal(bytesReceived, 0); + assert.equal(bytesExpected, 8); + }); + form._parseContentLength(); + assert.strictEqual(form.bytesReceived, 0); + assert.strictEqual(form.bytesExpected, 8); + + // JS can be evil, lets make sure we are not + form.headers['content-length'] = '08'; + gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { + assert.equal(event, 'progress'); + assert.equal(bytesReceived, 0); + assert.equal(bytesExpected, 8); + }); + form._parseContentLength(); + assert.strictEqual(form.bytesExpected, 8); +}); + +test(function _initMultipart() { + var BOUNDARY = '123', + PARSER; + + gently.expect(MultipartParserStub, 'new', function() { + PARSER = this; + }); + + gently.expect(MultipartParserStub.prototype, 'initWithBoundary', function(boundary) { + assert.equal(boundary, BOUNDARY); + }); + + form._initMultipart(BOUNDARY); + assert.equal(form.type, 'multipart'); + assert.strictEqual(form._parser, PARSER); + + (function testRegularField() { + var PART; + gently.expect(StreamStub, 'new', function() { + PART = this; + }); + + gently.expect(form, 'onPart', function(part) { + assert.strictEqual(part, PART); + assert.deepEqual + ( part.headers + , { 'content-disposition': 'form-data; name="field1"' + , 'foo': 'bar' + } + ); + assert.equal(part.name, 'field1'); + + var strings = ['hello', ' world']; + gently.expect(part, 'emit', 2, function(event, b) { + assert.equal(event, 'data'); + assert.equal(b.toString(), strings.shift()); + }); + + gently.expect(part, 'emit', function(event, b) { + assert.equal(event, 'end'); + }); + }); + + PARSER.onPartBegin(); + PARSER.onHeaderField(new Buffer('content-disposition'), 0, 10); + PARSER.onHeaderField(new Buffer('content-disposition'), 10, 19); + PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 0, 14); + PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 14, 24); + PARSER.onHeaderEnd(); + PARSER.onHeaderField(new Buffer('foo'), 0, 3); + PARSER.onHeaderValue(new Buffer('bar'), 0, 3); + PARSER.onHeaderEnd(); + PARSER.onHeadersEnd(); + PARSER.onPartData(new Buffer('hello world'), 0, 5); + PARSER.onPartData(new Buffer('hello world'), 5, 11); + PARSER.onPartEnd(); + })(); + + (function testFileField() { + var PART; + gently.expect(StreamStub, 'new', function() { + PART = this; + }); + + gently.expect(form, 'onPart', function(part) { + assert.deepEqual + ( part.headers + , { 'content-disposition': 'form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"' + , 'content-type': 'text/plain' + } + ); + assert.equal(part.name, 'field2'); + assert.equal(part.filename, 'Sun"et.jpg'); + assert.equal(part.mime, 'text/plain'); + + gently.expect(part, 'emit', function(event, b) { + assert.equal(event, 'data'); + assert.equal(b.toString(), '... contents of file1.txt ...'); + }); + + gently.expect(part, 'emit', function(event, b) { + assert.equal(event, 'end'); + }); + }); + + PARSER.onPartBegin(); + PARSER.onHeaderField(new Buffer('content-disposition'), 0, 19); + PARSER.onHeaderValue(new Buffer('form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"'), 0, 85); + PARSER.onHeaderEnd(); + PARSER.onHeaderField(new Buffer('Content-Type'), 0, 12); + PARSER.onHeaderValue(new Buffer('text/plain'), 0, 10); + PARSER.onHeaderEnd(); + PARSER.onHeadersEnd(); + PARSER.onPartData(new Buffer('... contents of file1.txt ...'), 0, 29); + PARSER.onPartEnd(); + })(); + + (function testEnd() { + gently.expect(form, '_maybeEnd'); + PARSER.onEnd(); + assert.ok(form.ended); + })(); +}); + +test(function _fileName() { + // TODO + return; +}); + +test(function _initUrlencoded() { + var PARSER; + + gently.expect(QuerystringParserStub, 'new', function() { + PARSER = this; + }); + + form._initUrlencoded(); + assert.equal(form.type, 'urlencoded'); + assert.strictEqual(form._parser, PARSER); + + (function testOnField() { + var KEY = 'KEY', VAL = 'VAL'; + gently.expect(form, 'emit', function(field, key, val) { + assert.equal(field, 'field'); + assert.equal(key, KEY); + assert.equal(val, VAL); + }); + + PARSER.onField(KEY, VAL); + })(); + + (function testOnEnd() { + gently.expect(form, '_maybeEnd'); + + PARSER.onEnd(); + assert.equal(form.ended, true); + })(); +}); + +test(function _error() { + var ERR = new Error('bla'); + + gently.expect(form, 'pause'); + gently.expect(form, 'emit', function(event, err) { + assert.equal(event, 'error'); + assert.strictEqual(err, ERR); + }); + + form._error(ERR); + assert.strictEqual(form.error, ERR); + + // make sure _error only does its thing once + form._error(ERR); +}); + +test(function onPart() { + var PART = {}; + gently.expect(form, 'handlePart', function(part) { + assert.strictEqual(part, PART); + }); + + form.onPart(PART); +}); + +test(function handlePart() { + (function testUtf8Field() { + var PART = new events.EventEmitter(); + PART.name = 'my_field'; + + gently.expect(form, 'emit', function(event, field, value) { + assert.equal(event, 'field'); + assert.equal(field, 'my_field'); + assert.equal(value, 'hello world: €'); + }); + + form.handlePart(PART); + PART.emit('data', new Buffer('hello')); + PART.emit('data', new Buffer(' world: ')); + PART.emit('data', new Buffer([0xE2])); + PART.emit('data', new Buffer([0x82, 0xAC])); + PART.emit('end'); + })(); + + (function testBinaryField() { + var PART = new events.EventEmitter(); + PART.name = 'my_field2'; + + gently.expect(form, 'emit', function(event, field, value) { + assert.equal(event, 'field'); + assert.equal(field, 'my_field2'); + assert.equal(value, 'hello world: '+new Buffer([0xE2, 0x82, 0xAC]).toString('binary')); + }); + + form.encoding = 'binary'; + form.handlePart(PART); + PART.emit('data', new Buffer('hello')); + PART.emit('data', new Buffer(' world: ')); + PART.emit('data', new Buffer([0xE2])); + PART.emit('data', new Buffer([0x82, 0xAC])); + PART.emit('end'); + })(); + + (function testFieldSize() { + form.maxFieldsSize = 8; + var PART = new events.EventEmitter(); + PART.name = 'my_field'; + + gently.expect(form, '_error', function(err) { + assert.equal(err.message, 'maxFieldsSize exceeded, received 9 bytes of field data'); + }); + + form.handlePart(PART); + form._fieldsSize = 1; + PART.emit('data', new Buffer(7)); + PART.emit('data', new Buffer(1)); + })(); + + (function testFilePart() { + var PART = new events.EventEmitter(), + FILE = new events.EventEmitter(), + PATH = '/foo/bar'; + + PART.name = 'my_file'; + PART.filename = 'sweet.txt'; + PART.mime = 'sweet.txt'; + + gently.expect(form, '_uploadPath', function(filename) { + assert.equal(filename, PART.filename); + return PATH; + }); + + gently.expect(FileStub, 'new', function(properties) { + assert.equal(properties.path, PATH); + assert.equal(properties.name, PART.filename); + assert.equal(properties.type, PART.mime); + FILE = this; + + gently.expect(form, 'emit', function (event, field, file) { + assert.equal(event, 'fileBegin'); + assert.strictEqual(field, PART.name); + assert.strictEqual(file, FILE); + }); + + gently.expect(FILE, 'open'); + }); + + form.handlePart(PART); + assert.equal(form._flushing, 1); + + var BUFFER; + gently.expect(form, 'pause'); + gently.expect(FILE, 'write', function(buffer, cb) { + assert.strictEqual(buffer, BUFFER); + gently.expect(form, 'resume'); + // @todo handle cb(new Err) + cb(); + }); + + PART.emit('data', BUFFER = new Buffer('test')); + + gently.expect(FILE, 'end', function(cb) { + gently.expect(form, 'emit', function(event, field, file) { + assert.equal(event, 'file'); + assert.strictEqual(file, FILE); + }); + + gently.expect(form, '_maybeEnd'); + + cb(); + assert.equal(form._flushing, 0); + }); + + PART.emit('end'); + })(); +}); + +test(function _uploadPath() { + (function testUniqueId() { + var UUID_A, UUID_B; + gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) { + assert.equal(uploadDir, form.uploadDir); + UUID_A = uuid; + }); + form._uploadPath(); + + gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) { + UUID_B = uuid; + }); + form._uploadPath(); + + assert.notEqual(UUID_A, UUID_B); + })(); + + (function testFileExtension() { + form.keepExtensions = true; + var FILENAME = 'foo.jpg', + EXT = '.bar'; + + gently.expect(GENTLY.hijacked.path, 'extname', function(filename) { + assert.equal(filename, FILENAME); + gently.restore(path, 'extname'); + + return EXT; + }); + + gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, name) { + assert.equal(path.extname(name), EXT); + }); + form._uploadPath(FILENAME); + })(); +}); + +test(function _maybeEnd() { + gently.expect(form, 'emit', 0); + form._maybeEnd(); + + form.ended = true; + form._flushing = 1; + form._maybeEnd(); + + gently.expect(form, 'emit', function(event) { + assert.equal(event, 'end'); + }); + + form.ended = true; + form._flushing = 0; + form._maybeEnd(); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js new file mode 100644 index 0000000..bf2cd5e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js @@ -0,0 +1,50 @@ +var common = require('../common'); +var multipartParser = require(common.lib + '/multipart_parser'), + MultipartParser = multipartParser.MultipartParser, + events = require('events'), + Buffer = require('buffer').Buffer, + parser; + +function test(test) { + parser = new MultipartParser(); + test(); +} + +test(function constructor() { + assert.equal(parser.boundary, null); + assert.equal(parser.state, 0); + assert.equal(parser.flags, 0); + assert.equal(parser.boundaryChars, null); + assert.equal(parser.index, null); + assert.equal(parser.lookbehind, null); + assert.equal(parser.constructor.name, 'MultipartParser'); +}); + +test(function initWithBoundary() { + var boundary = 'abc'; + parser.initWithBoundary(boundary); + assert.deepEqual(Array.prototype.slice.call(parser.boundary), [13, 10, 45, 45, 97, 98, 99]); + assert.equal(parser.state, multipartParser.START); + + assert.deepEqual(parser.boundaryChars, {10: true, 13: true, 45: true, 97: true, 98: true, 99: true}); +}); + +test(function parserError() { + var boundary = 'abc', + buffer = new Buffer(5); + + parser.initWithBoundary(boundary); + buffer.write('--ad', 'ascii', 0); + assert.equal(parser.write(buffer), 5); +}); + +test(function end() { + (function testError() { + assert.equal(parser.end().message, 'MultipartParser.end(): stream ended unexpectedly: ' + parser.explain()); + })(); + + (function testRegular() { + parser.state = multipartParser.END; + assert.strictEqual(parser.end(), undefined); + })(); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js new file mode 100644 index 0000000..54d3e2d --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js @@ -0,0 +1,45 @@ +var common = require('../common'); +var QuerystringParser = require(common.lib + '/querystring_parser').QuerystringParser, + Buffer = require('buffer').Buffer, + gently, + parser; + +function test(test) { + gently = new Gently(); + parser = new QuerystringParser(); + test(); + gently.verify(test.name); +} + +test(function constructor() { + assert.equal(parser.buffer, ''); + assert.equal(parser.constructor.name, 'QuerystringParser'); +}); + +test(function write() { + var a = new Buffer('a=1'); + assert.equal(parser.write(a), a.length); + + var b = new Buffer('&b=2'); + parser.write(b); + assert.equal(parser.buffer, a + b); +}); + +test(function end() { + var FIELDS = {a: ['b', {c: 'd'}], e: 'f'}; + + gently.expect(GENTLY.hijacked.querystring, 'parse', function(str) { + assert.equal(str, parser.buffer); + return FIELDS; + }); + + gently.expect(parser, 'onField', Object.keys(FIELDS).length, function(key, val) { + assert.deepEqual(FIELDS[key], val); + }); + + gently.expect(parser, 'onEnd'); + + parser.buffer = 'my buffer'; + parser.end(); + assert.equal(parser.buffer, ''); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js new file mode 100644 index 0000000..b35ffd6 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js @@ -0,0 +1,71 @@ +var common = require('../common'); +var BOUNDARY = '---------------------------10102754414578508781458777923', + FIXTURE = TEST_FIXTURES+'/multi_video.upload', + fs = require('fs'), + http = require('http'), + formidable = require(common.lib + '/index'), + server = http.createServer(); + +server.on('request', function(req, res) { + var form = new formidable.IncomingForm(), + uploads = {}; + + form.uploadDir = TEST_TMP; + form.hash = 'sha1'; + form.parse(req); + + form + .on('fileBegin', function(field, file) { + assert.equal(field, 'upload'); + + var tracker = {file: file, progress: [], ended: false}; + uploads[file.name] = tracker; + file + .on('progress', function(bytesReceived) { + tracker.progress.push(bytesReceived); + assert.equal(bytesReceived, file.size); + }) + .on('end', function() { + tracker.ended = true; + }); + }) + .on('field', function(field, value) { + assert.equal(field, 'title'); + assert.equal(value, ''); + }) + .on('file', function(field, file) { + assert.equal(field, 'upload'); + assert.strictEqual(uploads[file.name].file, file); + }) + .on('end', function() { + assert.ok(uploads['shortest_video.flv']); + assert.ok(uploads['shortest_video.flv'].ended); + assert.ok(uploads['shortest_video.flv'].progress.length > 3); + assert.equal(uploads['shortest_video.flv'].file.hash, 'd6a17616c7143d1b1438ceeef6836d1a09186b3a'); + assert.equal(uploads['shortest_video.flv'].progress.slice(-1), uploads['shortest_video.flv'].file.size); + assert.ok(uploads['shortest_video.mp4']); + assert.ok(uploads['shortest_video.mp4'].ended); + assert.ok(uploads['shortest_video.mp4'].progress.length > 3); + assert.equal(uploads['shortest_video.mp4'].file.hash, '937dfd4db263f4887ceae19341dcc8d63bcd557f'); + + server.close(); + res.writeHead(200); + res.end('good'); + }); +}); + +server.listen(TEST_PORT, function() { + var stat, headers, request, fixture; + + stat = fs.statSync(FIXTURE); + request = http.request({ + port: TEST_PORT, + path: '/', + method: 'POST', + headers: { + 'content-type': 'multipart/form-data; boundary='+BOUNDARY, + 'content-length': stat.size, + }, + }); + fs.createReadStream(FIXTURE).pipe(request); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js new file mode 100644 index 0000000..02d6d5c --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js @@ -0,0 +1 @@ +require('urun')(__dirname) diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-connection-aborted.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-connection-aborted.js new file mode 100644 index 0000000..4ea4431 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-connection-aborted.js @@ -0,0 +1,27 @@ +var assert = require('assert'); +var http = require('http'); +var net = require('net'); +var formidable = require('../../lib/index'); + +var server = http.createServer(function (req, res) { + var form = new formidable.IncomingForm(); + var aborted_received = false; + form.on('aborted', function () { + aborted_received = true; + }); + form.on('error', function () { + assert(aborted_received, 'Error event should follow aborted'); + server.close(); + }); + form.on('end', function () { + throw new Error('Unexpected "end" event'); + }); + form.parse(req); +}).listen(0, 'localhost', function () { + var client = net.connect(server.address().port); + client.write( + "POST / HTTP/1.1\r\n" + + "Content-Length: 70\r\n" + + "Content-Type: multipart/form-data; boundary=foo\r\n\r\n"); + client.end(); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-content-transfer-encoding.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-content-transfer-encoding.js new file mode 100644 index 0000000..165628a --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-content-transfer-encoding.js @@ -0,0 +1,48 @@ +var assert = require('assert'); +var common = require('../common'); +var formidable = require('../../lib/index'); +var http = require('http'); + +var server = http.createServer(function(req, res) { + var form = new formidable.IncomingForm(); + form.uploadDir = common.dir.tmp; + form.on('end', function () { + throw new Error('Unexpected "end" event'); + }); + form.on('error', function (e) { + res.writeHead(500); + res.end(e.message); + }); + form.parse(req); +}); + +server.listen(0, function() { + var body = + '--foo\r\n' + + 'Content-Disposition: form-data; name="file1"; filename="file1"\r\n' + + 'Content-Type: application/octet-stream\r\n' + + '\r\nThis is the first file\r\n' + + '--foo\r\n' + + 'Content-Type: application/octet-stream\r\n' + + 'Content-Disposition: form-data; name="file2"; filename="file2"\r\n' + + 'Content-Transfer-Encoding: unknown\r\n' + + '\r\nThis is the second file\r\n' + + '--foo--\r\n'; + + var req = http.request({ + method: 'POST', + port: server.address().port, + headers: { + 'Content-Length': body.length, + 'Content-Type': 'multipart/form-data; boundary=foo' + } + }); + req.on('response', function (res) { + assert.equal(res.statusCode, 500); + res.on('data', function () {}); + res.on('end', function () { + server.close(); + }); + }); + req.end(body); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-issue-46.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-issue-46.js new file mode 100644 index 0000000..1939328 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-issue-46.js @@ -0,0 +1,49 @@ +var http = require('http'), + formidable = require('../../lib/index'), + request = require('request'), + assert = require('assert'); + +var host = 'localhost'; + +var index = [ + '
    ', + ' ', + ' ', + '
    ' +].join("\n"); + +var server = http.createServer(function(req, res) { + + // Show a form for testing purposes. + if (req.method == 'GET') { + res.writeHead(200, {'content-type': 'text/html'}); + res.end(index); + return; + } + + // Parse form and write results to response. + var form = new formidable.IncomingForm(); + form.parse(req, function(err, fields, files) { + res.writeHead(200, {'content-type': 'text/plain'}); + res.write(JSON.stringify({err: err, fields: fields, files: files})); + res.end(); + }); + +}).listen(0, host, function() { + + console.log("Server up and running..."); + + var server = this, + url = 'http://' + host + ':' + server.address().port; + + var parts = [ + {'Content-Disposition': 'form-data; name="foo"', 'body': 'bar'} + ] + + var req = request({method: 'POST', url: url, multipart: parts}, function(e, res, body) { + var obj = JSON.parse(body); + assert.equal("bar", obj.fields.foo); + server.close(); + }); + +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/tools/base64.html b/node_modules/express/node_modules/connect/node_modules/formidable/test/tools/base64.html new file mode 100644 index 0000000..48ad92e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/tools/base64.html @@ -0,0 +1,67 @@ + + + Convert a file to a base64 request + + + + + + + +
    +
    +
    +
    +
    +
    +

    +Don't forget to save the output with windows (CRLF) line endings! +

    + + + diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-file.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-file.js new file mode 100644 index 0000000..fc8f36e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-file.js @@ -0,0 +1,33 @@ +var common = require('../common'); +var test = require('utest'); +var assert = common.assert; +var File = common.require('file'); + +var file; +var now = new Date; +test('IncomingForm', { + before: function() { + file = new File({ + size: 1024, + path: '/tmp/cat.png', + name: 'cat.png', + type: 'image/png', + lastModifiedDate: now, + filename: 'cat.png', + mime: 'image/png' + }) + }, + + '#toJSON()': function() { + var obj = file.toJSON(); + var len = Object.keys(obj).length; + assert.equal(1024, obj.size); + assert.equal('/tmp/cat.png', obj.path); + assert.equal('cat.png', obj.name); + assert.equal('image/png', obj.type); + assert.equal('image/png', obj.mime); + assert.equal('cat.png', obj.filename); + assert.equal(now, obj.mtime); + assert.equal(len, 8); + } +}); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js new file mode 100644 index 0000000..fe2ac1c --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js @@ -0,0 +1,63 @@ +var common = require('../common'); +var test = require('utest'); +var assert = common.assert; +var IncomingForm = common.require('incoming_form').IncomingForm; +var path = require('path'); + +var form; +test('IncomingForm', { + before: function() { + form = new IncomingForm(); + }, + + '#_fileName with regular characters': function() { + var filename = 'foo.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'foo.txt'); + }, + + '#_fileName with unescaped quote': function() { + var filename = 'my".txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my".txt'); + }, + + '#_fileName with escaped quote': function() { + var filename = 'my%22.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my".txt'); + }, + + '#_fileName with bad quote and additional sub-header': function() { + var filename = 'my".txt'; + var header = makeHeader(filename) + '; foo="bar"'; + assert.equal(form._fileName(header), filename); + }, + + '#_fileName with semicolon': function() { + var filename = 'my;.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my;.txt'); + }, + + '#_fileName with utf8 character': function() { + var filename = 'my☃.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my☃.txt'); + }, + + '#_uploadPath strips harmful characters from extension when keepExtensions': function() { + form.keepExtensions = true; + + var ext = path.extname(form._uploadPath('fine.jpg?foo=bar')); + assert.equal(ext, '.jpg'); + + var ext = path.extname(form._uploadPath('fine?foo=bar')); + assert.equal(ext, ''); + + var ext = path.extname(form._uploadPath('super.cr2+dsad')); + assert.equal(ext, '.cr2'); + + var ext = path.extname(form._uploadPath('super.bar')); + assert.equal(ext, '.bar'); + }, +}); + +function makeHeader(filename) { + return 'Content-Disposition: form-data; name="upload"; filename="' + filename + '"'; +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js b/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js new file mode 100644 index 0000000..9f1cef8 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js @@ -0,0 +1,47 @@ +var http = require('http'); +var fs = require('fs'); +var connections = 0; + +var server = http.createServer(function(req, res) { + var socket = req.socket; + console.log('Request: %s %s -> %s', req.method, req.url, socket.filename); + + req.on('end', function() { + if (req.url !== '/') { + res.end(JSON.stringify({ + method: req.method, + url: req.url, + filename: socket.filename, + })); + return; + } + + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '
    ' + ); + }); +}); + +server.on('connection', function(socket) { + connections++; + + socket.id = connections; + socket.filename = 'connection-' + socket.id + '.http'; + socket.file = fs.createWriteStream(socket.filename); + socket.pipe(socket.file); + + console.log('--> %s', socket.filename); + socket.on('close', function() { + console.log('<-- %s', socket.filename); + }); +}); + +var port = process.env.PORT || 8080; +server.listen(port, function() { + console.log('Recording connections on port %s', port); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/pause/.npmignore b/node_modules/express/node_modules/connect/node_modules/pause/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/express/node_modules/connect/node_modules/pause/History.md b/node_modules/express/node_modules/connect/node_modules/pause/History.md new file mode 100644 index 0000000..c8aa68f --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/History.md @@ -0,0 +1,5 @@ + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/node_modules/connect/node_modules/pause/Makefile b/node_modules/express/node_modules/connect/node_modules/pause/Makefile new file mode 100644 index 0000000..4e9c8d3 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/pause/Readme.md b/node_modules/express/node_modules/connect/node_modules/pause/Readme.md new file mode 100644 index 0000000..1cdd68a --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/Readme.md @@ -0,0 +1,29 @@ + +# pause + + Pause streams... + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/pause/index.js b/node_modules/express/node_modules/connect/node_modules/pause/index.js new file mode 100644 index 0000000..1b7b379 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/index.js @@ -0,0 +1,29 @@ + +module.exports = function(obj){ + var onData + , onEnd + , events = []; + + // buffer data + obj.on('data', onData = function(data, encoding){ + events.push(['data', data, encoding]); + }); + + // buffer end + obj.on('end', onEnd = function(data, encoding){ + events.push(['end', data, encoding]); + }); + + return { + end: function(){ + obj.removeListener('data', onData); + obj.removeListener('end', onEnd); + }, + resume: function(){ + this.end(); + for (var i = 0, len = events.length; i < len; ++i) { + obj.emit.apply(obj, events[i]); + } + } + }; +}; \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/pause/package.json b/node_modules/express/node_modules/connect/node_modules/pause/package.json new file mode 100644 index 0000000..c226dc9 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/package.json @@ -0,0 +1,24 @@ +{ + "name": "pause", + "version": "0.0.1", + "description": "Pause streams...", + "keywords": [], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "main": "index", + "readme": "\n# pause\n\n Pause streams...\n\n## License \n\n(The MIT License)\n\nCopyright (c) 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.", + "readmeFilename": "Readme.md", + "_id": "pause@0.0.1", + "dist": { + "shasum": "72e37ac0cb13fba367af37d6ae2c37d75e3029b4" + }, + "_from": "pause@0.0.1", + "_resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz" +} diff --git a/node_modules/express/node_modules/connect/node_modules/qs/.gitmodules b/node_modules/express/node_modules/connect/node_modules/qs/.gitmodules new file mode 100644 index 0000000..49e31da --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/.gitmodules @@ -0,0 +1,6 @@ +[submodule "support/expresso"] + path = support/expresso + url = git://github.com/visionmedia/expresso.git +[submodule "support/should"] + path = support/should + url = git://github.com/visionmedia/should.js.git diff --git a/node_modules/express/node_modules/connect/node_modules/qs/.npmignore b/node_modules/express/node_modules/connect/node_modules/qs/.npmignore new file mode 100644 index 0000000..e85ce2a --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/.npmignore @@ -0,0 +1,7 @@ +test +.travis.yml +benchmark.js +component.json +examples.js +History.md +Makefile diff --git a/node_modules/express/node_modules/connect/node_modules/qs/Readme.md b/node_modules/express/node_modules/connect/node_modules/qs/Readme.md new file mode 100644 index 0000000..27e54a4 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/Readme.md @@ -0,0 +1,58 @@ +# node-querystring + + query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others. + +## Installation + + $ npm install qs + +## Examples + +```js +var qs = require('qs'); + +qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com'); +// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } } + +qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }}) +// => user[name]=Tobi&user[email]=tobi%40learnboost.com +``` + +## Testing + +Install dev dependencies: + + $ npm install -d + +and execute: + + $ make test + +browser: + + $ open test/browser/index.html + +## License + +(The MIT License) + +Copyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/qs/index.js b/node_modules/express/node_modules/connect/node_modules/qs/index.js new file mode 100644 index 0000000..590491e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/index.js @@ -0,0 +1,387 @@ +/** + * Object#toString() ref for stringify(). + */ + +var toString = Object.prototype.toString; + +/** + * Object#hasOwnProperty ref + */ + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +/** + * Array#indexOf shim. + */ + +var indexOf = typeof Array.prototype.indexOf === 'function' + ? function(arr, el) { return arr.indexOf(el); } + : function(arr, el) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] === el) return i; + } + return -1; + }; + +/** + * Array.isArray shim. + */ + +var isArray = Array.isArray || function(arr) { + return toString.call(arr) == '[object Array]'; +}; + +/** + * Object.keys shim. + */ + +var objectKeys = Object.keys || function(obj) { + var ret = []; + for (var key in obj) ret.push(key); + return ret; +}; + +/** + * Array#forEach shim. + */ + +var forEach = typeof Array.prototype.forEach === 'function' + ? function(arr, fn) { return arr.forEach(fn); } + : function(arr, fn) { + for (var i = 0; i < arr.length; i++) fn(arr[i]); + }; + +/** + * Array#reduce shim. + */ + +var reduce = function(arr, fn, initial) { + if (typeof arr.reduce === 'function') return arr.reduce(fn, initial); + var res = initial; + for (var i = 0; i < arr.length; i++) res = fn(res, arr[i]); + return res; +}; + +/** + * Create a nullary object if possible + */ + +function createObject() { + return Object.create + ? Object.create(null) + : {}; +} + +/** + * Cache non-integer test regexp. + */ + +var isint = /^[0-9]+$/; + +function promote(parent, key) { + if (parent[key].length == 0) return parent[key] = createObject(); + var t = createObject(); + for (var i in parent[key]) { + if (hasOwnProperty.call(parent[key], i)) { + t[i] = parent[key][i]; + } + } + parent[key] = t; + return t; +} + +function parse(parts, parent, key, val) { + var part = parts.shift(); + // end + if (!part) { + if (isArray(parent[key])) { + parent[key].push(val); + } else if ('object' == typeof parent[key]) { + parent[key] = val; + } else if ('undefined' == typeof parent[key]) { + parent[key] = val; + } else { + parent[key] = [parent[key], val]; + } + // array + } else { + var obj = parent[key] = parent[key] || []; + if (']' == part) { + if (isArray(obj)) { + if ('' != val) obj.push(val); + } else if ('object' == typeof obj) { + obj[objectKeys(obj).length] = val; + } else { + obj = parent[key] = [parent[key], val]; + } + // prop + } else if (~indexOf(part, ']')) { + part = part.substr(0, part.length - 1); + if (!isint.test(part) && isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + // key + } else { + if (!isint.test(part) && isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + } + } +} + +/** + * Merge parent key/val pair. + */ + +function merge(parent, key, val){ + if (~indexOf(key, ']')) { + var parts = key.split('[') + , len = parts.length + , last = len - 1; + parse(parts, parent, 'base', val); + // optimize + } else { + if (!isint.test(key) && isArray(parent.base)) { + var t = createObject(); + for (var k in parent.base) t[k] = parent.base[k]; + parent.base = t; + } + set(parent.base, key, val); + } + + return parent; +} + +/** + * Compact sparse arrays. + */ + +function compact(obj) { + if ('object' != typeof obj) return obj; + + if (isArray(obj)) { + var ret = []; + + for (var i in obj) { + if (hasOwnProperty.call(obj, i)) { + ret.push(obj[i]); + } + } + + return ret; + } + + for (var key in obj) { + obj[key] = compact(obj[key]); + } + + return obj; +} + +/** + * Restore Object.prototype. + * see pull-request #58 + */ + +function restoreProto(obj) { + if (!Object.create) return obj; + if (isArray(obj)) return obj; + if (obj && 'object' != typeof obj) return obj; + + for (var key in obj) { + if (hasOwnProperty.call(obj, key)) { + obj[key] = restoreProto(obj[key]); + } + } + + obj.__proto__ = Object.prototype; + return obj; +} + +/** + * Parse the given obj. + */ + +function parseObject(obj){ + var ret = { base: {} }; + + forEach(objectKeys(obj), function(name){ + merge(ret, name, obj[name]); + }); + + return compact(ret.base); +} + +/** + * Parse the given str. + */ + +function parseString(str){ + var ret = reduce(String(str).split('&'), function(ret, pair){ + var eql = indexOf(pair, '=') + , brace = lastBraceInKey(pair) + , key = pair.substr(0, brace || eql) + , val = pair.substr(brace || eql, pair.length) + , val = val.substr(indexOf(val, '=') + 1, val.length); + + // ?foo + if ('' == key) key = pair, val = ''; + if ('' == key) return ret; + + return merge(ret, decode(key), decode(val)); + }, { base: createObject() }).base; + + return restoreProto(compact(ret)); +} + +/** + * Parse the given query `str` or `obj`, returning an object. + * + * @param {String} str | {Object} obj + * @return {Object} + * @api public + */ + +exports.parse = function(str){ + if (null == str || '' == str) return {}; + return 'object' == typeof str + ? parseObject(str) + : parseString(str); +}; + +/** + * Turn the given `obj` into a query string + * + * @param {Object} obj + * @return {String} + * @api public + */ + +var stringify = exports.stringify = function(obj, prefix) { + if (isArray(obj)) { + return stringifyArray(obj, prefix); + } else if ('[object Object]' == toString.call(obj)) { + return stringifyObject(obj, prefix); + } else if ('string' == typeof obj) { + return stringifyString(obj, prefix); + } else { + return prefix + '=' + encodeURIComponent(String(obj)); + } +}; + +/** + * Stringify the given `str`. + * + * @param {String} str + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyString(str, prefix) { + if (!prefix) throw new TypeError('stringify expects an object'); + return prefix + '=' + encodeURIComponent(str); +} + +/** + * Stringify the given `arr`. + * + * @param {Array} arr + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyArray(arr, prefix) { + var ret = []; + if (!prefix) throw new TypeError('stringify expects an object'); + for (var i = 0; i < arr.length; i++) { + ret.push(stringify(arr[i], prefix + '[' + i + ']')); + } + return ret.join('&'); +} + +/** + * Stringify the given `obj`. + * + * @param {Object} obj + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyObject(obj, prefix) { + var ret = [] + , keys = objectKeys(obj) + , key; + + for (var i = 0, len = keys.length; i < len; ++i) { + key = keys[i]; + if ('' == key) continue; + if (null == obj[key]) { + ret.push(encodeURIComponent(key) + '='); + } else { + ret.push(stringify(obj[key], prefix + ? prefix + '[' + encodeURIComponent(key) + ']' + : encodeURIComponent(key))); + } + } + + return ret.join('&'); +} + +/** + * Set `obj`'s `key` to `val` respecting + * the weird and wonderful syntax of a qs, + * where "foo=bar&foo=baz" becomes an array. + * + * @param {Object} obj + * @param {String} key + * @param {String} val + * @api private + */ + +function set(obj, key, val) { + var v = obj[key]; + if (undefined === v) { + obj[key] = val; + } else if (isArray(v)) { + v.push(val); + } else { + obj[key] = [v, val]; + } +} + +/** + * Locate last brace in `str` within the key. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function lastBraceInKey(str) { + var len = str.length + , brace + , c; + for (var i = 0; i < len; ++i) { + c = str[i]; + if (']' == c) brace = false; + if ('[' == c) brace = true; + if ('=' == c && !brace) return i; + } +} + +/** + * Decode `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +function decode(str) { + try { + return decodeURIComponent(str.replace(/\+/g, ' ')); + } catch (err) { + return str; + } +} diff --git a/node_modules/express/node_modules/connect/node_modules/qs/package.json b/node_modules/express/node_modules/connect/node_modules/qs/package.json new file mode 100644 index 0000000..b72410c --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/package.json @@ -0,0 +1,41 @@ +{ + "name": "qs", + "description": "querystring parser", + "version": "0.6.5", + "keywords": [ + "query string", + "parser", + "component" + ], + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/node-querystring.git" + }, + "devDependencies": { + "mocha": "*", + "expect.js": "*" + }, + "scripts": { + "test": "make test" + }, + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "main": "index", + "engines": { + "node": "*" + }, + "readme": "# node-querystring\n\n query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.\n\n## Installation\n\n $ npm install qs\n\n## Examples\n\n```js\nvar qs = require('qs');\n\nqs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');\n// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }\n\nqs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})\n// => user[name]=Tobi&user[email]=tobi%40learnboost.com\n```\n\n## Testing\n\nInstall dev dependencies:\n\n $ npm install -d\n\nand execute:\n\n $ make test\n\nbrowser:\n\n $ open test/browser/index.html\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 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.", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/visionmedia/node-querystring/issues" + }, + "_id": "qs@0.6.5", + "dist": { + "shasum": "8e3ecc3aa34363888bd3ab99a71e4babfddc34e2" + }, + "_from": "qs@0.6.5", + "_resolved": "https://registry.npmjs.org/qs/-/qs-0.6.5.tgz" +} diff --git a/node_modules/express/node_modules/connect/node_modules/uid2/index.js b/node_modules/express/node_modules/connect/node_modules/uid2/index.js new file mode 100644 index 0000000..d665f51 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/uid2/index.js @@ -0,0 +1,49 @@ +/** + * Module dependencies + */ + +var crypto = require('crypto'); + +/** + * The size ratio between a base64 string and the equivalent byte buffer + */ + +var ratio = Math.log(64) / Math.log(256); + +/** + * Make a Base64 string ready for use in URLs + * + * @param {String} + * @returns {String} + * @api private + */ + +function urlReady(str) { + return str.replace(/\+/g, '_').replace(/\//g, '-'); +} + +/** + * Generate an Unique Id + * + * @param {Number} length The number of chars of the uid + * @param {Number} cb (optional) Callback for async uid generation + * @api public + */ + +function uid(length, cb) { + var numbytes = Math.ceil(length * ratio); + if (typeof cb === 'undefined') { + return urlReady(crypto.randomBytes(numbytes).toString('base64').slice(0, length)); + } else { + crypto.randomBytes(numbytes, function(err, bytes) { + if (err) return cb(err); + cb(null, urlReady(bytes.toString('base64').slice(0, length))); + }) + } +} + +/** + * Exports + */ + +module.exports = uid; diff --git a/node_modules/express/node_modules/connect/node_modules/uid2/package.json b/node_modules/express/node_modules/connect/node_modules/uid2/package.json new file mode 100644 index 0000000..12ab8c8 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/uid2/package.json @@ -0,0 +1,16 @@ +{ + "name": "uid2", + "description": "strong uid", + "tags": [ + "uid" + ], + "version": "0.0.2", + "dependencies": {}, + "readme": "ERROR: No README data found!", + "_id": "uid2@0.0.2", + "dist": { + "shasum": "7b0863f685a8552f0a0250ce5b82570f4fb0f87e" + }, + "_from": "uid2@0.0.2", + "_resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.2.tgz" +} diff --git a/node_modules/express/node_modules/connect/package.json b/node_modules/express/node_modules/connect/package.json new file mode 100644 index 0000000..7a9c533 --- /dev/null +++ b/node_modules/express/node_modules/connect/package.json @@ -0,0 +1,59 @@ +{ + "name": "connect", + "version": "2.8.4", + "description": "High performance middleware framework", + "keywords": [ + "framework", + "web", + "middleware", + "connect", + "rack" + ], + "repository": { + "type": "git", + "url": "git://github.com/senchalabs/connect.git" + }, + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "dependencies": { + "qs": "0.6.5", + "formidable": "1.0.14", + "cookie-signature": "1.0.1", + "buffer-crc32": "0.2.1", + "cookie": "0.1.0", + "send": "0.1.3", + "bytes": "0.2.0", + "fresh": "0.1.0", + "pause": "0.0.1", + "uid2": "0.0.2", + "debug": "*", + "methods": "0.0.1" + }, + "devDependencies": { + "should": "*", + "mocha": "*", + "jade": "*", + "dox": "*" + }, + "main": "index", + "engines": { + "node": ">= 0.8.0" + }, + "scripts": { + "test": "make" + }, + "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", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/senchalabs/connect/issues" + }, + "_id": "connect@2.8.4", + "dist": { + "shasum": "3a7ee41144e9bd2a16724d7ac563f3d041cefa74" + }, + "_from": "connect@2.8.4", + "_resolved": "https://registry.npmjs.org/connect/-/connect-2.8.4.tgz" +} diff --git a/node_modules/express/node_modules/connect/test.js b/node_modules/express/node_modules/connect/test.js new file mode 100644 index 0000000..ef743f2 --- /dev/null +++ b/node_modules/express/node_modules/connect/test.js @@ -0,0 +1,8 @@ +var crypto = require('crypto') + +exports.uid = function(len) { + return crypto.randomBytes(Math.ceil(len * 3 / 4)) + .toString('hex') +}; + +console.log(exports.uid(10)); diff --git a/node_modules/express/node_modules/cookie-signature/.npmignore b/node_modules/express/node_modules/cookie-signature/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/express/node_modules/cookie-signature/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/express/node_modules/cookie-signature/History.md b/node_modules/express/node_modules/cookie-signature/History.md new file mode 100644 index 0000000..9e30179 --- /dev/null +++ b/node_modules/express/node_modules/cookie-signature/History.md @@ -0,0 +1,11 @@ + +1.0.1 / 2013-04-15 +================== + + * Revert "Changed underlying HMAC algo. to sha512." + * Revert "Fix for timing attacks on MAC verification." + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/node_modules/cookie-signature/Makefile b/node_modules/express/node_modules/cookie-signature/Makefile new file mode 100644 index 0000000..4e9c8d3 --- /dev/null +++ b/node_modules/express/node_modules/cookie-signature/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/cookie-signature/Readme.md b/node_modules/express/node_modules/cookie-signature/Readme.md new file mode 100644 index 0000000..2559e84 --- /dev/null +++ b/node_modules/express/node_modules/cookie-signature/Readme.md @@ -0,0 +1,42 @@ + +# cookie-signature + + Sign and unsign cookies. + +## Example + +```js +var cookie = require('cookie-signature'); + +var val = cookie.sign('hello', 'tobiiscool'); +val.should.equal('hello.DGDUkGlIkCzPz+C0B064FNgHdEjox7ch8tOBGslZ5QI'); + +var val = cookie.sign('hello', 'tobiiscool'); +cookie.unsign(val, 'tobiiscool').should.equal('hello'); +cookie.unsign(val, 'luna').should.be.false; +``` + +## License + +(The MIT License) + +Copyright (c) 2012 LearnBoost <tj@learnboost.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/express/node_modules/cookie-signature/index.js b/node_modules/express/node_modules/cookie-signature/index.js new file mode 100644 index 0000000..ed62814 --- /dev/null +++ b/node_modules/express/node_modules/cookie-signature/index.js @@ -0,0 +1,42 @@ + +/** + * Module dependencies. + */ + +var crypto = require('crypto'); + +/** + * Sign the given `val` with `secret`. + * + * @param {String} val + * @param {String} secret + * @return {String} + * @api private + */ + +exports.sign = function(val, secret){ + if ('string' != typeof val) throw new TypeError('cookie required'); + if ('string' != typeof secret) throw new TypeError('secret required'); + return val + '.' + crypto + .createHmac('sha256', secret) + .update(val) + .digest('base64') + .replace(/\=+$/, ''); +}; + +/** + * Unsign and decode the given `val` with `secret`, + * returning `false` if the signature is invalid. + * + * @param {String} val + * @param {String} secret + * @return {String|Boolean} + * @api private + */ + +exports.unsign = function(val, secret){ + if ('string' != typeof val) throw new TypeError('cookie required'); + if ('string' != typeof secret) throw new TypeError('secret required'); + var str = val.slice(0, val.lastIndexOf('.')); + return exports.sign(str, secret) == val ? str : false; +}; diff --git a/node_modules/express/node_modules/cookie-signature/package.json b/node_modules/express/node_modules/cookie-signature/package.json new file mode 100644 index 0000000..03b4718 --- /dev/null +++ b/node_modules/express/node_modules/cookie-signature/package.json @@ -0,0 +1,28 @@ +{ + "name": "cookie-signature", + "version": "1.0.1", + "description": "Sign and unsign cookies", + "keywords": [ + "cookie", + "sign", + "unsign" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@learnboost.com" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "main": "index", + "readme": "\n# cookie-signature\n\n Sign and unsign cookies.\n\n## Example\n\n```js\nvar cookie = require('cookie-signature');\n\nvar val = cookie.sign('hello', 'tobiiscool');\nval.should.equal('hello.DGDUkGlIkCzPz+C0B064FNgHdEjox7ch8tOBGslZ5QI');\n\nvar val = cookie.sign('hello', 'tobiiscool');\ncookie.unsign(val, 'tobiiscool').should.equal('hello');\ncookie.unsign(val, 'luna').should.be.false;\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 LearnBoost <tj@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.", + "readmeFilename": "Readme.md", + "_id": "cookie-signature@1.0.1", + "dist": { + "shasum": "95214a8d107a85a32f3eaa98b908ddd99af75bd2" + }, + "_from": "cookie-signature@1.0.1", + "_resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.1.tgz" +} diff --git a/node_modules/express/node_modules/cookie/.npmignore b/node_modules/express/node_modules/cookie/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/express/node_modules/cookie/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/express/node_modules/cookie/.travis.yml b/node_modules/express/node_modules/cookie/.travis.yml new file mode 100644 index 0000000..9400c11 --- /dev/null +++ b/node_modules/express/node_modules/cookie/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "0.6" + - "0.8" + - "0.10" diff --git a/node_modules/express/node_modules/cookie/LICENSE b/node_modules/express/node_modules/cookie/LICENSE new file mode 100644 index 0000000..249d9de --- /dev/null +++ b/node_modules/express/node_modules/cookie/LICENSE @@ -0,0 +1,9 @@ +// MIT License + +Copyright (C) Roman Shtylman + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/express/node_modules/cookie/README.md b/node_modules/express/node_modules/cookie/README.md new file mode 100644 index 0000000..5187ed1 --- /dev/null +++ b/node_modules/express/node_modules/cookie/README.md @@ -0,0 +1,44 @@ +# cookie [![Build Status](https://secure.travis-ci.org/shtylman/node-cookie.png?branch=master)](http://travis-ci.org/shtylman/node-cookie) # + +cookie is a basic cookie parser and serializer. It doesn't make assumptions about how you are going to deal with your cookies. It basically just provides a way to read and write the HTTP cookie headers. + +See [RFC6265](http://tools.ietf.org/html/rfc6265) for details about the http header for cookies. + +## how? + +``` +npm install cookie +``` + +```javascript +var cookie = require('cookie'); + +var hdr = cookie.serialize('foo', 'bar'); +// hdr = 'foo=bar'; + +var cookies = cookie.parse('foo=bar; cat=meow; dog=ruff'); +// cookies = { foo: 'bar', cat: 'meow', dog: 'ruff' }; +``` + +## more + +The serialize function takes a third parameter, an object, to set cookie options. See the RFC for valid values. + +### path +> cookie path + +### expires +> absolute expiration date for the cookie (Date object) + +### maxAge +> relative max age of the cookie from when the client receives it (seconds) + +### domain +> domain for the cookie + +### secure +> true or false + +### httpOnly +> true or false + diff --git a/node_modules/express/node_modules/cookie/index.js b/node_modules/express/node_modules/cookie/index.js new file mode 100644 index 0000000..16bdb65 --- /dev/null +++ b/node_modules/express/node_modules/cookie/index.js @@ -0,0 +1,70 @@ + +/// Serialize the a name value pair into a cookie string suitable for +/// http headers. An optional options object specified cookie parameters +/// +/// serialize('foo', 'bar', { httpOnly: true }) +/// => "foo=bar; httpOnly" +/// +/// @param {String} name +/// @param {String} val +/// @param {Object} options +/// @return {String} +var serialize = function(name, val, opt){ + opt = opt || {}; + var enc = opt.encode || encode; + var pairs = [name + '=' + enc(val)]; + + if (opt.maxAge) pairs.push('Max-Age=' + opt.maxAge); + if (opt.domain) pairs.push('Domain=' + opt.domain); + if (opt.path) pairs.push('Path=' + opt.path); + if (opt.expires) pairs.push('Expires=' + opt.expires.toUTCString()); + if (opt.httpOnly) pairs.push('HttpOnly'); + if (opt.secure) pairs.push('Secure'); + + return pairs.join('; '); +}; + +/// Parse the given cookie header string into an object +/// The object has the various cookies as keys(names) => values +/// @param {String} str +/// @return {Object} +var parse = function(str, opt) { + opt = opt || {}; + var obj = {} + var pairs = str.split(/[;,] */); + var dec = opt.decode || decode; + + pairs.forEach(function(pair) { + var eq_idx = pair.indexOf('=') + + // skip things that don't look like key=value + if (eq_idx < 0) { + return; + } + + var key = pair.substr(0, eq_idx).trim() + var val = pair.substr(++eq_idx, pair.length).trim(); + + // quoted values + if ('"' == val[0]) { + val = val.slice(1, -1); + } + + // only assign once + if (undefined == obj[key]) { + try { + obj[key] = dec(val); + } catch (e) { + obj[key] = val; + } + } + }); + + return obj; +}; + +var encode = encodeURIComponent; +var decode = decodeURIComponent; + +module.exports.serialize = serialize; +module.exports.parse = parse; diff --git a/node_modules/express/node_modules/cookie/package.json b/node_modules/express/node_modules/cookie/package.json new file mode 100644 index 0000000..df900a0 --- /dev/null +++ b/node_modules/express/node_modules/cookie/package.json @@ -0,0 +1,40 @@ +{ + "author": { + "name": "Roman Shtylman", + "email": "shtylman@gmail.com" + }, + "name": "cookie", + "description": "cookie parsing and serialization", + "version": "0.1.0", + "repository": { + "type": "git", + "url": "git://github.com/shtylman/node-cookie.git" + }, + "keywords": [ + "cookie", + "cookies" + ], + "main": "index.js", + "scripts": { + "test": "mocha" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "1.x.x" + }, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "readme": "# cookie [![Build Status](https://secure.travis-ci.org/shtylman/node-cookie.png?branch=master)](http://travis-ci.org/shtylman/node-cookie) #\n\ncookie is a basic cookie parser and serializer. It doesn't make assumptions about how you are going to deal with your cookies. It basically just provides a way to read and write the HTTP cookie headers.\n\nSee [RFC6265](http://tools.ietf.org/html/rfc6265) for details about the http header for cookies.\n\n## how?\n\n```\nnpm install cookie\n```\n\n```javascript\nvar cookie = require('cookie');\n\nvar hdr = cookie.serialize('foo', 'bar');\n// hdr = 'foo=bar';\n\nvar cookies = cookie.parse('foo=bar; cat=meow; dog=ruff');\n// cookies = { foo: 'bar', cat: 'meow', dog: 'ruff' };\n```\n\n## more\n\nThe serialize function takes a third parameter, an object, to set cookie options. See the RFC for valid values.\n\n### path\n> cookie path\n\n### expires\n> absolute expiration date for the cookie (Date object)\n\n### maxAge\n> relative max age of the cookie from when the client receives it (seconds)\n\n### domain\n> domain for the cookie\n\n### secure\n> true or false\n\n### httpOnly\n> true or false\n\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/shtylman/node-cookie/issues" + }, + "_id": "cookie@0.1.0", + "dist": { + "shasum": "5b90266eae9967ea1524d1374274aa2078d8b527" + }, + "_from": "cookie@0.1.0", + "_resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.0.tgz" +} diff --git a/node_modules/express/node_modules/cookie/test/mocha.opts b/node_modules/express/node_modules/cookie/test/mocha.opts new file mode 100644 index 0000000..e2bfcc5 --- /dev/null +++ b/node_modules/express/node_modules/cookie/test/mocha.opts @@ -0,0 +1 @@ +--ui qunit diff --git a/node_modules/express/node_modules/cookie/test/parse.js b/node_modules/express/node_modules/cookie/test/parse.js new file mode 100644 index 0000000..c6c27a2 --- /dev/null +++ b/node_modules/express/node_modules/cookie/test/parse.js @@ -0,0 +1,44 @@ + +var assert = require('assert'); + +var cookie = require('..'); + +suite('parse'); + +test('basic', function() { + assert.deepEqual({ foo: 'bar' }, cookie.parse('foo=bar')); + assert.deepEqual({ foo: '123' }, cookie.parse('foo=123')); +}); + +test('ignore spaces', function() { + assert.deepEqual({ FOO: 'bar', baz: 'raz' }, + cookie.parse('FOO = bar; baz = raz')); +}); + +test('escaping', function() { + assert.deepEqual({ foo: 'bar=123456789&name=Magic+Mouse' }, + cookie.parse('foo="bar=123456789&name=Magic+Mouse"')); + + assert.deepEqual({ email: ' ",;/' }, + cookie.parse('email=%20%22%2c%3b%2f')); +}); + +test('ignore escaping error and return original value', function() { + assert.deepEqual({ foo: '%1', bar: 'bar' }, cookie.parse('foo=%1;bar=bar')); +}); + +test('ignore non values', function() { + assert.deepEqual({ foo: '%1', bar: 'bar' }, cookie.parse('foo=%1;bar=bar;HttpOnly;Secure')); +}); + +test('unencoded', function() { + assert.deepEqual({ foo: 'bar=123456789&name=Magic+Mouse' }, + cookie.parse('foo="bar=123456789&name=Magic+Mouse"',{ + decode: function(value) { return value; } + })); + + assert.deepEqual({ email: '%20%22%2c%3b%2f' }, + cookie.parse('email=%20%22%2c%3b%2f',{ + decode: function(value) { return value; } + })); +}) diff --git a/node_modules/express/node_modules/cookie/test/serialize.js b/node_modules/express/node_modules/cookie/test/serialize.js new file mode 100644 index 0000000..86bb8c9 --- /dev/null +++ b/node_modules/express/node_modules/cookie/test/serialize.js @@ -0,0 +1,64 @@ +// builtin +var assert = require('assert'); + +var cookie = require('..'); + +suite('serialize'); + +test('basic', function() { + assert.equal('foo=bar', cookie.serialize('foo', 'bar')); + assert.equal('foo=bar%20baz', cookie.serialize('foo', 'bar baz')); +}); + +test('path', function() { + assert.equal('foo=bar; Path=/', cookie.serialize('foo', 'bar', { + path: '/' + })); +}); + +test('secure', function() { + assert.equal('foo=bar; Secure', cookie.serialize('foo', 'bar', { + secure: true + })); + + assert.equal('foo=bar', cookie.serialize('foo', 'bar', { + secure: false + })); +}); + +test('domain', function() { + assert.equal('foo=bar; Domain=example.com', cookie.serialize('foo', 'bar', { + domain: 'example.com' + })); +}); + +test('httpOnly', function() { + assert.equal('foo=bar; HttpOnly', cookie.serialize('foo', 'bar', { + httpOnly: true + })); +}); + +test('maxAge', function() { + assert.equal('foo=bar; Max-Age=1000', cookie.serialize('foo', 'bar', { + maxAge: 1000 + })); +}); + +test('escaping', function() { + assert.deepEqual('cat=%2B%20', cookie.serialize('cat', '+ ')); +}); + +test('parse->serialize', function() { + + assert.deepEqual({ cat: 'foo=123&name=baz five' }, cookie.parse( + cookie.serialize('cat', 'foo=123&name=baz five'))); + + assert.deepEqual({ cat: ' ";/' }, cookie.parse( + cookie.serialize('cat', ' ";/'))); +}); + +test('unencoded', function() { + assert.deepEqual('cat=+ ', cookie.serialize('cat', '+ ', { + encode: function(value) { return value; } + })); +}) diff --git a/node_modules/express/node_modules/debug/.npmignore b/node_modules/express/node_modules/debug/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/express/node_modules/debug/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/express/node_modules/debug/History.md b/node_modules/express/node_modules/debug/History.md new file mode 100644 index 0000000..f023269 --- /dev/null +++ b/node_modules/express/node_modules/debug/History.md @@ -0,0 +1,62 @@ + +0.7.2 / 2013-02-06 +================== + + * fix package.json + * fix: Mobile Safari (private mode) is broken with debug + * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript + +0.7.1 / 2013-02-05 +================== + + * add repository URL to package.json + * add DEBUG_COLORED to force colored output + * add browserify support + * fix component. Closes #24 + +0.7.0 / 2012-05-04 +================== + + * Added .component to package.json + * Added debug.component.js build + +0.6.0 / 2012-03-16 +================== + + * Added support for "-" prefix in DEBUG [Vinay Pulim] + * Added `.enabled` flag to the node version [TooTallNate] + +0.5.0 / 2012-02-02 +================== + + * Added: humanize diffs. Closes #8 + * Added `debug.disable()` to the CS variant + * Removed padding. Closes #10 + * Fixed: persist client-side variant again. Closes #9 + +0.4.0 / 2012-02-01 +================== + + * Added browser variant support for older browsers [TooTallNate] + * Added `debug.enable('project:*')` to browser variant [TooTallNate] + * Added padding to diff (moved it to the right) + +0.3.0 / 2012-01-26 +================== + + * Added millisecond diff when isatty, otherwise UTC string + +0.2.0 / 2012-01-22 +================== + + * Added wildcard support + +0.1.0 / 2011-12-02 +================== + + * Added: remove colors unless stderr isatty [TooTallNate] + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/node_modules/debug/Readme.md b/node_modules/express/node_modules/debug/Readme.md new file mode 100644 index 0000000..15ee501 --- /dev/null +++ b/node_modules/express/node_modules/debug/Readme.md @@ -0,0 +1,115 @@ + +# debug + + tiny node.js debugging utility modelled after node core's debugging technique. + +## Installation + +``` +$ npm install debug +``` + +## Usage + + With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility. + +Example _app.js_: + +```js +var debug = require('debug')('http') + , http = require('http') + , name = 'My App'; + +// fake app + +debug('booting %s', name); + +http.createServer(function(req, res){ + debug(req.method + ' ' + req.url); + res.end('hello\n'); +}).listen(3000, function(){ + debug('listening'); +}); + +// fake worker of some kind + +require('./worker'); +``` + +Example _worker.js_: + +```js +var debug = require('debug')('worker'); + +setInterval(function(){ + debug('doing some work'); +}, 1000); +``` + + The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples: + + ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png) + + ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png) + +## Millisecond diff + + When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls. + + ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png) + + When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below: + + ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png) + +## Conventions + + If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". + +## Wildcards + + The "*" character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`. + + You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with "connect:". + +## Browser support + + Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. + +```js +a = debug('worker:a'); +b = debug('worker:b'); + +setInterval(function(){ + a('doing some work'); +}, 1000); + +setInterval(function(){ + a('doing some work'); +}, 1200); +``` + +## License + +(The MIT License) + +Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/express/node_modules/debug/component.json b/node_modules/express/node_modules/debug/component.json new file mode 100644 index 0000000..4ad0971 --- /dev/null +++ b/node_modules/express/node_modules/debug/component.json @@ -0,0 +1,9 @@ +{ + "name": "debug", + "repo": "visionmedia/debug", + "description": "small debugging utility", + "version": "0.7.2", + "keywords": ["debug", "log", "debugger"], + "scripts": ["index.js", "debug.js"], + "dependencies": {} +} diff --git a/node_modules/express/node_modules/debug/debug.js b/node_modules/express/node_modules/debug/debug.js new file mode 100644 index 0000000..e47ba5b --- /dev/null +++ b/node_modules/express/node_modules/debug/debug.js @@ -0,0 +1,124 @@ + +/** + * Expose `debug()` as the module. + */ + +module.exports = debug; + +/** + * Create a debugger with the given `name`. + * + * @param {String} name + * @return {Type} + * @api public + */ + +function debug(name) { + if (!debug.enabled(name)) return function(){}; + + return function(fmt){ + var curr = new Date; + var ms = curr - (debug[name] || curr); + debug[name] = curr; + + fmt = name + + ' ' + + fmt + + ' +' + debug.humanize(ms); + + // This hackery is required for IE8 + // where `console.log` doesn't have 'apply' + window.console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); + } +} + +/** + * The currently active debug mode names. + */ + +debug.names = []; +debug.skips = []; + +/** + * Enables a debug mode by name. This can include modes + * separated by a colon and wildcards. + * + * @param {String} name + * @api public + */ + +debug.enable = function(name) { + try { + localStorage.debug = name; + } catch(e){} + + var split = (name || '').split(/[\s,]+/) + , len = split.length; + + for (var i = 0; i < len; i++) { + name = split[i].replace('*', '.*?'); + if (name[0] === '-') { + debug.skips.push(new RegExp('^' + name.substr(1) + '$')); + } + else { + debug.names.push(new RegExp('^' + name + '$')); + } + } +}; + +/** + * Disable debug output. + * + * @api public + */ + +debug.disable = function(){ + debug.enable(''); +}; + +/** + * Humanize the given `ms`. + * + * @param {Number} m + * @return {String} + * @api private + */ + +debug.humanize = function(ms) { + var sec = 1000 + , min = 60 * 1000 + , hour = 60 * min; + + if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; + if (ms >= min) return (ms / min).toFixed(1) + 'm'; + if (ms >= sec) return (ms / sec | 0) + 's'; + return ms + 'ms'; +}; + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +debug.enabled = function(name) { + for (var i = 0, len = debug.skips.length; i < len; i++) { + if (debug.skips[i].test(name)) { + return false; + } + } + for (var i = 0, len = debug.names.length; i < len; i++) { + if (debug.names[i].test(name)) { + return true; + } + } + return false; +}; + +// persist + +if (window.localStorage) debug.enable(localStorage.debug); diff --git a/node_modules/express/node_modules/debug/example/app.js b/node_modules/express/node_modules/debug/example/app.js new file mode 100644 index 0000000..05374d9 --- /dev/null +++ b/node_modules/express/node_modules/debug/example/app.js @@ -0,0 +1,19 @@ + +var debug = require('../')('http') + , http = require('http') + , name = 'My App'; + +// fake app + +debug('booting %s', name); + +http.createServer(function(req, res){ + debug(req.method + ' ' + req.url); + res.end('hello\n'); +}).listen(3000, function(){ + debug('listening'); +}); + +// fake worker of some kind + +require('./worker'); \ No newline at end of file diff --git a/node_modules/express/node_modules/debug/example/browser.html b/node_modules/express/node_modules/debug/example/browser.html new file mode 100644 index 0000000..7510eee --- /dev/null +++ b/node_modules/express/node_modules/debug/example/browser.html @@ -0,0 +1,24 @@ + + + debug() + + + + + + + diff --git a/node_modules/express/node_modules/debug/example/wildcards.js b/node_modules/express/node_modules/debug/example/wildcards.js new file mode 100644 index 0000000..1fdac20 --- /dev/null +++ b/node_modules/express/node_modules/debug/example/wildcards.js @@ -0,0 +1,10 @@ + +var debug = { + foo: require('../')('test:foo'), + bar: require('../')('test:bar'), + baz: require('../')('test:baz') +}; + +debug.foo('foo') +debug.bar('bar') +debug.baz('baz') \ No newline at end of file diff --git a/node_modules/express/node_modules/debug/example/worker.js b/node_modules/express/node_modules/debug/example/worker.js new file mode 100644 index 0000000..7f6d288 --- /dev/null +++ b/node_modules/express/node_modules/debug/example/worker.js @@ -0,0 +1,22 @@ + +// DEBUG=* node example/worker +// DEBUG=worker:* node example/worker +// DEBUG=worker:a node example/worker +// DEBUG=worker:b node example/worker + +var a = require('../')('worker:a') + , b = require('../')('worker:b'); + +function work() { + a('doing lots of uninteresting work'); + setTimeout(work, Math.random() * 1000); +} + +work(); + +function workb() { + b('doing some work'); + setTimeout(workb, Math.random() * 2000); +} + +workb(); \ No newline at end of file diff --git a/node_modules/express/node_modules/debug/index.js b/node_modules/express/node_modules/debug/index.js new file mode 100644 index 0000000..e02c13b --- /dev/null +++ b/node_modules/express/node_modules/debug/index.js @@ -0,0 +1,5 @@ +if ('undefined' == typeof window) { + module.exports = require('./lib/debug'); +} else { + module.exports = require('./debug'); +} diff --git a/node_modules/express/node_modules/debug/lib/debug.js b/node_modules/express/node_modules/debug/lib/debug.js new file mode 100644 index 0000000..0b07aa1 --- /dev/null +++ b/node_modules/express/node_modules/debug/lib/debug.js @@ -0,0 +1,134 @@ +/** + * Module dependencies. + */ + +var tty = require('tty'); + +/** + * Expose `debug()` as the module. + */ + +module.exports = debug; + +/** + * Enabled debuggers. + */ + +var names = [] + , skips = []; + +(process.env.DEBUG || '') + .split(/[\s,]+/) + .forEach(function(name){ + name = name.replace('*', '.*?'); + if (name[0] === '-') { + skips.push(new RegExp('^' + name.substr(1) + '$')); + } else { + names.push(new RegExp('^' + name + '$')); + } + }); + +/** + * Colors. + */ + +var colors = [6, 2, 3, 4, 5, 1]; + +/** + * Previous debug() call. + */ + +var prev = {}; + +/** + * Previously assigned color. + */ + +var prevColor = 0; + +/** + * Is stdout a TTY? Colored output is disabled when `true`. + */ + +var isatty = tty.isatty(2); + +/** + * Select a color. + * + * @return {Number} + * @api private + */ + +function color() { + return colors[prevColor++ % colors.length]; +} + +/** + * Humanize the given `ms`. + * + * @param {Number} m + * @return {String} + * @api private + */ + +function humanize(ms) { + var sec = 1000 + , min = 60 * 1000 + , hour = 60 * min; + + if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; + if (ms >= min) return (ms / min).toFixed(1) + 'm'; + if (ms >= sec) return (ms / sec | 0) + 's'; + return ms + 'ms'; +} + +/** + * Create a debugger with the given `name`. + * + * @param {String} name + * @return {Type} + * @api public + */ + +function debug(name) { + function disabled(){} + disabled.enabled = false; + + var match = skips.some(function(re){ + return re.test(name); + }); + + if (match) return disabled; + + match = names.some(function(re){ + return re.test(name); + }); + + if (!match) return disabled; + var c = color(); + + function colored(fmt) { + var curr = new Date; + var ms = curr - (prev[name] || curr); + prev[name] = curr; + + fmt = ' \u001b[9' + c + 'm' + name + ' ' + + '\u001b[3' + c + 'm\u001b[90m' + + fmt + '\u001b[3' + c + 'm' + + ' +' + humanize(ms) + '\u001b[0m'; + + console.error.apply(this, arguments); + } + + function plain(fmt) { + fmt = new Date().toUTCString() + + ' ' + name + ' ' + fmt; + console.error.apply(this, arguments); + } + + colored.enabled = plain.enabled = true; + + return isatty || process.env.DEBUG_COLORS + ? colored + : plain; +} diff --git a/node_modules/express/node_modules/debug/package.json b/node_modules/express/node_modules/debug/package.json new file mode 100644 index 0000000..adcadad --- /dev/null +++ b/node_modules/express/node_modules/debug/package.json @@ -0,0 +1,44 @@ +{ + "name": "debug", + "version": "0.7.2", + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/debug.git" + }, + "description": "small debugging utility", + "keywords": [ + "debug", + "log", + "debugger" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "*" + }, + "main": "lib/debug.js", + "browserify": "debug.js", + "engines": { + "node": "*" + }, + "component": { + "scripts": { + "debug/index.js": "index.js", + "debug/debug.js": "debug.js" + } + }, + "readme": "\n# debug\n\n tiny node.js debugging utility modelled after node core's debugging technique.\n\n## Installation\n\n```\n$ npm install debug\n```\n\n## Usage\n\n With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.\n \nExample _app.js_:\n\n```js\nvar debug = require('debug')('http')\n , http = require('http')\n , name = 'My App';\n\n// fake app\n\ndebug('booting %s', name);\n\nhttp.createServer(function(req, res){\n debug(req.method + ' ' + req.url);\n res.end('hello\\n');\n}).listen(3000, function(){\n debug('listening');\n});\n\n// fake worker of some kind\n\nrequire('./worker');\n```\n\nExample _worker.js_:\n\n```js\nvar debug = require('debug')('worker');\n\nsetInterval(function(){\n debug('doing some work');\n}, 1000);\n```\n\n The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:\n\n ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)\n\n ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)\n\n## Millisecond diff\n\n When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the \"+NNNms\" will show you how much time was spent between calls.\n\n ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)\n\n When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:\n \n ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)\n\n## Conventions\n\n If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use \":\" to separate features. For example \"bodyParser\" from Connect would then be \"connect:bodyParser\". \n\n## Wildcards\n\n The \"*\" character may be used as a wildcard. Suppose for example your library has debuggers named \"connect:bodyParser\", \"connect:compress\", \"connect:session\", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.\n\n You can also exclude specific debuggers by prefixing them with a \"-\" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with \"connect:\".\n\n## Browser support\n\n Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. \n\n```js\na = debug('worker:a');\nb = debug('worker:b');\n\nsetInterval(function(){\n a('doing some work');\n}, 1000);\n\nsetInterval(function(){\n a('doing some work');\n}, 1200);\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 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.", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/visionmedia/debug/issues" + }, + "_id": "debug@0.7.2", + "dist": { + "shasum": "87611f055831a342fffa832ddb46d8ba85d70153" + }, + "_from": "debug@*", + "_resolved": "https://registry.npmjs.org/debug/-/debug-0.7.2.tgz" +} diff --git a/node_modules/express/node_modules/fresh/.npmignore b/node_modules/express/node_modules/fresh/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/express/node_modules/fresh/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/express/node_modules/fresh/Makefile b/node_modules/express/node_modules/fresh/Makefile new file mode 100644 index 0000000..8e8640f --- /dev/null +++ b/node_modules/express/node_modules/fresh/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --reporter spec \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/fresh/Readme.md b/node_modules/express/node_modules/fresh/Readme.md new file mode 100644 index 0000000..273130d --- /dev/null +++ b/node_modules/express/node_modules/fresh/Readme.md @@ -0,0 +1,32 @@ + +# node-fresh + + HTTP response freshness testing + +## fresh(req, res) + + Check freshness of `req` and `res` headers. + + When the cache is "fresh" __true__ is returned, + otherwise __false__ is returned to indicate that + the cache is now stale. + +## Example: + +```js +var req = { 'if-none-match': 'tobi' }; +var res = { 'etag': 'luna' }; +fresh(req, res); +// => false + +var req = { 'if-none-match': 'tobi' }; +var res = { 'etag': 'tobi' }; +fresh(req, res); +// => true +``` + +## Installation + +``` +$ npm install fresh +``` \ No newline at end of file diff --git a/node_modules/express/node_modules/fresh/index.js b/node_modules/express/node_modules/fresh/index.js new file mode 100644 index 0000000..b2f4d41 --- /dev/null +++ b/node_modules/express/node_modules/fresh/index.js @@ -0,0 +1,49 @@ + +/** + * Expose `fresh()`. + */ + +module.exports = fresh; + +/** + * Check freshness of `req` and `res` headers. + * + * When the cache is "fresh" __true__ is returned, + * otherwise __false__ is returned to indicate that + * the cache is now stale. + * + * @param {Object} req + * @param {Object} res + * @return {Boolean} + * @api public + */ + +function fresh(req, res) { + // defaults + var etagMatches = true; + var notModified = true; + + // fields + var modifiedSince = req['if-modified-since']; + var noneMatch = req['if-none-match']; + var lastModified = res['last-modified']; + var etag = res['etag']; + + // unconditional request + if (!modifiedSince && !noneMatch) return false; + + // parse if-none-match + if (noneMatch) noneMatch = noneMatch.split(/ *, */); + + // if-none-match + if (noneMatch) etagMatches = ~noneMatch.indexOf(etag) || '*' == noneMatch[0]; + + // if-modified-since + if (modifiedSince) { + modifiedSince = new Date(modifiedSince); + lastModified = new Date(lastModified); + notModified = lastModified <= modifiedSince; + } + + return !! (etagMatches && notModified); +} \ No newline at end of file diff --git a/node_modules/express/node_modules/fresh/package.json b/node_modules/express/node_modules/fresh/package.json new file mode 100644 index 0000000..027de28 --- /dev/null +++ b/node_modules/express/node_modules/fresh/package.json @@ -0,0 +1,24 @@ +{ + "name": "fresh", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "description": "HTTP response freshness testing", + "version": "0.1.0", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "readme": "\n# node-fresh\n\n HTTP response freshness testing\n\n## fresh(req, res)\n\n Check freshness of `req` and `res` headers.\n\n When the cache is \"fresh\" __true__ is returned,\n otherwise __false__ is returned to indicate that\n the cache is now stale.\n\n## Example:\n\n```js\nvar req = { 'if-none-match': 'tobi' };\nvar res = { 'etag': 'luna' };\nfresh(req, res);\n// => false\n\nvar req = { 'if-none-match': 'tobi' };\nvar res = { 'etag': 'tobi' };\nfresh(req, res);\n// => true\n```\n\n## Installation\n\n```\n$ npm install fresh\n```", + "readmeFilename": "Readme.md", + "_id": "fresh@0.1.0", + "dist": { + "shasum": "88d3ada742d47e42baf7b4c0a3288e08986414e2" + }, + "_from": "fresh@0.1.0", + "_resolved": "https://registry.npmjs.org/fresh/-/fresh-0.1.0.tgz" +} diff --git a/node_modules/express/node_modules/methods/index.js b/node_modules/express/node_modules/methods/index.js new file mode 100644 index 0000000..297d022 --- /dev/null +++ b/node_modules/express/node_modules/methods/index.js @@ -0,0 +1,26 @@ + +module.exports = [ + 'get' + , 'post' + , 'put' + , 'head' + , 'delete' + , 'options' + , 'trace' + , 'copy' + , 'lock' + , 'mkcol' + , 'move' + , 'propfind' + , 'proppatch' + , 'unlock' + , 'report' + , 'mkactivity' + , 'checkout' + , 'merge' + , 'm-search' + , 'notify' + , 'subscribe' + , 'unsubscribe' + , 'patch' +]; \ No newline at end of file diff --git a/node_modules/express/node_modules/methods/package.json b/node_modules/express/node_modules/methods/package.json new file mode 100644 index 0000000..00901f4 --- /dev/null +++ b/node_modules/express/node_modules/methods/package.json @@ -0,0 +1,24 @@ +{ + "name": "methods", + "version": "0.0.1", + "description": "HTTP methods that node supports", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "http", + "methods" + ], + "author": { + "name": "TJ Holowaychuk" + }, + "license": "MIT", + "readme": "ERROR: No README data found!", + "_id": "methods@0.0.1", + "dist": { + "shasum": "a7b41634ec7800d4a6fc25c10de5d0c538af98fd" + }, + "_from": "methods@0.0.1", + "_resolved": "https://registry.npmjs.org/methods/-/methods-0.0.1.tgz" +} diff --git a/node_modules/express/node_modules/mkdirp/.npmignore b/node_modules/express/node_modules/mkdirp/.npmignore new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/express/node_modules/mkdirp/.travis.yml b/node_modules/express/node_modules/mkdirp/.travis.yml new file mode 100644 index 0000000..84fd7ca --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.9 diff --git a/node_modules/express/node_modules/mkdirp/LICENSE b/node_modules/express/node_modules/mkdirp/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/express/node_modules/mkdirp/examples/pow.js b/node_modules/express/node_modules/mkdirp/examples/pow.js new file mode 100644 index 0000000..e692421 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/examples/pow.js @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/express/node_modules/mkdirp/index.js b/node_modules/express/node_modules/mkdirp/index.js new file mode 100644 index 0000000..fda6de8 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/index.js @@ -0,0 +1,82 @@ +var path = require('path'); +var fs = require('fs'); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, mode, f, made) { + if (typeof mode === 'function' || mode === undefined) { + f = mode; + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + fs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), mode, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, mode, cb, made); + }); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + fs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} + +mkdirP.sync = function sync (p, mode, made) { + if (mode === undefined) { + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + try { + fs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), mode, made); + sync(p, mode, made); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = fs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + } + } + + return made; +}; diff --git a/node_modules/express/node_modules/mkdirp/package.json b/node_modules/express/node_modules/mkdirp/package.json new file mode 100644 index 0000000..598383e --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/package.json @@ -0,0 +1,37 @@ +{ + "name": "mkdirp", + "description": "Recursively mkdir, like `mkdir -p`", + "version": "0.3.5", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "main": "./index", + "keywords": [ + "mkdir", + "directory" + ], + "repository": { + "type": "git", + "url": "http://github.com/substack/node-mkdirp.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "devDependencies": { + "tap": "~0.4.0" + }, + "license": "MIT", + "readme": "# mkdirp\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\n# example\n\n## pow.js\n\n```js\nvar mkdirp = require('mkdirp');\n \nmkdirp('/tmp/foo/bar/baz', function (err) {\n if (err) console.error(err)\n else console.log('pow!')\n});\n```\n\nOutput\n\n```\npow!\n```\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\n# methods\n\n```js\nvar mkdirp = require('mkdirp');\n```\n\n## mkdirp(dir, mode, cb)\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\n## mkdirp.sync(dir, mode)\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\n# install\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm install mkdirp\n```\n\n# license\n\nMIT\n", + "readmeFilename": "readme.markdown", + "bugs": { + "url": "https://github.com/substack/node-mkdirp/issues" + }, + "_id": "mkdirp@0.3.5", + "dist": { + "shasum": "b272e3946023e206f8e6f60fb26d39bd3fc78d1c" + }, + "_from": "mkdirp@0.3.5", + "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" +} diff --git a/node_modules/express/node_modules/mkdirp/readme.markdown b/node_modules/express/node_modules/mkdirp/readme.markdown new file mode 100644 index 0000000..83b0216 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/readme.markdown @@ -0,0 +1,63 @@ +# mkdirp + +Like `mkdir -p`, but in node.js! + +[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp) + +# example + +## pow.js + +```js +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); +``` + +Output + +``` +pow! +``` + +And now /tmp/foo/bar/baz exists, huzzah! + +# methods + +```js +var mkdirp = require('mkdirp'); +``` + +## mkdirp(dir, mode, cb) + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +`cb(err, made)` fires with the error or the first directory `made` +that had to be created, if any. + +## mkdirp.sync(dir, mode) + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +Returns the first directory that had to be created, if any. + +# install + +With [npm](http://npmjs.org) do: + +``` +npm install mkdirp +``` + +# license + +MIT diff --git a/node_modules/express/node_modules/mkdirp/test/chmod.js b/node_modules/express/node_modules/mkdirp/test/chmod.js new file mode 100644 index 0000000..520dcb8 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/chmod.js @@ -0,0 +1,38 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +test('chmod-pre', function (t) { + var mode = 0744 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.equal(stat && stat.mode & 0777, mode, 'should be 0744'); + t.end(); + }); + }); +}); + +test('chmod', function (t) { + var mode = 0755 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.end(); + }); + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/clobber.js b/node_modules/express/node_modules/mkdirp/test/clobber.js new file mode 100644 index 0000000..0eb7099 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/clobber.js @@ -0,0 +1,37 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +// a file in the way +var itw = ps.slice(0, 3).join('/'); + + +test('clobber-pre', function (t) { + console.error("about to write to "+itw) + fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.'); + + fs.stat(itw, function (er, stat) { + t.ifError(er) + t.ok(stat && stat.isFile(), 'should be file') + t.end() + }) +}) + +test('clobber', function (t) { + t.plan(2); + mkdirp(file, 0755, function (err) { + t.ok(err); + t.equal(err.code, 'ENOTDIR'); + t.end(); + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/mkdirp.js b/node_modules/express/node_modules/mkdirp/test/mkdirp.js new file mode 100644 index 0000000..b07cd70 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/mkdirp.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('woo', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/perm.js b/node_modules/express/node_modules/mkdirp/test/perm.js new file mode 100644 index 0000000..23a7abb --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/perm.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('async perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); + +test('async root perm', function (t) { + mkdirp('/tmp', 0755, function (err) { + if (err) t.fail(err); + t.end(); + }); + t.end(); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/perm_sync.js b/node_modules/express/node_modules/mkdirp/test/perm_sync.js new file mode 100644 index 0000000..f685f60 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/perm_sync.js @@ -0,0 +1,39 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json'; + + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); + +test('sync root perm', function (t) { + t.plan(1); + + var file = '/tmp'; + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/race.js b/node_modules/express/node_modules/mkdirp/test/race.js new file mode 100644 index 0000000..96a0447 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/race.js @@ -0,0 +1,41 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('race', function (t) { + t.plan(4); + var ps = [ '', 'tmp' ]; + + for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); + } + var file = ps.join('/'); + + var res = 2; + mk(file, function () { + if (--res === 0) t.end(); + }); + + mk(file, function () { + if (--res === 0) t.end(); + }); + + function mk (file, cb) { + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + if (cb) cb(); + } + }) + }) + }); + } +}); diff --git a/node_modules/express/node_modules/mkdirp/test/rel.js b/node_modules/express/node_modules/mkdirp/test/rel.js new file mode 100644 index 0000000..7985824 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/rel.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('rel', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var cwd = process.cwd(); + process.chdir('/tmp'); + + var file = [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + process.chdir(cwd); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/return.js b/node_modules/express/node_modules/mkdirp/test/return.js new file mode 100644 index 0000000..bce68e5 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/return.js @@ -0,0 +1,25 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, '/tmp/' + x); + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, null); + }); + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/return_sync.js b/node_modules/express/node_modules/mkdirp/test/return_sync.js new file mode 100644 index 0000000..7c222d3 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/return_sync.js @@ -0,0 +1,24 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + // Note that this will throw on failure, which will fail the test. + var made = mkdirp.sync(file); + t.equal(made, '/tmp/' + x); + + // making the same file again should have no effect. + made = mkdirp.sync(file); + t.equal(made, null); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/root.js b/node_modules/express/node_modules/mkdirp/test/root.js new file mode 100644 index 0000000..97ad7a2 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/root.js @@ -0,0 +1,18 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('root', function (t) { + // '/' on unix, 'c:/' on windows. + var file = path.resolve('/'); + + mkdirp(file, 0755, function (err) { + if (err) throw err + fs.stat(file, function (er, stat) { + if (er) throw er + t.ok(stat.isDirectory(), 'target is a directory'); + t.end(); + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/sync.js b/node_modules/express/node_modules/mkdirp/test/sync.js new file mode 100644 index 0000000..7530cad --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file, 0755); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/umask.js b/node_modules/express/node_modules/mkdirp/test/umask.js new file mode 100644 index 0000000..64ccafe --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/umask.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('implicit mode from umask', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0777 & (~process.umask())); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/umask_sync.js b/node_modules/express/node_modules/mkdirp/test/umask_sync.js new file mode 100644 index 0000000..35bd5cb --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/umask_sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('umask sync modes', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, (0777 & (~process.umask()))); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/express/node_modules/range-parser/.npmignore b/node_modules/express/node_modules/range-parser/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/express/node_modules/range-parser/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/express/node_modules/range-parser/History.md b/node_modules/express/node_modules/range-parser/History.md new file mode 100644 index 0000000..82df7b1 --- /dev/null +++ b/node_modules/express/node_modules/range-parser/History.md @@ -0,0 +1,15 @@ + +0.0.4 / 2012-06-17 +================== + + * changed: ret -1 for unsatisfiable and -2 when invalid + +0.0.3 / 2012-06-17 +================== + + * fix last-byte-pos default to len - 1 + +0.0.2 / 2012-06-14 +================== + + * add `.type` diff --git a/node_modules/express/node_modules/range-parser/Makefile b/node_modules/express/node_modules/range-parser/Makefile new file mode 100644 index 0000000..8e8640f --- /dev/null +++ b/node_modules/express/node_modules/range-parser/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --reporter spec \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/range-parser/Readme.md b/node_modules/express/node_modules/range-parser/Readme.md new file mode 100644 index 0000000..b2a67fe --- /dev/null +++ b/node_modules/express/node_modules/range-parser/Readme.md @@ -0,0 +1,28 @@ + +# node-range-parser + + Range header field parser. + +## Example: + +```js +assert(-1 == parse(200, 'bytes=500-20')); +assert(-2 == parse(200, 'bytes=malformed')); +parse(200, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 199 }])); +parse(1000, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 499 }])); +parse(1000, 'bytes=40-80').should.eql(arr('bytes', [{ start: 40, end: 80 }])); +parse(1000, 'bytes=-500').should.eql(arr('bytes', [{ start: 500, end: 999 }])); +parse(1000, 'bytes=-400').should.eql(arr('bytes', [{ start: 600, end: 999 }])); +parse(1000, 'bytes=500-').should.eql(arr('bytes', [{ start: 500, end: 999 }])); +parse(1000, 'bytes=400-').should.eql(arr('bytes', [{ start: 400, end: 999 }])); +parse(1000, 'bytes=0-0').should.eql(arr('bytes', [{ start: 0, end: 0 }])); +parse(1000, 'bytes=-1').should.eql(arr('bytes', [{ start: 999, end: 999 }])); +parse(1000, 'items=0-5').should.eql(arr('items', [{ start: 0, end: 5 }])); +parse(1000, 'bytes=40-80,-1').should.eql(arr('bytes', [{ start: 40, end: 80 }, { start: 999, end: 999 }])); +``` + +## Installation + +``` +$ npm install range-parser +``` \ No newline at end of file diff --git a/node_modules/express/node_modules/range-parser/index.js b/node_modules/express/node_modules/range-parser/index.js new file mode 100644 index 0000000..9b0f7a8 --- /dev/null +++ b/node_modules/express/node_modules/range-parser/index.js @@ -0,0 +1,49 @@ + +/** + * Parse "Range" header `str` relative to the given file `size`. + * + * @param {Number} size + * @param {String} str + * @return {Array} + * @api public + */ + +module.exports = function(size, str){ + var valid = true; + var i = str.indexOf('='); + + if (-1 == i) return -2; + + var arr = str.slice(i + 1).split(',').map(function(range){ + var range = range.split('-') + , start = parseInt(range[0], 10) + , end = parseInt(range[1], 10); + + // -nnn + if (isNaN(start)) { + start = size - end; + end = size - 1; + // nnn- + } else if (isNaN(end)) { + end = size - 1; + } + + // limit last-byte-pos to current length + if (end > size - 1) end = size - 1; + + // invalid + if (isNaN(start) + || isNaN(end) + || start > end + || start < 0) valid = false; + + return { + start: start, + end: end + }; + }); + + arr.type = str.slice(0, i); + + return valid ? arr : -1; +}; \ No newline at end of file diff --git a/node_modules/express/node_modules/range-parser/package.json b/node_modules/express/node_modules/range-parser/package.json new file mode 100644 index 0000000..b7a4c46 --- /dev/null +++ b/node_modules/express/node_modules/range-parser/package.json @@ -0,0 +1,24 @@ +{ + "name": "range-parser", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "description": "Range header field string parser", + "version": "0.0.4", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "readme": "\n# node-range-parser\n\n Range header field parser.\n\n## Example:\n\n```js\nassert(-1 == parse(200, 'bytes=500-20'));\nassert(-2 == parse(200, 'bytes=malformed'));\nparse(200, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 199 }]));\nparse(1000, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 499 }]));\nparse(1000, 'bytes=40-80').should.eql(arr('bytes', [{ start: 40, end: 80 }]));\nparse(1000, 'bytes=-500').should.eql(arr('bytes', [{ start: 500, end: 999 }]));\nparse(1000, 'bytes=-400').should.eql(arr('bytes', [{ start: 600, end: 999 }]));\nparse(1000, 'bytes=500-').should.eql(arr('bytes', [{ start: 500, end: 999 }]));\nparse(1000, 'bytes=400-').should.eql(arr('bytes', [{ start: 400, end: 999 }]));\nparse(1000, 'bytes=0-0').should.eql(arr('bytes', [{ start: 0, end: 0 }]));\nparse(1000, 'bytes=-1').should.eql(arr('bytes', [{ start: 999, end: 999 }]));\nparse(1000, 'items=0-5').should.eql(arr('items', [{ start: 0, end: 5 }]));\nparse(1000, 'bytes=40-80,-1').should.eql(arr('bytes', [{ start: 40, end: 80 }, { start: 999, end: 999 }]));\n```\n\n## Installation\n\n```\n$ npm install range-parser\n```", + "readmeFilename": "Readme.md", + "_id": "range-parser@0.0.4", + "dist": { + "shasum": "8aae102e1035de1c98dfc67147b6672510097e8c" + }, + "_from": "range-parser@0.0.4", + "_resolved": "https://registry.npmjs.org/range-parser/-/range-parser-0.0.4.tgz" +} diff --git a/node_modules/express/node_modules/send/.npmignore b/node_modules/express/node_modules/send/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/express/node_modules/send/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/express/node_modules/send/History.md b/node_modules/express/node_modules/send/History.md new file mode 100644 index 0000000..e348db5 --- /dev/null +++ b/node_modules/express/node_modules/send/History.md @@ -0,0 +1,35 @@ + +0.1.3 / 2013-07-08 +================== + + * Revert "Fix fd leak" + +0.1.2 / 2013-07-03 +================== + + * Fix fd leak + +0.1.0 / 2012-08-25 +================== + + * add options parameter to send() that is passed to fs.createReadStream() [kanongil] + +0.0.4 / 2012-08-16 +================== + + * allow custom "Accept-Ranges" definition + +0.0.3 / 2012-07-16 +================== + + * fix normalization of the root directory. Closes #3 + +0.0.2 / 2012-07-09 +================== + + * add passing of req explicitly for now (YUCK) + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/node_modules/send/Makefile b/node_modules/express/node_modules/send/Makefile new file mode 100644 index 0000000..a9dcfd5 --- /dev/null +++ b/node_modules/express/node_modules/send/Makefile @@ -0,0 +1,8 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec \ + --bail + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/send/Readme.md b/node_modules/express/node_modules/send/Readme.md new file mode 100644 index 0000000..ea7b234 --- /dev/null +++ b/node_modules/express/node_modules/send/Readme.md @@ -0,0 +1,128 @@ +# send + + Send is Connect's `static()` extracted for generalized use, a streaming static file + server supporting partial responses (Ranges), conditional-GET negotiation, high test coverage, and granular events which may be leveraged to take appropriate actions in your application or framework. + +## Installation + + $ npm install send + +## Examples + + Small: + +```js +var http = require('http'); +var send = require('send'); + +var app = http.createServer(function(req, res){ + send(req, req.url).pipe(res); +}).listen(3000); +``` + + Serving from a root directory with custom error-handling: + +```js +var http = require('http'); +var send = require('send'); +var url = require('url'); + +var app = http.createServer(function(req, res){ + // your custom error-handling logic: + function error(err) { + res.statusCode = err.status || 500; + res.end(err.message); + } + + // your custom directory handling logic: + function redirect() { + res.statusCode = 301; + res.setHeader('Location', req.url + '/'); + res.end('Redirecting to ' + req.url + '/'); + } + + // transfer arbitrary files from within + // /www/example.com/public/* + send(req, url.parse(req.url).pathname) + .root('/www/example.com/public') + .on('error', error) + .on('directory', redirect) + .pipe(res); +}).listen(3000); +``` + +## API + +### Events + + - `error` an error occurred `(err)` + - `directory` a directory was requested + - `file` a file was requested `(path, stat)` + - `stream` file streaming has started `(stream)` + - `end` streaming has completed + +### .root(dir) + + Serve files relative to `path`. Aliased as `.from(dir)`. + +### .index(path) + + By default send supports "index.html" files, to disable this + invoke `.index(false)` or to supply a new index pass a string. + +### .maxage(ms) + + Provide a max-age in milliseconds for http caching, defaults to 0. + +### .hidden(bool) + + Enable or disable transfer of hidden files, defaults to false. + +## Error-handling + + By default when no `error` listeners are present an automatic response will be made, otherwise you have full control over the response, aka you may show a 5xx page etc. + +## Caching + + It does _not_ perform internal caching, you should use a reverse proxy cache such + as Varnish for this, or those fancy things called CDNs. If your application is small enough that it would benefit from single-node memory caching, it's small enough that it does not need caching at all ;). + +## Debugging + + To enable `debug()` instrumentation output export __DEBUG__: + +``` +$ DEBUG=send node app +``` + +## Running tests + +``` +$ npm install +$ make test +``` + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/express/node_modules/send/index.js b/node_modules/express/node_modules/send/index.js new file mode 100644 index 0000000..f17158d --- /dev/null +++ b/node_modules/express/node_modules/send/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/send'); \ No newline at end of file diff --git a/node_modules/express/node_modules/send/lib/send.js b/node_modules/express/node_modules/send/lib/send.js new file mode 100644 index 0000000..a3d94a6 --- /dev/null +++ b/node_modules/express/node_modules/send/lib/send.js @@ -0,0 +1,474 @@ + +/** + * Module dependencies. + */ + +var debug = require('debug')('send') + , parseRange = require('range-parser') + , Stream = require('stream') + , mime = require('mime') + , fresh = require('fresh') + , path = require('path') + , http = require('http') + , fs = require('fs') + , basename = path.basename + , normalize = path.normalize + , join = path.join + , utils = require('./utils'); + +/** + * Expose `send`. + */ + +exports = module.exports = send; + +/** + * Expose mime module. + */ + +exports.mime = mime; + +/** + * Return a `SendStream` for `req` and `path`. + * + * @param {Request} req + * @param {String} path + * @param {Object} options + * @return {SendStream} + * @api public + */ + +function send(req, path, options) { + return new SendStream(req, path, options); +} + +/** + * Initialize a `SendStream` with the given `path`. + * + * Events: + * + * - `error` an error occurred + * - `stream` file streaming has started + * - `end` streaming has completed + * - `directory` a directory was requested + * + * @param {Request} req + * @param {String} path + * @param {Object} options + * @api private + */ + +function SendStream(req, path, options) { + var self = this; + this.req = req; + this.path = path; + this.options = options || {}; + this.maxage(0); + this.hidden(false); + this.index('index.html'); +} + +/** + * Inherits from `Stream.prototype`. + */ + +SendStream.prototype.__proto__ = Stream.prototype; + +/** + * Enable or disable "hidden" (dot) files. + * + * @param {Boolean} path + * @return {SendStream} + * @api public + */ + +SendStream.prototype.hidden = function(val){ + debug('hidden %s', val); + this._hidden = val; + return this; +}; + +/** + * Set index `path`, set to a falsy + * value to disable index support. + * + * @param {String|Boolean} path + * @return {SendStream} + * @api public + */ + +SendStream.prototype.index = function(path){ + debug('index %s', path); + this._index = path; + return this; +}; + +/** + * Set root `path`. + * + * @param {String} path + * @return {SendStream} + * @api public + */ + +SendStream.prototype.root = +SendStream.prototype.from = function(path){ + this._root = normalize(path); + return this; +}; + +/** + * Set max-age to `ms`. + * + * @param {Number} ms + * @return {SendStream} + * @api public + */ + +SendStream.prototype.maxage = function(ms){ + if (Infinity == ms) ms = 60 * 60 * 24 * 365 * 1000; + debug('max-age %d', ms); + this._maxage = ms; + return this; +}; + +/** + * Emit error with `status`. + * + * @param {Number} status + * @api private + */ + +SendStream.prototype.error = function(status, err){ + var res = this.res; + var msg = http.STATUS_CODES[status]; + err = err || new Error(msg); + err.status = status; + if (this.listeners('error').length) return this.emit('error', err); + res.statusCode = err.status; + res.end(msg); +}; + +/** + * Check if the pathname is potentially malicious. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isMalicious = function(){ + return !this._root && ~this.path.indexOf('..'); +}; + +/** + * Check if the pathname ends with "/". + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.hasTrailingSlash = function(){ + return '/' == this.path[this.path.length - 1]; +}; + +/** + * Check if the basename leads with ".". + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.hasLeadingDot = function(){ + return '.' == basename(this.path)[0]; +}; + +/** + * Check if this is a conditional GET request. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isConditionalGET = function(){ + return this.req.headers['if-none-match'] + || this.req.headers['if-modified-since']; +}; + +/** + * Strip content-* header fields. + * + * @api private + */ + +SendStream.prototype.removeContentHeaderFields = function(){ + var res = this.res; + Object.keys(res._headers).forEach(function(field){ + if (0 == field.indexOf('content')) { + res.removeHeader(field); + } + }); +}; + +/** + * Respond with 304 not modified. + * + * @api private + */ + +SendStream.prototype.notModified = function(){ + var res = this.res; + debug('not modified'); + this.removeContentHeaderFields(); + res.statusCode = 304; + res.end(); +}; + +/** + * Check if the request is cacheable, aka + * responded with 2xx or 304 (see RFC 2616 section 14.2{5,6}). + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isCachable = function(){ + var res = this.res; + return (res.statusCode >= 200 && res.statusCode < 300) || 304 == res.statusCode; +}; + +/** + * Handle stat() error. + * + * @param {Error} err + * @api private + */ + +SendStream.prototype.onStatError = function(err){ + var notfound = ['ENOENT', 'ENAMETOOLONG', 'ENOTDIR']; + if (~notfound.indexOf(err.code)) return this.error(404, err); + this.error(500, err); +}; + +/** + * Check if the cache is fresh. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isFresh = function(){ + return fresh(this.req.headers, this.res._headers); +}; + +/** + * Redirect to `path`. + * + * @param {String} path + * @api private + */ + +SendStream.prototype.redirect = function(path){ + if (this.listeners('directory').length) return this.emit('directory'); + var res = this.res; + path += '/'; + res.statusCode = 301; + res.setHeader('Location', path); + res.end('Redirecting to ' + utils.escape(path)); +}; + +/** + * Pipe to `res. + * + * @param {Stream} res + * @return {Stream} res + * @api public + */ + +SendStream.prototype.pipe = function(res){ + var self = this + , args = arguments + , path = this.path + , root = this._root; + + // references + this.res = res; + + // invalid request uri + path = utils.decode(path); + if (-1 == path) return this.error(400); + + // null byte(s) + if (~path.indexOf('\0')) return this.error(400); + + // join / normalize from optional root dir + if (root) path = normalize(join(this._root, path)); + + // ".." is malicious without "root" + if (this.isMalicious()) return this.error(403); + + // malicious path + if (root && 0 != path.indexOf(root)) return this.error(403); + + // hidden file support + if (!this._hidden && this.hasLeadingDot()) return this.error(404); + + // index file support + if (this._index && this.hasTrailingSlash()) path += this._index; + + debug('stat "%s"', path); + fs.stat(path, function(err, stat){ + if (err) return self.onStatError(err); + if (stat.isDirectory()) return self.redirect(self.path); + self.emit('file', path, stat); + self.send(path, stat); + }); + + return res; +}; + +/** + * Transfer `path`. + * + * @param {String} path + * @api public + */ + +SendStream.prototype.send = function(path, stat){ + var options = this.options; + var len = stat.size; + var res = this.res; + var req = this.req; + var ranges = req.headers.range; + var offset = options.start || 0; + + // set header fields + this.setHeader(stat); + + // set content-type + this.type(path); + + // conditional GET support + if (this.isConditionalGET() + && this.isCachable() + && this.isFresh()) { + return this.notModified(); + } + + // adjust len to start/end options + len = Math.max(0, len - offset); + if (options.end !== undefined) { + var bytes = options.end - offset + 1; + if (len > bytes) len = bytes; + } + + // Range support + if (ranges) { + ranges = parseRange(len, ranges); + + // unsatisfiable + if (-1 == ranges) { + res.setHeader('Content-Range', 'bytes */' + stat.size); + return this.error(416); + } + + // valid (syntactically invalid ranges are treated as a regular response) + if (-2 != ranges) { + options.start = offset + ranges[0].start; + options.end = offset + ranges[0].end; + + // Content-Range + res.statusCode = 206; + res.setHeader('Content-Range', 'bytes ' + + ranges[0].start + + '-' + + ranges[0].end + + '/' + + len); + len = options.end - options.start + 1; + } + } + + // content-length + res.setHeader('Content-Length', len); + + // HEAD support + if ('HEAD' == req.method) return res.end(); + + this.stream(path, options); +}; + +/** + * Stream `path` to the response. + * + * @param {String} path + * @param {Object} options + * @api private + */ + +SendStream.prototype.stream = function(path, options){ + // TODO: this is all lame, refactor meeee + var self = this; + var res = this.res; + var req = this.req; + + // pipe + var stream = fs.createReadStream(path, options); + this.emit('stream', stream); + stream.pipe(res); + + // socket closed, done with the fd + req.on('close', stream.destroy.bind(stream)); + + // error handling code-smell + stream.on('error', function(err){ + // no hope in responding + if (res._header) { + console.error(err.stack); + req.destroy(); + return; + } + + // 500 + err.status = 500; + self.emit('error', err); + }); + + // end + stream.on('end', function(){ + self.emit('end'); + }); +}; + +/** + * Set content-type based on `path` + * if it hasn't been explicitly set. + * + * @param {String} path + * @api private + */ + +SendStream.prototype.type = function(path){ + var res = this.res; + if (res.getHeader('Content-Type')) return; + var type = mime.lookup(path); + var charset = mime.charsets.lookup(type); + debug('content-type %s', type); + res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : '')); +}; + +/** + * Set reaponse header fields, most + * fields may be pre-defined. + * + * @param {Object} stat + * @api private + */ + +SendStream.prototype.setHeader = function(stat){ + var res = this.res; + if (!res.getHeader('Accept-Ranges')) res.setHeader('Accept-Ranges', 'bytes'); + if (!res.getHeader('ETag')) res.setHeader('ETag', utils.etag(stat)); + if (!res.getHeader('Date')) res.setHeader('Date', new Date().toUTCString()); + if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + (this._maxage / 1000)); + if (!res.getHeader('Last-Modified')) res.setHeader('Last-Modified', stat.mtime.toUTCString()); +}; diff --git a/node_modules/express/node_modules/send/lib/utils.js b/node_modules/express/node_modules/send/lib/utils.js new file mode 100644 index 0000000..950e5a2 --- /dev/null +++ b/node_modules/express/node_modules/send/lib/utils.js @@ -0,0 +1,47 @@ + +/** + * Return an ETag in the form of `"-"` + * from the given `stat`. + * + * @param {Object} stat + * @return {String} + * @api private + */ + +exports.etag = function(stat) { + return '"' + stat.size + '-' + Number(stat.mtime) + '"'; +}; + +/** + * decodeURIComponent. + * + * Allows V8 to only deoptimize this fn instead of all + * of send(). + * + * @param {String} path + * @api private + */ + +exports.decode = function(path){ + try { + return decodeURIComponent(path); + } catch (err) { + return -1; + } +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; \ No newline at end of file diff --git a/node_modules/express/node_modules/send/node_modules/mime/LICENSE b/node_modules/express/node_modules/send/node_modules/mime/LICENSE new file mode 100644 index 0000000..451fc45 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/express/node_modules/send/node_modules/mime/README.md b/node_modules/express/node_modules/send/node_modules/mime/README.md new file mode 100644 index 0000000..6ca19bd --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/README.md @@ -0,0 +1,66 @@ +# mime + +Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community. + +## Install + +Install with [npm](http://github.com/isaacs/npm): + + npm install mime + +## API - Queries + +### mime.lookup(path) +Get the mime type associated with a file, if no mime type is found `application/octet-stream` is returned. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g. + + var mime = require('mime'); + + mime.lookup('/path/to/file.txt'); // => 'text/plain' + mime.lookup('file.txt'); // => 'text/plain' + mime.lookup('.TXT'); // => 'text/plain' + mime.lookup('htm'); // => 'text/html' + +### mime.default_type +Sets the mime type returned when `mime.lookup` fails to find the extension searched for. (Default is `application/octet-stream`.) + +### mime.extension(type) +Get the default extension for `type` + + mime.extension('text/html'); // => 'html' + mime.extension('application/octet-stream'); // => 'bin' + +### mime.charsets.lookup() + +Map mime-type to charset + + mime.charsets.lookup('text/plain'); // => 'UTF-8' + +(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.) + +## API - Defining Custom Types + +The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types). + +### mime.define() + +Add custom mime/extension mappings + + mime.define({ + 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'], + 'application/x-my-type': ['x-mt', 'x-mtt'], + // etc ... + }); + + mime.lookup('x-sft'); // => 'text/x-some-format' + +The first entry in the extensions array is returned by `mime.extension()`. E.g. + + mime.extension('text/x-some-format'); // => 'x-sf' + +### mime.load(filepath) + +Load mappings from an Apache ".types" format file + + mime.load('./my_project.types'); + +The .types file format is simple - See the `types` dir for examples. diff --git a/node_modules/express/node_modules/send/node_modules/mime/mime.js b/node_modules/express/node_modules/send/node_modules/mime/mime.js new file mode 100644 index 0000000..8a7eb09 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/mime.js @@ -0,0 +1,114 @@ +var path = require('path'); +var fs = require('fs'); + +function Mime() { + // Map of extension -> mime type + this.types = Object.create(null); + + // Map of mime type -> extension + this.extensions = Object.create(null); +} + +/** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * @param map (Object) type definitions + */ +Mime.prototype.define = function (map) { + for (var type in map) { + var exts = map[type]; + + for (var i = 0; i < exts.length; i++) { + if (process.env.DEBUG_MIME && this.types[exts]) { + console.warn(this._loading.replace(/.*\//, ''), 'changes "' + exts[i] + '" extension type from ' + + this.types[exts] + ' to ' + type); + } + + this.types[exts[i]] = type; + } + + // Default extension is the first one we encounter + if (!this.extensions[type]) { + this.extensions[type] = exts[0]; + } + } +}; + +/** + * Load an Apache2-style ".types" file + * + * This may be called multiple times (it's expected). Where files declare + * overlapping types/extensions, the last file wins. + * + * @param file (String) path of file to load. + */ +Mime.prototype.load = function(file) { + + this._loading = file; + // Read file and split into lines + var map = {}, + content = fs.readFileSync(file, 'ascii'), + lines = content.split(/[\r\n]+/); + + lines.forEach(function(line) { + // Clean up whitespace/comments, and split into fields + var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/); + map[fields.shift()] = fields; + }); + + this.define(map); + + this._loading = null; +}; + +/** + * Lookup a mime type based on extension + */ +Mime.prototype.lookup = function(path, fallback) { + var ext = path.replace(/.*[\.\/]/, '').toLowerCase(); + + return this.types[ext] || fallback || this.default_type; +}; + +/** + * Return file extension associated with a mime type + */ +Mime.prototype.extension = function(mimeType) { + var type = mimeType.match(/^\s*([^;\s]*)(?:;|\s|$)/)[1].toLowerCase(); + return this.extensions[type]; +}; + +// Default instance +var mime = new Mime(); + +// Load local copy of +// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +mime.load(path.join(__dirname, 'types/mime.types')); + +// Load additional types from node.js community +mime.load(path.join(__dirname, 'types/node.types')); + +// Default type +mime.default_type = mime.lookup('bin'); + +// +// Additional API specific to the default instance +// + +mime.Mime = Mime; + +/** + * Lookup a charset based on mime type. + */ +mime.charsets = { + lookup: function(mimeType, fallback) { + // Assume text types are utf8 + return (/^text\//).test(mimeType) ? 'UTF-8' : fallback; + } +}; + +module.exports = mime; diff --git a/node_modules/express/node_modules/send/node_modules/mime/package.json b/node_modules/express/node_modules/send/node_modules/mime/package.json new file mode 100644 index 0000000..63b94d3 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/package.json @@ -0,0 +1,39 @@ +{ + "author": { + "name": "Robert Kieffer", + "email": "robert@broofa.com", + "url": "http://github.com/broofa" + }, + "contributors": [ + { + "name": "Benjamin Thomas", + "email": "benjamin@benjaminthomas.org", + "url": "http://github.com/bentomas" + } + ], + "dependencies": {}, + "description": "A comprehensive library for mime-type mapping", + "devDependencies": {}, + "keywords": [ + "util", + "mime" + ], + "main": "mime.js", + "name": "mime", + "repository": { + "url": "https://github.com/broofa/node-mime", + "type": "git" + }, + "version": "1.2.10", + "readme": "# mime\n\nComprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.\n\n## Install\n\nInstall with [npm](http://github.com/isaacs/npm):\n\n npm install mime\n\n## API - Queries\n\n### mime.lookup(path)\nGet the mime type associated with a file, if no mime type is found `application/octet-stream` is returned. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g.\n\n var mime = require('mime');\n\n mime.lookup('/path/to/file.txt'); // => 'text/plain'\n mime.lookup('file.txt'); // => 'text/plain'\n mime.lookup('.TXT'); // => 'text/plain'\n mime.lookup('htm'); // => 'text/html'\n\n### mime.default_type\nSets the mime type returned when `mime.lookup` fails to find the extension searched for. (Default is `application/octet-stream`.)\n\n### mime.extension(type)\nGet the default extension for `type`\n\n mime.extension('text/html'); // => 'html'\n mime.extension('application/octet-stream'); // => 'bin'\n\n### mime.charsets.lookup()\n\nMap mime-type to charset\n\n mime.charsets.lookup('text/plain'); // => 'UTF-8'\n\n(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.)\n\n## API - Defining Custom Types\n\nThe following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types).\n\n### mime.define()\n\nAdd custom mime/extension mappings\n\n mime.define({\n 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],\n 'application/x-my-type': ['x-mt', 'x-mtt'],\n // etc ...\n });\n\n mime.lookup('x-sft'); // => 'text/x-some-format'\n\nThe first entry in the extensions array is returned by `mime.extension()`. E.g.\n\n mime.extension('text/x-some-format'); // => 'x-sf'\n\n### mime.load(filepath)\n\nLoad mappings from an Apache \".types\" format file\n\n mime.load('./my_project.types');\n\nThe .types file format is simple - See the `types` dir for examples.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/broofa/node-mime/issues" + }, + "_id": "mime@1.2.10", + "dist": { + "shasum": "53e34f228990f1f6975a3aeeb15dfb1e0404a581" + }, + "_from": "mime@~1.2.9", + "_resolved": "https://registry.npmjs.org/mime/-/mime-1.2.10.tgz" +} diff --git a/node_modules/express/node_modules/send/node_modules/mime/test.js b/node_modules/express/node_modules/send/node_modules/mime/test.js new file mode 100644 index 0000000..27df440 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/test.js @@ -0,0 +1,84 @@ +/** + * Usage: node test.js + */ + +var mime = require('./mime'); +var assert = require('assert'); +var path = require('path'); + +function eq(a, b) { + console.log('Test: ' + a + ' === ' + b); + assert.strictEqual.apply(null, arguments); +} + +console.log(Object.keys(mime.extensions).length + ' types'); +console.log(Object.keys(mime.types).length + ' extensions\n'); + +// +// Test mime lookups +// + +eq('text/plain', mime.lookup('text.txt')); +eq('text/plain', mime.lookup('.text.txt')); +eq('text/plain', mime.lookup('.txt')); +eq('text/plain', mime.lookup('txt')); +eq('application/octet-stream', mime.lookup('text.nope')); +eq('fallback', mime.lookup('text.fallback', 'fallback')); +eq('application/octet-stream', mime.lookup('constructor')); +eq('text/plain', mime.lookup('TEXT.TXT')); +eq('text/event-stream', mime.lookup('text/event-stream')); +eq('application/x-web-app-manifest+json', mime.lookup('text.webapp')); + +// +// Test extensions +// + +eq('txt', mime.extension(mime.types.text)); +eq('html', mime.extension(mime.types.htm)); +eq('bin', mime.extension('application/octet-stream')); +eq('bin', mime.extension('application/octet-stream ')); +eq('html', mime.extension(' text/html; charset=UTF-8')); +eq('html', mime.extension('text/html; charset=UTF-8 ')); +eq('html', mime.extension('text/html; charset=UTF-8')); +eq('html', mime.extension('text/html ; charset=UTF-8')); +eq('html', mime.extension('text/html;charset=UTF-8')); +eq('html', mime.extension('text/Html;charset=UTF-8')); +eq(undefined, mime.extension('constructor')); + +// +// Test node types +// + +eq('application/font-woff', mime.lookup('file.woff')); +eq('application/octet-stream', mime.lookup('file.buffer')); +eq('audio/mp4', mime.lookup('file.m4a')); +eq('font/opentype', mime.lookup('file.otf')); + +// +// Test charsets +// + +eq('UTF-8', mime.charsets.lookup('text/plain')); +eq(undefined, mime.charsets.lookup(mime.types.js)); +eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback')); + +// +// Test for overlaps between mime.types and node.types +// + +var apacheTypes = new mime.Mime(), nodeTypes = new mime.Mime(); +apacheTypes.load(path.join(__dirname, 'types/mime.types')); +nodeTypes.load(path.join(__dirname, 'types/node.types')); + +var keys = [].concat(Object.keys(apacheTypes.types)) + .concat(Object.keys(nodeTypes.types)); +keys.sort(); +for (var i = 1; i < keys.length; i++) { + if (keys[i] == keys[i-1]) { + console.warn('Warning: ' + + 'node.types defines ' + keys[i] + '->' + nodeTypes.types[keys[i]] + + ', mime.types defines ' + keys[i] + '->' + apacheTypes.types[keys[i]]); + } +} + +console.log('\nOK'); diff --git a/node_modules/express/node_modules/send/node_modules/mime/types/mime.types b/node_modules/express/node_modules/send/node_modules/mime/types/mime.types new file mode 100644 index 0000000..da8cd69 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/types/mime.types @@ -0,0 +1,1588 @@ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redisribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/calendar+xml +# application/cals-1840 +# application/ccmp+xml +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dns +application/docbook+xml dbk +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +application/gml+xml gml +application/gpx+xml gpx +application/gxf gxf +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +application/inkml+xml ink inkml +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +application/jsonml+json jsonml +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +# application/mathml-content+xml +# application/mathml-presentation+xml +application/mathml+xml mathml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink+xml metalink +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogx +application/omdoc+xml omdoc +application/onenote onetoc onetoc2 onetmp onepkg +application/oxps oxps +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rpki-ghostbusters gbr +application/rpki-manifest mft +application/rpki-roa roa +# application/rpki-updown +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssdl+xml ssdl +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vcard+xml +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.formscentral.fcdt fcdt +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.astraea-software.iota iota +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.collection+json +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +# application/vnd.curl +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.dart dart +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.dece.zip uvz uvvz +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.ds-keypoint kpxx +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +# application/vnd.eprints.data+xml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +# application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +# application/vnd.hal+json +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +# application/vnd.hzn-3d-crossword +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +# application/vnd.innopath.wamp.notification +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.newsmessage+xml +# application/vnd.iptc.g2.packageitem+xml +# application/vnd.iptc.g2.planningitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +# application/vnd.ms-color.iccprofile +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +# application/vnd.ms-opentype +# application/vnd.ms-package.obfuscated-opentype +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +# application/vnd.ms-printing.printticket+xml +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +application/vnd.mynfc taglet +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.nitf ntf nitf +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oftn.l10n+json +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-feature-handler+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.cab-user-prefs+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.pal+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.quobject-quoxdocument +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +application/vnd.osgi.subsystem esa +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.rn-realmedia-vbr rmvb +application/vnd.route66.link66+xml link66 +# application/vnd.rs-274x +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.package smzip +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +# application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tcpdump.pcap pcap cap dmp +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.through-ngn +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +# application/x-amf +application/x-apple-diskimage dmg +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-blorb blb blorb +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cbr cbr cba cbt cbz cb7 +application/x-cdlink vcd +application/x-cfs-compressed cfs +application/x-chat chat +application/x-chess-pgn pgn +application/x-conference nsc +# application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-dgc-compressed dgc +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-envoy evy +application/x-eva eva +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-ttf ttf ttc +application/x-font-type1 pfa pfb pfm afm +application/font-woff woff +# application/x-font-vfont +application/x-freearc arc +application/x-futuresplash spl +application/x-gca-compressed gca +application/x-glulx ulx +application/x-gnumeric gnumeric +application/x-gramps-xml gramps +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-install-instructions install +application/x-iso9660-image iso +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-lzh-compressed lzh lha +application/x-mie mie +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-shortcut lnk +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf wmz emf emz +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-nzb nzb +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-research-info-systems ris +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-sql sql +application/x-stuffit sit +application/x-stuffitx sitx +application/x-subrip srt +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-t3vm-image t3 +application/x-tads gam +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-tgif obj +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xliff+xml xlf +application/x-xpinstall xpi +application/x-xz xz +application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8 +# application/x400-bp +application/xaml+xml xaml +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info-diff+xml +# application/xcon-conference-info+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xproc+xml xpl +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dv +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/fwdred +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/ip-mr_v2.5 +# audio/isac +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +# audio/mpeg4-generic +# audio/musepack +audio/ogg oga ogg spx +# audio/opus +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu-wb +# audio/pcmu +# audio/prs.sid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +audio/s3m s3m +audio/silk sil +# audio/smv +# audio/smv0 +# audio/smv-qcp +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.dvb.file +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-caf caf +audio/x-flac flac +audio/x-matroska mka +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +# audio/x-tta +audio/x-wav wav +audio/xm xm +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/sgi sgi +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.dvb.subtitle sub +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.ms-photo wdp +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-3ds 3ds +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-mrsid-image sid +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-tga tga +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +model/x3d+binary x3db x3dbz +model/x3d+vrml x3dv x3dvz +model/x3d+xml x3d x3dz +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# text/1d-interleaved-parityfec +text/cache-manifest appcache +text/calendar ics ifb +text/css css +text/csv csv +# text/directory +# text/dns +# text/ecmascript +# text/enriched +# text/example +# text/fwdred +text/html html htm +# text/javascript +text/n3 n3 +# text/parityfec +text/plain txt text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/vnd.radisys.msml-basic-layout +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +text/vcard vcard +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.scurl scurl +text/vnd.curl.mcurl mcurl +# text/vnd.dmclientscript +text/vnd.dvb.subtitle sub +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-java-source java +text/x-opml opml +text/x-pascal p pas +text/x-nfo nfo +text/x-setext etx +text/x-sfv sfv +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.dvb.file dvb +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-matroska mkv mk3d mks +video/x-mng mng +video/x-ms-asf asf asx +video/x-ms-vob vob +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +video/x-smv smv +x-conference/x-cooltalk ice diff --git a/node_modules/express/node_modules/send/node_modules/mime/types/node.types b/node_modules/express/node_modules/send/node_modules/mime/types/node.types new file mode 100644 index 0000000..55b2cf7 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/types/node.types @@ -0,0 +1,77 @@ +# What: WebVTT +# Why: To allow formats intended for marking up external text track resources. +# http://dev.w3.org/html5/webvtt/ +# Added by: niftylettuce +text/vtt vtt + +# What: Google Chrome Extension +# Why: To allow apps to (work) be served with the right content type header. +# http://codereview.chromium.org/2830017 +# Added by: niftylettuce +application/x-chrome-extension crx + +# What: HTC support +# Why: To properly render .htc files such as CSS3PIE +# Added by: niftylettuce +text/x-component htc + +# What: HTML5 application cache manifes ('.manifest' extension) +# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps +# per https://developer.mozilla.org/en/offline_resources_in_firefox +# Added by: louisremi +text/cache-manifest manifest + +# What: node binary buffer format +# Why: semi-standard extension w/in the node community +# Added by: tootallnate +application/octet-stream buffer + +# What: The "protected" MP-4 formats used by iTunes. +# Why: Required for streaming music to browsers (?) +# Added by: broofa +application/mp4 m4p +audio/mp4 m4a + +# What: Video format, Part of RFC1890 +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +video/MP2T ts + +# What: EventSource mime type +# Why: mime type of Server-Sent Events stream +# http://www.w3.org/TR/eventsource/#text-event-stream +# Added by: francois2metz +text/event-stream event-stream + +# What: Mozilla App manifest mime type +# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests +# Added by: ednapiranha +application/x-web-app-manifest+json webapp + +# What: Lua file types +# Why: Googling around shows de-facto consensus on these +# Added by: creationix (Issue #45) +text/x-lua lua +application/x-lua-bytecode luac + +# What: Markdown files, as per http://daringfireball.net/projects/markdown/syntax +# Why: http://stackoverflow.com/questions/10701983/what-is-the-mime-type-for-markdown +# Added by: avoidwork +text/x-markdown markdown md mkd + +# What: ini files +# Why: because they're just text files +# Added by: Matthew Kastor +text/plain ini + +# What: DASH Adaptive Streaming manifest +# Why: https://developer.mozilla.org/en-US/docs/DASH_Adaptive_Streaming_for_HTML_5_Video +# Added by: eelcocramer +application/dash+xml mdp + +# What: OpenType font files - http://www.microsoft.com/typography/otspec/ +# Why: Browsers usually ignore the font MIME types and sniff the content, +# but Chrome, shows a warning if OpenType fonts aren't served with +# the `font/opentype` MIME type: http://i.imgur.com/8c5RN8M.png. +# Added by: alrra +font/opentype otf diff --git a/node_modules/express/node_modules/send/package.json b/node_modules/express/node_modules/send/package.json new file mode 100644 index 0000000..a53f5a6 --- /dev/null +++ b/node_modules/express/node_modules/send/package.json @@ -0,0 +1,45 @@ +{ + "name": "send", + "version": "0.1.3", + "description": "Better streaming static file server with Range and conditional-GET support", + "keywords": [ + "static", + "file", + "server" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": { + "debug": "*", + "mime": "~1.2.9", + "fresh": "0.1.0", + "range-parser": "0.0.4" + }, + "devDependencies": { + "mocha": "*", + "should": "*", + "supertest": "0.0.1", + "connect": "2.x" + }, + "scripts": { + "test": "make test" + }, + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/send.git" + }, + "main": "index", + "readme": "# send\n\n Send is Connect's `static()` extracted for generalized use, a streaming static file\n server supporting partial responses (Ranges), conditional-GET negotiation, high test coverage, and granular events which may be leveraged to take appropriate actions in your application or framework.\n\n## Installation\n\n $ npm install send\n\n## Examples\n\n Small:\n\n```js\nvar http = require('http');\nvar send = require('send');\n\nvar app = http.createServer(function(req, res){\n send(req, req.url).pipe(res);\n}).listen(3000);\n```\n\n Serving from a root directory with custom error-handling:\n\n```js\nvar http = require('http');\nvar send = require('send');\nvar url = require('url');\n\nvar app = http.createServer(function(req, res){\n // your custom error-handling logic:\n function error(err) {\n res.statusCode = err.status || 500;\n res.end(err.message);\n }\n\n // your custom directory handling logic:\n function redirect() {\n res.statusCode = 301;\n res.setHeader('Location', req.url + '/');\n res.end('Redirecting to ' + req.url + '/');\n }\n\n // transfer arbitrary files from within\n // /www/example.com/public/*\n send(req, url.parse(req.url).pathname)\n .root('/www/example.com/public')\n .on('error', error)\n .on('directory', redirect)\n .pipe(res);\n}).listen(3000);\n```\n\n## API\n\n### Events\n\n - `error` an error occurred `(err)`\n - `directory` a directory was requested\n - `file` a file was requested `(path, stat)`\n - `stream` file streaming has started `(stream)`\n - `end` streaming has completed\n\n### .root(dir)\n\n Serve files relative to `path`. Aliased as `.from(dir)`.\n\n### .index(path)\n\n By default send supports \"index.html\" files, to disable this\n invoke `.index(false)` or to supply a new index pass a string.\n\n### .maxage(ms)\n\n Provide a max-age in milliseconds for http caching, defaults to 0.\n\n### .hidden(bool)\n\n Enable or disable transfer of hidden files, defaults to false.\n\n## Error-handling\n\n By default when no `error` listeners are present an automatic response will be made, otherwise you have full control over the response, aka you may show a 5xx page etc.\n\n## Caching\n\n It does _not_ perform internal caching, you should use a reverse proxy cache such\n as Varnish for this, or those fancy things called CDNs. If your application is small enough that it would benefit from single-node memory caching, it's small enough that it does not need caching at all ;).\n\n## Debugging\n\n To enable `debug()` instrumentation output export __DEBUG__:\n\n```\n$ DEBUG=send node app\n```\n\n## Running tests\n\n```\n$ npm install\n$ make test\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 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", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/visionmedia/send/issues" + }, + "_id": "send@0.1.3", + "dist": { + "shasum": "d9803d3472c0708ff9874dd3e2bebc5476f61fcf" + }, + "_from": "send@0.1.3", + "_resolved": "https://registry.npmjs.org/send/-/send-0.1.3.tgz" +} diff --git a/node_modules/express/package.json b/node_modules/express/package.json new file mode 100644 index 0000000..ebce440 --- /dev/null +++ b/node_modules/express/package.json @@ -0,0 +1,88 @@ +{ + "name": "express", + "description": "Sinatra inspired web development framework", + "version": "3.3.4", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "contributors": [ + { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + { + "name": "Aaron Heckmann", + "email": "aaron.heckmann+github@gmail.com" + }, + { + "name": "Ciaran Jessup", + "email": "ciaranj@gmail.com" + }, + { + "name": "Guillermo Rauch", + "email": "rauchg@gmail.com" + } + ], + "dependencies": { + "connect": "2.8.4", + "commander": "1.2.0", + "range-parser": "0.0.4", + "mkdirp": "0.3.5", + "cookie": "0.1.0", + "buffer-crc32": "0.2.1", + "fresh": "0.1.0", + "methods": "0.0.1", + "send": "0.1.3", + "cookie-signature": "1.0.1", + "debug": "*" + }, + "devDependencies": { + "ejs": "*", + "mocha": "*", + "jade": "0.30.0", + "hjs": "*", + "stylus": "*", + "should": "*", + "connect-redis": "*", + "marked": "*", + "supertest": "0.6.0" + }, + "keywords": [ + "express", + "framework", + "sinatra", + "web", + "rest", + "restful", + "router", + "app", + "api" + ], + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/express" + }, + "main": "index", + "bin": { + "express": "./bin/express" + }, + "scripts": { + "prepublish": "npm prune", + "test": "make test" + }, + "engines": { + "node": "*" + }, + "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", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/visionmedia/express/issues" + }, + "_id": "express@3.3.4", + "dist": { + "shasum": "e07a8793345fbbc59d0c54be11bee60bd98c9ad2" + }, + "_from": "express@", + "_resolved": "https://registry.npmjs.org/express/-/express-3.3.4.tgz" +} diff --git a/node_modules/express/test.js b/node_modules/express/test.js new file mode 100644 index 0000000..e7dca26 --- /dev/null +++ b/node_modules/express/test.js @@ -0,0 +1,17 @@ +var http = require('http'); +var express = require('express'); + +var app = express(); +var sub = express(); + +app.use('/', function (req, res, next) { + next(new Error('something broke')); +}); + +sub.use(function (err, req, res, next) { + res.send('error handled'); +}); + +app.use(sub); + +http.createServer(app).listen(4000); diff --git a/node_modules/ws/.npmignore b/node_modules/ws/.npmignore new file mode 100644 index 0000000..8233793 --- /dev/null +++ b/node_modules/ws/.npmignore @@ -0,0 +1,6 @@ +npm-debug.log +node_modules +.*.swp +.lock-* +build + diff --git a/node_modules/ws/.travis.yml b/node_modules/ws/.travis.yml new file mode 100644 index 0000000..08e4dad --- /dev/null +++ b/node_modules/ws/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +npm_args: --ws:native +node_js: + - "0.6" + - "0.8" + - "0.10" diff --git a/node_modules/ws/History.md b/node_modules/ws/History.md new file mode 100644 index 0000000..97c6ec2 --- /dev/null +++ b/node_modules/ws/History.md @@ -0,0 +1,260 @@ +v0.4.25 - December 17th, 2012 +===================== +* Removed install.js. [shtylman] +* Added browser field to package.json. [shtylman] +* Support overwriting host header. [Raynos] +* Emit 'listening' also with custom http server. [sebiq] + +v0.4.24 - December 6th, 2012 +===================== +* Yet another intermediate release, to not delay minor features any longer. +* Native support installation issues further circumvented. [einaros] + +v0.4.23 - November 19th, 2012 +===================== +* Service release - last before major upgrade. +* Changes default host from 127.0.0.1 to 0.0.0.0. [einaros] + +v0.4.22 - October 3rd, 2012 +===================== +* clear failsafe cleanup timeout once cleanup is called [AndreasMadsen] +* added w3c compatible CloseEvent for onclose / addEventListener("close", ...). [einaros] +* fix the sub protocol header handler [sonnyp] +* fix unhandled exception if socket closes and 'error' is emitted [jmatthewsr-ms] + +v0.4.21 - July 14th, 2012 +===================== +* Emit error if server reponds with anything other than status code 101. [einaros] +* Added 'headers' event to server. [rauchg] +* path.exists moved to fs.exists. [blakmatrix] + +v0.4.20 - June 26th, 2012 +===================== +* node v0.8.0 compatibility release. + +v0.4.19 - June 19th, 2012 +===================== +* Change sender to merge buffers for relatively small payloads, may improve perf in some cases [einaros] +* Avoid EventEmitter for Receiver classes. As above this may improve perf. [einaros] +* Renamed fallback files from the somewhat misleading '*Windows'. [einaros] + +v0.4.18 - June 14th 2012 +===================== +* Fixed incorrect md5 digest encoding in Hixie handshake [nicokaiser] +* Added example of use with Express 3 [einaros] +* Change installation procedure to not require --ws:native to build native extensions. They will now build if a compiler is available. [einaros] + +v0.4.17 - June 13th 2012 +===================== +* Improve error handling during connection handshaking [einaros] +* Ensure that errors are caught also after connection teardown [nicokaiser] +* Update 'mocha' version to 1.1.0. [einaros] +* Stop showing 'undefined' for some error logs. [tricknotes] +* Update 'should' version to 0.6.3 [tricknotes] + +v0.4.16 - June 1st 2012 +===================== +* Build fix for Windows. [einaros] + +v0.4.15 - May 20th 2012 +===================== +* Enable fauxe streaming for hixie tansport. [einaros] +* Allow hixie sender to deal with buffers. [einaros/pigne] +* Allow error code 1011. [einaros] +* Fix framing for empty packets (empty pings and pongs might break). [einaros] +* Improve error and close handling, to avoid connections lingering in CLOSING state. [einaros] + +v0.4.14 - Apr 30th 2012 +===================== +* use node-gyp instead of node-waf [TooTallNate] +* remove old windows compatibility makefile, and silently fall back to native modules [einaros] +* ensure connection status [nicokaiser] +* websocket client updated to use port 443 by default for wss:// connections [einaros] +* support unix sockets [kschzt] + +v0.4.13 - Apr 12th 2012 +===================== + +* circumvent node 0.6+ related memory leak caused by Object.defineProperty [nicokaiser] +* improved error handling, improving stability in massive load use cases [nicokaiser] + +v0.4.12 - Mar 30th 2012 +===================== + +* various memory leak / possible memory leak cleanups [einaros] +* api documentation [nicokaiser] +* add option to disable client tracking [nicokaiser] + +v0.4.11 - Mar 24th 2012 +===================== + +* node v0.7 compatibillity release +* gyp support [TooTallNate] +* commander dependency update [jwueller] +* loadbalancer support [nicokaiser] + +v0.4.10 - Mar 22th 2012 +===================== + +* Final hixie close frame fixes. [nicokaiser] + +v0.4.9 - Mar 21st 2012 +===================== + +* Various hixie bugfixes (such as proper close frame handling). [einaros] + +v0.4.8 - Feb 29th 2012 +===================== + +* Allow verifyClient to run asynchronously [karlsequin] +* Various bugfixes and cleanups. [einaros] + +v0.4.7 - Feb 21st 2012 +===================== + +* Exposed bytesReceived from websocket client object, which makes it possible to implement bandwidth sampling. [einaros] +* Updated browser based file upload example to include and output per websocket channel bandwidth sampling. [einaros] +* Changed build scripts to check which architecture is currently in use. Required after the node.js changes to have prebuilt packages target ia32 by default. [einaros] + +v0.4.6 - Feb 9th 2012 +===================== + +* Added browser based file upload example. [einaros] +* Added server-to-browser status push example. [einaros] +* Exposed pause() and resume() on WebSocket object, to enable client stream shaping. [einaros] + +v0.4.5 - Feb 7th 2012 +===================== + +* Corrected regression bug in handling of connections with the initial frame delivered across both http upgrade head and a standalone packet. This would lead to a race condition, which in some cases could cause message corruption. [einaros] + +v0.4.4 - Feb 6th 2012 +===================== + +* Pass original request object to verifyClient, for cookie or authentication verifications. [einaros] +* Implemented addEventListener and slightly improved the emulation API by adding a MessageEvent with a readonly data attribute. [aslakhellesoy] +* Rewrite parts of hybi receiver to avoid stack overflows for large amounts of packets bundled in the same buffer / packet. [einaros] + +v0.4.3 - Feb 4th 2012 +===================== + +* Prioritized update: Corrected issue which would cause sockets to stay open longer than necessary, and resource leakage because of this. [einaros] + +v0.4.2 - Feb 4th 2012 +===================== + +* Breaking change: WebSocketServer's verifyOrigin option has been renamed to verifyClient. [einaros] +* verifyClient now receives { origin: 'origin header', secure: true/false }, where 'secure' will be true for ssl connections. [einaros] +* Split benchmark, in preparation for more thorough case. [einaros] +* Introduced hixie-76 draft support for server, since Safari (iPhone / iPad / OS X) and Opera still aren't updated to use Hybi. [einaros] +* Expose 'supports' object from WebSocket, to indicate e.g. the underlying transport's support for binary data. [einaros] +* Test and code cleanups. [einaros] + +v0.4.1 - Jan 25th 2012 +===================== + +* Use readline in wscat [tricknotes] +* Refactor _state away, in favor of the new _readyState [tricknotes] +* travis-ci integration [einaros] +* Fixed race condition in testsuite, causing a few tests to fail (without actually indicating errors) on travis [einaros] +* Expose pong event [paddybyers] +* Enabled running of WebSocketServer in noServer-mode, meaning that upgrades are passed in manually. [einaros] +* Reworked connection procedure for WebSocketServer, and cleaned up tests. [einaros] + +v0.4.0 - Jan 2nd 2012 +===================== + +* Windows compatibility [einaros] +* Windows compatible test script [einaros] + +v0.3.9 - Jan 1st 2012 +====================== + +* Improved protocol framing performance [einaros] +* WSS support [kazuyukitanimura] +* WSS tests [einaros] +* readyState exposed [justinlatimer, tricknotes] +* url property exposed [justinlatimer] +* Removed old 'state' property [einaros] +* Test cleanups [einaros] + +v0.3.8 - Dec 27th 2011 +====================== + +* Made it possible to listen on specific paths, which is especially good to have for precreated http servers [einaros] +* Extensive WebSocket / WebSocketServer cleanup, including changing all internal properties to unconfigurable, unenumerable properties [einaros] +* Receiver modifications to ensure even better performance with fragmented sends [einaros] +* Fixed issue in sender.js, which would cause SlowBuffer instances (such as returned from the crypto library's randomBytes) to be copied (and thus be dead slow) [einaros] +* Removed redundant buffer copy in sender.js, which should improve server performance [einaros] + +v0.3.7 - Dec 25nd 2011 +====================== + +* Added a browser based API which uses EventEmitters internally [3rd-Eden] +* Expose request information from upgrade event for websocket server clients [mmalecki] + +v0.3.6 - Dec 19th 2011 +====================== + +* Added option to let WebSocket.Server use an already existing http server [mmalecki] +* Migrating various option structures to use options.js module [einaros] +* Added a few more tests, options and handshake verifications to ensure that faulty connections are dealt with [einaros] +* Code cleanups in Sender and Receiver, to ensure even faster parsing [einaros] + +v0.3.5 - Dec 13th 2011 +====================== + +* Optimized Sender.js, Receiver.js and bufferutil.cc: + * Apply loop-unrolling-like small block copies rather than use node.js Buffer#copy() (which is slow). + * Mask blocks of data using combination of 32bit xor and loop-unrolling, instead of single bytes. + * Keep pre-made send buffer for small transfers. +* Leak fixes and code cleanups. + +v0.3.3 - Dec 12th 2011 +====================== + +* Compile fix for Linux. +* Rewrote parts of WebSocket.js, to avoid try/catch and thus avoid optimizer bailouts. + +v0.3.2 - Dec 11th 2011 +====================== + +* Further performance updates, including the additions of a native BufferUtil module, which deals with several of the cpu intensive WebSocket operations. + +v0.3.1 - Dec 8th 2011 +====================== + +* Service release, fixing broken tests. + +v0.3.0 - Dec 8th 2011 +====================== + +* Node.js v0.4.x compatibility. +* Code cleanups and efficiency improvements. +* WebSocket server added, although this will still mainly be a client library. +* WebSocket server certified to pass the Autobahn test suite. +* Protocol improvements and corrections - such as handling (redundant) masks for empty fragments. +* 'wscat' command line utility added, which can act as either client or server. + +v0.2.6 - Dec 3rd 2011 +====================== + +* Renamed to 'ws'. Big woop, right -- but easy-websocket really just doesn't cut it anymore! + +v0.2.5 - Dec 3rd 2011 +====================== + + * Rewrote much of the WebSocket parser, to ensure high speed for highly fragmented messages. + * Added a BufferPool, as a start to more efficiently deal with allocations for WebSocket connections. More work to come, in that area. + * Updated the Autobahn report, at http://einaros.github.com/easy-websocket, with comparisons against WebSocket-Node 1.0.2 and Chrome 16. + +v0.2.0 - Nov 25th 2011 +====================== + + * Major rework to make sure all the Autobahn test cases pass. Also updated the internal tests to cover more corner cases. + +v0.1.2 - Nov 14th 2011 +====================== + + * Back and forth, back and forth: now settled on keeping the api (event names, methods) closer to the websocket browser api. This will stick now. + * Started keeping this history record. Better late than never, right? diff --git a/node_modules/ws/Makefile b/node_modules/ws/Makefile new file mode 100644 index 0000000..a0b82a1 --- /dev/null +++ b/node_modules/ws/Makefile @@ -0,0 +1,38 @@ +ALL_TESTS = $(shell find test/ -name '*.test.js') +ALL_INTEGRATION = $(shell find test/ -name '*.integration.js') + +all: + node-gyp configure build + +clean: + node-gyp clean + +run-tests: + @./node_modules/.bin/mocha \ + -t 2000 \ + $(TESTFLAGS) \ + $(TESTS) + +run-integrationtests: + @./node_modules/.bin/mocha \ + -t 5000 \ + $(TESTFLAGS) \ + $(TESTS) + +test: + @$(MAKE) NODE_TLS_REJECT_UNAUTHORIZED=0 NODE_PATH=lib TESTS="$(ALL_TESTS)" run-tests + +integrationtest: + @$(MAKE) NODE_TLS_REJECT_UNAUTHORIZED=0 NODE_PATH=lib TESTS="$(ALL_INTEGRATION)" run-integrationtests + +benchmark: + @node bench/sender.benchmark.js + @node bench/parser.benchmark.js + +autobahn: + @NODE_PATH=lib node test/autobahn.js + +autobahn-server: + @NODE_PATH=lib node test/autobahn-server.js + +.PHONY: test diff --git a/node_modules/ws/README.md b/node_modules/ws/README.md new file mode 100644 index 0000000..7eb1a47 --- /dev/null +++ b/node_modules/ws/README.md @@ -0,0 +1,159 @@ +[![Build Status](https://secure.travis-ci.org/einaros/ws.png)](http://travis-ci.org/einaros/ws) + +# ws: a node.js websocket library # + +`ws` is a simple to use websocket implementation, up-to-date against RFC-6455, and [probably the fastest WebSocket library for node.js](http://hobbycoding.posterous.com/the-fastest-websocket-module-for-nodejs). + +Passes the quite extensive Autobahn test suite. See http://einaros.github.com/ws for the full reports. + +Comes with a command line utility, `wscat`, which can either act as a server (--listen), or client (--connect); Use it to debug simple websocket services. + +## Protocol support ## + +* **Hixie draft 76** (Old and deprecated, but still in use by Safari and Opera. Added to ws version 0.4.2, but server only. Can be disabled by setting the `disableHixie` option to true.) +* **HyBi drafts 07-12** (Use the option `protocolVersion: 8`, or argument `-p 8` for wscat) +* **HyBi drafts 13-17** (Current default, alternatively option `protocolVersion: 13`, or argument `-p 13` for wscat) + +_See the echo.websocket.org example below for how to use the `protocolVersion` option._ + +## Usage ## + +### Installing ### + +`npm install ws` + +### Sending and receiving text data ### + +```js +var WebSocket = require('ws'); +var ws = new WebSocket('ws://www.host.com/path'); +ws.on('open', function() { + ws.send('something'); +}); +ws.on('message', function(data, flags) { + // flags.binary will be set if a binary data is received + // flags.masked will be set if the data was masked +}); +``` + +### Sending binary data ### + +```js +var WebSocket = require('ws'); +var ws = new WebSocket('ws://www.host.com/path'); +ws.on('open', function() { + var array = new Float32Array(5); + for (var i = 0; i < array.length; ++i) array[i] = i / 2; + ws.send(array, {binary: true, mask: true}); +}); +``` + +Setting `mask`, as done for the send options above, will cause the data to be masked according to the websocket protocol. The same option applies for text data. + +### Server example ### + +```js +var WebSocketServer = require('ws').Server + , wss = new WebSocketServer({port: 8080}); +wss.on('connection', function(ws) { + ws.on('message', function(message) { + console.log('received: %s', message); + }); + ws.send('something'); +}); +``` + +### Error handling best practices ### + +```js +// If the WebSocket is closed before the following send is attempted +ws.send('something'); + +// Errors (both immediate and async write errors) can be detected in an optional callback. +// The callback is also the only way of being notified that data has actually been sent. +ws.send('something', function(error) { + // if error is null, the send has been completed, + // otherwise the error object will indicate what failed. +}); + +// Immediate errors can also be handled with try/catch-blocks, but **note** +// that since sends are inherently asynchronous, socket write failures will *not* +// be captured when this technique is used. +try { + ws.send('something'); +} +catch (e) { + // handle error +} +``` + +### echo.websocket.org demo ### + +```js +var WebSocket = require('ws'); +var ws = new WebSocket('ws://echo.websocket.org/', {protocolVersion: 8, origin: 'http://websocket.org'}); +ws.on('open', function() { + console.log('connected'); + ws.send(Date.now().toString(), {mask: true}); +}); +ws.on('close', function() { + console.log('disconnected'); +}); +ws.on('message', function(data, flags) { + console.log('Roundtrip time: ' + (Date.now() - parseInt(data)) + 'ms', flags); + setTimeout(function() { + ws.send(Date.now().toString(), {mask: true}); + }, 500); +}); +``` + +### wscat against echo.websocket.org ### + + $ npm install -g ws + $ wscat -c ws://echo.websocket.org -p 8 + connected (press CTRL+C to quit) + > hi there + < hi there + > are you a happy parrot? + < are you a happy parrot? + +### Other examples ### + +For a full example with a browser client communicating with a ws server, see the examples folder. + +Note that the usage together with Express 3.0 is quite different from Express 2.x. The difference is expressed in the two different serverstats-examples. + +Otherwise, see the test cases. + +### Running the tests ### + +`make test` + +## API Docs ## + +See the doc/ directory for Node.js-like docs for the ws classes. + +## License ## + +(The MIT License) + +Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/ws/bench/parser.benchmark.js b/node_modules/ws/bench/parser.benchmark.js new file mode 100644 index 0000000..ff5f737 --- /dev/null +++ b/node_modules/ws/bench/parser.benchmark.js @@ -0,0 +1,115 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +/** + * Benchmark dependencies. + */ + +var benchmark = require('benchmark') + , Receiver = require('../').Receiver + , suite = new benchmark.Suite('Receiver'); +require('tinycolor'); +require('./util'); + +/** + * Setup receiver. + */ + +suite.on('start', function () { + receiver = new Receiver(); +}); + +suite.on('cycle', function () { + receiver = new Receiver(); +}); + +/** + * Benchmarks. + */ + +var pingMessage = 'Hello' + , pingPacket1 = getBufferFromHexString('89 ' + (pack(2, 0x80 | pingMessage.length)) + + ' 34 83 a8 68 '+ getHexStringFromBuffer(mask(pingMessage, '34 83 a8 68'))); +suite.add('ping message', function () { + receiver.add(pingPacket1); +}); + +var pingPacket2 = getBufferFromHexString('89 00') +suite.add('ping with no data', function () { + receiver.add(pingPacket2); +}); + +var closePacket = getBufferFromHexString('88 00'); +suite.add('close message', function () { + receiver.add(closePacket); + receiver.endPacket(); +}); + +var maskedTextPacket = getBufferFromHexString('81 93 34 83 a8 68 01 b9 92 52 4f a1 c6 09 59 e6 8a 52 16 e6 cb 00 5b a1 d5'); +suite.add('masked text message', function () { + receiver.add(maskedTextPacket); +}); + +binaryDataPacket = (function() { + var length = 125 + , message = new Buffer(length) + for (var i = 0; i < length; ++i) message[i] = i % 10; + return getBufferFromHexString('82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + + getHexStringFromBuffer(mask(message), '34 83 a8 68')); +})(); +suite.add('binary data (125 bytes)', function () { + try { + receiver.add(binaryDataPacket); + + } + catch(e) {console.log(e)} +}); + +binaryDataPacket2 = (function() { + var length = 65535 + , message = new Buffer(length) + for (var i = 0; i < length; ++i) message[i] = i % 10; + return getBufferFromHexString('82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + + getHexStringFromBuffer(mask(message), '34 83 a8 68')); +})(); +suite.add('binary data (65535 bytes)', function () { + receiver.add(binaryDataPacket2); +}); + +binaryDataPacket3 = (function() { + var length = 200*1024 + , message = new Buffer(length) + for (var i = 0; i < length; ++i) message[i] = i % 10; + return getBufferFromHexString('82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + + getHexStringFromBuffer(mask(message), '34 83 a8 68')); +})(); +suite.add('binary data (200 kB)', function () { + receiver.add(binaryDataPacket3); +}); + +/** + * Output progress. + */ + +suite.on('cycle', function (bench, details) { + console.log('\n ' + suite.name.grey, details.name.white.bold); + console.log(' ' + [ + details.hz.toFixed(2).cyan + ' ops/sec'.grey + , details.count.toString().white + ' times executed'.grey + , 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey + , + ].join(', '.grey)); +}); + +/** + * Run/export benchmarks. + */ + +if (!module.parent) { + suite.run(); +} else { + module.exports = suite; +} diff --git a/node_modules/ws/bench/sender.benchmark.js b/node_modules/ws/bench/sender.benchmark.js new file mode 100644 index 0000000..20c171a --- /dev/null +++ b/node_modules/ws/bench/sender.benchmark.js @@ -0,0 +1,66 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +/** + * Benchmark dependencies. + */ + +var benchmark = require('benchmark') + , Sender = require('../').Sender + , suite = new benchmark.Suite('Sender'); +require('tinycolor'); +require('./util'); + +/** + * Setup sender. + */ + +suite.on('start', function () { + sender = new Sender(); + sender._socket = { write: function() {} }; +}); + +suite.on('cycle', function () { + sender = new Sender(); + sender._socket = { write: function() {} }; +}); + +/** + * Benchmarks + */ + +framePacket = new Buffer(200*1024); +framePacket.fill(99); +suite.add('frameAndSend, unmasked (200 kB)', function () { + sender.frameAndSend(0x2, framePacket, true, false); +}); +suite.add('frameAndSend, masked (200 kB)', function () { + sender.frameAndSend(0x2, framePacket, true, true); +}); + +/** + * Output progress. + */ + +suite.on('cycle', function (bench, details) { + console.log('\n ' + suite.name.grey, details.name.white.bold); + console.log(' ' + [ + details.hz.toFixed(2).cyan + ' ops/sec'.grey + , details.count.toString().white + ' times executed'.grey + , 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey + , + ].join(', '.grey)); +}); + +/** + * Run/export benchmarks. + */ + +if (!module.parent) { + suite.run(); +} else { + module.exports = suite; +} diff --git a/node_modules/ws/bench/speed.js b/node_modules/ws/bench/speed.js new file mode 100644 index 0000000..3ce6414 --- /dev/null +++ b/node_modules/ws/bench/speed.js @@ -0,0 +1,105 @@ +var cluster = require('cluster') + , WebSocket = require('../') + , WebSocketServer = WebSocket.Server + , crypto = require('crypto') + , util = require('util') + , ansi = require('ansi'); +require('tinycolor'); + +function roundPrec(num, prec) { + var mul = Math.pow(10, prec); + return Math.round(num * mul) / mul; +} + +function humanSize(bytes) { + if (bytes >= 1048576) return roundPrec(bytes / 1048576, 2) + ' MB'; + if (bytes >= 1024) return roundPrec(bytes / 1024, 2) + ' kB'; + return roundPrec(bytes, 2) + ' B'; +} + +function generateRandomData(size) { + var buffer = new Buffer(size); + for (var i = 0; i < size; ++i) { + buffer[i] = ~~(Math.random() * 127); + } + return buffer; +} + +if (cluster.isMaster) { + var wss = new WebSocketServer({port: 8181}, function() { + cluster.fork(); + }); + wss.on('connection', function(ws) { + ws.on('message', function(data, flags) { + ws.send(data, {binary: flags&&flags.binary}); + }); + ws.on('close', function() {}); + }); + cluster.on('death', function(worker) { + wss.close(); + }); +} +else { + var cursor = ansi(process.stdout); + + var configs = [ + [true, 10000, 64], + [true, 5000, 16*1024], + [true, 1000, 128*1024], + [true, 100, 1024*1024], + [true, 1, 500*1024*1024], + [false, 10000, 64], + [false, 5000, 16*1024], + [false, 1000, 128*1024], + [false, 100, 1024*1024], + ]; + + var largest = configs[0][1]; + for (var i = 0, l = configs.length; i < l; ++i) { + if (configs[i][2] > largest) largest = configs[i][2]; + } + + console.log('Generating %s of test data ...', humanSize(largest)); + var randomBytes = generateRandomData(largest); + + function roundtrip(useBinary, roundtrips, size, cb) { + var data = randomBytes.slice(0, size); + var prefix = util.format('Running %d roundtrips of %s %s data', roundtrips, humanSize(size), useBinary ? 'binary' : 'text'); + console.log(prefix); + var client = new WebSocket('ws://localhost:' + '8181'); + var dt; + var roundtrip = 0; + function send() { + client.send(data, {binary: useBinary}); + } + client.on('error', function(e) { + console.error(e); + process.exit(); + }); + client.on('open', function() { + dt = Date.now(); + send(); + }); + client.on('message', function(data, flags) { + if (++roundtrip == roundtrips) { + var elapsed = Date.now() - dt; + cursor.up(); + console.log('%s:\t%ss\t%s' + , useBinary ? prefix.green : prefix.cyan + , roundPrec(elapsed / 1000, 1).toString().green.bold + , (humanSize((size * roundtrips) / elapsed * 1000) + '/s').blue.bold); + client.close(); + cb(); + return; + } + process.nextTick(send); + }); + } + + (function run() { + if (configs.length == 0) process.exit(); + var config = configs.shift(); + config.push(run); + roundtrip.apply(null, config); + })(); +} \ No newline at end of file diff --git a/node_modules/ws/bench/util.js b/node_modules/ws/bench/util.js new file mode 100644 index 0000000..5f01281 --- /dev/null +++ b/node_modules/ws/bench/util.js @@ -0,0 +1,105 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +/** + * Returns a Buffer from a "ff 00 ff"-type hex string. + */ + +getBufferFromHexString = function(byteStr) { + var bytes = byteStr.split(' '); + var buf = new Buffer(bytes.length); + for (var i = 0; i < bytes.length; ++i) { + buf[i] = parseInt(bytes[i], 16); + } + return buf; +} + +/** + * Returns a hex string from a Buffer. + */ + +getHexStringFromBuffer = function(data) { + var s = ''; + for (var i = 0; i < data.length; ++i) { + s += padl(data[i].toString(16), 2, '0') + ' '; + } + return s.trim(); +} + +/** + * Splits a buffer in two parts. + */ + +splitBuffer = function(buffer) { + var b1 = new Buffer(Math.ceil(buffer.length / 2)); + buffer.copy(b1, 0, 0, b1.length); + var b2 = new Buffer(Math.floor(buffer.length / 2)); + buffer.copy(b2, 0, b1.length, b1.length + b2.length); + return [b1, b2]; +} + +/** + * Performs hybi07+ type masking on a hex string or buffer. + */ + +mask = function(buf, maskString) { + if (typeof buf == 'string') buf = new Buffer(buf); + var mask = getBufferFromHexString(maskString || '34 83 a8 68'); + for (var i = 0; i < buf.length; ++i) { + buf[i] ^= mask[i % 4]; + } + return buf; +} + +/** + * Returns a hex string representing the length of a message + */ + +getHybiLengthAsHexString = function(len, masked) { + if (len < 126) { + var buf = new Buffer(1); + buf[0] = (masked ? 0x80 : 0) | len; + } + else if (len < 65536) { + var buf = new Buffer(3); + buf[0] = (masked ? 0x80 : 0) | 126; + getBufferFromHexString(pack(4, len)).copy(buf, 1); + } + else { + var buf = new Buffer(9); + buf[0] = (masked ? 0x80 : 0) | 127; + getBufferFromHexString(pack(16, len)).copy(buf, 1); + } + return getHexStringFromBuffer(buf); +} + +/** + * Unpacks a Buffer into a number. + */ + +unpack = function(buffer) { + var n = 0; + for (var i = 0; i < buffer.length; ++i) { + n = (i == 0) ? buffer[i] : (n * 256) + buffer[i]; + } + return n; +} + +/** + * Returns a hex string, representing a specific byte count 'length', from a number. + */ + +pack = function(length, number) { + return padl(number.toString(16), length, '0').replace(/([0-9a-f][0-9a-f])/gi, '$1 ').trim(); +} + +/** + * Left pads the string 's' to a total length of 'n' with char 'c'. + */ + +padl = function(s, n, c) { + return new Array(1 + n - s.length).join(c) + s; +} diff --git a/node_modules/ws/bin/wscat b/node_modules/ws/bin/wscat new file mode 100644 index 0000000..0ec894d --- /dev/null +++ b/node_modules/ws/bin/wscat @@ -0,0 +1,190 @@ +#!/usr/bin/env node + +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var WebSocket = require('../') + , fs = require('fs') + , program = require('commander') + , util = require('util') + , events = require('events') + , readline = require('readline'); + +/** + * InputReader - processes console input + */ + +function Console() { + this.stdin = process.stdin; + this.stdout = process.stdout; + + this.readlineInterface = readline.createInterface(this.stdin, this.stdout); + + var self = this; + this.readlineInterface.on('line', function(data) { + self.emit('line', data); + }); + this.readlineInterface.on('close', function() { + self.emit('close'); + }); + + this._resetInput = function() { + self.clear(); + } +} +util.inherits(Console, events.EventEmitter); + +Console.Colors = { + Red: '\033[31m', + Green: '\033[32m', + Yellow: '\033[33m', + Blue: '\033[34m', + Default: '\033[39m' +}; + +Console.prototype.prompt = function() { + this.readlineInterface.prompt(); +} + +Console.prototype.print = function(msg, color) { + this.clear(); + color = color || Console.Colors.Default; + this.stdout.write(color + msg + Console.Colors.Default + '\n'); + this.prompt(); +} + +Console.prototype.clear = function() { + this.stdout.write('\033[2K\033[E'); +} + +Console.prototype.pause = function() { + this.stdin.on('keypress', this._resetInput); +} + +Console.prototype.resume = function() { + this.stdin.removeListener('keypress', this._resetInput); +} + +/** + * The actual application + */ + +var version = JSON.parse(fs.readFileSync(__dirname + '/../package.json', 'utf8')).version; +program + .version(version) + .usage('[options] ') + .option('-l, --listen ', 'listen on port') + .option('-c, --connect ', 'connect to a websocket server') + .option('-p, --protocol ', 'optional protocol version') + .option('-o, --origin ', 'optional origin') + .option('--host ', 'optional host') + .option('-s, --subprotocol ', 'optional subprotocol') + .parse(process.argv); + +if (program.listen && program.connect) { + console.error('\033[33merror: use either --listen or --connect\033[39m'); + process.exit(-1); +} +else if (program.listen) { + var wsConsole = new Console(); + wsConsole.pause(); + var options = {}; + if (program.protocol) options.protocolVersion = program.protocol; + if (program.origin) options.origin = program.origin; + if (program.subprotocol) options.protocol = program.subprotocol; + var ws = null; + var wss = new WebSocket.Server({port: program.listen}, function() { + wsConsole.print('listening on port ' + program.listen + ' (press CTRL+C to quit)', Console.Colors.Green); + wsConsole.clear(); + }); + wsConsole.on('close', function() { + if (ws) { + try { + ws.close(); + } + catch (e) {} + } + process.exit(0); + }); + wsConsole.on('line', function(data) { + if (ws) { + ws.send(data, {mask: false}); + wsConsole.prompt(); + } + }); + wss.on('connection', function(newClient) { + if (ws) { + // limit to one client + newClient.terminate(); + return; + }; + ws = newClient; + wsConsole.resume(); + wsConsole.prompt(); + wsConsole.print('client connected', Console.Colors.Green); + ws.on('close', function() { + wsConsole.print('disconnected', Console.Colors.Green); + wsConsole.clear(); + wsConsole.pause(); + ws = null; + }); + ws.on('error', function(code, description) { + wsConsole.print('error: ' + code + (description ? ' ' + description : ''), Console.Colors.Yellow); + }); + ws.on('message', function(data, flags) { + wsConsole.print('< ' + data, Console.Colors.Blue); + }); + }); + wss.on('error', function(error) { + wsConsole.print('error: ' + error.toString(), Console.Colors.Yellow); + process.exit(-1); + }); +} +else if (program.connect) { + var wsConsole = new Console(); + var options = {}; + if (program.protocol) options.protocolVersion = program.protocol; + if (program.origin) options.origin = program.origin; + if (program.subprotocol) options.protocol = program.subprotocol; + if (program.host) options.host = program.host; + var ws = new WebSocket(program.connect, options); + ws.on('open', function() { + wsConsole.print('connected (press CTRL+C to quit)', Console.Colors.Green); + wsConsole.on('line', function(data) { + ws.send(data, {mask: true}); + wsConsole.prompt(); + }); + }); + ws.on('close', function() { + wsConsole.print('disconnected', Console.Colors.Green); + wsConsole.clear(); + process.exit(); + }); + ws.on('error', function(code, description) { + wsConsole.print('error: ' + code + (description ? ' ' + description : ''), Console.Colors.Yellow); + process.exit(-1); + }); + ws.on('message', function(data, flags) { + wsConsole.print('< ' + data, Console.Colors.Blue); + }); + wsConsole.on('close', function() { + if (ws) { + try { + ws.close(); + } + catch(e) {} + process.exit(); + } + }); +} +else { + console.error('\033[33merror: use either --listen or --connect\033[39m'); + process.exit(-1); +} diff --git a/node_modules/ws/binding.gyp b/node_modules/ws/binding.gyp new file mode 100644 index 0000000..a83d279 --- /dev/null +++ b/node_modules/ws/binding.gyp @@ -0,0 +1,14 @@ +{ + 'targets': [ + { + 'target_name': 'validation', + 'cflags': [ '-O3' ], + 'sources': [ 'src/validation.cc' ] + }, + { + 'target_name': 'bufferutil', + 'cflags': [ '-O3' ], + 'sources': [ 'src/bufferutil.cc' ] + } + ] +} diff --git a/node_modules/ws/builderror.log b/node_modules/ws/builderror.log new file mode 100644 index 0000000..a3b0a0c --- /dev/null +++ b/node_modules/ws/builderror.log @@ -0,0 +1,11 @@ +gyp ERR! configure error +gyp ERR! stack Error: Can't find Python executable "python", you can set the PYTHON env variable. +gyp ERR! stack at failNoPython (C:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\lib\configure.js:118:14) +gyp ERR! stack at C:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\lib\configure.js:81:11 +gyp ERR! stack at Object.oncomplete (fs.js:107:15) +gyp ERR! System Windows_NT 6.1.7600 +gyp ERR! command "node" "C:\\Program Files\\nodejs\\node_modules\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild" +gyp ERR! cwd C:\Users\Administrator\Downloads\webRTCCopy-master\server\node_modules\ws +gyp ERR! node -v v0.10.15 +gyp ERR! node-gyp -v v0.10.6 +gyp ERR! not ok diff --git a/node_modules/ws/doc/ws.md b/node_modules/ws/doc/ws.md new file mode 100644 index 0000000..c7c6fcb --- /dev/null +++ b/node_modules/ws/doc/ws.md @@ -0,0 +1,179 @@ +# ws + +## Class: ws.Server + +This class is a WebSocket server. It is an `EventEmitter`. + +### new ws.Server([options], [callback]) + +* `options` Object + * `host` String + * `port` Number + * `server` http.Server + * `verifyClient` Function + * `path` String + * `noServer` Boolean + * `disableHixie` Boolean + * `clientTracking` Boolean +* `callback` Function + +Construct a new server object. + +Either `port` or `server` must be provided, otherwise you might enable +`noServer` if you want to pass the requests directly. Please note that the +`callback` is only used when you supply the a `port` number in the options. + +### server.close([code], [data]) + +Close the server and terminate all clients + +### server.handleUpgrade(request, socket, upgradeHead, callback) + +Handles a HTTP Upgrade request. `request` is an instance of `http.ServerRequest`, `socket` is an instance of `net.Socket`. + +When the Upgrade was successfully, the `callback` will be called with a `ws.WebSocket` object as parameter. + +### Event: 'error' + +`function (error) { }` + +If the underlying server emits an error, it will be forwarded here. + +### Event: 'headers' + +`function (headers) { }` + +Emitted with the object of HTTP headers that are going to be written to the `Stream` as part of the handshake. + +### Event: 'connection' + +`function (socket) { }` + +When a new WebSocket connection is established. `socket` is an object of type `ws.WebSocket`. + + +## Class: ws.WebSocket + +This class represents a WebSocket connection. It is an `EventEmitter`. + +### new ws.WebSocket(address, [options]) + +* `address` String|Array +* `options` Object + * `protocol` String + * `protocolVersion` Number|String + -- the following only apply if `address` is a String + * `host` String + * `origin` String + * `pfx` String|Buffer + * `key` String|Buffer + * `passphrase` String + * `cert` String|Buffer + * `ca` Array + * `ciphers` String + * `rejectUnauthorized` Boolean + +Instantiating with an `address` creates a new WebSocket client object. If `address` is an Array (request, socket, rest), it is instantiated as a Server client (e.g. called from the `ws.Server`). + +### websocket.bytesReceived + +Received bytes count. + +### websocket.readyState + +Possible states are `WebSocket.CONNECTING`, `WebSocket.OPEN`, `WebSocket.CLOSING`, `WebSocket.CLOSED`. + +### websocket.protocolVersion + +The WebSocket protocol version used for this connection, `8`, `13` or `hixie-76` (the latter only for server clients). + +### websocket.url + +The URL of the WebSocket server (only for clients) + +### websocket.supports + +Describes the feature of the used protocol version. E.g. `supports.binary` is a boolean that describes if the connection supports binary messages. + +### websocket.close([code], [data]) + +Gracefully closes the connection, after sending a description message + +### websocket.pause() + +Pause the client stream + +### websocket.ping([data], [options], [dontFailWhenClosed]) + +Sends a ping. `data` is sent, `options` is an object with members `mask` and `binary`. `dontFailWhenClosed` indicates whether or not to throw if the connection isnt open. + +### websocket.pong([data], [options], [dontFailWhenClosed]) + +Sends a pong. `data` is sent, `options` is an object with members `mask` and `binary`. `dontFailWhenClosed` indicates whether or not to throw if the connection isnt open. + + +### websocket.resume() + +Resume the client stream + +### websocket.send(data, [options], [callback]) + +Sends `data` through the connection. `options` can be an object with members `mask` and `binary`. The optional `callback` is executed after the send completes. + +### websocket.stream([options], callback) + +Streams data through calls to a user supplied function. `options` can be an object with members `mask` and `binary`. `callback` is executed on successive ticks of which send is `function (data, final)`. + +### websocket.terminate() + +Immediately shuts down the connection + +### websocket.onopen +### websocket.onerror +### websocket.onclose +### websocket.onmessage + +Emulates the W3C Browser based WebSocket interface using function members. + +### websocket.addEventListener(method, listener) + +Emulates the W3C Browser based WebSocket interface using addEventListener. + +### Event: 'error' + +`function (error) { }` + +If the client emits an error, this event is emitted (errors from the underlying `net.Socket` are forwarded here). + +### Event: 'close' + +`function (code, message) { }` + +Is emitted when the connection is closed. `code` is defined in the WebSocket specification. + +The `close` event is also emitted when then underlying `net.Socket` closes the connection (`end` or `close`). + +### Event: 'message' + +`function (data, flags) { }` + +Is emitted when data is received. `flags` is an object with member `binary`. + +### Event: 'ping' + +`function (data, flags) { }` + +Is emitted when a ping is received. `flags` is an object with member `binary`. + +### Event: 'pong' + +`function (data, flags) { }` + +Is emitted when a pong is received. `flags` is an object with member `binary`. + +### Event: 'open' + +`function () { }` + +Emitted when the connection is established. + diff --git a/node_modules/ws/examples/fileapi/.npmignore b/node_modules/ws/examples/fileapi/.npmignore new file mode 100644 index 0000000..dcd5756 --- /dev/null +++ b/node_modules/ws/examples/fileapi/.npmignore @@ -0,0 +1 @@ +uploaded diff --git a/node_modules/ws/examples/fileapi/package.json b/node_modules/ws/examples/fileapi/package.json new file mode 100644 index 0000000..7816f27 --- /dev/null +++ b/node_modules/ws/examples/fileapi/package.json @@ -0,0 +1,18 @@ +{ + "author": "", + "name": "fileapi", + "version": "0.0.0", + "repository": { + "type": "git", + "url": "git://github.com/einaros/ws.git" + }, + "engines": { + "node": "~0.6.8" + }, + "dependencies": { + "express": "latest", + "ansi": "https://github.com/einaros/ansi.js/tarball/master" + }, + "devDependencies": {}, + "optionalDependencies": {} +} diff --git a/node_modules/ws/examples/fileapi/public/app.js b/node_modules/ws/examples/fileapi/public/app.js new file mode 100644 index 0000000..e812cc3 --- /dev/null +++ b/node_modules/ws/examples/fileapi/public/app.js @@ -0,0 +1,39 @@ +function onFilesSelected(e) { + var button = e.srcElement; + button.disabled = true; + var progress = document.querySelector('div#progress'); + progress.innerHTML = '0%'; + var files = e.target.files; + var totalFiles = files.length; + var filesSent = 0; + if (totalFiles) { + var uploader = new Uploader('ws://localhost:8080', function () { + Array.prototype.slice.call(files, 0).forEach(function(file) { + if (file.name == '.') { + --totalFiles; + return; + } + uploader.sendFile(file, function(error) { + if (error) { + console.log(error); + return; + } + ++filesSent; + progress.innerHTML = ~~(filesSent / totalFiles * 100) + '%'; + console.log('Sent: ' + file.name); + }); + }); + }); + } + uploader.ondone = function() { + uploader.close(); + progress.innerHTML = '100% done, ' + totalFiles + ' files sent.'; + } +} + +window.onload = function() { + var importButtons = document.querySelectorAll('[type="file"]'); + Array.prototype.slice.call(importButtons, 0).forEach(function(importButton) { + importButton.addEventListener('change', onFilesSelected, false); + }); +} diff --git a/node_modules/ws/examples/fileapi/public/index.html b/node_modules/ws/examples/fileapi/public/index.html new file mode 100644 index 0000000..0d463dd --- /dev/null +++ b/node_modules/ws/examples/fileapi/public/index.html @@ -0,0 +1,22 @@ + + + + + + + + +

    This example will upload an entire directory tree to the node.js server via a fast and persistent WebSocket connection.

    +

    Note that the example is Chrome only for now.

    +

    + Upload status: +
    Please select a directory to upload.
    + + diff --git a/node_modules/ws/examples/fileapi/public/uploader.js b/node_modules/ws/examples/fileapi/public/uploader.js new file mode 100644 index 0000000..0c34a7f --- /dev/null +++ b/node_modules/ws/examples/fileapi/public/uploader.js @@ -0,0 +1,55 @@ +function Uploader(url, cb) { + this.ws = new WebSocket(url); + if (cb) this.ws.onopen = cb; + this.sendQueue = []; + this.sending = null; + this.sendCallback = null; + this.ondone = null; + var self = this; + this.ws.onmessage = function(event) { + var data = JSON.parse(event.data); + if (data.event == 'complete') { + if (data.path != self.sending.path) { + self.sendQueue = []; + self.sending = null; + self.sendCallback = null; + throw new Error('Got message for wrong file!'); + } + self.sending = null; + var callback = self.sendCallback; + self.sendCallback = null; + if (callback) callback(); + if (self.sendQueue.length === 0 && self.ondone) self.ondone(null); + if (self.sendQueue.length > 0) { + var args = self.sendQueue.pop(); + setTimeout(function() { self.sendFile.apply(self, args); }, 0); + } + } + else if (data.event == 'error') { + self.sendQueue = []; + self.sending = null; + var callback = self.sendCallback; + self.sendCallback = null; + var error = new Error('Server reported send error for file ' + data.path); + if (callback) callback(error); + if (self.ondone) self.ondone(error); + } + } +} + +Uploader.prototype.sendFile = function(file, cb) { + if (this.ws.readyState != WebSocket.OPEN) throw new Error('Not connected'); + if (this.sending) { + this.sendQueue.push(arguments); + return; + } + var fileData = { name: file.name, path: file.webkitRelativePath }; + this.sending = fileData; + this.sendCallback = cb; + this.ws.send(JSON.stringify(fileData)); + this.ws.send(file); +} + +Uploader.prototype.close = function() { + this.ws.close(); +} diff --git a/node_modules/ws/examples/fileapi/server.js b/node_modules/ws/examples/fileapi/server.js new file mode 100644 index 0000000..badfeba --- /dev/null +++ b/node_modules/ws/examples/fileapi/server.js @@ -0,0 +1,103 @@ +var WebSocketServer = require('../../').Server + , express = require('express') + , fs = require('fs') + , http = require('http') + , util = require('util') + , path = require('path') + , app = express.createServer() + , events = require('events') + , ansi = require('ansi') + , cursor = ansi(process.stdout); + +function BandwidthSampler(ws, interval) { + interval = interval || 2000; + var previousByteCount = 0; + var self = this; + var intervalId = setInterval(function() { + var byteCount = ws.bytesReceived; + var bytesPerSec = (byteCount - previousByteCount) / (interval / 1000); + previousByteCount = byteCount; + self.emit('sample', bytesPerSec); + }, interval); + ws.on('close', function() { + clearInterval(intervalId); + }); +} +util.inherits(BandwidthSampler, events.EventEmitter); + +function makePathForFile(filePath, prefix, cb) { + if (typeof cb !== 'function') throw new Error('callback is required'); + filePath = path.dirname(path.normalize(filePath)).replace(/^(\/|\\)+/, ''); + var pieces = filePath.split(/(\\|\/)/); + var incrementalPath = prefix; + function step(error) { + if (error) return cb(error); + if (pieces.length == 0) return cb(null, incrementalPath); + incrementalPath += '/' + pieces.shift(); + fs.exists(incrementalPath, function(exists) { + if (!exists) fs.mkdir(incrementalPath, step); + else process.nextTick(step); + }); + } + step(); +} + +cursor.eraseData(2).goto(1, 1); +app.use(express.static(__dirname + '/public')); + +var clientId = 0; +var wss = new WebSocketServer({server: app}); +wss.on('connection', function(ws) { + var thisId = ++clientId; + cursor.goto(1, 4 + thisId).eraseLine(); + console.log('Client #%d connected', thisId); + + var sampler = new BandwidthSampler(ws); + sampler.on('sample', function(bps) { + cursor.goto(1, 4 + thisId).eraseLine(); + console.log('WebSocket #%d incoming bandwidth: %d MB/s', thisId, Math.round(bps / (1024*1024))); + }); + + var filesReceived = 0; + var currentFile = null; + ws.on('message', function(data, flags) { + if (!flags.binary) { + currentFile = JSON.parse(data); + // note: a real-world app would want to sanity check the data + } + else { + if (currentFile == null) return; + makePathForFile(currentFile.path, __dirname + '/uploaded', function(error, path) { + if (error) { + console.log(error); + ws.send(JSON.stringify({event: 'error', path: currentFile.path, message: error.message})); + return; + } + fs.writeFile(path + '/' + currentFile.name, data, function(error) { + ++filesReceived; + // console.log('received %d bytes long file, %s', data.length, currentFile.path); + ws.send(JSON.stringify({event: 'complete', path: currentFile.path})); + currentFile = null; + }); + }); + } + }); + + ws.on('close', function() { + cursor.goto(1, 4 + thisId).eraseLine(); + console.log('Client #%d disconnected. %d files received.', thisId, filesReceived); + }); + + ws.on('error', function(e) { + cursor.goto(1, 4 + thisId).eraseLine(); + console.log('Client #%d error: %s', thisId, e.message); + }); +}); + +fs.mkdir(__dirname + '/uploaded', function(error) { + // ignore errors, most likely means directory exists + console.log('Uploaded files will be saved to %s/uploaded.', __dirname); + console.log('Remember to wipe this directory if you upload lots and lots.'); + app.listen(8080); + console.log('Listening on http://localhost:8080'); +}); diff --git a/node_modules/ws/examples/serverstats-express_3/package.json b/node_modules/ws/examples/serverstats-express_3/package.json new file mode 100644 index 0000000..99722c4 --- /dev/null +++ b/node_modules/ws/examples/serverstats-express_3/package.json @@ -0,0 +1,17 @@ +{ + "author": "", + "name": "serverstats", + "version": "0.0.0", + "repository": { + "type": "git", + "url": "git://github.com/einaros/ws.git" + }, + "engines": { + "node": ">0.4.0" + }, + "dependencies": { + "express": "~3.0.0" + }, + "devDependencies": {}, + "optionalDependencies": {} +} diff --git a/node_modules/ws/examples/serverstats-express_3/public/index.html b/node_modules/ws/examples/serverstats-express_3/public/index.html new file mode 100644 index 0000000..24d84e1 --- /dev/null +++ b/node_modules/ws/examples/serverstats-express_3/public/index.html @@ -0,0 +1,33 @@ + + + + + + + + Server Stats
    + RSS:

    + Heap total:

    + Heap used:

    + + diff --git a/node_modules/ws/examples/serverstats-express_3/server.js b/node_modules/ws/examples/serverstats-express_3/server.js new file mode 100644 index 0000000..88bbc9e --- /dev/null +++ b/node_modules/ws/examples/serverstats-express_3/server.js @@ -0,0 +1,21 @@ +var WebSocketServer = require('../../').Server + , http = require('http') + , express = require('express') + , app = express(); + +app.use(express.static(__dirname + '/public')); + +var server = http.createServer(app); +server.listen(8080); + +var wss = new WebSocketServer({server: server}); +wss.on('connection', function(ws) { + var id = setInterval(function() { + ws.send(JSON.stringify(process.memoryUsage()), function() { /* ignore errors */ }); + }, 100); + console.log('started client interval'); + ws.on('close', function() { + console.log('stopping client interval'); + clearInterval(id); + }); +}); diff --git a/node_modules/ws/examples/serverstats/package.json b/node_modules/ws/examples/serverstats/package.json new file mode 100644 index 0000000..65c900a --- /dev/null +++ b/node_modules/ws/examples/serverstats/package.json @@ -0,0 +1,17 @@ +{ + "author": "", + "name": "serverstats", + "version": "0.0.0", + "repository": { + "type": "git", + "url": "git://github.com/einaros/ws.git" + }, + "engines": { + "node": ">0.4.0" + }, + "dependencies": { + "express": "2.x" + }, + "devDependencies": {}, + "optionalDependencies": {} +} diff --git a/node_modules/ws/examples/serverstats/public/index.html b/node_modules/ws/examples/serverstats/public/index.html new file mode 100644 index 0000000..24d84e1 --- /dev/null +++ b/node_modules/ws/examples/serverstats/public/index.html @@ -0,0 +1,33 @@ + + + + + + + + Server Stats
    + RSS:

    + Heap total:

    + Heap used:

    + + diff --git a/node_modules/ws/examples/serverstats/server.js b/node_modules/ws/examples/serverstats/server.js new file mode 100644 index 0000000..0bbce36 --- /dev/null +++ b/node_modules/ws/examples/serverstats/server.js @@ -0,0 +1,19 @@ +var WebSocketServer = require('../../').Server + , http = require('http') + , express = require('express') + , app = express.createServer(); + +app.use(express.static(__dirname + '/public')); +app.listen(8080); + +var wss = new WebSocketServer({server: app}); +wss.on('connection', function(ws) { + var id = setInterval(function() { + ws.send(JSON.stringify(process.memoryUsage()), function() { /* ignore errors */ }); + }, 100); + console.log('started client interval'); + ws.on('close', function() { + console.log('stopping client interval'); + clearInterval(id); + }) +}); diff --git a/node_modules/ws/examples/ssl.js b/node_modules/ws/examples/ssl.js new file mode 100644 index 0000000..bf1bf53 --- /dev/null +++ b/node_modules/ws/examples/ssl.js @@ -0,0 +1,59 @@ + +(function(){ + + "use strict"; + + var fs = require('fs'); + + // you'll probably load configuration from config + var cfg = { + ssl: true, + port: 8080, + ssl_key: '/path/to/you/ssl.key', + ssl_cert: '/path/to/you/ssl.crt' + }; + + var httpServ = ( cfg.ssl ) ? require('https') : require('http'); + + var WebSocketServer = require('../').Server; + + var app = null; + + // dummy request processing + var processRequest = function( req, res ) { + + res.writeHead(200); + res.end("All glory to WebSockets!\n"); + }; + + if ( cfg.ssl ) { + + app = httpServ.createServer({ + + // providing server with SSL key/cert + key: fs.readFileSync( cfg.ssl_key ), + cert: fs.readFileSync( cfg.ssl_cert ) + + }, processRequest ).listen( cfg.port ); + + } else { + + app = httpServ.createServer( processRequest ).listen( cfg.port ); + } + + // passing or reference to web server so WS would knew port and SSL capabilities + var wss = new WebSocketServer( { server: app } ); + + + wss.on( 'connection', function ( wsConnect ) { + + wsConnect.on( 'message', function ( message ) { + + console.log( message ); + + }); + + }); + + +}()); \ No newline at end of file diff --git a/node_modules/ws/index.js b/node_modules/ws/index.js new file mode 100644 index 0000000..3423ff2 --- /dev/null +++ b/node_modules/ws/index.js @@ -0,0 +1,26 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +module.exports = require('./lib/WebSocket'); +module.exports.Server = require('./lib/WebSocketServer'); +module.exports.Sender = require('./lib/Sender'); +module.exports.Receiver = require('./lib/Receiver'); + +module.exports.createServer = function (options, connectionListener) { + var server = new module.exports.Server(options); + if (typeof connectionListener === 'function') { + server.on('connection', connectionListener); + } + return server; +}; + +module.exports.connect = module.exports.createConnection = function (address, openListener) { + var client = new module.exports(address); + if (typeof openListener === 'function') { + client.on('open', openListener); + } + return client; +}; diff --git a/node_modules/ws/lib/BufferPool.js b/node_modules/ws/lib/BufferPool.js new file mode 100644 index 0000000..faf8637 --- /dev/null +++ b/node_modules/ws/lib/BufferPool.js @@ -0,0 +1,59 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var util = require('util'); + +function BufferPool(initialSize, growStrategy, shrinkStrategy) { + if (typeof initialSize === 'function') { + shrinkStrategy = growStrategy; + growStrategy = initialSize; + initialSize = 0; + } + else if (typeof initialSize === 'undefined') { + initialSize = 0; + } + this._growStrategy = (growStrategy || function(db, size) { + return db.used + size; + }).bind(null, this); + this._shrinkStrategy = (shrinkStrategy || function(db) { + return initialSize; + }).bind(null, this); + this._buffer = initialSize ? new Buffer(initialSize) : null; + this._offset = 0; + this._used = 0; + this._changeFactor = 0; + this.__defineGetter__('size', function(){ + return this._buffer == null ? 0 : this._buffer.length; + }); + this.__defineGetter__('used', function(){ + return this._used; + }); +} + +BufferPool.prototype.get = function(length) { + if (this._buffer == null || this._offset + length > this._buffer.length) { + var newBuf = new Buffer(this._growStrategy(length)); + this._buffer = newBuf; + this._offset = 0; + } + this._used += length; + var buf = this._buffer.slice(this._offset, this._offset + length); + this._offset += length; + return buf; +} + +BufferPool.prototype.reset = function(forceNewBuffer) { + var len = this._shrinkStrategy(); + if (len < this.size) this._changeFactor -= 1; + if (forceNewBuffer || this._changeFactor < -2) { + this._changeFactor = 0; + this._buffer = len ? new Buffer(len) : null; + } + this._offset = 0; + this._used = 0; +} + +module.exports = BufferPool; diff --git a/node_modules/ws/lib/BufferUtil.fallback.js b/node_modules/ws/lib/BufferUtil.fallback.js new file mode 100644 index 0000000..508542c --- /dev/null +++ b/node_modules/ws/lib/BufferUtil.fallback.js @@ -0,0 +1,47 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +module.exports.BufferUtil = { + merge: function(mergedBuffer, buffers) { + var offset = 0; + for (var i = 0, l = buffers.length; i < l; ++i) { + var buf = buffers[i]; + buf.copy(mergedBuffer, offset); + offset += buf.length; + } + }, + mask: function(source, mask, output, offset, length) { + var maskNum = mask.readUInt32LE(0, true); + var i = 0; + for (; i < length - 3; i += 4) { + var num = maskNum ^ source.readUInt32LE(i, true); + if (num < 0) num = 4294967296 + num; + output.writeUInt32LE(num, offset + i, true); + } + switch (length % 4) { + case 3: output[offset + i + 2] = source[i + 2] ^ mask[2]; + case 2: output[offset + i + 1] = source[i + 1] ^ mask[1]; + case 1: output[offset + i] = source[i] ^ mask[0]; + case 0:; + } + }, + unmask: function(data, mask) { + var maskNum = mask.readUInt32LE(0, true); + var length = data.length; + var i = 0; + for (; i < length - 3; i += 4) { + var num = maskNum ^ data.readUInt32LE(i, true); + if (num < 0) num = 4294967296 + num; + data.writeUInt32LE(num, i, true); + } + switch (length % 4) { + case 3: data[i + 2] = data[i + 2] ^ mask[2]; + case 2: data[i + 1] = data[i + 1] ^ mask[1]; + case 1: data[i] = data[i] ^ mask[0]; + case 0:; + } + } +} diff --git a/node_modules/ws/lib/BufferUtil.js b/node_modules/ws/lib/BufferUtil.js new file mode 100644 index 0000000..15d35b9 --- /dev/null +++ b/node_modules/ws/lib/BufferUtil.js @@ -0,0 +1,16 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +try { + module.exports = require('../build/Release/bufferutil'); +} catch (e) { try { + module.exports = require('../build/default/bufferutil'); +} catch (e) { try { + module.exports = require('./BufferUtil.fallback'); +} catch (e) { + console.error('bufferutil.node seems to not have been built. Run npm install.'); + throw e; +}}} diff --git a/node_modules/ws/lib/ErrorCodes.js b/node_modules/ws/lib/ErrorCodes.js new file mode 100644 index 0000000..55ebd52 --- /dev/null +++ b/node_modules/ws/lib/ErrorCodes.js @@ -0,0 +1,24 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +module.exports = { + isValidErrorCode: function(code) { + return (code >= 1000 && code <= 1011 && code != 1004 && code != 1005 && code != 1006) || + (code >= 3000 && code <= 4999); + }, + 1000: 'normal', + 1001: 'going away', + 1002: 'protocol error', + 1003: 'unsupported data', + 1004: 'reserved', + 1005: 'reserved for extensions', + 1006: 'reserved for extensions', + 1007: 'inconsistent or invalid data', + 1008: 'policy violation', + 1009: 'message too big', + 1010: 'extension handshake missing', + 1011: 'an unexpected condition prevented the request from being fulfilled', +}; \ No newline at end of file diff --git a/node_modules/ws/lib/Receiver.hixie.js b/node_modules/ws/lib/Receiver.hixie.js new file mode 100644 index 0000000..f54ad96 --- /dev/null +++ b/node_modules/ws/lib/Receiver.hixie.js @@ -0,0 +1,180 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var util = require('util'); + +/** + * State constants + */ + +var EMPTY = 0 + , BODY = 1; +var BINARYLENGTH = 2 + , BINARYBODY = 3; + +/** + * Hixie Receiver implementation + */ + +function Receiver () { + this.state = EMPTY; + this.buffers = []; + this.messageEnd = -1; + this.spanLength = 0; + this.dead = false; + + this.onerror = function() {}; + this.ontext = function() {}; + this.onbinary = function() {}; + this.onclose = function() {}; + this.onping = function() {}; + this.onpong = function() {}; +} + +module.exports = Receiver; + +/** + * Add new data to the parser. + * + * @api public + */ + +Receiver.prototype.add = function(data) { + var self = this; + function doAdd() { + if (self.state === EMPTY) { + if (data.length == 2 && data[0] == 0xFF && data[1] == 0x00) { + self.reset(); + self.onclose(); + return; + } + if (data[0] === 0x80) { + self.messageEnd = 0; + self.state = BINARYLENGTH; + data = data.slice(1); + } else { + + if (data[0] !== 0x00) { + self.error('payload must start with 0x00 byte', true); + return; + } + data = data.slice(1); + self.state = BODY; + + } + } + if (self.state === BINARYLENGTH) { + var i = 0; + while ((i < data.length) && (data[i] & 0x80)) { + self.messageEnd = 128 * self.messageEnd + (data[i] & 0x7f); + ++i; + } + if (i < data.length) { + self.messageEnd = 128 * self.messageEnd + (data[i] & 0x7f); + self.state = BINARYBODY; + ++i; + } + if (i > 0) + data = data.slice(i); + } + if (self.state === BINARYBODY) { + var dataleft = self.messageEnd - self.spanLength; + if (data.length >= dataleft) { + // consume the whole buffer to finish the frame + self.buffers.push(data); + self.spanLength += dataleft; + self.messageEnd = dataleft; + return self.parse(); + } + // frame's not done even if we consume it all + self.buffers.push(data); + self.spanLength += data.length; + return; + } + self.buffers.push(data); + if ((self.messageEnd = bufferIndex(data, 0xFF)) != -1) { + self.spanLength += self.messageEnd; + return self.parse(); + } + else self.spanLength += data.length; + } + while(data) data = doAdd(); +} + +/** + * Releases all resources used by the receiver. + * + * @api public + */ + +Receiver.prototype.cleanup = function() { + this.dead = true; + this.state = EMPTY; + this.buffers = []; +} + +/** + * Process buffered data. + * + * @api public + */ + +Receiver.prototype.parse = function() { + var output = new Buffer(this.spanLength); + var outputIndex = 0; + for (var bi = 0, bl = this.buffers.length; bi < bl - 1; ++bi) { + var buffer = this.buffers[bi]; + buffer.copy(output, outputIndex); + outputIndex += buffer.length; + } + var lastBuffer = this.buffers[this.buffers.length - 1]; + if (this.messageEnd > 0) lastBuffer.copy(output, outputIndex, 0, this.messageEnd); + if (this.state !== BODY) --this.messageEnd; + var tail = null; + if (this.messageEnd < lastBuffer.length - 1) { + tail = lastBuffer.slice(this.messageEnd + 1); + } + this.reset(); + this.ontext(output.toString('utf8')); + return tail; +} + +/** + * Handles an error + * + * @api private + */ + +Receiver.prototype.error = function (reason, terminate) { + this.reset(); + this.onerror(reason, terminate); + return this; +} + +/** + * Reset parser state + * + * @api private + */ + +Receiver.prototype.reset = function (reason) { + if (this.dead) return; + this.state = EMPTY; + this.buffers = []; + this.messageEnd = -1; + this.spanLength = 0; +} + +/** + * Internal api + */ + +function bufferIndex(buffer, byte) { + for (var i = 0, l = buffer.length; i < l; ++i) { + if (buffer[i] === byte) return i; + } + return -1; +} diff --git a/node_modules/ws/lib/Receiver.js b/node_modules/ws/lib/Receiver.js new file mode 100644 index 0000000..2752726 --- /dev/null +++ b/node_modules/ws/lib/Receiver.js @@ -0,0 +1,591 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var util = require('util') + , Validation = require('./Validation').Validation + , ErrorCodes = require('./ErrorCodes') + , BufferPool = require('./BufferPool') + , bufferUtil = require('./BufferUtil').BufferUtil; + +/** + * Node version 0.4 and 0.6 compatibility + */ + +var isNodeV4 = /^v0\.4/.test(process.version); + +/** + * HyBi Receiver implementation + */ + +function Receiver () { + // memory pool for fragmented messages + var fragmentedPoolPrevUsed = -1; + this.fragmentedBufferPool = new BufferPool(1024, function(db, length) { + return db.used + length; + }, function(db) { + return fragmentedPoolPrevUsed = fragmentedPoolPrevUsed >= 0 ? + (fragmentedPoolPrevUsed + db.used) / 2 : + db.used; + }); + + // memory pool for unfragmented messages + var unfragmentedPoolPrevUsed = -1; + this.unfragmentedBufferPool = new BufferPool(1024, function(db, length) { + return db.used + length; + }, function(db) { + return unfragmentedPoolPrevUsed = unfragmentedPoolPrevUsed >= 0 ? + (unfragmentedPoolPrevUsed + db.used) / 2 : + db.used; + }); + + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0, + fragmentedOperation: false + }; + this.overflow = []; + this.headerBuffer = new Buffer(10); + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.currentMessage = []; + this.expectHeader(2, this.processPacket); + this.dead = false; + + this.onerror = function() {}; + this.ontext = function() {}; + this.onbinary = function() {}; + this.onclose = function() {}; + this.onping = function() {}; + this.onpong = function() {}; +}; + +module.exports = Receiver; + +/** + * Add new data to the parser. + * + * @api public + */ + +Receiver.prototype.add = function(data) { + var dataLength = data.length; + if (dataLength == 0) return; + if (this.expectBuffer == null) { + this.overflow.push(data); + return; + } + var toRead = Math.min(dataLength, this.expectBuffer.length - this.expectOffset); + fastCopy(toRead, data, this.expectBuffer, this.expectOffset); + this.expectOffset += toRead; + if (toRead < dataLength) { + this.overflow.push(data.slice(toRead)); + } + while (this.expectBuffer && this.expectOffset == this.expectBuffer.length) { + var bufferForHandler = this.expectBuffer; + this.expectBuffer = null; + this.expectOffset = 0; + this.expectHandler.call(this, bufferForHandler); + } +} + +/** + * Releases all resources used by the receiver. + * + * @api public + */ + +Receiver.prototype.cleanup = function() { + this.dead = true; + this.overflow = null; + this.headerBuffer = null; + this.expectBuffer = null; + this.expectHandler = null; + this.unfragmentedBufferPool = null; + this.fragmentedBufferPool = null; + this.state = null; + this.currentMessage = null; + this.onerror = null; + this.ontext = null; + this.onbinary = null; + this.onclose = null; + this.onping = null; + this.onpong = null; +} + +/** + * Waits for a certain amount of header bytes to be available, then fires a callback. + * + * @api private + */ + +Receiver.prototype.expectHeader = function(length, handler) { + if (length == 0) { + handler(null); + return; + } + this.expectBuffer = this.headerBuffer.slice(this.expectOffset, this.expectOffset + length); + this.expectHandler = handler; + var toRead = length; + while (toRead > 0 && this.overflow.length > 0) { + var fromOverflow = this.overflow.pop(); + if (toRead < fromOverflow.length) this.overflow.push(fromOverflow.slice(toRead)); + var read = Math.min(fromOverflow.length, toRead); + fastCopy(read, fromOverflow, this.expectBuffer, this.expectOffset); + this.expectOffset += read; + toRead -= read; + } +} + +/** + * Waits for a certain amount of data bytes to be available, then fires a callback. + * + * @api private + */ + +Receiver.prototype.expectData = function(length, handler) { + if (length == 0) { + handler(null); + return; + } + this.expectBuffer = this.allocateFromPool(length, this.state.fragmentedOperation); + this.expectHandler = handler; + var toRead = length; + while (toRead > 0 && this.overflow.length > 0) { + var fromOverflow = this.overflow.pop(); + if (toRead < fromOverflow.length) this.overflow.push(fromOverflow.slice(toRead)); + var read = Math.min(fromOverflow.length, toRead); + fastCopy(read, fromOverflow, this.expectBuffer, this.expectOffset); + this.expectOffset += read; + toRead -= read; + } +} + +/** + * Allocates memory from the buffer pool. + * + * @api private + */ + +Receiver.prototype.allocateFromPool = !isNodeV4 + ? function(length, isFragmented) { return (isFragmented ? this.fragmentedBufferPool : this.unfragmentedBufferPool).get(length); } + : function(length) { return new Buffer(length); }; + +/** + * Start processing a new packet. + * + * @api private + */ + +Receiver.prototype.processPacket = function (data) { + if ((data[0] & 0x70) != 0) { + this.error('reserved fields must be empty', 1002); + return; + } + this.state.lastFragment = (data[0] & 0x80) == 0x80; + this.state.masked = (data[1] & 0x80) == 0x80; + var opcode = data[0] & 0xf; + if (opcode === 0) { + // continuation frame + this.state.fragmentedOperation = true; + this.state.opcode = this.state.activeFragmentedOperation; + if (!(this.state.opcode == 1 || this.state.opcode == 2)) { + this.error('continuation frame cannot follow current opcode', 1002); + return; + } + } + else { + if (opcode < 3 && this.state.activeFragmentedOperation != null) { + this.error('data frames after the initial data frame must have opcode 0', 1002); + return; + } + this.state.opcode = opcode; + if (this.state.lastFragment === false) { + this.state.fragmentedOperation = true; + this.state.activeFragmentedOperation = opcode; + } + else this.state.fragmentedOperation = false; + } + var handler = opcodes[this.state.opcode]; + if (typeof handler == 'undefined') this.error('no handler for opcode ' + this.state.opcode, 1002); + else { + handler.start.call(this, data); + } +} + +/** + * Endprocessing a packet. + * + * @api private + */ + +Receiver.prototype.endPacket = function() { + if (!this.state.fragmentedOperation) this.unfragmentedBufferPool.reset(true); + else if (this.state.lastFragment) this.fragmentedBufferPool.reset(false); + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + if (this.state.lastFragment && this.state.opcode === this.state.activeFragmentedOperation) { + // end current fragmented operation + this.state.activeFragmentedOperation = null; + } + this.state.lastFragment = false; + this.state.opcode = this.state.activeFragmentedOperation != null ? this.state.activeFragmentedOperation : 0; + this.state.masked = false; + this.expectHeader(2, this.processPacket); +} + +/** + * Reset the parser state. + * + * @api private + */ + +Receiver.prototype.reset = function() { + if (this.dead) return; + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0, + fragmentedOperation: false + }; + this.fragmentedBufferPool.reset(true); + this.unfragmentedBufferPool.reset(true); + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.overflow = []; + this.currentMessage = []; +} + +/** + * Unmask received data. + * + * @api private + */ + +Receiver.prototype.unmask = function (mask, buf, binary) { + if (mask != null && buf != null) bufferUtil.unmask(buf, mask); + if (binary) return buf; + return buf != null ? buf.toString('utf8') : ''; +} + +/** + * Concatenates a list of buffers. + * + * @api private + */ + +Receiver.prototype.concatBuffers = function(buffers) { + var length = 0; + for (var i = 0, l = buffers.length; i < l; ++i) length += buffers[i].length; + var mergedBuffer = new Buffer(length); + bufferUtil.merge(mergedBuffer, buffers); + return mergedBuffer; +} + +/** + * Handles an error + * + * @api private + */ + +Receiver.prototype.error = function (reason, protocolErrorCode) { + this.reset(); + this.onerror(reason, protocolErrorCode); + return this; +} + +/** + * Buffer utilities + */ + +function readUInt16BE(start) { + return (this[start]<<8) + + this[start+1]; +} + +function readUInt32BE(start) { + return (this[start]<<24) + + (this[start+1]<<16) + + (this[start+2]<<8) + + this[start+3]; +} + +function fastCopy(length, srcBuffer, dstBuffer, dstOffset) { + switch (length) { + default: srcBuffer.copy(dstBuffer, dstOffset, 0, length); break; + case 16: dstBuffer[dstOffset+15] = srcBuffer[15]; + case 15: dstBuffer[dstOffset+14] = srcBuffer[14]; + case 14: dstBuffer[dstOffset+13] = srcBuffer[13]; + case 13: dstBuffer[dstOffset+12] = srcBuffer[12]; + case 12: dstBuffer[dstOffset+11] = srcBuffer[11]; + case 11: dstBuffer[dstOffset+10] = srcBuffer[10]; + case 10: dstBuffer[dstOffset+9] = srcBuffer[9]; + case 9: dstBuffer[dstOffset+8] = srcBuffer[8]; + case 8: dstBuffer[dstOffset+7] = srcBuffer[7]; + case 7: dstBuffer[dstOffset+6] = srcBuffer[6]; + case 6: dstBuffer[dstOffset+5] = srcBuffer[5]; + case 5: dstBuffer[dstOffset+4] = srcBuffer[4]; + case 4: dstBuffer[dstOffset+3] = srcBuffer[3]; + case 3: dstBuffer[dstOffset+2] = srcBuffer[2]; + case 2: dstBuffer[dstOffset+1] = srcBuffer[1]; + case 1: dstBuffer[dstOffset] = srcBuffer[0]; + } +} + +/** + * Opcode handlers + */ + +var opcodes = { + // text + '1': { + start: function(data) { + var self = this; + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + opcodes['1'].getData.call(self, firstLength); + } + else if (firstLength == 126) { + self.expectHeader(2, function(data) { + opcodes['1'].getData.call(self, readUInt16BE.call(data, 0)); + }); + } + else if (firstLength == 127) { + self.expectHeader(8, function(data) { + if (readUInt32BE.call(data, 0) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported', 1008); + return; + } + opcodes['1'].getData.call(self, readUInt32BE.call(data, 4)); + }); + } + }, + getData: function(length) { + var self = this; + if (self.state.masked) { + self.expectHeader(4, function(data) { + var mask = data; + self.expectData(length, function(data) { + opcodes['1'].finish.call(self, mask, data); + }); + }); + } + else { + self.expectData(length, function(data) { + opcodes['1'].finish.call(self, null, data); + }); + } + }, + finish: function(mask, data) { + var packet = this.unmask(mask, data, true); + if (packet != null) this.currentMessage.push(packet); + if (this.state.lastFragment) { + var messageBuffer = this.concatBuffers(this.currentMessage); + if (!Validation.isValidUTF8(messageBuffer)) { + this.error('invalid utf8 sequence', 1007); + return; + } + this.ontext(messageBuffer.toString('utf8'), {masked: this.state.masked, buffer: messageBuffer}); + this.currentMessage = []; + } + this.endPacket(); + } + }, + // binary + '2': { + start: function(data) { + var self = this; + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + opcodes['2'].getData.call(self, firstLength); + } + else if (firstLength == 126) { + self.expectHeader(2, function(data) { + opcodes['2'].getData.call(self, readUInt16BE.call(data, 0)); + }); + } + else if (firstLength == 127) { + self.expectHeader(8, function(data) { + if (readUInt32BE.call(data, 0) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported', 1008); + return; + } + opcodes['2'].getData.call(self, readUInt32BE.call(data, 4, true)); + }); + } + }, + getData: function(length) { + var self = this; + if (self.state.masked) { + self.expectHeader(4, function(data) { + var mask = data; + self.expectData(length, function(data) { + opcodes['2'].finish.call(self, mask, data); + }); + }); + } + else { + self.expectData(length, function(data) { + opcodes['2'].finish.call(self, null, data); + }); + } + }, + finish: function(mask, data) { + var packet = this.unmask(mask, data, true); + if (packet != null) this.currentMessage.push(packet); + if (this.state.lastFragment) { + var messageBuffer = this.concatBuffers(this.currentMessage); + this.onbinary(messageBuffer, {masked: this.state.masked, buffer: messageBuffer}); + this.currentMessage = []; + } + this.endPacket(); + } + }, + // close + '8': { + start: function(data) { + var self = this; + if (self.state.lastFragment == false) { + self.error('fragmented close is not supported', 1002); + return; + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + opcodes['8'].getData.call(self, firstLength); + } + else { + self.error('control frames cannot have more than 125 bytes of data', 1002); + } + }, + getData: function(length) { + var self = this; + if (self.state.masked) { + self.expectHeader(4, function(data) { + var mask = data; + self.expectData(length, function(data) { + opcodes['8'].finish.call(self, mask, data); + }); + }); + } + else { + self.expectData(length, function(data) { + opcodes['8'].finish.call(self, null, data); + }); + } + }, + finish: function(mask, data) { + var self = this; + data = self.unmask(mask, data, true); + if (data && data.length == 1) { + self.error('close packets with data must be at least two bytes long', 1002); + return; + } + var code = data && data.length > 1 ? readUInt16BE.call(data, 0) : 1000; + if (!ErrorCodes.isValidErrorCode(code)) { + self.error('invalid error code', 1002); + return; + } + var message = ''; + if (data && data.length > 2) { + var messageBuffer = data.slice(2); + if (!Validation.isValidUTF8(messageBuffer)) { + self.error('invalid utf8 sequence', 1007); + return; + } + message = messageBuffer.toString('utf8'); + } + this.onclose(code, message, {masked: self.state.masked}); + this.reset(); + }, + }, + // ping + '9': { + start: function(data) { + var self = this; + if (self.state.lastFragment == false) { + self.error('fragmented ping is not supported', 1002); + return; + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + opcodes['9'].getData.call(self, firstLength); + } + else { + self.error('control frames cannot have more than 125 bytes of data', 1002); + } + }, + getData: function(length) { + var self = this; + if (self.state.masked) { + self.expectHeader(4, function(data) { + var mask = data; + self.expectData(length, function(data) { + opcodes['9'].finish.call(self, mask, data); + }); + }); + } + else { + self.expectData(length, function(data) { + opcodes['9'].finish.call(self, null, data); + }); + } + }, + finish: function(mask, data) { + this.onping(this.unmask(mask, data, true), {masked: this.state.masked, binary: true}); + this.endPacket(); + } + }, + // pong + '10': { + start: function(data) { + var self = this; + if (self.state.lastFragment == false) { + self.error('fragmented pong is not supported', 1002); + return; + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + opcodes['10'].getData.call(self, firstLength); + } + else { + self.error('control frames cannot have more than 125 bytes of data', 1002); + } + }, + getData: function(length) { + var self = this; + if (this.state.masked) { + this.expectHeader(4, function(data) { + var mask = data; + self.expectData(length, function(data) { + opcodes['10'].finish.call(self, mask, data); + }); + }); + } + else { + this.expectData(length, function(data) { + opcodes['10'].finish.call(self, null, data); + }); + } + }, + finish: function(mask, data) { + this.onpong(this.unmask(mask, data, true), {masked: this.state.masked, binary: true}); + this.endPacket(); + } + } +} diff --git a/node_modules/ws/lib/Sender.hixie.js b/node_modules/ws/lib/Sender.hixie.js new file mode 100644 index 0000000..1754afb --- /dev/null +++ b/node_modules/ws/lib/Sender.hixie.js @@ -0,0 +1,123 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var events = require('events') + , util = require('util') + , EventEmitter = events.EventEmitter; + +/** + * Hixie Sender implementation + */ + +function Sender(socket) { + this.socket = socket; + this.continuationFrame = false; + this.isClosed = false; +} + +module.exports = Sender; + +/** + * Inherits from EventEmitter. + */ + +util.inherits(Sender, events.EventEmitter); + +/** + * Frames and writes data. + * + * @api public + */ + +Sender.prototype.send = function(data, options, cb) { + if (this.isClosed) return; +/* + if (options && options.binary) { + this.error('hixie websockets do not support binary'); + return; + } +*/ + var isString = typeof data == 'string' + , length = isString ? Buffer.byteLength(data) : data.length + , lengthbytes = (length > 127) ? 2 : 1 // assume less than 2**14 bytes + , writeStartMarker = this.continuationFrame == false + , writeEndMarker = !options || !(typeof options.fin != 'undefined' && !options.fin) + , buffer = new Buffer((writeStartMarker ? ((options && options.binary) ? (1 + lengthbytes) : 1) : 0) + length + ((writeEndMarker && !(options && options.binary)) ? 1 : 0)) + , offset = writeStartMarker ? 1 : 0; + + if (writeStartMarker) { + if (options && options.binary) { + buffer.write('\x80', 'binary'); + // assume length less than 2**14 bytes + if (lengthbytes > 1) + buffer.write(String.fromCharCode(128+length/128), offset++, 'binary'); + buffer.write(String.fromCharCode(length&0x7f), offset++, 'binary'); + } else + buffer.write('\x00', 'binary'); + } + + if (isString) buffer.write(data, offset, 'utf8'); + else data.copy(buffer, offset, 0); + + if (writeEndMarker) { + if (options && options.binary) { + // sending binary, not writing end marker + } else + buffer.write('\xff', offset + length, 'binary'); + this.continuationFrame = false; + } + else this.continuationFrame = true; + + try { + this.socket.write(buffer, 'binary', cb); + } catch (e) { + this.error(e.toString()); + } +} + +/** + * Sends a close instruction to the remote party. + * + * @api public + */ + +Sender.prototype.close = function(code, data, mask, cb) { + if (this.isClosed) return; + this.isClosed = true; + try { + if (this.continuationFrame) this.socket.write(new Buffer([0xff], 'binary')); + this.socket.write(new Buffer([0xff, 0x00]), 'binary', cb); + } catch (e) { + this.error(e.toString()); + } +} + +/** + * Sends a ping message to the remote party. Not available for hixie. + * + * @api public + */ + +Sender.prototype.ping = function(data, options) {} + +/** + * Sends a pong message to the remote party. Not available for hixie. + * + * @api public + */ + +Sender.prototype.pong = function(data, options) {} + +/** + * Handles an error + * + * @api private + */ + +Sender.prototype.error = function (reason) { + this.emit('error', reason); + return this; +} diff --git a/node_modules/ws/lib/Sender.js b/node_modules/ws/lib/Sender.js new file mode 100644 index 0000000..db109be --- /dev/null +++ b/node_modules/ws/lib/Sender.js @@ -0,0 +1,226 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var events = require('events') + , util = require('util') + , EventEmitter = events.EventEmitter + , ErrorCodes = require('./ErrorCodes') + , bufferUtil = require('./BufferUtil').BufferUtil; + +/** + * HyBi Sender implementation + */ + +function Sender(socket) { + this._socket = socket; + this.firstFragment = true; +} + +/** + * Inherits from EventEmitter. + */ + +util.inherits(Sender, events.EventEmitter); + +/** + * Sends a close instruction to the remote party. + * + * @api public + */ + +Sender.prototype.close = function(code, data, mask) { + if (typeof code !== 'undefined') { + if (typeof code !== 'number' || + !ErrorCodes.isValidErrorCode(code)) throw new Error('first argument must be a valid error code number'); + } + code = code || 1000; + var dataBuffer = new Buffer(2 + (data ? Buffer.byteLength(data) : 0)); + writeUInt16BE.call(dataBuffer, code, 0); + if (dataBuffer.length > 2) dataBuffer.write(data, 2); + this.frameAndSend(0x8, dataBuffer, true, mask); +} + +/** + * Sends a ping message to the remote party. + * + * @api public + */ + +Sender.prototype.ping = function(data, options) { + var mask = options && options.mask; + this.frameAndSend(0x9, data || '', true, mask); +} + +/** + * Sends a pong message to the remote party. + * + * @api public + */ + +Sender.prototype.pong = function(data, options) { + var mask = options && options.mask; + this.frameAndSend(0xa, data || '', true, mask); +} + +/** + * Sends text or binary data to the remote party. + * + * @api public + */ + +Sender.prototype.send = function(data, options, cb) { + var finalFragment = options && options.fin === false ? false : true; + var mask = options && options.mask; + var opcode = options && options.binary ? 2 : 1; + if (this.firstFragment === false) opcode = 0; + else this.firstFragment = false; + if (finalFragment) this.firstFragment = true + this.frameAndSend(opcode, data, finalFragment, mask, cb); +} + +/** + * Frames and sends a piece of data according to the HyBi WebSocket protocol. + * + * @api private + */ + +Sender.prototype.frameAndSend = function(opcode, data, finalFragment, maskData, cb) { + var canModifyData = false; + + if (!data) { + try { + this._socket.write(new Buffer([opcode | (finalFragment ? 0x80 : 0), 0 | (maskData ? 0x80 : 0)].concat(maskData ? [0, 0, 0, 0] : [])), 'binary', cb); + } + catch (e) { + if (typeof cb == 'function') cb(e); + else this.emit('error', e); + } + return; + } + + if (!Buffer.isBuffer(data)) { + canModifyData = true; + if (data && (typeof data.byteLength !== 'undefined' || typeof data.buffer !== 'undefined')) { + data = getArrayBuffer(data); + } else { + data = new Buffer(data); + } + } + + var dataLength = data.length + , dataOffset = maskData ? 6 : 2 + , secondByte = dataLength; + + if (dataLength >= 65536) { + dataOffset += 8; + secondByte = 127; + } + else if (dataLength > 125) { + dataOffset += 2; + secondByte = 126; + } + + var mergeBuffers = dataLength < 32768 || (maskData && !canModifyData); + var totalLength = mergeBuffers ? dataLength + dataOffset : dataOffset; + var outputBuffer = new Buffer(totalLength); + outputBuffer[0] = finalFragment ? opcode | 0x80 : opcode; + + switch (secondByte) { + case 126: + writeUInt16BE.call(outputBuffer, dataLength, 2); + break; + case 127: + writeUInt32BE.call(outputBuffer, 0, 2); + writeUInt32BE.call(outputBuffer, dataLength, 6); + } + + if (maskData) { + outputBuffer[1] = secondByte | 0x80; + var mask = this._randomMask || (this._randomMask = getRandomMask()); + outputBuffer[dataOffset - 4] = mask[0]; + outputBuffer[dataOffset - 3] = mask[1]; + outputBuffer[dataOffset - 2] = mask[2]; + outputBuffer[dataOffset - 1] = mask[3]; + if (mergeBuffers) { + bufferUtil.mask(data, mask, outputBuffer, dataOffset, dataLength); + try { + this._socket.write(outputBuffer, 'binary', cb); + } + catch (e) { + if (typeof cb == 'function') cb(e); + else this.emit('error', e); + } + } + else { + bufferUtil.mask(data, mask, data, 0, dataLength); + try { + this._socket.write(outputBuffer, 'binary'); + this._socket.write(data, 'binary', cb); + } + catch (e) { + if (typeof cb == 'function') cb(e); + else this.emit('error', e); + } + } + } + else { + outputBuffer[1] = secondByte; + if (mergeBuffers) { + data.copy(outputBuffer, dataOffset); + try { + this._socket.write(outputBuffer, 'binary', cb); + } + catch (e) { + if (typeof cb == 'function') cb(e); + else this.emit('error', e); + } + } + else { + try { + this._socket.write(outputBuffer, 'binary'); + this._socket.write(data, 'binary', cb); + } + catch (e) { + if (typeof cb == 'function') cb(e); + else this.emit('error', e); + } + } + } +} + +module.exports = Sender; + +function writeUInt16BE(value, offset) { + this[offset] = (value & 0xff00)>>8; + this[offset+1] = value & 0xff; +} + +function writeUInt32BE(value, offset) { + this[offset] = (value & 0xff000000)>>24; + this[offset+1] = (value & 0xff0000)>>16; + this[offset+2] = (value & 0xff00)>>8; + this[offset+3] = value & 0xff; +} + +function getArrayBuffer(data) { + // data is either an ArrayBuffer or ArrayBufferView. + var array = data.buffer || data + , l = data.byteLength || data.length + , buffer = new Buffer(l); + for (var i = 0; i < l; ++i) { + buffer[i] = array[i]; + } + return buffer; +} + +function getRandomMask() { + return new Buffer([ + ~~(Math.random() * 255), + ~~(Math.random() * 255), + ~~(Math.random() * 255), + ~~(Math.random() * 255) + ]); +} diff --git a/node_modules/ws/lib/Validation.fallback.js b/node_modules/ws/lib/Validation.fallback.js new file mode 100644 index 0000000..2c7c4fd --- /dev/null +++ b/node_modules/ws/lib/Validation.fallback.js @@ -0,0 +1,12 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +module.exports.Validation = { + isValidUTF8: function(buffer) { + return true; + } +}; + diff --git a/node_modules/ws/lib/Validation.js b/node_modules/ws/lib/Validation.js new file mode 100644 index 0000000..0f3109a --- /dev/null +++ b/node_modules/ws/lib/Validation.js @@ -0,0 +1,16 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +try { + module.exports = require('../build/Release/validation'); +} catch (e) { try { + module.exports = require('../build/default/validation'); +} catch (e) { try { + module.exports = require('./Validation.fallback'); +} catch (e) { + console.error('validation.node seems to not have been built. Run npm install.'); + throw e; +}}} diff --git a/node_modules/ws/lib/WebSocket.js b/node_modules/ws/lib/WebSocket.js new file mode 100644 index 0000000..5f40658 --- /dev/null +++ b/node_modules/ws/lib/WebSocket.js @@ -0,0 +1,766 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var util = require('util') + , events = require('events') + , http = require('http') + , https = require('https') + , crypto = require('crypto') + , url = require('url') + , fs = require('fs') + , Options = require('options') + , Sender = require('./Sender') + , Receiver = require('./Receiver') + , SenderHixie = require('./Sender.hixie') + , ReceiverHixie = require('./Receiver.hixie'); + +/** + * Constants + */ + +// Default protocol version + +var protocolVersion = 13; + +// Close timeout + +var closeTimeout = 30000; // Allow 5 seconds to terminate the connection cleanly + +/** + * Node version 0.4 and 0.6 compatibility + */ + +var isNodeV4 = /^v0\.4/.test(process.version); + +/** + * WebSocket implementation + */ + +function WebSocket(address, options) { + var self = this; + + this._socket = null; + this.bytesReceived = 0; + this.readyState = null; + this.supports = {}; + + if (Object.prototype.toString.call(address) == '[object Array]') { + initAsServerClient.apply(this, address.concat(options)); + } + else initAsClient.apply(this, arguments); +} + +/** + * Inherits from EventEmitter. + */ + +util.inherits(WebSocket, events.EventEmitter); + +/** + * Ready States + */ + +["CONNECTING", "OPEN", "CLOSING", "CLOSED"].forEach(function (state, index) { + WebSocket.prototype[state] = WebSocket[state] = index; +}); + +/** + * Gracefully closes the connection, after sending a description message to the server + * + * @param {Object} data to be sent to the server + * @api public + */ + +WebSocket.prototype.close = function(code, data) { + if (this.readyState == WebSocket.CLOSING || this.readyState == WebSocket.CLOSED) return; + if (this.readyState == WebSocket.CONNECTING) { + this.readyState = WebSocket.CLOSED; + return; + } + try { + this.readyState = WebSocket.CLOSING; + this._closeCode = code; + this._closeMessage = data; + var mask = !this._isServer; + this._sender.close(code, data, mask); + } + catch (e) { + this.emit('error', e); + } + finally { + this.terminate(); + } +} + +/** + * Pause the client stream + * + * @api public + */ + +WebSocket.prototype.pause = function() { + if (this.readyState != WebSocket.OPEN) throw new Error('not opened'); + return this._socket.pause(); +} + +/** + * Sends a ping + * + * @param {Object} data to be sent to the server + * @param {Object} Members - mask: boolean, binary: boolean + * @param {boolean} dontFailWhenClosed indicates whether or not to throw if the connection isnt open + * @api public + */ + +WebSocket.prototype.ping = function(data, options, dontFailWhenClosed) { + if (this.readyState != WebSocket.OPEN) { + if (dontFailWhenClosed === true) return; + throw new Error('not opened'); + } + options = options || {}; + if (typeof options.mask == 'undefined') options.mask = !this._isServer; + this._sender.ping(data, options); +} + +/** + * Sends a pong + * + * @param {Object} data to be sent to the server + * @param {Object} Members - mask: boolean, binary: boolean + * @param {boolean} dontFailWhenClosed indicates whether or not to throw if the connection isnt open + * @api public + */ + +WebSocket.prototype.pong = function(data, options, dontFailWhenClosed) { + if (this.readyState != WebSocket.OPEN) { + if (dontFailWhenClosed === true) return; + throw new Error('not opened'); + } + options = options || {}; + if (typeof options.mask == 'undefined') options.mask = !this._isServer; + this._sender.pong(data, options); +} + +/** + * Resume the client stream + * + * @api public + */ + +WebSocket.prototype.resume = function() { + if (this.readyState != WebSocket.OPEN) throw new Error('not opened'); + return this._socket.resume(); +} + +/** + * Sends a piece of data + * + * @param {Object} data to be sent to the server + * @param {Object} Members - mask: boolean, binary: boolean + * @param {function} Optional callback which is executed after the send completes + * @api public + */ + +WebSocket.prototype.send = function(data, options, cb) { + if (typeof options == 'function') { + cb = options; + options = {}; + } + if (this.readyState != WebSocket.OPEN) { + if (typeof cb == 'function') cb(new Error('not opened')); + else throw new Error('not opened'); + return; + } + if (!data) data = ''; + if (this._queue) { + var self = this; + this._queue.push(function() { self.send(data, options, cb); }); + return; + } + options = options || {}; + options.fin = true; + if (typeof options.binary == 'undefined') { + options.binary = (data instanceof ArrayBuffer || data instanceof Buffer); + } + if (typeof options.mask == 'undefined') options.mask = !this._isServer; + if (data instanceof fs.ReadStream) { + startQueue(this); + var self = this; + sendStream(this, data, options, function(error) { + process.nextTick(function() { executeQueueSends(self); }); + if (typeof cb == 'function') cb(error); + }); + } + else this._sender.send(data, options, cb); +} + +/** + * Streams data through calls to a user supplied function + * + * @param {Object} Members - mask: boolean, binary: boolean + * @param {function} 'function (error, send)' which is executed on successive ticks of which send is 'function (data, final)'. + * @api public + */ + +WebSocket.prototype.stream = function(options, cb) { + if (typeof options == 'function') { + cb = options; + options = {}; + } + if (typeof cb != 'function') throw new Error('callback must be provided'); + if (this.readyState != WebSocket.OPEN) { + if (typeof cb == 'function') cb(new Error('not opened')); + else throw new Error('not opened'); + return; + } + if (this._queue) { + var self = this; + this._queue.push(function() { self.stream(options, cb); }); + return; + } + options = options || {}; + if (typeof options.mask == 'undefined') options.mask = !this._isServer; + startQueue(this); + var self = this; + var send = function(data, final) { + try { + if (self.readyState != WebSocket.OPEN) throw new Error('not opened'); + options.fin = final === true; + self._sender.send(data, options); + if (!final) process.nextTick(cb.bind(null, null, send)); + else executeQueueSends(self); + } + catch (e) { + if (typeof cb == 'function') cb(e); + else { + delete self._queue; + self.emit('error', e); + } + } + } + process.nextTick(cb.bind(null, null, send)); +} + +/** + * Immediately shuts down the connection + * + * @api public + */ + +WebSocket.prototype.terminate = function() { + if (this.readyState == WebSocket.CLOSED) return; + if (this._socket) { + try { + // End the connection + this._socket.end(); + } + catch (e) { + // Socket error during end() call, so just destroy it right now + cleanupWebsocketResources.call(this, true); + return; + } + + // Add a timeout to ensure that the connection is completely + // cleaned up within 30 seconds, even if the clean close procedure + // fails for whatever reason + this._closeTimer = setTimeout(cleanupWebsocketResources.bind(this, true), closeTimeout); + } + else if (this.readyState == WebSocket.CONNECTING) { + cleanupWebsocketResources.call(this, true); + } +}; + +/** + * Expose bufferedAmount + * + * @api public + */ + +Object.defineProperty(WebSocket.prototype, 'bufferedAmount', { + get: function get() { + return this._socket ? this._socket.bufferSize : 0; + } +}); + +/** + * Emulates the W3C Browser based WebSocket interface using function members. + * + * @see http://dev.w3.org/html5/websockets/#the-websocket-interface + * @api public + */ + +['open', 'error', 'close', 'message'].forEach(function(method) { + Object.defineProperty(WebSocket.prototype, 'on' + method, { + /** + * Returns the current listener + * + * @returns {Mixed} the set function or undefined + * @api public + */ + + get: function get() { + var listener = this.listeners(method)[0]; + return listener ? (listener._listener ? listener._listener : listener) : undefined; + }, + + /** + * Start listening for events + * + * @param {Function} listener the listener + * @returns {Mixed} the set function or undefined + * @api public + */ + + set: function set(listener) { + this.removeAllListeners(method); + this.addEventListener(method, listener); + } + }); +}); + +/** + * Emulates the W3C Browser based WebSocket interface using addEventListener. + * + * @see https://developer.mozilla.org/en/DOM/element.addEventListener + * @see http://dev.w3.org/html5/websockets/#the-websocket-interface + * @api public + */ +WebSocket.prototype.addEventListener = function(method, listener) { + var target = this; + if (typeof listener === 'function') { + if (method === 'message') { + function onMessage (data, flags) { + listener.call(this, new MessageEvent(data, flags.binary ? 'Binary' : 'Text', target)); + } + // store a reference so we can return the original function from the addEventListener hook + onMessage._listener = listener; + this.on(method, onMessage); + } else if (method === 'close') { + function onClose (code, message) { + listener.call(this, new CloseEvent(code, message, target)); + } + // store a reference so we can return the original function from the addEventListener hook + onClose._listener = listener; + this.on(method, onClose); + } else if (method === 'error') { + function onError (event) { + event.target = target; + listener.call(this, event); + } + // store a reference so we can return the original function from the addEventListener hook + onError._listener = listener; + this.on(method, onError); + } else if (method === 'open') { + function onOpen () { + listener.call(this, new OpenEvent(target)); + } + // store a reference so we can return the original function from the addEventListener hook + onOpen._listener = listener; + this.on(method, onOpen); + } else { + this.on(method, listener); + } + } +} + +module.exports = WebSocket; + +/** + * W3C MessageEvent + * + * @see http://www.w3.org/TR/html5/comms.html + * @api private + */ + +function MessageEvent(dataArg, typeArg, target) { + this.data = dataArg; + this.type = typeArg; + this.target = target; +} + +/** + * W3C CloseEvent + * + * @see http://www.w3.org/TR/html5/comms.html + * @api private + */ + +function CloseEvent(code, reason, target) { + this.wasClean = (typeof code == 'undefined' || code == 1000); + this.code = code; + this.reason = reason; + this.target = target; +} + +/** + * W3C OpenEvent + * + * @see http://www.w3.org/TR/html5/comms.html + * @api private + */ + +function OpenEvent(target) { + this.target = target; +} + +/** + * Entirely private apis, + * which may or may not be bound to a sepcific WebSocket instance. + */ + +function initAsServerClient(req, socket, upgradeHead, options) { + options = new Options({ + protocolVersion: protocolVersion, + protocol: null + }).merge(options); + + // expose state properties + this.protocol = options.value.protocol; + this.protocolVersion = options.value.protocolVersion; + this.supports.binary = (this.protocolVersion != 'hixie-76'); + this.upgradeReq = req; + this.readyState = WebSocket.CONNECTING; + this._isServer = true; + + // establish connection + if (options.value.protocolVersion == 'hixie-76') establishConnection.call(this, ReceiverHixie, SenderHixie, socket, upgradeHead); + else establishConnection.call(this, Receiver, Sender, socket, upgradeHead); +} + +function initAsClient(address, options) { + options = new Options({ + origin: null, + protocolVersion: protocolVersion, + host: null, + protocol: null, + + // ssl-related options + pfx: null, + key: null, + passphrase: null, + cert: null, + ca: null, + ciphers: null, + rejectUnauthorized: null + }).merge(options); + if (options.value.protocolVersion != 8 && options.value.protocolVersion != 13) { + throw new Error('unsupported protocol version'); + } + + // verify url and establish http class + var serverUrl = url.parse(address); + var isUnixSocket = serverUrl.protocol === 'ws+unix:'; + if (!serverUrl.host && !isUnixSocket) throw new Error('invalid url'); + var isSecure = serverUrl.protocol === 'wss:' || serverUrl.protocol === 'https:'; + var httpObj = isSecure ? https : http; + var port = serverUrl.port || (isSecure ? 443 : 80); + + // expose state properties + this._isServer = false; + this.url = address; + this.protocolVersion = options.value.protocolVersion; + this.supports.binary = (this.protocolVersion != 'hixie-76'); + + // begin handshake + var key = new Buffer(options.value.protocolVersion + '-' + Date.now()).toString('base64'); + var shasum = crypto.createHash('sha1'); + shasum.update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'); + var expectedServerKey = shasum.digest('base64'); + + // node<=v0.4.x compatibility + var agent; + if (isNodeV4) { + isNodeV4 = true; + agent = new httpObj.Agent({ + host: serverUrl.hostname, + port: port + }); + } + + var headerHost = serverUrl.hostname + ':' + port; + var requestOptions = { + port: port, + host: serverUrl.hostname, + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Host': headerHost, + 'Origin': headerHost, + 'Sec-WebSocket-Version': options.value.protocolVersion, + 'Sec-WebSocket-Key': key + } + }; + if (options.value.protocol) { + requestOptions.headers['Sec-WebSocket-Protocol'] = options.value.protocol; + } + if (options.value.host) { + requestOptions.headers['Host'] = options.value.host; + } + + if (options.isDefinedAndNonNull('pfx') + || options.isDefinedAndNonNull('key') + || options.isDefinedAndNonNull('passphrase') + || options.isDefinedAndNonNull('cert') + || options.isDefinedAndNonNull('ca') + || options.isDefinedAndNonNull('ciphers') + || options.isDefinedAndNonNull('rejectUnauthorized')) { + + if (isNodeV4) { + throw new Error('Client side certificates are not supported on Node 0.4.x'); + } + + if (options.isDefinedAndNonNull('pfx')) requestOptions.pfx = options.value.pfx; + if (options.isDefinedAndNonNull('key')) requestOptions.key = options.value.key; + if (options.isDefinedAndNonNull('passphrase')) requestOptions.passphrase = options.value.passphrase; + if (options.isDefinedAndNonNull('cert')) requestOptions.cert = options.value.cert; + if (options.isDefinedAndNonNull('ca')) requestOptions.ca = options.value.ca; + if (options.isDefinedAndNonNull('ciphers')) requestOptions.ciphers = options.value.ciphers; + if (options.isDefinedAndNonNull('rejectUnauthorized')) requestOptions.rejectUnauthorized = options.value.rejectUnauthorized; + + // global agent ignores client side certificates + agent = new httpObj.Agent(requestOptions); + } + + if (isNodeV4) { + requestOptions.path = (serverUrl.pathname || '/') + (serverUrl.search || ''); + } + else requestOptions.path = serverUrl.path || '/'; + + if (agent) { + requestOptions.agent = agent; + } + + if (isUnixSocket) { + requestOptions.socketPath = serverUrl.pathname; + } + if (options.value.origin) { + if (options.value.protocolVersion < 13) requestOptions.headers['Sec-WebSocket-Origin'] = options.value.origin; + else requestOptions.headers['Origin'] = options.value.origin; + } + + var self = this; + var req = httpObj.request(requestOptions); + + (isNodeV4 ? agent : req).on('error', function(error) { + self.emit('error', error); + cleanupWebsocketResources.call(this, error); + }); + (isNodeV4 ? agent : req).once('response', function(res) { + var error = new Error('unexpected server response (' + res.statusCode + ')'); + self.emit('error', error); + cleanupWebsocketResources.call(this, error); + }); + (isNodeV4 ? agent : req).once('upgrade', function(res, socket, upgradeHead) { + if (self.readyState == WebSocket.CLOSED) { + // client closed before server accepted connection + self.emit('close'); + removeAllListeners(self); + socket.end(); + return; + } + var serverKey = res.headers['sec-websocket-accept']; + if (typeof serverKey == 'undefined' || serverKey !== expectedServerKey) { + self.emit('error', 'invalid server key'); + removeAllListeners(self); + socket.end(); + return; + } + + var serverProt = res.headers['sec-websocket-protocol']; + var protList = (options.value.protocol || "").split(/, */); + var protError = null; + if (!options.value.protocol && serverProt) { + protError = 'server sent a subprotocol even though none requested'; + } else if (options.value.protocol && !serverProt) { + protError = 'server sent no subprotocol even though requested'; + } else if (serverProt && protList.indexOf(serverProt) === -1) { + protError = 'server responded with an invalid protocol'; + } + if (protError) { + self.emit('error', protError); + removeAllListeners(self); + socket.end(); + return; + } else if (serverProt) { + self.protocol = serverProt; + } + + establishConnection.call(self, Receiver, Sender, socket, upgradeHead); + + // perform cleanup on http resources + removeAllListeners(isNodeV4 ? agent : req); + req = null; + agent = null; + }); + + req.end(); + this.readyState = WebSocket.CONNECTING; +} + +function establishConnection(ReceiverClass, SenderClass, socket, upgradeHead) { + this._socket = socket; + socket.setTimeout(0); + socket.setNoDelay(true); + var self = this; + this._receiver = new ReceiverClass(); + + // socket cleanup handlers + socket.on('end', cleanupWebsocketResources.bind(this)); + socket.on('close', cleanupWebsocketResources.bind(this)); + socket.on('error', cleanupWebsocketResources.bind(this)); + + // ensure that the upgradeHead is added to the receiver + function firstHandler(data) { + if (self.readyState != WebSocket.OPEN) return; + if (upgradeHead && upgradeHead.length > 0) { + self.bytesReceived += upgradeHead.length; + var head = upgradeHead; + upgradeHead = null; + self._receiver.add(head); + } + dataHandler = realHandler; + if (data) { + self.bytesReceived += data.length; + self._receiver.add(data); + } + } + // subsequent packets are pushed straight to the receiver + function realHandler(data) { + if (data) self.bytesReceived += data.length; + self._receiver.add(data); + } + var dataHandler = firstHandler; + socket.on('data', dataHandler); + // if data was passed along with the http upgrade, + // this will schedule a push of that on to the receiver. + // this has to be done on next tick, since the caller + // hasn't had a chance to set event handlers on this client + // object yet. + process.nextTick(firstHandler); + + // receiver event handlers + self._receiver.ontext = function (data, flags) { + flags = flags || {}; + self.emit('message', data, flags); + }; + self._receiver.onbinary = function (data, flags) { + flags = flags || {}; + flags.binary = true; + self.emit('message', data, flags); + }; + self._receiver.onping = function(data, flags) { + flags = flags || {}; + self.pong(data, {mask: !self._isServer, binary: flags.binary === true}, true); + self.emit('ping', data, flags); + }; + self._receiver.onpong = function(data, flags) { + self.emit('pong', data, flags); + }; + self._receiver.onclose = function(code, data, flags) { + flags = flags || {}; + self.close(code, data); + }; + self._receiver.onerror = function(reason, errorCode) { + // close the connection when the receiver reports a HyBi error code + self.close(typeof errorCode != 'undefined' ? errorCode : 1002, ''); + self.emit('error', reason, errorCode); + }; + + // finalize the client + this._sender = new SenderClass(socket); + this._sender.on('error', function(error) { + self.close(1002, ''); + self.emit('error', error); + }); + this.readyState = WebSocket.OPEN; + this.emit('open'); +} + +function startQueue(instance) { + instance._queue = instance._queue || []; +} + +function executeQueueSends(instance) { + var queue = instance._queue; + if (typeof queue == 'undefined') return; + delete instance._queue; + for (var i = 0, l = queue.length; i < l; ++i) { + queue[i](); + } +} + +function sendStream(instance, stream, options, cb) { + stream.on('data', function(data) { + if (instance.readyState != WebSocket.OPEN) { + if (typeof cb == 'function') cb(new Error('not opened')); + else { + delete instance._queue; + instance.emit('error', new Error('not opened')); + } + return; + } + options.fin = false; + instance._sender.send(data, options); + }); + stream.on('end', function() { + if (instance.readyState != WebSocket.OPEN) { + if (typeof cb == 'function') cb(new Error('not opened')); + else { + delete instance._queue; + instance.emit('error', new Error('not opened')); + } + return; + } + options.fin = true; + instance._sender.send(null, options); + if (typeof cb == 'function') cb(null); + }); +} + +function cleanupWebsocketResources(error) { + if (this.readyState == WebSocket.CLOSED) return; + var emitClose = this.readyState != WebSocket.CONNECTING; + this.readyState = WebSocket.CLOSED; + + clearTimeout(this._closeTimer); + this._closeTimer = null; + if (emitClose) this.emit('close', this._closeCode || 1000, this._closeMessage || ''); + + if (this._socket) { + removeAllListeners(this._socket); + // catch all socket error after removing all standard handlers + var socket = this._socket; + this._socket.on('error', function() { + try { socket.destroy(); } catch (e) {} + }); + try { + if (!error) this._socket.end(); + else this._socket.destroy(); + } + catch (e) { /* Ignore termination errors */ } + this._socket = null; + } + if (this._sender) { + removeAllListeners(this._sender); + this._sender = null; + } + if (this._receiver) { + this._receiver.cleanup(); + this._receiver = null; + } + removeAllListeners(this); + this.on('error', function() {}); // catch all errors after this + delete this._queue; +} + +function removeAllListeners(instance) { + if (isNodeV4) { + // node v4 doesn't *actually* remove all listeners globally, + // so we do that instead + instance._events = {}; + } + else instance.removeAllListeners(); +} diff --git a/node_modules/ws/lib/WebSocketServer.js b/node_modules/ws/lib/WebSocketServer.js new file mode 100644 index 0000000..ee47f10 --- /dev/null +++ b/node_modules/ws/lib/WebSocketServer.js @@ -0,0 +1,460 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var util = require('util') + , events = require('events') + , http = require('http') + , crypto = require('crypto') + , url = require('url') + , Options = require('options') + , WebSocket = require('./WebSocket') + , tls = require('tls') + , url = require('url'); + +/** + * WebSocket Server implementation + */ + +function WebSocketServer(options, callback) { + options = new Options({ + host: '0.0.0.0', + port: null, + server: null, + verifyClient: null, + handleProtocols: null, + path: null, + noServer: false, + disableHixie: false, + clientTracking: true + }).merge(options); + + if (!options.isDefinedAndNonNull('port') && !options.isDefinedAndNonNull('server') && !options.value.noServer) { + throw new TypeError('`port` or a `server` must be provided'); + } + + var self = this; + + if (options.isDefinedAndNonNull('port')) { + this._server = http.createServer(function (req, res) { + res.writeHead(200, {'Content-Type': 'text/plain'}); + res.end('Not implemented'); + }); + this._server.listen(options.value.port, options.value.host, callback); + this._closeServer = function() { self._server.close(); }; + } + else if (options.value.server) { + this._server = options.value.server; + if (options.value.path) { + // take note of the path, to avoid collisions when multiple websocket servers are + // listening on the same http server + if (this._server._webSocketPaths && options.value.server._webSocketPaths[options.value.path]) { + throw new Error('two instances of WebSocketServer cannot listen on the same http server path'); + } + if (typeof this._server._webSocketPaths !== 'object') { + this._server._webSocketPaths = {}; + } + this._server._webSocketPaths[options.value.path] = 1; + } + } + if (this._server) this._server.once('listening', function() { self.emit('listening'); }); + + if (typeof this._server != 'undefined') { + this._server.on('error', function(error) { + self.emit('error', error) + }); + this._server.on('upgrade', function(req, socket, upgradeHead) { + //copy upgradeHead to avoid retention of large slab buffers used in node core + var head = new Buffer(upgradeHead.length); + upgradeHead.copy(head); + + self.handleUpgrade(req, socket, head, function(client) { + self.emit('connection'+req.url, client); + self.emit('connection', client); + }); + }); + } + + this.options = options.value; + this.path = options.value.path; + this.clients = []; +} + +/** + * Inherits from EventEmitter. + */ + +util.inherits(WebSocketServer, events.EventEmitter); + +/** + * Immediately shuts down the connection. + * + * @api public + */ + +WebSocketServer.prototype.close = function() { + // terminate all associated clients + var error = null; + try { + for (var i = 0, l = this.clients.length; i < l; ++i) { + this.clients[i].terminate(); + } + } + catch (e) { + error = e; + } + + // remove path descriptor, if any + if (this.path && this._server._webSocketPaths) { + delete this._server._webSocketPaths[this.path]; + if (Object.keys(this._server._webSocketPaths).length == 0) { + delete this._server._webSocketPaths; + } + } + + // close the http server if it was internally created + try { + if (typeof this._closeServer !== 'undefined') { + this._closeServer(); + } + } + finally { + delete this._server; + } + if (error) throw error; +} + +/** + * Handle a HTTP Upgrade request. + * + * @api public + */ + +WebSocketServer.prototype.handleUpgrade = function(req, socket, upgradeHead, cb) { + // check for wrong path + if (this.options.path) { + var u = url.parse(req.url); + if (u && u.pathname !== this.options.path) return; + } + + if (typeof req.headers.upgrade === 'undefined' || req.headers.upgrade.toLowerCase() !== 'websocket') { + abortConnection(socket, 400, 'Bad Request'); + return; + } + + if (req.headers['sec-websocket-key1']) handleHixieUpgrade.apply(this, arguments); + else handleHybiUpgrade.apply(this, arguments); +} + +module.exports = WebSocketServer; + +/** + * Entirely private apis, + * which may or may not be bound to a sepcific WebSocket instance. + */ + +function handleHybiUpgrade(req, socket, upgradeHead, cb) { + // handle premature socket errors + var errorHandler = function() { + try { socket.destroy(); } catch (e) {} + } + socket.on('error', errorHandler); + + // verify key presence + if (!req.headers['sec-websocket-key']) { + abortConnection(socket, 400, 'Bad Request'); + return; + } + + // verify version + var version = parseInt(req.headers['sec-websocket-version']); + if ([8, 13].indexOf(version) === -1) { + abortConnection(socket, 400, 'Bad Request'); + return; + } + + // verify protocol + var protocols = req.headers['sec-websocket-protocol']; + + // verify client + var origin = version < 13 ? + req.headers['sec-websocket-origin'] : + req.headers['origin']; + + // handler to call when the connection sequence completes + var self = this; + var completeHybiUpgrade2 = function(protocol) { + + // calc key + var key = req.headers['sec-websocket-key']; + var shasum = crypto.createHash('sha1'); + shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); + key = shasum.digest('base64'); + + var headers = [ + 'HTTP/1.1 101 Switching Protocols' + , 'Upgrade: websocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Accept: ' + key + ]; + + if (typeof protocol != 'undefined') { + headers.push('Sec-WebSocket-Protocol: ' + protocol); + } + + // allows external modification/inspection of handshake headers + self.emit('headers', headers); + + socket.setTimeout(0); + socket.setNoDelay(true); + try { + socket.write(headers.concat('', '').join('\r\n')); + } + catch (e) { + // if the upgrade write fails, shut the connection down hard + try { socket.destroy(); } catch (e) {} + return; + } + + var client = new WebSocket([req, socket, upgradeHead], { + protocolVersion: version, + protocol: protocol + }); + + if (self.options.clientTracking) { + self.clients.push(client); + client.on('close', function() { + var index = self.clients.indexOf(client); + if (index != -1) { + self.clients.splice(index, 1); + } + }); + } + + // signal upgrade complete + socket.removeListener('error', errorHandler); + cb(client); + } + + // optionally call external protocol selection handler before + // calling completeHybiUpgrade2 + var completeHybiUpgrade1 = function() { + // choose from the sub-protocols + if (typeof self.options.handleProtocols == 'function') { + var protList = (protocols || "").split(/, */); + var callbackCalled = false; + var res = self.options.handleProtocols(protList, function(result, protocol) { + callbackCalled = true; + if (!result) abortConnection(socket, 404, 'Unauthorized') + else completeHybiUpgrade2(protocol); + }); + if (!callbackCalled) { + // the handleProtocols handler never called our callback + abortConnection(socket, 501, 'Could not process protocols'); + } + return; + } else { + if (typeof protocols !== 'undefined') { + completeHybiUpgrade2(protocols.split(/, */)[0]); + } + else { + completeHybiUpgrade2(); + } + } + } + + // optionally call external client verification handler + if (typeof this.options.verifyClient == 'function') { + var info = { + origin: origin, + secure: typeof req.connection.encrypted !== 'undefined', + req: req + }; + if (this.options.verifyClient.length == 2) { + this.options.verifyClient(info, function(result) { + if (!result) abortConnection(socket, 401, 'Unauthorized') + else completeHybiUpgrade1(); + }); + return; + } + else if (!this.options.verifyClient(info)) { + abortConnection(socket, 401, 'Unauthorized'); + return; + } + } + + completeHybiUpgrade1(); +} + +function handleHixieUpgrade(req, socket, upgradeHead, cb) { + // handle premature socket errors + var errorHandler = function() { + try { socket.destroy(); } catch (e) {} + } + socket.on('error', errorHandler); + + // bail if options prevent hixie + if (this.options.disableHixie) { + abortConnection(socket, 401, 'Hixie support disabled'); + return; + } + + // verify key presence + if (!req.headers['sec-websocket-key2']) { + abortConnection(socket, 400, 'Bad Request'); + return; + } + + var origin = req.headers['origin'] + , self = this; + + // setup handshake completion to run after client has been verified + var onClientVerified = function() { + var wshost; + if (!req.headers['x-forwarded-host']) + wshost = req.headers.host; + else + wshost = req.headers['x-forwarded-host']; + var location = ((req.headers['x-forwarded-proto'] === 'https' || socket.encrypted) ? 'wss' : 'ws') + '://' + wshost + req.url + , protocol = req.headers['sec-websocket-protocol']; + + // handshake completion code to run once nonce has been successfully retrieved + var completeHandshake = function(nonce, rest) { + // calculate key + var k1 = req.headers['sec-websocket-key1'] + , k2 = req.headers['sec-websocket-key2'] + , md5 = crypto.createHash('md5'); + + [k1, k2].forEach(function (k) { + var n = parseInt(k.replace(/[^\d]/g, '')) + , spaces = k.replace(/[^ ]/g, '').length; + if (spaces === 0 || n % spaces !== 0){ + abortConnection(socket, 400, 'Bad Request'); + return; + } + n /= spaces; + md5.update(String.fromCharCode( + n >> 24 & 0xFF, + n >> 16 & 0xFF, + n >> 8 & 0xFF, + n & 0xFF)); + }); + md5.update(nonce.toString('binary')); + + var headers = [ + 'HTTP/1.1 101 Switching Protocols' + , 'Upgrade: WebSocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Location: ' + location + ]; + if (typeof protocol != 'undefined') headers.push('Sec-WebSocket-Protocol: ' + protocol); + if (typeof origin != 'undefined') headers.push('Sec-WebSocket-Origin: ' + origin); + + socket.setTimeout(0); + socket.setNoDelay(true); + try { + // merge header and hash buffer + var headerBuffer = new Buffer(headers.concat('', '').join('\r\n')); + var hashBuffer = new Buffer(md5.digest('binary'), 'binary'); + var handshakeBuffer = new Buffer(headerBuffer.length + hashBuffer.length); + headerBuffer.copy(handshakeBuffer, 0); + hashBuffer.copy(handshakeBuffer, headerBuffer.length); + + // do a single write, which - upon success - causes a new client websocket to be setup + socket.write(handshakeBuffer, 'binary', function(err) { + if (err) return; // do not create client if an error happens + var client = new WebSocket([req, socket, rest], { + protocolVersion: 'hixie-76', + protocol: protocol + }); + if (self.options.clientTracking) { + self.clients.push(client); + client.on('close', function() { + var index = self.clients.indexOf(client); + if (index != -1) { + self.clients.splice(index, 1); + } + }); + } + + // signal upgrade complete + socket.removeListener('error', errorHandler); + cb(client); + }); + } + catch (e) { + try { socket.destroy(); } catch (e) {} + return; + } + } + + // retrieve nonce + var nonceLength = 8; + if (upgradeHead && upgradeHead.length >= nonceLength) { + var nonce = upgradeHead.slice(0, nonceLength); + var rest = upgradeHead.length > nonceLength ? upgradeHead.slice(nonceLength) : null; + completeHandshake.call(self, nonce, rest); + } + else { + // nonce not present in upgradeHead, so we must wait for enough data + // data to arrive before continuing + var nonce = new Buffer(nonceLength); + upgradeHead.copy(nonce, 0); + var received = upgradeHead.length; + var rest = null; + var handler = function (data) { + var toRead = Math.min(data.length, nonceLength - received); + if (toRead === 0) return; + data.copy(nonce, received, 0, toRead); + received += toRead; + if (received == nonceLength) { + socket.removeListener('data', handler); + if (toRead < data.length) rest = data.slice(toRead); + completeHandshake.call(self, nonce, rest); + } + } + socket.on('data', handler); + } + } + + // verify client + if (typeof this.options.verifyClient == 'function') { + var info = { + origin: origin, + secure: typeof req.connection.encrypted !== 'undefined', + req: req + }; + if (this.options.verifyClient.length == 2) { + var self = this; + this.options.verifyClient(info, function(result) { + if (!result) abortConnection(socket, 401, 'Unauthorized') + else onClientVerified.apply(self); + }); + return; + } + else if (!this.options.verifyClient(info)) { + abortConnection(socket, 401, 'Unauthorized'); + return; + } + } + + // no client verification required + onClientVerified(); +} + +function abortConnection(socket, code, name) { + try { + var response = [ + 'HTTP/1.1 ' + code + ' ' + name, + 'Content-type: text/html' + ]; + socket.write(response.concat('', '').join('\r\n')); + } + catch (e) { /* ignore errors - we've aborted this connection */ } + finally { + // ensure that an early aborted connection is shut down completely + try { socket.destroy(); } catch (e) {} + } +} diff --git a/node_modules/ws/lib/browser.js b/node_modules/ws/lib/browser.js new file mode 100644 index 0000000..37cafe1 --- /dev/null +++ b/node_modules/ws/lib/browser.js @@ -0,0 +1,5 @@ +/// shim for browser packaging + +module.exports = function() { + return global.WebSocket || global.MozWebSocket; +} diff --git a/node_modules/ws/node_modules/commander/.npmignore b/node_modules/ws/node_modules/commander/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/ws/node_modules/commander/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/ws/node_modules/commander/.travis.yml b/node_modules/ws/node_modules/commander/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/ws/node_modules/commander/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/node_modules/ws/node_modules/commander/History.md b/node_modules/ws/node_modules/commander/History.md new file mode 100644 index 0000000..4961d2e --- /dev/null +++ b/node_modules/ws/node_modules/commander/History.md @@ -0,0 +1,107 @@ + +0.6.1 / 2012-06-01 +================== + + * Added: append (yes or no) on confirmation + * Added: allow node.js v0.7.x + +0.6.0 / 2012-04-10 +================== + + * Added `.prompt(obj, callback)` support. Closes #49 + * Added default support to .choose(). Closes #41 + * Fixed the choice example + +0.5.1 / 2011-12-20 +================== + + * Fixed `password()` for recent nodes. Closes #36 + +0.5.0 / 2011-12-04 +================== + + * Added sub-command option support [itay] + +0.4.3 / 2011-12-04 +================== + + * Fixed custom help ordering. Closes #32 + +0.4.2 / 2011-11-24 +================== + + * Added travis support + * Fixed: line-buffered input automatically trimmed. Closes #31 + +0.4.1 / 2011-11-18 +================== + + * Removed listening for "close" on --help + +0.4.0 / 2011-11-15 +================== + + * Added support for `--`. Closes #24 + +0.3.3 / 2011-11-14 +================== + + * Fixed: wait for close event when writing help info [Jerry Hamlet] + +0.3.2 / 2011-11-01 +================== + + * Fixed long flag definitions with values [felixge] + +0.3.1 / 2011-10-31 +================== + + * Changed `--version` short flag to `-V` from `-v` + * Changed `.version()` so it's configurable [felixge] + +0.3.0 / 2011-10-31 +================== + + * Added support for long flags only. Closes #18 + +0.2.1 / 2011-10-24 +================== + + * "node": ">= 0.4.x < 0.7.0". Closes #20 + +0.2.0 / 2011-09-26 +================== + + * Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs] + +0.1.0 / 2011-08-24 +================== + + * Added support for custom `--help` output + +0.0.5 / 2011-08-18 +================== + + * Changed: when the user enters nothing prompt for password again + * Fixed issue with passwords beginning with numbers [NuckChorris] + +0.0.4 / 2011-08-15 +================== + + * Fixed `Commander#args` + +0.0.3 / 2011-08-15 +================== + + * Added default option value support + +0.0.2 / 2011-08-15 +================== + + * Added mask support to `Command#password(str[, mask], fn)` + * Added `Command#password(str, fn)` + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/ws/node_modules/commander/Makefile b/node_modules/ws/node_modules/commander/Makefile new file mode 100644 index 0000000..0074625 --- /dev/null +++ b/node_modules/ws/node_modules/commander/Makefile @@ -0,0 +1,7 @@ + +TESTS = $(shell find test/test.*.js) + +test: + @./test/run $(TESTS) + +.PHONY: test \ No newline at end of file diff --git a/node_modules/ws/node_modules/commander/Readme.md b/node_modules/ws/node_modules/commander/Readme.md new file mode 100644 index 0000000..b8328c3 --- /dev/null +++ b/node_modules/ws/node_modules/commander/Readme.md @@ -0,0 +1,262 @@ +# Commander.js + + The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander). + + [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js) + +## Installation + + $ npm install commander + +## Option parsing + + Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander'); + +program + .version('0.0.1') + .option('-p, --peppers', 'Add peppers') + .option('-P, --pineapple', 'Add pineapple') + .option('-b, --bbq', 'Add bbq sauce') + .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble') + .parse(process.argv); + +console.log('you ordered a pizza with:'); +if (program.peppers) console.log(' - peppers'); +if (program.pineapple) console.log(' - pineappe'); +if (program.bbq) console.log(' - bbq'); +console.log(' - %s cheese', program.cheese); +``` + + Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc. + +## Automated --help + + The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free: + +``` + $ ./examples/pizza --help + + Usage: pizza [options] + + Options: + + -V, --version output the version number + -p, --peppers Add peppers + -P, --pineapple Add pineappe + -b, --bbq Add bbq sauce + -c, --cheese Add the specified type of cheese [marble] + -h, --help output usage information + +``` + +## Coercion + +```js +function range(val) { + return val.split('..').map(Number); +} + +function list(val) { + return val.split(','); +} + +program + .version('0.0.1') + .usage('[options] ') + .option('-i, --integer ', 'An integer argument', parseInt) + .option('-f, --float ', 'A float argument', parseFloat) + .option('-r, --range ..', 'A range', range) + .option('-l, --list ', 'A list', list) + .option('-o, --optional [value]', 'An optional value') + .parse(process.argv); + +console.log(' int: %j', program.integer); +console.log(' float: %j', program.float); +console.log(' optional: %j', program.optional); +program.range = program.range || []; +console.log(' range: %j..%j', program.range[0], program.range[1]); +console.log(' list: %j', program.list); +console.log(' args: %j', program.args); +``` + +## Custom help + + You can display arbitrary `-h, --help` information + by listening for "--help". Commander will automatically + exit once you are done so that the remainder of your program + does not execute causing undesired behaviours, for example + in the following executable "stuff" will not output when + `--help` is used. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('../'); + +function list(val) { + return val.split(',').map(Number); +} + +program + .version('0.0.1') + .option('-f, --foo', 'enable some foo') + .option('-b, --bar', 'enable some bar') + .option('-B, --baz', 'enable some baz'); + +// must be before .parse() since +// node's emit() is immediate + +program.on('--help', function(){ + console.log(' Examples:'); + console.log(''); + console.log(' $ custom-help --help'); + console.log(' $ custom-help -h'); + console.log(''); +}); + +program.parse(process.argv); + +console.log('stuff'); +``` + +yielding the following help output: + +``` + +Usage: custom-help [options] + +Options: + + -h, --help output usage information + -V, --version output the version number + -f, --foo enable some foo + -b, --bar enable some bar + -B, --baz enable some baz + +Examples: + + $ custom-help --help + $ custom-help -h + +``` + +## .prompt(msg, fn) + + Single-line prompt: + +```js +program.prompt('name: ', function(name){ + console.log('hi %s', name); +}); +``` + + Multi-line prompt: + +```js +program.prompt('description:', function(name){ + console.log('hi %s', name); +}); +``` + + Coercion: + +```js +program.prompt('Age: ', Number, function(age){ + console.log('age: %j', age); +}); +``` + +```js +program.prompt('Birthdate: ', Date, function(date){ + console.log('date: %s', date); +}); +``` + +## .password(msg[, mask], fn) + +Prompt for password without echoing: + +```js +program.password('Password: ', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +Prompt for password with mask char "*": + +```js +program.password('Password: ', '*', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +## .confirm(msg, fn) + + Confirm with the given `msg`: + +```js +program.confirm('continue? ', function(ok){ + console.log(' got %j', ok); +}); +``` + +## .choose(list, fn) + + Let the user choose from a `list`: + +```js +var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + +console.log('Choose the coolest pet:'); +program.choose(list, function(i){ + console.log('you chose %d "%s"', i, list[i]); +}); +``` + +## Links + + - [API documentation](http://visionmedia.github.com/commander.js/) + - [ascii tables](https://github.com/LearnBoost/cli-table) + - [progress bars](https://github.com/visionmedia/node-progress) + - [more progress bars](https://github.com/substack/node-multimeter) + - [examples](https://github.com/visionmedia/commander.js/tree/master/examples) + +## License + +(The MIT License) + +Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/ws/node_modules/commander/index.js b/node_modules/ws/node_modules/commander/index.js new file mode 100644 index 0000000..06ec1e4 --- /dev/null +++ b/node_modules/ws/node_modules/commander/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/commander'); \ No newline at end of file diff --git a/node_modules/ws/node_modules/commander/lib/commander.js b/node_modules/ws/node_modules/commander/lib/commander.js new file mode 100644 index 0000000..5ba87eb --- /dev/null +++ b/node_modules/ws/node_modules/commander/lib/commander.js @@ -0,0 +1,1026 @@ + +/*! + * commander + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , path = require('path') + , tty = require('tty') + , basename = path.basename; + +/** + * Expose the root command. + */ + +exports = module.exports = new Command; + +/** + * Expose `Command`. + */ + +exports.Command = Command; + +/** + * Expose `Option`. + */ + +exports.Option = Option; + +/** + * Initialize a new `Option` with the given `flags` and `description`. + * + * @param {String} flags + * @param {String} description + * @api public + */ + +function Option(flags, description) { + this.flags = flags; + this.required = ~flags.indexOf('<'); + this.optional = ~flags.indexOf('['); + this.bool = !~flags.indexOf('-no-'); + flags = flags.split(/[ ,|]+/); + if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift(); + this.long = flags.shift(); + this.description = description; +} + +/** + * Return option name. + * + * @return {String} + * @api private + */ + +Option.prototype.name = function(){ + return this.long + .replace('--', '') + .replace('no-', ''); +}; + +/** + * Check if `arg` matches the short or long flag. + * + * @param {String} arg + * @return {Boolean} + * @api private + */ + +Option.prototype.is = function(arg){ + return arg == this.short + || arg == this.long; +}; + +/** + * Initialize a new `Command`. + * + * @param {String} name + * @api public + */ + +function Command(name) { + this.commands = []; + this.options = []; + this.args = []; + this.name = name; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Command.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add command `name`. + * + * The `.action()` callback is invoked when the + * command `name` is specified via __ARGV__, + * and the remaining arguments are applied to the + * function for access. + * + * When the `name` is "*" an un-matched command + * will be passed as the first arg, followed by + * the rest of __ARGV__ remaining. + * + * Examples: + * + * program + * .version('0.0.1') + * .option('-C, --chdir ', 'change the working directory') + * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') + * .option('-T, --no-tests', 'ignore test hook') + * + * program + * .command('setup') + * .description('run remote setup commands') + * .action(function(){ + * console.log('setup'); + * }); + * + * program + * .command('exec ') + * .description('run the given remote command') + * .action(function(cmd){ + * console.log('exec "%s"', cmd); + * }); + * + * program + * .command('*') + * .description('deploy the given env') + * .action(function(env){ + * console.log('deploying "%s"', env); + * }); + * + * program.parse(process.argv); + * + * @param {String} name + * @return {Command} the new command + * @api public + */ + +Command.prototype.command = function(name){ + var args = name.split(/ +/); + var cmd = new Command(args.shift()); + this.commands.push(cmd); + cmd.parseExpectedArgs(args); + cmd.parent = this; + return cmd; +}; + +/** + * Parse expected `args`. + * + * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. + * + * @param {Array} args + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parseExpectedArgs = function(args){ + if (!args.length) return; + var self = this; + args.forEach(function(arg){ + switch (arg[0]) { + case '<': + self.args.push({ required: true, name: arg.slice(1, -1) }); + break; + case '[': + self.args.push({ required: false, name: arg.slice(1, -1) }); + break; + } + }); + return this; +}; + +/** + * Register callback `fn` for the command. + * + * Examples: + * + * program + * .command('help') + * .description('display verbose help') + * .action(function(){ + * // output help here + * }); + * + * @param {Function} fn + * @return {Command} for chaining + * @api public + */ + +Command.prototype.action = function(fn){ + var self = this; + this.parent.on(this.name, function(args, unknown){ + // Parse any so-far unknown options + unknown = unknown || []; + var parsed = self.parseOptions(unknown); + + // Output help if necessary + outputHelpIfNecessary(self, parsed.unknown); + + // If there are still any unknown options, then we simply + // die, unless someone asked for help, in which case we give it + // to them, and then we die. + if (parsed.unknown.length > 0) { + self.unknownOption(parsed.unknown[0]); + } + + self.args.forEach(function(arg, i){ + if (arg.required && null == args[i]) { + self.missingArgument(arg.name); + } + }); + + // Always append ourselves to the end of the arguments, + // to make sure we match the number of arguments the user + // expects + if (self.args.length) { + args[self.args.length] = self; + } else { + args.push(self); + } + + fn.apply(this, args); + }); + return this; +}; + +/** + * Define option with `flags`, `description` and optional + * coercion `fn`. + * + * The `flags` string should contain both the short and long flags, + * separated by comma, a pipe or space. The following are all valid + * all will output this way when `--help` is used. + * + * "-p, --pepper" + * "-p|--pepper" + * "-p --pepper" + * + * Examples: + * + * // simple boolean defaulting to false + * program.option('-p, --pepper', 'add pepper'); + * + * --pepper + * program.pepper + * // => Boolean + * + * // simple boolean defaulting to false + * program.option('-C, --no-cheese', 'remove cheese'); + * + * program.cheese + * // => true + * + * --no-cheese + * program.cheese + * // => true + * + * // required argument + * program.option('-C, --chdir ', 'change the working directory'); + * + * --chdir /tmp + * program.chdir + * // => "/tmp" + * + * // optional argument + * program.option('-c, --cheese [type]', 'add cheese [marble]'); + * + * @param {String} flags + * @param {String} description + * @param {Function|Mixed} fn or default + * @param {Mixed} defaultValue + * @return {Command} for chaining + * @api public + */ + +Command.prototype.option = function(flags, description, fn, defaultValue){ + var self = this + , option = new Option(flags, description) + , oname = option.name() + , name = camelcase(oname); + + // default as 3rd arg + if ('function' != typeof fn) defaultValue = fn, fn = null; + + // preassign default value only for --no-*, [optional], or + if (false == option.bool || option.optional || option.required) { + // when --no-* we make sure default is true + if (false == option.bool) defaultValue = true; + // preassign only if we have a default + if (undefined !== defaultValue) self[name] = defaultValue; + } + + // register the option + this.options.push(option); + + // when it's passed assign the value + // and conditionally invoke the callback + this.on(oname, function(val){ + // coercion + if (null != val && fn) val = fn(val); + + // unassigned or bool + if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) { + // if no value, bool true, and we have a default, then use it! + if (null == val) { + self[name] = option.bool + ? defaultValue || true + : false; + } else { + self[name] = val; + } + } else if (null !== val) { + // reassign + self[name] = val; + } + }); + + return this; +}; + +/** + * Parse `argv`, settings options and invoking commands when defined. + * + * @param {Array} argv + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parse = function(argv){ + // store raw args + this.rawArgs = argv; + + // guess name + if (!this.name) this.name = basename(argv[1]); + + // process argv + var parsed = this.parseOptions(this.normalize(argv.slice(2))); + this.args = parsed.args; + return this.parseArgs(this.args, parsed.unknown); +}; + +/** + * Normalize `args`, splitting joined short flags. For example + * the arg "-abc" is equivalent to "-a -b -c". + * + * @param {Array} args + * @return {Array} + * @api private + */ + +Command.prototype.normalize = function(args){ + var ret = [] + , arg; + + for (var i = 0, len = args.length; i < len; ++i) { + arg = args[i]; + if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) { + arg.slice(1).split('').forEach(function(c){ + ret.push('-' + c); + }); + } else { + ret.push(arg); + } + } + + return ret; +}; + +/** + * Parse command `args`. + * + * When listener(s) are available those + * callbacks are invoked, otherwise the "*" + * event is emitted and those actions are invoked. + * + * @param {Array} args + * @return {Command} for chaining + * @api private + */ + +Command.prototype.parseArgs = function(args, unknown){ + var cmds = this.commands + , len = cmds.length + , name; + + if (args.length) { + name = args[0]; + if (this.listeners(name).length) { + this.emit(args.shift(), args, unknown); + } else { + this.emit('*', args); + } + } else { + outputHelpIfNecessary(this, unknown); + + // If there were no args and we have unknown options, + // then they are extraneous and we need to error. + if (unknown.length > 0) { + this.unknownOption(unknown[0]); + } + } + + return this; +}; + +/** + * Return an option matching `arg` if any. + * + * @param {String} arg + * @return {Option} + * @api private + */ + +Command.prototype.optionFor = function(arg){ + for (var i = 0, len = this.options.length; i < len; ++i) { + if (this.options[i].is(arg)) { + return this.options[i]; + } + } +}; + +/** + * Parse options from `argv` returning `argv` + * void of these options. + * + * @param {Array} argv + * @return {Array} + * @api public + */ + +Command.prototype.parseOptions = function(argv){ + var args = [] + , len = argv.length + , literal + , option + , arg; + + var unknownOptions = []; + + // parse options + for (var i = 0; i < len; ++i) { + arg = argv[i]; + + // literal args after -- + if ('--' == arg) { + literal = true; + continue; + } + + if (literal) { + args.push(arg); + continue; + } + + // find matching Option + option = this.optionFor(arg); + + // option is defined + if (option) { + // requires arg + if (option.required) { + arg = argv[++i]; + if (null == arg) return this.optionMissingArgument(option); + if ('-' == arg[0]) return this.optionMissingArgument(option, arg); + this.emit(option.name(), arg); + // optional arg + } else if (option.optional) { + arg = argv[i+1]; + if (null == arg || '-' == arg[0]) { + arg = null; + } else { + ++i; + } + this.emit(option.name(), arg); + // bool + } else { + this.emit(option.name()); + } + continue; + } + + // looks like an option + if (arg.length > 1 && '-' == arg[0]) { + unknownOptions.push(arg); + + // If the next argument looks like it might be + // an argument for this option, we pass it on. + // If it isn't, then it'll simply be ignored + if (argv[i+1] && '-' != argv[i+1][0]) { + unknownOptions.push(argv[++i]); + } + continue; + } + + // arg + args.push(arg); + } + + return { args: args, unknown: unknownOptions }; +}; + +/** + * Argument `name` is missing. + * + * @param {String} name + * @api private + */ + +Command.prototype.missingArgument = function(name){ + console.error(); + console.error(" error: missing required argument `%s'", name); + console.error(); + process.exit(1); +}; + +/** + * `Option` is missing an argument, but received `flag` or nothing. + * + * @param {String} option + * @param {String} flag + * @api private + */ + +Command.prototype.optionMissingArgument = function(option, flag){ + console.error(); + if (flag) { + console.error(" error: option `%s' argument missing, got `%s'", option.flags, flag); + } else { + console.error(" error: option `%s' argument missing", option.flags); + } + console.error(); + process.exit(1); +}; + +/** + * Unknown option `flag`. + * + * @param {String} flag + * @api private + */ + +Command.prototype.unknownOption = function(flag){ + console.error(); + console.error(" error: unknown option `%s'", flag); + console.error(); + process.exit(1); +}; + +/** + * Set the program version to `str`. + * + * This method auto-registers the "-V, --version" flag + * which will print the version number when passed. + * + * @param {String} str + * @param {String} flags + * @return {Command} for chaining + * @api public + */ + +Command.prototype.version = function(str, flags){ + if (0 == arguments.length) return this._version; + this._version = str; + flags = flags || '-V, --version'; + this.option(flags, 'output the version number'); + this.on('version', function(){ + console.log(str); + process.exit(0); + }); + return this; +}; + +/** + * Set the description `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.description = function(str){ + if (0 == arguments.length) return this._description; + this._description = str; + return this; +}; + +/** + * Set / get the command usage `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.usage = function(str){ + var args = this.args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }); + + var usage = '[options' + + (this.commands.length ? '] [command' : '') + + ']' + + (this.args.length ? ' ' + args : ''); + if (0 == arguments.length) return this._usage || usage; + this._usage = str; + + return this; +}; + +/** + * Return the largest option length. + * + * @return {Number} + * @api private + */ + +Command.prototype.largestOptionLength = function(){ + return this.options.reduce(function(max, option){ + return Math.max(max, option.flags.length); + }, 0); +}; + +/** + * Return help for options. + * + * @return {String} + * @api private + */ + +Command.prototype.optionHelp = function(){ + var width = this.largestOptionLength(); + + // Prepend the help information + return [pad('-h, --help', width) + ' ' + 'output usage information'] + .concat(this.options.map(function(option){ + return pad(option.flags, width) + + ' ' + option.description; + })) + .join('\n'); +}; + +/** + * Return command help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.commandHelp = function(){ + if (!this.commands.length) return ''; + return [ + '' + , ' Commands:' + , '' + , this.commands.map(function(cmd){ + var args = cmd.args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }).join(' '); + + return cmd.name + + (cmd.options.length + ? ' [options]' + : '') + ' ' + args + + (cmd.description() + ? '\n' + cmd.description() + : ''); + }).join('\n\n').replace(/^/gm, ' ') + , '' + ].join('\n'); +}; + +/** + * Return program help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.helpInformation = function(){ + return [ + '' + , ' Usage: ' + this.name + ' ' + this.usage() + , '' + this.commandHelp() + , ' Options:' + , '' + , '' + this.optionHelp().replace(/^/gm, ' ') + , '' + , '' + ].join('\n'); +}; + +/** + * Prompt for a `Number`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForNumber = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseNumber(val){ + val = Number(val); + if (isNaN(val)) return self.promptSingleLine(str + '(must be a number) ', parseNumber); + fn(val); + }); +}; + +/** + * Prompt for a `Date`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForDate = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseDate(val){ + val = new Date(val); + if (isNaN(val.getTime())) return self.promptSingleLine(str + '(must be a date) ', parseDate); + fn(val); + }); +}; + +/** + * Single-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptSingleLine = function(str, fn){ + if ('function' == typeof arguments[2]) { + return this['promptFor' + (fn.name || fn)](str, arguments[2]); + } + + process.stdout.write(str); + process.stdin.setEncoding('utf8'); + process.stdin.once('data', function(val){ + fn(val.trim()); + }).resume(); +}; + +/** + * Multi-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptMultiLine = function(str, fn){ + var buf = []; + console.log(str); + process.stdin.setEncoding('utf8'); + process.stdin.on('data', function(val){ + if ('\n' == val || '\r\n' == val) { + process.stdin.removeAllListeners('data'); + fn(buf.join('\n')); + } else { + buf.push(val.trimRight()); + } + }).resume(); +}; + +/** + * Prompt `str` and callback `fn(val)` + * + * Commander supports single-line and multi-line prompts. + * To issue a single-line prompt simply add white-space + * to the end of `str`, something like "name: ", whereas + * for a multi-line prompt omit this "description:". + * + * + * Examples: + * + * program.prompt('Username: ', function(name){ + * console.log('hi %s', name); + * }); + * + * program.prompt('Description:', function(desc){ + * console.log('description was "%s"', desc.trim()); + * }); + * + * @param {String|Object} str + * @param {Function} fn + * @api public + */ + +Command.prototype.prompt = function(str, fn){ + var self = this; + + if ('string' == typeof str) { + if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments); + this.promptMultiLine(str, fn); + } else { + var keys = Object.keys(str) + , obj = {}; + + function next() { + var key = keys.shift() + , label = str[key]; + + if (!key) return fn(obj); + self.prompt(label, function(val){ + obj[key] = val; + next(); + }); + } + + next(); + } +}; + +/** + * Prompt for password with `str`, `mask` char and callback `fn(val)`. + * + * The mask string defaults to '', aka no output is + * written while typing, you may want to use "*" etc. + * + * Examples: + * + * program.password('Password: ', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * program.password('Password: ', '*', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {String} mask + * @param {Function} fn + * @api public + */ + +Command.prototype.password = function(str, mask, fn){ + var self = this + , buf = ''; + + // default mask + if ('function' == typeof mask) { + fn = mask; + mask = ''; + } + + process.stdin.resume(); + tty.setRawMode(true); + process.stdout.write(str); + + // keypress + process.stdin.on('keypress', function(c, key){ + if (key && 'enter' == key.name) { + console.log(); + process.stdin.removeAllListeners('keypress'); + tty.setRawMode(false); + if (!buf.trim().length) return self.password(str, mask, fn); + fn(buf); + return; + } + + if (key && key.ctrl && 'c' == key.name) { + console.log('%s', buf); + process.exit(); + } + + process.stdout.write(mask); + buf += c; + }).resume(); +}; + +/** + * Confirmation prompt with `str` and callback `fn(bool)` + * + * Examples: + * + * program.confirm('continue? ', function(ok){ + * console.log(' got %j', ok); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {Function} fn + * @api public + */ + + +Command.prototype.confirm = function(str, fn, verbose){ + var self = this; + this.prompt(str, function(ok){ + if (!ok.trim()) { + if (!verbose) str += '(yes or no) '; + return self.confirm(str, fn, true); + } + fn(parseBool(ok)); + }); +}; + +/** + * Choice prompt with `list` of items and callback `fn(index, item)` + * + * Examples: + * + * var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + * + * console.log('Choose the coolest pet:'); + * program.choose(list, function(i){ + * console.log('you chose %d "%s"', i, list[i]); + * process.stdin.destroy(); + * }); + * + * @param {Array} list + * @param {Number|Function} index or fn + * @param {Function} fn + * @api public + */ + +Command.prototype.choose = function(list, index, fn){ + var self = this + , hasDefault = 'number' == typeof index; + + if (!hasDefault) { + fn = index; + index = null; + } + + list.forEach(function(item, i){ + if (hasDefault && i == index) { + console.log('* %d) %s', i + 1, item); + } else { + console.log(' %d) %s', i + 1, item); + } + }); + + function again() { + self.prompt(' : ', function(val){ + val = parseInt(val, 10) - 1; + if (hasDefault && isNaN(val)) val = index; + + if (null == list[val]) { + again(); + } else { + fn(val, list[val]); + } + }); + } + + again(); +}; + +/** + * Camel-case the given `flag` + * + * @param {String} flag + * @return {String} + * @api private + */ + +function camelcase(flag) { + return flag.split('-').reduce(function(str, word){ + return str + word[0].toUpperCase() + word.slice(1); + }); +} + +/** + * Parse a boolean `str`. + * + * @param {String} str + * @return {Boolean} + * @api private + */ + +function parseBool(str) { + return /^y|yes|ok|true$/i.test(str); +} + +/** + * Pad `str` to `width`. + * + * @param {String} str + * @param {Number} width + * @return {String} + * @api private + */ + +function pad(str, width) { + var len = Math.max(0, width - str.length); + return str + Array(len + 1).join(' '); +} + +/** + * Output help information if necessary + * + * @param {Command} command to output help for + * @param {Array} array of options to search for -h or --help + * @api private + */ + +function outputHelpIfNecessary(cmd, options) { + options = options || []; + for (var i = 0; i < options.length; i++) { + if (options[i] == '--help' || options[i] == '-h') { + process.stdout.write(cmd.helpInformation()); + cmd.emit('--help'); + process.exit(0); + } + } +} diff --git a/node_modules/ws/node_modules/commander/package.json b/node_modules/ws/node_modules/commander/package.json new file mode 100644 index 0000000..b82c5b1 --- /dev/null +++ b/node_modules/ws/node_modules/commander/package.json @@ -0,0 +1,42 @@ +{ + "name": "commander", + "version": "0.6.1", + "description": "the complete solution for node.js command-line programs", + "keywords": [ + "command", + "option", + "parser", + "prompt", + "stdin" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "repository": { + "type": "git", + "url": "https://github.com/visionmedia/commander.js.git" + }, + "dependencies": {}, + "devDependencies": { + "should": ">= 0.0.1" + }, + "scripts": { + "test": "make test" + }, + "main": "index", + "engines": { + "node": ">= 0.4.x" + }, + "readme": "# Commander.js\n\n The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander).\n\n [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js)\n\n## Installation\n\n $ npm install commander\n\n## Option parsing\n\n Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('commander');\n\nprogram\n .version('0.0.1')\n .option('-p, --peppers', 'Add peppers')\n .option('-P, --pineapple', 'Add pineapple')\n .option('-b, --bbq', 'Add bbq sauce')\n .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')\n .parse(process.argv);\n\nconsole.log('you ordered a pizza with:');\nif (program.peppers) console.log(' - peppers');\nif (program.pineapple) console.log(' - pineappe');\nif (program.bbq) console.log(' - bbq');\nconsole.log(' - %s cheese', program.cheese);\n```\n\n Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as \"--template-engine\" are camel-cased, becoming `program.templateEngine` etc.\n\n## Automated --help\n\n The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free:\n\n``` \n $ ./examples/pizza --help\n\n Usage: pizza [options]\n\n Options:\n\n -V, --version output the version number\n -p, --peppers Add peppers\n -P, --pineapple Add pineappe\n -b, --bbq Add bbq sauce\n -c, --cheese Add the specified type of cheese [marble]\n -h, --help output usage information\n\n```\n\n## Coercion\n\n```js\nfunction range(val) {\n return val.split('..').map(Number);\n}\n\nfunction list(val) {\n return val.split(',');\n}\n\nprogram\n .version('0.0.1')\n .usage('[options] ')\n .option('-i, --integer ', 'An integer argument', parseInt)\n .option('-f, --float ', 'A float argument', parseFloat)\n .option('-r, --range ..', 'A range', range)\n .option('-l, --list ', 'A list', list)\n .option('-o, --optional [value]', 'An optional value')\n .parse(process.argv);\n\nconsole.log(' int: %j', program.integer);\nconsole.log(' float: %j', program.float);\nconsole.log(' optional: %j', program.optional);\nprogram.range = program.range || [];\nconsole.log(' range: %j..%j', program.range[0], program.range[1]);\nconsole.log(' list: %j', program.list);\nconsole.log(' args: %j', program.args);\n```\n\n## Custom help\n\n You can display arbitrary `-h, --help` information\n by listening for \"--help\". Commander will automatically\n exit once you are done so that the remainder of your program\n does not execute causing undesired behaviours, for example\n in the following executable \"stuff\" will not output when\n `--help` is used.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('../');\n\nfunction list(val) {\n return val.split(',').map(Number);\n}\n\nprogram\n .version('0.0.1')\n .option('-f, --foo', 'enable some foo')\n .option('-b, --bar', 'enable some bar')\n .option('-B, --baz', 'enable some baz');\n\n// must be before .parse() since\n// node's emit() is immediate\n\nprogram.on('--help', function(){\n console.log(' Examples:');\n console.log('');\n console.log(' $ custom-help --help');\n console.log(' $ custom-help -h');\n console.log('');\n});\n\nprogram.parse(process.argv);\n\nconsole.log('stuff');\n```\n\nyielding the following help output:\n\n```\n\nUsage: custom-help [options]\n\nOptions:\n\n -h, --help output usage information\n -V, --version output the version number\n -f, --foo enable some foo\n -b, --bar enable some bar\n -B, --baz enable some baz\n\nExamples:\n\n $ custom-help --help\n $ custom-help -h\n\n```\n\n## .prompt(msg, fn)\n\n Single-line prompt:\n\n```js\nprogram.prompt('name: ', function(name){\n console.log('hi %s', name);\n});\n```\n\n Multi-line prompt:\n\n```js\nprogram.prompt('description:', function(name){\n console.log('hi %s', name);\n});\n```\n\n Coercion:\n\n```js\nprogram.prompt('Age: ', Number, function(age){\n console.log('age: %j', age);\n});\n```\n\n```js\nprogram.prompt('Birthdate: ', Date, function(date){\n console.log('date: %s', date);\n});\n```\n\n## .password(msg[, mask], fn)\n\nPrompt for password without echoing:\n\n```js\nprogram.password('Password: ', function(pass){\n console.log('got \"%s\"', pass);\n process.stdin.destroy();\n});\n```\n\nPrompt for password with mask char \"*\":\n\n```js\nprogram.password('Password: ', '*', function(pass){\n console.log('got \"%s\"', pass);\n process.stdin.destroy();\n});\n```\n\n## .confirm(msg, fn)\n\n Confirm with the given `msg`:\n\n```js\nprogram.confirm('continue? ', function(ok){\n console.log(' got %j', ok);\n});\n```\n\n## .choose(list, fn)\n\n Let the user choose from a `list`:\n\n```js\nvar list = ['tobi', 'loki', 'jane', 'manny', 'luna'];\n\nconsole.log('Choose the coolest pet:');\nprogram.choose(list, function(i){\n console.log('you chose %d \"%s\"', i, list[i]);\n});\n```\n\n## Links\n\n - [API documentation](http://visionmedia.github.com/commander.js/)\n - [ascii tables](https://github.com/LearnBoost/cli-table)\n - [progress bars](https://github.com/visionmedia/node-progress)\n - [more progress bars](https://github.com/substack/node-multimeter)\n - [examples](https://github.com/visionmedia/commander.js/tree/master/examples)\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 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.", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/visionmedia/commander.js/issues" + }, + "_id": "commander@0.6.1", + "dist": { + "shasum": "41be1203fe9f03dfa7933bc2e023817bf091e9e3" + }, + "_from": "commander@~0.6.1", + "_resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz" +} diff --git a/node_modules/ws/node_modules/options/.npmignore b/node_modules/ws/node_modules/options/.npmignore new file mode 100644 index 0000000..6bfffbb --- /dev/null +++ b/node_modules/ws/node_modules/options/.npmignore @@ -0,0 +1,5 @@ +npm-debug.log +node_modules +.*.swp +.lock-* +build/ diff --git a/node_modules/ws/node_modules/options/Makefile b/node_modules/ws/node_modules/options/Makefile new file mode 100644 index 0000000..7496b6f --- /dev/null +++ b/node_modules/ws/node_modules/options/Makefile @@ -0,0 +1,12 @@ +ALL_TESTS = $(shell find test/ -name '*.test.js') + +run-tests: + @./node_modules/.bin/mocha \ + -t 2000 \ + $(TESTFLAGS) \ + $(TESTS) + +test: + @$(MAKE) NODE_PATH=lib TESTS="$(ALL_TESTS)" run-tests + +.PHONY: test diff --git a/node_modules/ws/node_modules/options/README.md b/node_modules/ws/node_modules/options/README.md new file mode 100644 index 0000000..4b39a2a --- /dev/null +++ b/node_modules/ws/node_modules/options/README.md @@ -0,0 +1,28 @@ +# options.js # + +A very light-weight in-code option parsers for node.js. + +## License ## + +(The MIT License) + +Copyright (c) 2012 Einar Otto Stangvik <einaros@gmail.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/ws/node_modules/options/lib/options.js b/node_modules/ws/node_modules/options/lib/options.js new file mode 100644 index 0000000..4fc45e9 --- /dev/null +++ b/node_modules/ws/node_modules/options/lib/options.js @@ -0,0 +1,86 @@ +/*! + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var fs = require('fs'); + +function Options(defaults) { + var internalValues = {}; + var values = this.value = {}; + Object.keys(defaults).forEach(function(key) { + internalValues[key] = defaults[key]; + Object.defineProperty(values, key, { + get: function() { return internalValues[key]; }, + configurable: false, + enumerable: true + }); + }); + this.reset = function() { + Object.keys(defaults).forEach(function(key) { + internalValues[key] = defaults[key]; + }); + return this; + }; + this.merge = function(options, required) { + options = options || {}; + if (Object.prototype.toString.call(required) === '[object Array]') { + var missing = []; + for (var i = 0, l = required.length; i < l; ++i) { + var key = required[i]; + if (!(key in options)) { + missing.push(key); + } + } + if (missing.length > 0) { + if (missing.length > 1) { + throw new Error('options ' + + missing.slice(0, missing.length - 1).join(', ') + ' and ' + + missing[missing.length - 1] + ' must be defined'); + } + else throw new Error('option ' + missing[0] + ' must be defined'); + } + } + Object.keys(options).forEach(function(key) { + if (key in internalValues) { + internalValues[key] = options[key]; + } + }); + return this; + }; + this.copy = function(keys) { + var obj = {}; + Object.keys(defaults).forEach(function(key) { + if (keys.indexOf(key) !== -1) { + obj[key] = values[key]; + } + }); + return obj; + }; + this.read = function(filename, cb) { + if (typeof cb == 'function') { + var self = this; + fs.readFile(filename, function(error, data) { + if (error) return cb(error); + var conf = JSON.parse(data); + self.merge(conf); + cb(); + }); + } + else { + var conf = JSON.parse(fs.readFileSync(filename)); + this.merge(conf); + } + return this; + }; + this.isDefined = function(key) { + return typeof values[key] != 'undefined'; + }; + this.isDefinedAndNonNull = function(key) { + return typeof values[key] != 'undefined' && values[key] !== null; + }; + Object.freeze(values); + Object.freeze(this); +} + +module.exports = Options; diff --git a/node_modules/ws/node_modules/options/package.json b/node_modules/ws/node_modules/options/package.json new file mode 100644 index 0000000..6e5bdf8 --- /dev/null +++ b/node_modules/ws/node_modules/options/package.json @@ -0,0 +1,36 @@ +{ + "author": { + "name": "Einar Otto Stangvik", + "email": "einaros@gmail.com", + "url": "http://2x.io" + }, + "name": "options", + "description": "A very light-weight in-code option parsers for node.js.", + "version": "0.0.5", + "repository": { + "type": "git", + "url": "git://github.com/einaros/options.js.git" + }, + "main": "lib/options", + "scripts": { + "test": "make test" + }, + "engines": { + "node": ">=0.4.0" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "latest" + }, + "readme": "# options.js #\n\nA very light-weight in-code option parsers for node.js.\n\n## License ##\n\n(The MIT License)\n\nCopyright (c) 2012 Einar Otto Stangvik <einaros@gmail.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", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/einaros/options.js/issues" + }, + "_id": "options@0.0.5", + "dist": { + "shasum": "4f79a4434f2d0703250db48ef2fa5f5050f08f15" + }, + "_from": "options@>=0.0.5", + "_resolved": "https://registry.npmjs.org/options/-/options-0.0.5.tgz" +} diff --git a/node_modules/ws/node_modules/options/test/fixtures/test.conf b/node_modules/ws/node_modules/options/test/fixtures/test.conf new file mode 100644 index 0000000..6e62444 --- /dev/null +++ b/node_modules/ws/node_modules/options/test/fixtures/test.conf @@ -0,0 +1,4 @@ +{ + "a": "foobar", + "b": false +} \ No newline at end of file diff --git a/node_modules/ws/node_modules/options/test/options.test.js b/node_modules/ws/node_modules/options/test/options.test.js new file mode 100644 index 0000000..6a1d9f5 --- /dev/null +++ b/node_modules/ws/node_modules/options/test/options.test.js @@ -0,0 +1,140 @@ +var Options = require('options') + , assert = require('assert'); + +describe('Options', function() { + describe('#ctor', function() { + it('initializes options', function() { + var option = new Options({a: true, b: false}); + assert.strictEqual(true, option.value.a); + assert.strictEqual(false, option.value.b); + }); + }); + + describe('#merge', function() { + it('merges options from another object', function() { + var option = new Options({a: true, b: false}); + option.merge({b: true}); + assert.strictEqual(true, option.value.a); + assert.strictEqual(true, option.value.b); + }); + it('does nothing when arguments are undefined', function() { + var option = new Options({a: true, b: false}); + option.merge(undefined); + assert.strictEqual(true, option.value.a); + assert.strictEqual(false, option.value.b); + }); + it('cannot set values that werent already there', function() { + var option = new Options({a: true, b: false}); + option.merge({c: true}); + assert.strictEqual('undefined', typeof option.value.c); + }); + it('can require certain options to be defined', function() { + var option = new Options({a: true, b: false, c: 3}); + var caughtException = false; + try { + option.merge({}, ['a', 'b', 'c']); + } + catch (e) { + caughtException = e.toString() == 'Error: options a, b and c must be defined'; + } + assert.strictEqual(true, caughtException); + }); + it('can require certain options to be defined, when options are undefined', function() { + var option = new Options({a: true, b: false, c: 3}); + var caughtException = false; + try { + option.merge(undefined, ['a', 'b', 'c']); + } + catch (e) { + caughtException = e.toString() == 'Error: options a, b and c must be defined'; + } + assert.strictEqual(true, caughtException); + }); + it('returns "this"', function() { + var option = new Options({a: true, b: false, c: 3}); + assert.strictEqual(option, option.merge()); + }); + }); + + describe('#copy', function() { + it('returns a new object with the indicated options', function() { + var option = new Options({a: true, b: false, c: 3}); + option.merge({c: 4}); + var obj = option.copy(['a', 'c']); + assert.strictEqual(true, obj.a); + assert.strictEqual(4, obj.c); + assert.strictEqual('undefined', typeof obj.b); + }); + }); + + describe('#value', function() { + it('can be enumerated', function() { + var option = new Options({a: true, b: false}); + assert.strictEqual(2, Object.keys(option.value).length); + }); + it('can not be used to set values', function() { + var option = new Options({a: true, b: false}); + option.value.b = true; + assert.strictEqual(false, option.value.b); + }); + it('can not be used to add values', function() { + var option = new Options({a: true, b: false}); + option.value.c = 3; + assert.strictEqual('undefined', typeof option.value.c); + }); + }); + + describe('#isDefined', function() { + it('returns true if the named value is defined', function() { + var option = new Options({a: undefined}); + assert.strictEqual(false, option.isDefined('a')); + option.merge({a: false}); + assert.strictEqual(true, option.isDefined('a')); + }); + }); + + describe('#isDefinedAndNonNull', function() { + it('returns true if the named value is defined and non-null', function() { + var option = new Options({a: undefined}); + assert.strictEqual(false, option.isDefinedAndNonNull('a')); + option.merge({a: null}); + assert.strictEqual(false, option.isDefinedAndNonNull('a')); + option.merge({a: 2}); + assert.strictEqual(true, option.isDefinedAndNonNull('a')); + }); + }); + + describe('#read', function() { + it('reads and merges config from a file', function() { + var option = new Options({a: true, b: true}); + option.read(__dirname + '/fixtures/test.conf'); + assert.strictEqual('foobar', option.value.a); + assert.strictEqual(false, option.value.b); + }); + + it('asynchronously reads and merges config from a file when a callback is passed', function(done) { + var option = new Options({a: true, b: true}); + option.read(__dirname + '/fixtures/test.conf', function(error) { + assert.strictEqual('foobar', option.value.a); + assert.strictEqual(false, option.value.b); + done(); + }); + }); + }); + + describe('#reset', function() { + it('resets options to defaults', function() { + var option = new Options({a: true, b: false}); + option.merge({b: true}); + assert.strictEqual(true, option.value.b); + option.reset(); + assert.strictEqual(false, option.value.b); + }); + }); + + it('is immutable', function() { + var option = new Options({a: true, b: false}); + option.foo = 2; + assert.strictEqual('undefined', typeof option.foo); + }); +}); diff --git a/node_modules/ws/node_modules/tinycolor/.npmignore b/node_modules/ws/node_modules/tinycolor/.npmignore new file mode 100644 index 0000000..6bfffbb --- /dev/null +++ b/node_modules/ws/node_modules/tinycolor/.npmignore @@ -0,0 +1,5 @@ +npm-debug.log +node_modules +.*.swp +.lock-* +build/ diff --git a/node_modules/ws/node_modules/tinycolor/README.md b/node_modules/ws/node_modules/tinycolor/README.md new file mode 100644 index 0000000..55eb3c1 --- /dev/null +++ b/node_modules/ws/node_modules/tinycolor/README.md @@ -0,0 +1,3 @@ +# tinycolor # + +This is a no-fuzz, barebone, zero muppetry color module for node.js. \ No newline at end of file diff --git a/node_modules/ws/node_modules/tinycolor/example.js b/node_modules/ws/node_modules/tinycolor/example.js new file mode 100644 index 0000000..f754046 --- /dev/null +++ b/node_modules/ws/node_modules/tinycolor/example.js @@ -0,0 +1,3 @@ +require('./tinycolor'); +console.log('this should be red and have an underline!'.grey.underline); +console.log('this should have a blue background!'.bgBlue); \ No newline at end of file diff --git a/node_modules/ws/node_modules/tinycolor/package.json b/node_modules/ws/node_modules/tinycolor/package.json new file mode 100644 index 0000000..890d233 --- /dev/null +++ b/node_modules/ws/node_modules/tinycolor/package.json @@ -0,0 +1,31 @@ +{ + "author": { + "name": "Einar Otto Stangvik", + "email": "einaros@gmail.com", + "url": "http://2x.io" + }, + "name": "tinycolor", + "description": "a to-the-point color module for node", + "version": "0.0.1", + "repository": { + "type": "git", + "url": "git://github.com/einaros/tinycolor.git" + }, + "engines": { + "node": ">=0.4.0" + }, + "dependencies": {}, + "devDependencies": {}, + "main": "tinycolor", + "readme": "# tinycolor #\n\nThis is a no-fuzz, barebone, zero muppetry color module for node.js.", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/einaros/tinycolor/issues" + }, + "_id": "tinycolor@0.0.1", + "dist": { + "shasum": "dc96ac2859b0dcf0a1cb0aec6aaf31d3883c0ecb" + }, + "_from": "tinycolor@0.x", + "_resolved": "https://registry.npmjs.org/tinycolor/-/tinycolor-0.0.1.tgz" +} diff --git a/node_modules/ws/node_modules/tinycolor/tinycolor.js b/node_modules/ws/node_modules/tinycolor/tinycolor.js new file mode 100644 index 0000000..36e552c --- /dev/null +++ b/node_modules/ws/node_modules/tinycolor/tinycolor.js @@ -0,0 +1,31 @@ +var styles = { + 'bold': ['\033[1m', '\033[22m'], + 'italic': ['\033[3m', '\033[23m'], + 'underline': ['\033[4m', '\033[24m'], + 'inverse': ['\033[7m', '\033[27m'], + 'black': ['\033[30m', '\033[39m'], + 'red': ['\033[31m', '\033[39m'], + 'green': ['\033[32m', '\033[39m'], + 'yellow': ['\033[33m', '\033[39m'], + 'blue': ['\033[34m', '\033[39m'], + 'magenta': ['\033[35m', '\033[39m'], + 'cyan': ['\033[36m', '\033[39m'], + 'white': ['\033[37m', '\033[39m'], + 'default': ['\033[39m', '\033[39m'], + 'grey': ['\033[90m', '\033[39m'], + 'bgBlack': ['\033[40m', '\033[49m'], + 'bgRed': ['\033[41m', '\033[49m'], + 'bgGreen': ['\033[42m', '\033[49m'], + 'bgYellow': ['\033[43m', '\033[49m'], + 'bgBlue': ['\033[44m', '\033[49m'], + 'bgMagenta': ['\033[45m', '\033[49m'], + 'bgCyan': ['\033[46m', '\033[49m'], + 'bgWhite': ['\033[47m', '\033[49m'], + 'bgDefault': ['\033[49m', '\033[49m'] +} +Object.keys(styles).forEach(function(style) { + Object.defineProperty(String.prototype, style, { + get: function() { return styles[style][0] + this + styles[style][1]; }, + enumerable: false + }); +}); diff --git a/node_modules/ws/package.json b/node_modules/ws/package.json new file mode 100644 index 0000000..5a1859c --- /dev/null +++ b/node_modules/ws/package.json @@ -0,0 +1,48 @@ +{ + "author": { + "name": "Einar Otto Stangvik", + "email": "einaros@gmail.com", + "url": "http://2x.io" + }, + "name": "ws", + "description": "simple to use, blazing fast and thoroughly tested websocket client, server and console for node.js, up-to-date against RFC-6455", + "version": "0.4.27", + "repository": { + "type": "git", + "url": "git://github.com/einaros/ws.git" + }, + "bin": { + "wscat": "./bin/wscat" + }, + "scripts": { + "test": "make test", + "install": "(node-gyp rebuild 2> builderror.log) || (exit 0)" + }, + "engines": { + "node": ">=0.4.0" + }, + "dependencies": { + "commander": "~0.6.1", + "tinycolor": "0.x", + "options": ">=0.0.5" + }, + "devDependencies": { + "mocha": "~1.2.1", + "should": "0.6.x", + "expect.js": "0.1.x", + "benchmark": "0.3.x", + "ansi": "latest" + }, + "browser": "./lib/browser.js", + "readme": "[![Build Status](https://secure.travis-ci.org/einaros/ws.png)](http://travis-ci.org/einaros/ws)\n\n# ws: a node.js websocket library #\n\n`ws` is a simple to use websocket implementation, up-to-date against RFC-6455, and [probably the fastest WebSocket library for node.js](http://hobbycoding.posterous.com/the-fastest-websocket-module-for-nodejs).\n\nPasses the quite extensive Autobahn test suite. See http://einaros.github.com/ws for the full reports.\n\nComes with a command line utility, `wscat`, which can either act as a server (--listen), or client (--connect); Use it to debug simple websocket services.\n\n## Protocol support ##\n\n* **Hixie draft 76** (Old and deprecated, but still in use by Safari and Opera. Added to ws version 0.4.2, but server only. Can be disabled by setting the `disableHixie` option to true.)\n* **HyBi drafts 07-12** (Use the option `protocolVersion: 8`, or argument `-p 8` for wscat)\n* **HyBi drafts 13-17** (Current default, alternatively option `protocolVersion: 13`, or argument `-p 13` for wscat)\n\n_See the echo.websocket.org example below for how to use the `protocolVersion` option._\n\n## Usage ##\n\n### Installing ###\n\n`npm install ws`\n\n### Sending and receiving text data ###\n\n```js\nvar WebSocket = require('ws');\nvar ws = new WebSocket('ws://www.host.com/path');\nws.on('open', function() {\n ws.send('something');\n});\nws.on('message', function(data, flags) {\n // flags.binary will be set if a binary data is received\n // flags.masked will be set if the data was masked\n});\n```\n\n### Sending binary data ###\n\n```js\nvar WebSocket = require('ws');\nvar ws = new WebSocket('ws://www.host.com/path');\nws.on('open', function() {\n var array = new Float32Array(5);\n for (var i = 0; i < array.length; ++i) array[i] = i / 2;\n ws.send(array, {binary: true, mask: true});\n});\n```\n\nSetting `mask`, as done for the send options above, will cause the data to be masked according to the websocket protocol. The same option applies for text data.\n\n### Server example ###\n\n```js\nvar WebSocketServer = require('ws').Server\n , wss = new WebSocketServer({port: 8080});\nwss.on('connection', function(ws) {\n ws.on('message', function(message) {\n console.log('received: %s', message);\n });\n ws.send('something');\n});\n```\n\n### Error handling best practices ###\n\n```js\n// If the WebSocket is closed before the following send is attempted\nws.send('something');\n\n// Errors (both immediate and async write errors) can be detected in an optional callback.\n// The callback is also the only way of being notified that data has actually been sent.\nws.send('something', function(error) {\n // if error is null, the send has been completed,\n // otherwise the error object will indicate what failed.\n});\n\n// Immediate errors can also be handled with try/catch-blocks, but **note**\n// that since sends are inherently asynchronous, socket write failures will *not*\n// be captured when this technique is used.\ntry {\n ws.send('something');\n}\ncatch (e) {\n // handle error\n}\n```\n\n### echo.websocket.org demo ###\n\n```js\nvar WebSocket = require('ws');\nvar ws = new WebSocket('ws://echo.websocket.org/', {protocolVersion: 8, origin: 'http://websocket.org'});\nws.on('open', function() {\n console.log('connected');\n ws.send(Date.now().toString(), {mask: true});\n});\nws.on('close', function() {\n console.log('disconnected');\n});\nws.on('message', function(data, flags) {\n console.log('Roundtrip time: ' + (Date.now() - parseInt(data)) + 'ms', flags);\n setTimeout(function() {\n ws.send(Date.now().toString(), {mask: true});\n }, 500);\n});\n```\n\n### wscat against echo.websocket.org ###\n\n $ npm install -g ws\n $ wscat -c ws://echo.websocket.org -p 8\n connected (press CTRL+C to quit)\n > hi there\n < hi there\n > are you a happy parrot?\n < are you a happy parrot?\n\n### Other examples ###\n\nFor a full example with a browser client communicating with a ws server, see the examples folder.\n\nNote that the usage together with Express 3.0 is quite different from Express 2.x. The difference is expressed in the two different serverstats-examples.\n\nOtherwise, see the test cases.\n\n### Running the tests ###\n\n`make test`\n\n## API Docs ##\n\nSee the doc/ directory for Node.js-like docs for the ws classes.\n\n## License ##\n\n(The MIT License)\n\nCopyright (c) 2011 Einar Otto Stangvik <einaros@gmail.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", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/einaros/ws/issues" + }, + "_id": "ws@0.4.27", + "dist": { + "shasum": "be50a5b1f71c0f2aa3e8ff49f4cf0a45f2d59811" + }, + "_from": "ws@", + "_resolved": "https://registry.npmjs.org/ws/-/ws-0.4.27.tgz" +} diff --git a/node_modules/ws/src/bufferutil.cc b/node_modules/ws/src/bufferutil.cc new file mode 100644 index 0000000..866c28b --- /dev/null +++ b/node_modules/ws/src/bufferutil.cc @@ -0,0 +1,115 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace v8; +using namespace node; + +class BufferUtil : public ObjectWrap +{ +public: + + static void Initialize(v8::Handle target) + { + HandleScope scope; + Local t = FunctionTemplate::New(New); + t->InstanceTemplate()->SetInternalFieldCount(1); + NODE_SET_METHOD(t->GetFunction(), "unmask", BufferUtil::Unmask); + NODE_SET_METHOD(t->GetFunction(), "mask", BufferUtil::Mask); + NODE_SET_METHOD(t->GetFunction(), "merge", BufferUtil::Merge); + target->Set(String::NewSymbol("BufferUtil"), t->GetFunction()); + } + +protected: + + static Handle New(const Arguments& args) + { + HandleScope scope; + BufferUtil* bufferUtil = new BufferUtil(); + bufferUtil->Wrap(args.This()); + return args.This(); + } + + static Handle Merge(const Arguments& args) + { + HandleScope scope; + Local bufferObj = args[0]->ToObject(); + char* buffer = Buffer::Data(bufferObj); + Local array = Local::Cast(args[1]); + unsigned int arrayLength = array->Length(); + unsigned int offset = 0; + unsigned int i; + for (i = 0; i < arrayLength; ++i) { + Local src = array->Get(i)->ToObject(); + unsigned int length = Buffer::Length(src); + memcpy(buffer + offset, Buffer::Data(src), length); + offset += length; + } + return scope.Close(True()); + } + + static Handle Unmask(const Arguments& args) + { + HandleScope scope; + Local buffer_obj = args[0]->ToObject(); + unsigned int length = Buffer::Length(buffer_obj); + Local mask_obj = args[1]->ToObject(); + unsigned int *mask = (unsigned int*)Buffer::Data(mask_obj); + unsigned int* from = (unsigned int*)Buffer::Data(buffer_obj); + unsigned int len32 = length / 4; + unsigned int i; + for (i = 0; i < len32; ++i) *(from + i) ^= *mask; + from += i; + switch (length % 4) { + case 3: *((unsigned char*)from+2) = *((unsigned char*)from+2) ^ ((unsigned char*)mask)[2]; + case 2: *((unsigned char*)from+1) = *((unsigned char*)from+1) ^ ((unsigned char*)mask)[1]; + case 1: *((unsigned char*)from ) = *((unsigned char*)from ) ^ ((unsigned char*)mask)[0]; + case 0:; + } + return True(); + } + + static Handle Mask(const Arguments& args) + { + HandleScope scope; + Local buffer_obj = args[0]->ToObject(); + Local mask_obj = args[1]->ToObject(); + unsigned int *mask = (unsigned int*)Buffer::Data(mask_obj); + Local output_obj = args[2]->ToObject(); + unsigned int dataOffset = args[3]->Int32Value(); + unsigned int length = args[4]->Int32Value(); + unsigned int* to = (unsigned int*)(Buffer::Data(output_obj) + dataOffset); + unsigned int* from = (unsigned int*)Buffer::Data(buffer_obj); + unsigned int len32 = length / 4; + unsigned int i; + for (i = 0; i < len32; ++i) *(to + i) = *(from + i) ^ *mask; + to += i; + from += i; + switch (length % 4) { + case 3: *((unsigned char*)to+2) = *((unsigned char*)from+2) ^ *((unsigned char*)mask+2); + case 2: *((unsigned char*)to+1) = *((unsigned char*)from+1) ^ *((unsigned char*)mask+1); + case 1: *((unsigned char*)to ) = *((unsigned char*)from ) ^ *((unsigned char*)mask); + case 0:; + } + return True(); + } +}; + +extern "C" void init (Handle target) +{ + HandleScope scope; + BufferUtil::Initialize(target); +} + +NODE_MODULE(bufferutil, init) diff --git a/node_modules/ws/src/validation.cc b/node_modules/ws/src/validation.cc new file mode 100644 index 0000000..b900164 --- /dev/null +++ b/node_modules/ws/src/validation.cc @@ -0,0 +1,143 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +#include +#include +#include +#include +#include +#include +#include + +using namespace v8; +using namespace node; + +#define UNI_SUR_HIGH_START (uint32_t) 0xD800 +#define UNI_SUR_LOW_END (uint32_t) 0xDFFF +#define UNI_REPLACEMENT_CHAR (uint32_t) 0x0000FFFD +#define UNI_MAX_LEGAL_UTF32 (uint32_t) 0x0010FFFF + +static const uint8_t trailingBytesForUTF8[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +static const uint32_t offsetsFromUTF8[6] = { + 0x00000000, 0x00003080, 0x000E2080, + 0x03C82080, 0xFA082080, 0x82082080 +}; + +static int isLegalUTF8(const uint8_t *source, const int length) +{ + uint8_t a; + const uint8_t *srcptr = source+length; + switch (length) { + default: return 0; + /* Everything else falls through when "true"... */ + /* RFC3629 makes 5 & 6 bytes UTF-8 illegal + case 6: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; + case 5: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; */ + case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; + case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; + case 2: if ((a = (*--srcptr)) > 0xBF) return 0; + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: if (a < 0xA0) return 0; break; + case 0xED: if (a > 0x9F) return 0; break; + case 0xF0: if (a < 0x90) return 0; break; + case 0xF4: if (a > 0x8F) return 0; break; + default: if (a < 0x80) return 0; + } + + case 1: if (*source >= 0x80 && *source < 0xC2) return 0; + } + if (*source > 0xF4) return 0; + return 1; +} + +int is_valid_utf8 (size_t len, char *value) +{ + /* is the string valid UTF-8? */ + for (unsigned int i = 0; i < len; i++) { + uint32_t ch = 0; + uint8_t extrabytes = trailingBytesForUTF8[(uint8_t) value[i]]; + + if (extrabytes + i >= len) + return 0; + + if (isLegalUTF8 ((uint8_t *) (value + i), extrabytes + 1) == 0) return 0; + + switch (extrabytes) { + case 5 : ch += (uint8_t) value[i++]; ch <<= 6; + case 4 : ch += (uint8_t) value[i++]; ch <<= 6; + case 3 : ch += (uint8_t) value[i++]; ch <<= 6; + case 2 : ch += (uint8_t) value[i++]; ch <<= 6; + case 1 : ch += (uint8_t) value[i++]; ch <<= 6; + case 0 : ch += (uint8_t) value[i]; + } + + ch -= offsetsFromUTF8[extrabytes]; + + if (ch <= UNI_MAX_LEGAL_UTF32) { + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) + return 0; + } else { + return 0; + } + } + + return 1; +} + +class Validation : public ObjectWrap +{ +public: + + static void Initialize(v8::Handle target) + { + HandleScope scope; + Local t = FunctionTemplate::New(New); + t->InstanceTemplate()->SetInternalFieldCount(1); + NODE_SET_METHOD(t->GetFunction(), "isValidUTF8", Validation::IsValidUTF8); + target->Set(String::NewSymbol("Validation"), t->GetFunction()); + } + +protected: + + static Handle New(const Arguments& args) + { + HandleScope scope; + Validation* validation = new Validation(); + validation->Wrap(args.This()); + return args.This(); + } + + static Handle IsValidUTF8(const Arguments& args) + { + HandleScope scope; + if (!Buffer::HasInstance(args[0])) { + return ThrowException(Exception::Error(String::New("First argument needs to be a buffer"))); + } + Local buffer_obj = args[0]->ToObject(); + char *buffer_data = Buffer::Data(buffer_obj); + size_t buffer_length = Buffer::Length(buffer_obj); + return is_valid_utf8(buffer_length, buffer_data) == 1 ? scope.Close(True()) : scope.Close(False()); + } +}; + +extern "C" void init (Handle target) +{ + HandleScope scope; + Validation::Initialize(target); +} + +NODE_MODULE(validation, init) diff --git a/node_modules/ws/test/BufferPool.test.js b/node_modules/ws/test/BufferPool.test.js new file mode 100644 index 0000000..1ee7ff0 --- /dev/null +++ b/node_modules/ws/test/BufferPool.test.js @@ -0,0 +1,63 @@ +var BufferPool = require('../lib/BufferPool'); +require('should'); + +describe('BufferPool', function() { + describe('#ctor', function() { + it('allocates pool', function() { + var db = new BufferPool(1000); + db.size.should.eql(1000); + }); + }); + describe('#get', function() { + it('grows the pool if necessary', function() { + var db = new BufferPool(1000); + var buf = db.get(2000); + db.size.should.be.above(1000); + db.used.should.eql(2000); + buf.length.should.eql(2000); + }); + it('grows the pool after the first call, if necessary', function() { + var db = new BufferPool(1000); + var buf = db.get(1000); + db.used.should.eql(1000); + db.size.should.eql(1000); + buf.length.should.eql(1000); + var buf2 = db.get(1000); + db.used.should.eql(2000); + db.size.should.be.above(1000); + buf2.length.should.eql(1000); + }); + it('grows the pool according to the growStrategy if necessary', function() { + var db = new BufferPool(1000, function(db, length) { + return db.size + 2345; + }); + var buf = db.get(2000); + db.size.should.eql(3345); + buf.length.should.eql(2000); + }); + it('doesnt grow the pool if theres enough room available', function() { + var db = new BufferPool(1000); + var buf = db.get(1000); + db.size.should.eql(1000); + buf.length.should.eql(1000); + }); + }); + describe('#reset', function() { + it('shinks the pool', function() { + var db = new BufferPool(1000); + var buf = db.get(2000); + db.reset(true); + db.size.should.eql(1000); + }); + it('shrinks the pool according to the shrinkStrategy', function() { + var db = new BufferPool(1000, function(db, length) { + return db.used + length; + }, function(db) { + return 0; + }); + var buf = db.get(2000); + db.reset(true); + db.size.should.eql(0); + }); + }); +}); diff --git a/node_modules/ws/test/Receiver.hixie.test.js b/node_modules/ws/test/Receiver.hixie.test.js new file mode 100644 index 0000000..043d3bc --- /dev/null +++ b/node_modules/ws/test/Receiver.hixie.test.js @@ -0,0 +1,158 @@ +var assert = require('assert') + , expect = require('expect.js') + , Receiver = require('../lib/Receiver.hixie'); +require('./hybi-common'); + +describe('Receiver', function() { + it('can parse text message', function() { + var p = new Receiver(); + var packet = '00 48 65 6c 6c 6f ff'; + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal('Hello', data); + }; + + p.add(getBufferFromHexString(packet)); + expect(gotData).to.equal(true); + }); + + it('can parse multiple text messages', function() { + var p = new Receiver(); + var packet = '00 48 65 6c 6c 6f ff 00 48 65 6c 6c 6f ff'; + + var gotData = false; + var messages = []; + p.ontext = function(data) { + gotData = true; + messages.push(data); + }; + + p.add(getBufferFromHexString(packet)); + expect(gotData).to.equal(true); + for (var i = 0; i < 2; ++i) { + expect(messages[i]).to.equal('Hello'); + } + }); + + it('can parse empty message', function() { + var p = new Receiver(); + var packet = '00 ff'; + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal('', data); + }; + + p.add(getBufferFromHexString(packet)); + expect(gotData).to.equal(true); + }); + + it('can parse text messages delivered over multiple frames', function() { + var p = new Receiver(); + var packets = [ + '00 48', + '65 6c 6c', + '6f ff 00 48', + '65', + '6c 6c 6f', + 'ff' + ]; + + var gotData = false; + var messages = []; + p.ontext = function(data) { + gotData = true; + messages.push(data); + }; + + for (var i = 0; i < packets.length; ++i) { + p.add(getBufferFromHexString(packets[i])); + } + expect(gotData).to.equal(true); + for (var i = 0; i < 2; ++i) { + expect(messages[i]).to.equal('Hello'); + } + }); + + it('emits an error if a payload doesnt start with 0x00', function() { + var p = new Receiver(); + var packets = [ + '00 6c ff', + '00 6c ff ff', + 'ff 00 6c ff 00 6c ff', + '00', + '6c 6c 6f', + 'ff' + ]; + + var gotData = false; + var gotError = false; + var messages = []; + p.ontext = function(data) { + gotData = true; + messages.push(data); + }; + p.onerror = function(reason, code) { + gotError = code == true; + }; + + for (var i = 0; i < packets.length && !gotError; ++i) { + p.add(getBufferFromHexString(packets[i])); + } + expect(gotError).to.equal(true); + expect(messages[0]).to.equal('l'); + expect(messages[1]).to.equal('l'); + expect(messages.length).to.equal(2); + }); + + it('can parse close messages', function() { + var p = new Receiver(); + var packets = [ + 'ff 00' + ]; + + var gotClose = false; + var gotError = false; + p.onclose = function() { + gotClose = true; + }; + p.onerror = function(reason, code) { + gotError = code == true; + }; + + for (var i = 0; i < packets.length && !gotError; ++i) { + p.add(getBufferFromHexString(packets[i])); + } + expect(gotClose).to.equal(true); + expect(gotError).to.equal(false); + }); + + it('can parse binary messages delivered over multiple frames', function() { + var p = new Receiver(); + var packets = [ + '80 05 48', + '65 6c 6c', + '6f 80 80 05 48', + '65', + '6c 6c 6f' + ]; + + var gotData = false; + var messages = []; + p.ontext = function(data) { + gotData = true; + messages.push(data); + }; + + for (var i = 0; i < packets.length; ++i) { + p.add(getBufferFromHexString(packets[i])); + } + expect(gotData).to.equal(true); + for (var i = 0; i < 2; ++i) { + expect(messages[i]).to.equal('Hello'); + } + }); +}); diff --git a/node_modules/ws/test/Receiver.test.js b/node_modules/ws/test/Receiver.test.js new file mode 100644 index 0000000..b0b5c0a --- /dev/null +++ b/node_modules/ws/test/Receiver.test.js @@ -0,0 +1,255 @@ +var assert = require('assert') + , Receiver = require('../lib/Receiver'); +require('should'); +require('./hybi-common'); + +describe('Receiver', function() { + it('can parse unmasked text message', function() { + var p = new Receiver(); + var packet = '81 05 48 65 6c 6c 6f'; + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal('Hello', data); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); + it('can parse close message', function() { + var p = new Receiver(); + var packet = '88 00'; + + var gotClose = false; + p.onclose = function(data) { + gotClose = true; + }; + + p.add(getBufferFromHexString(packet)); + gotClose.should.be.ok; + }); + it('can parse masked text message', function() { + var p = new Receiver(); + var packet = '81 93 34 83 a8 68 01 b9 92 52 4f a1 c6 09 59 e6 8a 52 16 e6 cb 00 5b a1 d5'; + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal('5:::{"name":"echo"}', data); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); + it('can parse a masked text message longer than 125 bytes', function() { + var p = new Receiver(); + var message = 'A'; + for (var i = 0; i < 300; ++i) message += (i % 5).toString(); + var packet = '81 FE ' + pack(4, message.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68')); + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal(message, data); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); + it('can parse a really long masked text message', function() { + var p = new Receiver(); + var message = 'A'; + for (var i = 0; i < 64*1024; ++i) message += (i % 5).toString(); + var packet = '81 FF ' + pack(16, message.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68')); + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal(message, data); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); + it('can parse a fragmented masked text message of 300 bytes', function() { + var p = new Receiver(); + var message = 'A'; + for (var i = 0; i < 300; ++i) message += (i % 5).toString(); + var msgpiece1 = message.substr(0, 150); + var msgpiece2 = message.substr(150); + var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece1, '34 83 a8 68')); + var packet2 = '80 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece2, '34 83 a8 68')); + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal(message, data); + }; + + p.add(getBufferFromHexString(packet1)); + p.add(getBufferFromHexString(packet2)); + gotData.should.be.ok; + }); + it('can parse a ping message', function() { + var p = new Receiver(); + var message = 'Hello'; + var packet = '89 ' + getHybiLengthAsHexString(message.length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68')); + + var gotPing = false; + p.onping = function(data) { + gotPing = true; + assert.equal(message, data); + }; + + p.add(getBufferFromHexString(packet)); + gotPing.should.be.ok; + }); + it('can parse a ping with no data', function() { + var p = new Receiver(); + var packet = '89 00'; + + var gotPing = false; + p.onping = function(data) { + gotPing = true; + }; + + p.add(getBufferFromHexString(packet)); + gotPing.should.be.ok; + }); + it('can parse a fragmented masked text message of 300 bytes with a ping in the middle', function() { + var p = new Receiver(); + var message = 'A'; + for (var i = 0; i < 300; ++i) message += (i % 5).toString(); + + var msgpiece1 = message.substr(0, 150); + var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece1, '34 83 a8 68')); + + var pingMessage = 'Hello'; + var pingPacket = '89 ' + getHybiLengthAsHexString(pingMessage.length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(pingMessage, '34 83 a8 68')); + + var msgpiece2 = message.substr(150); + var packet2 = '80 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece2, '34 83 a8 68')); + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal(message, data); + }; + var gotPing = false; + p.onping = function(data) { + gotPing = true; + assert.equal(pingMessage, data); + }; + + p.add(getBufferFromHexString(packet1)); + p.add(getBufferFromHexString(pingPacket)); + p.add(getBufferFromHexString(packet2)); + gotData.should.be.ok; + gotPing.should.be.ok; + }); + it('can parse a fragmented masked text message of 300 bytes with a ping in the middle, which is delievered over sevaral tcp packets', function() { + var p = new Receiver(); + var message = 'A'; + for (var i = 0; i < 300; ++i) message += (i % 5).toString(); + + var msgpiece1 = message.substr(0, 150); + var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece1, '34 83 a8 68')); + + var pingMessage = 'Hello'; + var pingPacket = '89 ' + getHybiLengthAsHexString(pingMessage.length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(pingMessage, '34 83 a8 68')); + + var msgpiece2 = message.substr(150); + var packet2 = '80 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece2, '34 83 a8 68')); + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal(message, data); + }; + var gotPing = false; + p.onping = function(data) { + gotPing = true; + assert.equal(pingMessage, data); + }; + + var buffers = []; + buffers = buffers.concat(splitBuffer(getBufferFromHexString(packet1))); + buffers = buffers.concat(splitBuffer(getBufferFromHexString(pingPacket))); + buffers = buffers.concat(splitBuffer(getBufferFromHexString(packet2))); + for (var i = 0; i < buffers.length; ++i) { + p.add(buffers[i]); + } + gotData.should.be.ok; + gotPing.should.be.ok; + }); + it('can parse a 100 byte long masked binary message', function() { + var p = new Receiver(); + var length = 100; + var message = new Buffer(length); + for (var i = 0; i < length; ++i) message[i] = i % 256; + var originalMessage = getHexStringFromBuffer(message); + var packet = '82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68')); + + var gotData = false; + p.onbinary = function(data) { + gotData = true; + assert.equal(originalMessage, getHexStringFromBuffer(data)); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); + it('can parse a 256 byte long masked binary message', function() { + var p = new Receiver(); + var length = 256; + var message = new Buffer(length); + for (var i = 0; i < length; ++i) message[i] = i % 256; + var originalMessage = getHexStringFromBuffer(message); + var packet = '82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68')); + + var gotData = false; + p.onbinary = function(data) { + gotData = true; + assert.equal(originalMessage, getHexStringFromBuffer(data)); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); + it('can parse a 200kb long masked binary message', function() { + var p = new Receiver(); + var length = 200 * 1024; + var message = new Buffer(length); + for (var i = 0; i < length; ++i) message[i] = i % 256; + var originalMessage = getHexStringFromBuffer(message); + var packet = '82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68')); + + var gotData = false; + p.onbinary = function(data) { + gotData = true; + assert.equal(originalMessage, getHexStringFromBuffer(data)); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); + it('can parse a 200kb long unmasked binary message', function() { + var p = new Receiver(); + var length = 200 * 1024; + var message = new Buffer(length); + for (var i = 0; i < length; ++i) message[i] = i % 256; + var originalMessage = getHexStringFromBuffer(message); + var packet = '82 ' + getHybiLengthAsHexString(length, false) + ' ' + getHexStringFromBuffer(message); + + var gotData = false; + p.onbinary = function(data) { + gotData = true; + assert.equal(originalMessage, getHexStringFromBuffer(data)); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); +}); + diff --git a/node_modules/ws/test/Sender.hixie.test.js b/node_modules/ws/test/Sender.hixie.test.js new file mode 100644 index 0000000..783f892 --- /dev/null +++ b/node_modules/ws/test/Sender.hixie.test.js @@ -0,0 +1,134 @@ +var assert = require('assert') + , Sender = require('../lib/Sender.hixie'); +require('should'); +require('./hybi-common'); + +describe('Sender', function() { + describe('#send', function() { + it('frames and sends a text message', function(done) { + var message = 'Hello world'; + var received; + var socket = { + write: function(data, encoding, cb) { + received = data; + process.nextTick(cb); + } + }; + var sender = new Sender(socket, {}); + sender.send(message, {}, function() { + received.toString('utf8').should.eql('\u0000' + message + '\ufffd'); + done(); + }); + }); + + it('frames and sends an empty message', function(done) { + var socket = { + write: function(data, encoding, cb) { + done(); + } + }; + var sender = new Sender(socket, {}); + sender.send('', {}, function() {}); + }); + + it('frames and sends a buffer', function(done) { + var received; + var socket = { + write: function(data, encoding, cb) { + received = data; + process.nextTick(cb); + } + }; + var sender = new Sender(socket, {}); + sender.send(new Buffer('foobar'), {}, function() { + received.toString('utf8').should.eql('\u0000foobar\ufffd'); + done(); + }); + }); + + it('frames and sends a binary message', function(done) { + var message = 'Hello world'; + var received; + var socket = { + write: function(data, encoding, cb) { + received = data; + process.nextTick(cb); + } + }; + var sender = new Sender(socket, {}); + sender.send(message, {binary: true}, function() { + received.toString('hex').should.eql( + // 0x80 0x0b H e l l o w o r l d + '800b48656c6c6f20776f726c64'); + done(); + }); + }); +/* + it('throws an exception for binary data', function(done) { + var socket = { + write: function(data, encoding, cb) { + process.nextTick(cb); + } + }; + var sender = new Sender(socket, {}); + sender.on('error', function() { + done(); + }); + sender.send(new Buffer(100), {binary: true}, function() {}); + }); +*/ + it('can fauxe stream data', function(done) { + var received = []; + var socket = { + write: function(data, encoding, cb) { + received.push(data); + process.nextTick(cb); + } + }; + var sender = new Sender(socket, {}); + sender.send(new Buffer('foobar'), { fin: false }, function() {}); + sender.send('bazbar', { fin: false }, function() {}); + sender.send(new Buffer('end'), { fin: true }, function() { + received[0].toString('utf8').should.eql('\u0000foobar'); + received[1].toString('utf8').should.eql('bazbar'); + received[2].toString('utf8').should.eql('end\ufffd'); + done(); + }); + }); + }); + + describe('#close', function() { + it('sends a hixie close frame', function(done) { + var received; + var socket = { + write: function(data, encoding, cb) { + received = data; + process.nextTick(cb); + } + }; + var sender = new Sender(socket, {}); + sender.close(null, null, null, function() { + received.toString('utf8').should.eql('\ufffd\u0000'); + done(); + }); + }); + + it('sends a message end marker if fauxe streaming has started, before hixie close frame', function(done) { + var received = []; + var socket = { + write: function(data, encoding, cb) { + received.push(data); + if (cb) process.nextTick(cb); + } + }; + var sender = new Sender(socket, {}); + sender.send(new Buffer('foobar'), { fin: false }, function() {}); + sender.close(null, null, null, function() { + received[0].toString('utf8').should.eql('\u0000foobar'); + received[1].toString('utf8').should.eql('\ufffd'); + received[2].toString('utf8').should.eql('\ufffd\u0000'); + done(); + }); + }); + }); +}); diff --git a/node_modules/ws/test/Sender.test.js b/node_modules/ws/test/Sender.test.js new file mode 100644 index 0000000..43b4864 --- /dev/null +++ b/node_modules/ws/test/Sender.test.js @@ -0,0 +1,24 @@ +var Sender = require('../lib/Sender'); +require('should'); + +describe('Sender', function() { + describe('#frameAndSend', function() { + it('does not modify a masked binary buffer', function() { + var sender = new Sender({ write: function() {} }); + var buf = new Buffer([1, 2, 3, 4, 5]); + sender.frameAndSend(2, buf, true, true); + buf[0].should.eql(1); + buf[1].should.eql(2); + buf[2].should.eql(3); + buf[3].should.eql(4); + buf[4].should.eql(5); + }); + + it('does not modify a masked text buffer', function() { + var sender = new Sender({ write: function() {} }); + var text = 'hi there'; + sender.frameAndSend(1, text, true, true); + text.should.eql('hi there'); + }); + }); +}); diff --git a/node_modules/ws/test/Validation.test.js b/node_modules/ws/test/Validation.test.js new file mode 100644 index 0000000..37c3399 --- /dev/null +++ b/node_modules/ws/test/Validation.test.js @@ -0,0 +1,23 @@ +var Validation = require('../lib/Validation').Validation; +require('should'); + +describe('Validation', function() { + describe('isValidUTF8', function() { + it('should return true for a valid utf8 string', function() { + var validBuffer = new Buffer('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque gravida mattis rhoncus. Donec iaculis, metus quis varius accumsan, erat mauris condimentum diam, et egestas erat enim ut ligula. Praesent sollicitudin tellus eget dolor euismod euismod. Nullam ac augue nec neque varius luctus. Curabitur elit mi, consequat ultricies adipiscing mollis, scelerisque in erat. Phasellus facilisis fermentum ullamcorper. Nulla et sem eu arcu pharetra pellentesque. Praesent consectetur tempor justo, vel iaculis dui ullamcorper sit amet. Integer tristique viverra ullamcorper. Vivamus laoreet, nulla eget suscipit eleifend, lacus lectus feugiat libero, non fermentum erat nisi at risus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut pulvinar dignissim tellus, eu dignissim lorem vulputate quis. Morbi ut pulvinar augue.'); + Validation.isValidUTF8(validBuffer).should.be.ok; + }); + it('should return false for an erroneous string', function() { + var invalidBuffer = new Buffer([0xce, 0xba, 0xe1, 0xbd, 0xb9, 0xcf, 0x83, 0xce, 0xbc, 0xce, 0xb5, 0xed, 0xa0, 0x80, 0x65, 0x64, 0x69, 0x74, 0x65, 0x64]); + Validation.isValidUTF8(invalidBuffer).should.not.be.ok; + }); + it('should return true for valid cases from the autobahn test suite', function() { + Validation.isValidUTF8(new Buffer('\xf0\x90\x80\x80')).should.be.ok; + Validation.isValidUTF8(new Buffer([0xf0, 0x90, 0x80, 0x80])).should.be.ok; + }); + it('should return false for erroneous autobahn strings', function() { + Validation.isValidUTF8(new Buffer([0xce, 0xba, 0xe1, 0xbd])).should.not.be.ok; + }); + }); +}); + diff --git a/node_modules/ws/test/WebSocket.integration.js b/node_modules/ws/test/WebSocket.integration.js new file mode 100644 index 0000000..51a7e3a --- /dev/null +++ b/node_modules/ws/test/WebSocket.integration.js @@ -0,0 +1,42 @@ +var assert = require('assert') + , WebSocket = require('../') + , server = require('./testserver'); + +var port = 20000; + +function getArrayBuffer(buf) { + var l = buf.length; + var arrayBuf = new ArrayBuffer(l); + for (var i = 0; i < l; ++i) { + arrayBuf[i] = buf[i]; + } + return arrayBuf; +} + +function areArraysEqual(x, y) { + if (x.length != y.length) return false; + for (var i = 0, l = x.length; i < l; ++i) { + if (x[i] !== y[i]) return false; + } + return true; +} + +describe('WebSocket', function() { + it('communicates successfully with echo service', function(done) { + var ws = new WebSocket('ws://echo.websocket.org', {protocolVersion: 8, origin: 'http://websocket.org'}); + var str = Date.now().toString(); + var dataReceived = false; + ws.on('open', function() { + ws.send(str, {mask: true}); + }); + ws.on('close', function() { + assert.equal(true, dataReceived); + done(); + }); + ws.on('message', function(data, flags) { + assert.equal(str, data); + ws.terminate(); + dataReceived = true; + }); + }); +}); \ No newline at end of file diff --git a/node_modules/ws/test/WebSocket.test.js b/node_modules/ws/test/WebSocket.test.js new file mode 100644 index 0000000..93e95da --- /dev/null +++ b/node_modules/ws/test/WebSocket.test.js @@ -0,0 +1,1609 @@ +var assert = require('assert') + , https = require('https') + , http = require('http') + , should = require('should') + , WebSocket = require('../') + , WebSocketServer = require('../').Server + , fs = require('fs') + , server = require('./testserver') + , crypto = require('crypto'); + +var port = 20000; + +function getArrayBuffer(buf) { + var l = buf.length; + var arrayBuf = new ArrayBuffer(l); + for (var i = 0; i < l; ++i) { + arrayBuf[i] = buf[i]; + } + return arrayBuf; +} + +function areArraysEqual(x, y) { + if (x.length != y.length) return false; + for (var i = 0, l = x.length; i < l; ++i) { + if (x[i] !== y[i]) return false; + } + return true; +} + +describe('WebSocket', function() { + describe('#ctor', function() { + it('throws exception for invalid url', function(done) { + try { + var ws = new WebSocket('echo.websocket.org'); + } + catch (e) { + done(); + } + }); + }); + + describe('properties', function() { + it('#bytesReceived exposes number of bytes received', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('message', function() { + ws.bytesReceived.should.eql(8); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + ws.send('foobar'); + }); + }); + + it('#url exposes the server url', function(done) { + server.createServer(++port, function(srv) { + var url = 'ws://localhost:' + port; + var ws = new WebSocket(url); + assert.equal(url, ws.url); + ws.terminate(); + ws.on('close', function() { + srv.close(); + done(); + }); + }); + }); + + it('#protocolVersion exposes the protocol version', function(done) { + server.createServer(++port, function(srv) { + var url = 'ws://localhost:' + port; + var ws = new WebSocket(url); + assert.equal(13, ws.protocolVersion); + ws.terminate(); + ws.on('close', function() { + srv.close(); + done(); + }); + }); + }); + + describe('#bufferedAmount', function() { + it('defaults to zero', function(done) { + server.createServer(++port, function(srv) { + var url = 'ws://localhost:' + port; + var ws = new WebSocket(url); + assert.equal(0, ws.bufferedAmount); + ws.terminate(); + ws.on('close', function() { + srv.close(); + done(); + }); + }); + }); + + it('stress kernel write buffer', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(ws) { + while (true) { + if (ws.bufferedAmount > 0) break; + ws.send((new Array(10000)).join('hello')); + } + ws.terminate(); + ws.on('close', function() { + wss.close(); + done(); + }); + }); + }); + }); + + describe('#readyState', function() { + it('defaults to connecting', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + assert.equal(WebSocket.CONNECTING, ws.readyState); + ws.terminate(); + ws.on('close', function() { + srv.close(); + done(); + }); + }); + }); + + it('set to open once connection is established', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + assert.equal(WebSocket.OPEN, ws.readyState); + srv.close(); + done(); + }); + }); + }); + + it('set to closed once connection is closed', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.close(1001); + ws.on('close', function() { + assert.equal(WebSocket.CLOSED, ws.readyState); + srv.close(); + done(); + }); + }); + }); + + it('set to closed once connection is terminated', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.terminate(); + ws.on('close', function() { + assert.equal(WebSocket.CLOSED, ws.readyState); + srv.close(); + done(); + }); + }); + }); + }); + + /* + * Ready state constants + */ + + var readyStates = { + CONNECTING: 0, + OPEN: 1, + CLOSING: 2, + CLOSED: 3 + }; + + /* + * Ready state constant tests + */ + + Object.keys(readyStates).forEach(function(state) { + describe('.' + state, function() { + it('is enumerable property of class', function() { + var propertyDescripter = Object.getOwnPropertyDescriptor(WebSocket, state) + assert.equal(readyStates[state], propertyDescripter.value); + assert.equal(true, propertyDescripter.enumerable); + }); + }); + }); + + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + Object.keys(readyStates).forEach(function(state) { + describe('.' + state, function() { + it('is property of instance', function() { + assert.equal(readyStates[state], ws[state]); + }); + }); + }); + }); + }); + + describe('events', function() { + it('emits a ping event', function(done) { + var wss = new WebSocketServer({port: ++port}); + wss.on('connection', function(client) { + client.ping(); + }); + var ws = new WebSocket('ws://localhost:' + port); + ws.on('ping', function() { + ws.terminate(); + wss.close(); + done(); + }); + }); + + it('emits a pong event', function(done) { + var wss = new WebSocketServer({port: ++port}); + wss.on('connection', function(client) { + client.pong(); + }); + var ws = new WebSocket('ws://localhost:' + port); + ws.on('pong', function() { + ws.terminate(); + wss.close(); + done(); + }); + }); + }); + + describe('connection establishing', function() { + it('can disconnect before connection is established', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.terminate(); + ws.on('open', function() { + assert.fail('connect shouldnt be raised here'); + }); + ws.on('close', function() { + srv.close(); + done(); + }); + }); + }); + + it('can close before connection is established', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.close(1001); + ws.on('open', function() { + assert.fail('connect shouldnt be raised here'); + }); + ws.on('close', function() { + srv.close(); + done(); + }); + }); + }); + + it('invalid server key is denied', function(done) { + server.createServer(++port, server.handlers.invalidKey, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() { + srv.close(); + done(); + }); + }); + }); + + it('close event is raised when server closes connection', function(done) { + server.createServer(++port, server.handlers.closeAfterConnect, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('close', function() { + srv.close(); + done(); + }); + }); + }); + + it('error is emitted if server aborts connection', function(done) { + server.createServer(++port, server.handlers.return401, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + assert.fail('connect shouldnt be raised here'); + }); + ws.on('error', function() { + srv.close(); + done(); + }); + }); + }); + }); + + describe('#pause and #resume', function() { + it('pauses the underlying stream', function(done) { + // this test is sort-of racecondition'y, since an unlikely slow connection + // to localhost can cause the test to succeed even when the stream pausing + // isn't working as intended. that is an extremely unlikely scenario, though + // and an acceptable risk for the test. + var client; + var serverClient; + var openCount = 0; + function onOpen() { + if (++openCount == 2) { + var paused = true; + serverClient.on('message', function() { + paused.should.not.be.ok; + wss.close(); + done(); + }); + serverClient.pause(); + setTimeout(function() { + paused = false; + serverClient.resume(); + }, 200); + client.send('foo'); + } + } + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + serverClient = ws; + serverClient.on('open', onOpen); + }); + wss.on('connection', function(ws) { + client = ws; + onOpen(); + }); + }); + }); + + describe('#ping', function() { + it('before connect should fail', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() {}); + try { + ws.ping(); + } + catch (e) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + + it('before connect can silently fail', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() {}); + ws.ping('', {}, true); + srv.close(); + ws.terminate(); + done(); + }); + }); + + it('without message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.ping(); + }); + srv.on('ping', function(message) { + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.ping('hi'); + }); + srv.on('ping', function(message) { + assert.equal('hi', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with encoded message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.ping('hi', {mask: true}); + }); + srv.on('ping', function(message, flags) { + assert.ok(flags.masked); + assert.equal('hi', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + }); + + describe('#pong', function() { + it('before connect should fail', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() {}); + try { + ws.pong(); + } + catch (e) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + + it('before connect can silently fail', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() {}); + ws.pong('', {}, true); + srv.close(); + ws.terminate(); + done(); + }); + }); + + it('without message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.pong(); + }); + srv.on('pong', function(message) { + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.pong('hi'); + }); + srv.on('pong', function(message) { + assert.equal('hi', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with encoded message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.pong('hi', {mask: true}); + }); + srv.on('pong', function(message, flags) { + assert.ok(flags.masked); + assert.equal('hi', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + }); + + describe('#send', function() { + it('very long binary data can be sent and received (with echoing server)', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var array = new Float32Array(5 * 1024 * 1024); + for (var i = 0; i < array.length; ++i) array[i] = i / 5; + ws.on('open', function() { + ws.send(array, {binary: true}); + }); + ws.on('message', function(message, flags) { + assert.ok(flags.binary); + assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('can send and receive text data', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.send('hi'); + }); + ws.on('message', function(message, flags) { + assert.equal('hi', message); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('send and receive binary data as an array', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var array = new Float32Array(5); + for (var i = 0; i < array.length; ++i) array[i] = i / 2; + ws.on('open', function() { + ws.send(array, {binary: true}); + }); + ws.on('message', function(message, flags) { + assert.ok(flags.binary); + assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('binary data can be sent and received as buffer', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var buf = new Buffer('foobar'); + ws.on('open', function() { + ws.send(buf, {binary: true}); + }); + ws.on('message', function(message, flags) { + assert.ok(flags.binary); + assert.ok(areArraysEqual(buf, message)); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('ArrayBuffer is auto-detected without binary flag', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var array = new Float32Array(5); + for (var i = 0; i < array.length; ++i) array[i] = i / 2; + ws.on('open', function() { + ws.send(array.buffer); + }); + ws.onmessage = function (event) { + assert.ok(event.type = 'Binary'); + assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(event.data)))); + ws.terminate(); + srv.close(); + done(); + }; + }); + }); + + it('Buffer is auto-detected without binary flag', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var buf = new Buffer('foobar'); + ws.on('open', function() { + ws.send(buf); + }); + ws.onmessage = function (event) { + assert.ok(event.type = 'Binary'); + assert.ok(areArraysEqual(event.data, buf)); + ws.terminate(); + srv.close(); + done(); + }; + }); + }); + + it('before connect should fail', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() {}); + try { + ws.send('hi'); + } + catch (e) { + ws.terminate(); + srv.close(); + done(); + } + }); + }); + + it('before connect should pass error through callback, if present', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() {}); + ws.send('hi', function(error) { + assert.ok(error instanceof Error); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('without data should be successful', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.send(); + }); + srv.on('message', function(message, flags) { + assert.equal('', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('calls optional callback when flushed', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.send('hi', function() { + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + }); + + it('with unencoded message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.send('hi'); + }); + srv.on('message', function(message, flags) { + assert.equal('hi', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with encoded message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.send('hi', {mask: true}); + }); + srv.on('message', function(message, flags) { + assert.ok(flags.masked); + assert.equal('hi', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with unencoded binary message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var array = new Float32Array(5); + for (var i = 0; i < array.length; ++i) array[i] = i / 2; + ws.on('open', function() { + ws.send(array, {binary: true}); + }); + srv.on('message', function(message, flags) { + assert.ok(flags.binary); + assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with encoded binary message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var array = new Float32Array(5); + for (var i = 0; i < array.length; ++i) array[i] = i / 2; + ws.on('open', function() { + ws.send(array, {mask: true, binary: true}); + }); + srv.on('message', function(message, flags) { + assert.ok(flags.binary); + assert.ok(flags.masked); + assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with binary stream will send fragmented data', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var callbackFired = false; + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.bufferSize = 100; + ws.send(fileStream, {binary: true}, function(error) { + assert.equal(null, error); + callbackFired = true; + }); + }); + srv.on('message', function(data, flags) { + assert.ok(flags.binary); + assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile'), data)); + ws.terminate(); + }); + ws.on('close', function() { + assert.ok(callbackFired); + srv.close(); + done(); + }); + }); + }); + + it('with text stream will send fragmented data', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var callbackFired = false; + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.setEncoding('utf8'); + fileStream.bufferSize = 100; + ws.send(fileStream, {binary: false}, function(error) { + assert.equal(null, error); + callbackFired = true; + }); + }); + srv.on('message', function(data, flags) { + assert.ok(!flags.binary); + assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); + ws.terminate(); + }); + ws.on('close', function() { + assert.ok(callbackFired); + srv.close(); + done(); + }); + }); + }); + + it('will cause intermittent send to be delayed in order', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.setEncoding('utf8'); + fileStream.bufferSize = 100; + ws.send(fileStream); + ws.send('foobar'); + ws.send('baz'); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + ++receivedIndex; + if (receivedIndex == 1) { + assert.ok(!flags.binary); + assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); + } + else if (receivedIndex == 2) { + assert.ok(!flags.binary); + assert.equal('foobar', data); + } + else { + assert.ok(!flags.binary); + assert.equal('baz', data); + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent stream to be delayed in order', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.setEncoding('utf8'); + fileStream.bufferSize = 100; + ws.send(fileStream); + var i = 0; + ws.stream(function(error, send) { + assert.ok(!error); + if (++i == 1) send('foo'); + else send('bar', true); + }); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + ++receivedIndex; + if (receivedIndex == 1) { + assert.ok(!flags.binary); + assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); + } + else if (receivedIndex == 2) { + assert.ok(!flags.binary); + assert.equal('foobar', data); + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent ping to be delivered', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.setEncoding('utf8'); + fileStream.bufferSize = 100; + ws.send(fileStream); + ws.ping('foobar'); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + assert.ok(!flags.binary); + assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + srv.on('ping', function(data) { + assert.equal('foobar', data); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent pong to be delivered', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.setEncoding('utf8'); + fileStream.bufferSize = 100; + ws.send(fileStream); + ws.pong('foobar'); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + assert.ok(!flags.binary); + assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + srv.on('pong', function(data) { + assert.equal('foobar', data); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent close to be delivered', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.setEncoding('utf8'); + fileStream.bufferSize = 100; + ws.send(fileStream); + ws.close(1000, 'foobar'); + }); + ws.on('close', function() { + srv.close(); + ws.terminate(); + done(); + }); + ws.on('error', function() { /* That's quite alright -- a send was attempted after close */ }); + srv.on('message', function(data, flags) { + assert.ok(!flags.binary); + assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); + }); + srv.on('close', function(code, data) { + assert.equal(1000, code); + assert.equal('foobar', data); + }); + }); + }); + }); + + describe('#stream', function() { + it('very long binary data can be streamed', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var buffer = new Buffer(10 * 1024); + for (var i = 0; i < buffer.length; ++i) buffer[i] = i % 0xff; + ws.on('open', function() { + var i = 0; + var blockSize = 800; + var bufLen = buffer.length; + ws.stream({binary: true}, function(error, send) { + assert.ok(!error); + var start = i * blockSize; + var toSend = Math.min(blockSize, bufLen - (i * blockSize)); + var end = start + toSend; + var isFinal = toSend < blockSize; + send(buffer.slice(start, end), isFinal); + i += 1; + }); + }); + srv.on('message', function(data, flags) { + assert.ok(flags.binary); + assert.ok(areArraysEqual(buffer, data)); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('before connect should pass error through callback', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() {}); + ws.stream(function(error) { + assert.ok(error instanceof Error); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('without callback should fail', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var payload = 'HelloWorld'; + ws.on('open', function() { + try { + ws.stream(); + } + catch (e) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent send to be delayed in order', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var payload = 'HelloWorld'; + ws.on('open', function() { + var i = 0; + ws.stream(function(error, send) { + assert.ok(!error); + if (++i == 1) { + send(payload.substr(0, 5)); + ws.send('foobar'); + ws.send('baz'); + } + else { + send(payload.substr(5, 5), true); + } + }); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + ++receivedIndex; + if (receivedIndex == 1) { + assert.ok(!flags.binary); + assert.equal(payload, data); + } + else if (receivedIndex == 2) { + assert.ok(!flags.binary); + assert.equal('foobar', data); + } + else { + assert.ok(!flags.binary); + assert.equal('baz', data); + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent stream to be delayed in order', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var payload = 'HelloWorld'; + ws.on('open', function() { + var i = 0; + ws.stream(function(error, send) { + assert.ok(!error); + if (++i == 1) { + send(payload.substr(0, 5)); + var i2 = 0; + ws.stream(function(error, send) { + assert.ok(!error); + if (++i2 == 1) send('foo'); + else send('bar', true); + }); + ws.send('baz'); + } + else send(payload.substr(5, 5), true); + }); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + ++receivedIndex; + if (receivedIndex == 1) { + assert.ok(!flags.binary); + assert.equal(payload, data); + } + else if (receivedIndex == 2) { + assert.ok(!flags.binary); + assert.equal('foobar', data); + } + else if (receivedIndex == 3){ + assert.ok(!flags.binary); + assert.equal('baz', data); + setTimeout(function() { + srv.close(); + ws.terminate(); + done(); + }, 1000); + } + else throw new Error('more messages than we actually sent just arrived'); + }); + }); + }); + + it('will cause intermittent ping to be delivered', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var payload = 'HelloWorld'; + ws.on('open', function() { + var i = 0; + ws.stream(function(error, send) { + assert.ok(!error); + if (++i == 1) { + send(payload.substr(0, 5)); + ws.ping('foobar'); + } + else { + send(payload.substr(5, 5), true); + } + }); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + assert.ok(!flags.binary); + assert.equal(payload, data); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + srv.on('ping', function(data) { + assert.equal('foobar', data); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent pong to be delivered', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var payload = 'HelloWorld'; + ws.on('open', function() { + var i = 0; + ws.stream(function(error, send) { + assert.ok(!error); + if (++i == 1) { + send(payload.substr(0, 5)); + ws.pong('foobar'); + } + else { + send(payload.substr(5, 5), true); + } + }); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + assert.ok(!flags.binary); + assert.equal(payload, data); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + srv.on('pong', function(data) { + assert.equal('foobar', data); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent close to be delivered', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var payload = 'HelloWorld'; + var errorGiven = false; + ws.on('open', function() { + var i = 0; + ws.stream(function(error, send) { + if (++i == 1) { + send(payload.substr(0, 5)); + ws.close(1000, 'foobar'); + } + else if(i == 2) { + send(payload.substr(5, 5), true); + } + else if (i == 3) { + assert.ok(error); + errorGiven = true; + } + }); + }); + ws.on('close', function() { + assert.ok(errorGiven); + srv.close(); + ws.terminate(); + done(); + }); + srv.on('message', function(data, flags) { + assert.ok(!flags.binary); + assert.equal(payload, data); + }); + srv.on('close', function(code, data) { + assert.equal(1000, code); + assert.equal('foobar', data); + }); + }); + }); + }); + + describe('#close', function() { + it('will raise error callback, if any, if called during send stream', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var errorGiven = false; + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.setEncoding('utf8'); + fileStream.bufferSize = 100; + ws.send(fileStream, function(error) { + errorGiven = error != null; + }); + ws.close(1000, 'foobar'); + }); + ws.on('close', function() { + setTimeout(function() { + assert.ok(errorGiven); + srv.close(); + ws.terminate(); + done(); + }, 1000); + }); + }); + }); + + it('without invalid first argument throws exception', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + try { + ws.close('error'); + } + catch (e) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('without reserved error code 1004 throws exception', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + try { + ws.close(1004); + } + catch (e) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('without message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.close(1000); + }); + srv.on('close', function(code, message, flags) { + assert.equal('', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.close(1000, 'some reason'); + }); + srv.on('close', function(code, message, flags) { + assert.ok(flags.masked); + assert.equal('some reason', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with encoded message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.close(1000, 'some reason', {mask: true}); + }); + srv.on('close', function(code, message, flags) { + assert.ok(flags.masked); + assert.equal('some reason', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('ends connection to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var connectedOnce = false; + ws.on('open', function() { + connectedOnce = true; + ws.close(1000, 'some reason', {mask: true}); + }); + ws.on('close', function() { + assert.ok(connectedOnce); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + }); + + describe('W3C API emulation', function() { + it('should not throw errors when getting and setting', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var listener = function () {}; + + ws.onmessage = listener; + ws.onerror = listener; + ws.onclose = listener; + ws.onopen = listener; + + assert.ok(ws.onopen === listener); + assert.ok(ws.onmessage === listener); + assert.ok(ws.onclose === listener); + assert.ok(ws.onerror === listener); + + srv.close(); + ws.terminate(); + done(); + }); + }); + + it('should work the same as the EventEmitter api', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var listener = function() {}; + var message = 0; + var close = 0; + var open = 0; + + ws.onmessage = function(messageEvent) { + assert.ok(!!messageEvent.data); + ++message; + ws.close(); + }; + + ws.onopen = function() { + ++open; + } + + ws.onclose = function() { + ++close; + } + + ws.on('open', function() { + ws.send('foo'); + }); + + ws.on('close', function() { + process.nextTick(function() { + assert.ok(message === 1); + assert.ok(open === 1); + assert.ok(close === 1); + + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + }); + + it('should receive text data wrapped in a MessageEvent when using addEventListener', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.addEventListener('open', function() { + ws.send('hi'); + }); + ws.addEventListener('message', function(messageEvent) { + assert.equal('hi', messageEvent.data); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('should receive valid CloseEvent when server closes with code 1000', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + ws.addEventListener('close', function(closeEvent) { + assert.equal(true, closeEvent.wasClean); + assert.equal(1000, closeEvent.code); + ws.terminate(); + wss.close(); + done(); + }); + }); + wss.on('connection', function(client) { + client.close(1000); + }); + }); + + it('should receive valid CloseEvent when server closes with code 1001', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + ws.addEventListener('close', function(closeEvent) { + assert.equal(false, closeEvent.wasClean); + assert.equal(1001, closeEvent.code); + assert.equal('some daft reason', closeEvent.reason); + ws.terminate(); + wss.close(); + done(); + }); + }); + wss.on('connection', function(client) { + client.close(1001, 'some daft reason'); + }); + }); + + it('should have target set on Events', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + ws.addEventListener('open', function(openEvent) { + assert.equal(ws, openEvent.target); + }); + ws.addEventListener('message', function(messageEvent) { + assert.equal(ws, messageEvent.target); + wss.close(); + }); + ws.addEventListener('close', function(closeEvent) { + assert.equal(ws, closeEvent.target); + ws.emit('error', new Error('forced')); + }); + ws.addEventListener('error', function(errorEvent) { + assert.equal(errorEvent.message, 'forced'); + assert.equal(ws, errorEvent.target); + ws.terminate(); + done(); + }); + }); + wss.on('connection', function(client) { + client.send('hi') + }); + }); + }); + + describe('ssl', function() { + it('can connect to secure websocket server', function(done) { + var options = { + key: fs.readFileSync('test/fixtures/key.pem'), + cert: fs.readFileSync('test/fixtures/certificate.pem') + }; + var app = https.createServer(options, function (req, res) { + res.writeHead(200); + res.end(); + }); + var wss = new WebSocketServer({server: app}); + app.listen(++port, function() { + var ws = new WebSocket('wss://localhost:' + port); + }); + wss.on('connection', function(ws) { + app.close(); + ws.terminate(); + wss.close(); + done(); + }); + }); + + it('can connect to secure websocket server with client side certificate', function(done) { + var options = { + key: fs.readFileSync('test/fixtures/key.pem'), + cert: fs.readFileSync('test/fixtures/certificate.pem'), + ca: [fs.readFileSync('test/fixtures/ca1-cert.pem')], + requestCert: true + }; + var clientOptions = { + key: fs.readFileSync('test/fixtures/agent1-key.pem'), + cert: fs.readFileSync('test/fixtures/agent1-cert.pem') + }; + var app = https.createServer(options, function (req, res) { + res.writeHead(200); + res.end(); + }); + var success = false; + var wss = new WebSocketServer({ + server: app, + verifyClient: function(info) { + success = !!info.req.client.authorized; + return true; + } + }); + app.listen(++port, function() { + var ws = new WebSocket('wss://localhost:' + port, clientOptions); + }); + wss.on('connection', function(ws) { + app.close(); + ws.terminate(); + wss.close(); + success.should.be.ok; + done(); + }); + }); + + it('cannot connect to secure websocket server via ws://', function(done) { + var options = { + key: fs.readFileSync('test/fixtures/key.pem'), + cert: fs.readFileSync('test/fixtures/certificate.pem') + }; + var app = https.createServer(options, function (req, res) { + res.writeHead(200); + res.end(); + }); + var wss = new WebSocketServer({server: app}); + app.listen(++port, function() { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() { + app.close(); + ws.terminate(); + wss.close(); + done(); + }); + }); + }); + + it('can send and receive text data', function(done) { + var options = { + key: fs.readFileSync('test/fixtures/key.pem'), + cert: fs.readFileSync('test/fixtures/certificate.pem') + }; + var app = https.createServer(options, function (req, res) { + res.writeHead(200); + res.end(); + }); + var wss = new WebSocketServer({server: app}); + app.listen(++port, function() { + var ws = new WebSocket('wss://localhost:' + port); + ws.on('open', function() { + ws.send('foobar'); + }); + }); + wss.on('connection', function(ws) { + ws.on('message', function(message, flags) { + message.should.eql('foobar'); + app.close(); + ws.terminate(); + wss.close(); + done(); + }); + }); + }); + + it('can send and receive very long binary data', function(done) { + var options = { + key: fs.readFileSync('test/fixtures/key.pem'), + cert: fs.readFileSync('test/fixtures/certificate.pem') + } + var app = https.createServer(options, function (req, res) { + res.writeHead(200); + res.end(); + }); + crypto.randomBytes(5 * 1024 * 1024, function(ex, buf) { + if (ex) throw ex; + var wss = new WebSocketServer({server: app}); + app.listen(++port, function() { + var ws = new WebSocket('wss://localhost:' + port); + ws.on('open', function() { + ws.send(buf, {binary: true}); + }); + ws.on('message', function(message, flags) { + flags.binary.should.be.ok; + areArraysEqual(buf, message).should.be.ok; + app.close(); + ws.terminate(); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + ws.on('message', function(message, flags) { + ws.send(message, {binary: true}); + }); + }); + }); + }); + }); + + describe('protocol support discovery', function() { + describe('#supports', function() { + describe('#binary', function() { + it('returns true for hybi transport', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(client) { + assert.equal(true, client.supports.binary); + wss.close(); + done(); + }); + }); + + it('returns false for hixie transport', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + }); + wss.on('connection', function(client) { + assert.equal(false, client.supports.binary); + wss.close(); + done(); + }); + }); + }); + }); + }); +}); diff --git a/node_modules/ws/test/WebSocketServer.test.js b/node_modules/ws/test/WebSocketServer.test.js new file mode 100644 index 0000000..c21fd97 --- /dev/null +++ b/node_modules/ws/test/WebSocketServer.test.js @@ -0,0 +1,1103 @@ +var http = require('http') + , https = require('https') + , WebSocket = require('../') + , WebSocketServer = WebSocket.Server + , fs = require('fs') + , should = require('should'); + +var port = 8000; + +function getArrayBuffer(buf) { + var l = buf.length; + var arrayBuf = new ArrayBuffer(l); + for (var i = 0; i < l; ++i) { + arrayBuf[i] = buf[i]; + } + return arrayBuf; +} + +function areArraysEqual(x, y) { + if (x.length != y.length) return false; + for (var i = 0, l = x.length; i < l; ++i) { + if (x[i] !== y[i]) return false; + } + return true; +} + +describe('WebSocketServer', function() { + describe('#ctor', function() { + it('throws an error if no option object is passed', function() { + var gotException = false; + try { + var wss = new WebSocketServer(); + } + catch (e) { + gotException = true; + } + gotException.should.be.ok; + }); + + it('throws an error if no port or server is specified', function() { + var gotException = false; + try { + var wss = new WebSocketServer({}); + } + catch (e) { + gotException = true; + } + gotException.should.be.ok; + }); + + it('does not throw an error if no port or server is specified, when the noServer option is true', function() { + var gotException = false; + try { + var wss = new WebSocketServer({noServer: true}); + } + catch (e) { + gotException = true; + } + gotException.should.eql(false); + }); + + it('emits an error if http server bind fails', function(done) { + var wss = new WebSocketServer({port: 1}); + wss.on('error', function() { done(); }); + }); + + it('starts a server on a given port', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(client) { + wss.close(); + done(); + }); + }); + + it('uses a precreated http server', function (done) { + var srv = http.createServer(); + srv.listen(++port, function () { + var wss = new WebSocketServer({server: srv}); + var ws = new WebSocket('ws://localhost:' + port); + + wss.on('connection', function(client) { + wss.close(); + srv.close(); + done(); + }); + }); + }); + + it('uses a precreated http server listening on unix socket', function (done) { + var srv = http.createServer(); + var sockPath = '/tmp/ws_socket_'+new Date().getTime()+'.'+Math.floor(Math.random() * 1000); + srv.listen(sockPath, function () { + var wss = new WebSocketServer({server: srv}); + var ws = new WebSocket('ws+unix://'+sockPath); + + wss.on('connection', function(client) { + wss.close(); + srv.close(); + done(); + }); + }); + }); + + it('emits path specific connection event', function (done) { + var srv = http.createServer(); + srv.listen(++port, function () { + var wss = new WebSocketServer({server: srv}); + var ws = new WebSocket('ws://localhost:' + port+'/endpointName'); + + wss.on('connection/endpointName', function(client) { + wss.close(); + srv.close(); + done(); + }); + }); + }); + + it('can have two different instances listening on the same http server with two different paths', function(done) { + var srv = http.createServer(); + srv.listen(++port, function () { + var wss1 = new WebSocketServer({server: srv, path: '/wss1'}) + , wss2 = new WebSocketServer({server: srv, path: '/wss2'}); + var doneCount = 0; + wss1.on('connection', function(client) { + wss1.close(); + if (++doneCount == 2) { + srv.close(); + done(); + } + }); + wss2.on('connection', function(client) { + wss2.close(); + if (++doneCount == 2) { + srv.close(); + done(); + } + }); + var ws1 = new WebSocket('ws://localhost:' + port + '/wss1'); + var ws2 = new WebSocket('ws://localhost:' + port + '/wss2?foo=1'); + }); + }); + + it('cannot have two different instances listening on the same http server with the same path', function(done) { + var srv = http.createServer(); + srv.listen(++port, function () { + var wss1 = new WebSocketServer({server: srv, path: '/wss1'}); + try { + var wss2 = new WebSocketServer({server: srv, path: '/wss1'}); + } + catch (e) { + wss1.close(); + srv.close(); + done(); + } + }); + }); + }); + + describe('#close', function() { + it('will close all clients', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('close', function() { + if (++closes == 2) done(); + }); + }); + var closes = 0; + wss.on('connection', function(client) { + client.on('close', function() { + if (++closes == 2) done(); + }); + wss.close(); + }); + }); + + it('does not close a precreated server', function(done) { + var srv = http.createServer(); + var realClose = srv.close; + srv.close = function() { + should.fail('must not close pre-created server'); + } + srv.listen(++port, function () { + var wss = new WebSocketServer({server: srv}); + var ws = new WebSocket('ws://localhost:' + port); + wss.on('connection', function(client) { + wss.close(); + srv.close = realClose; + srv.close(); + done(); + }); + }); + }); + + it('cleans up websocket data on a precreated server', function(done) { + var srv = http.createServer(); + srv.listen(++port, function () { + var wss1 = new WebSocketServer({server: srv, path: '/wss1'}) + , wss2 = new WebSocketServer({server: srv, path: '/wss2'}); + (typeof srv._webSocketPaths).should.eql('object'); + Object.keys(srv._webSocketPaths).length.should.eql(2); + wss1.close(); + Object.keys(srv._webSocketPaths).length.should.eql(1); + wss2.close(); + (typeof srv._webSocketPaths).should.eql('undefined'); + srv.close(); + done(); + }); + }); + }); + + describe('#clients', function() { + it('returns a list of connected clients', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + wss.clients.length.should.eql(0); + var ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(client) { + wss.clients.length.should.eql(1); + wss.close(); + done(); + }); + }); + + it('can be disabled', function(done) { + var wss = new WebSocketServer({port: ++port, clientTracking: false}, function() { + wss.clients.length.should.eql(0); + var ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(client) { + wss.clients.length.should.eql(0); + wss.close(); + done(); + }); + }); + + it('is updated when client terminates the connection', function(done) { + var ws; + var wss = new WebSocketServer({port: ++port}, function() { + ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(client) { + client.on('close', function() { + wss.clients.length.should.eql(0); + wss.close(); + done(); + }); + ws.terminate(); + }); + }); + + it('is updated when client closes the connection', function(done) { + var ws; + var wss = new WebSocketServer({port: ++port}, function() { + ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(client) { + client.on('close', function() { + wss.clients.length.should.eql(0); + wss.close(); + done(); + }); + ws.close(); + }); + }); + }); + + describe('#options', function() { + it('exposes options passed to constructor', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + wss.options.port.should.eql(port); + wss.close(); + done(); + }); + }); + }); + + describe('#handleUpgrade', function() { + it('can be used for a pre-existing server', function (done) { + var srv = http.createServer(); + srv.listen(++port, function () { + var wss = new WebSocketServer({noServer: true}); + srv.on('upgrade', function(req, socket, upgradeHead) { + wss.handleUpgrade(req, socket, upgradeHead, function(client) { + client.send('hello'); + }); + }); + var ws = new WebSocket('ws://localhost:' + port); + ws.on('message', function(message) { + message.should.eql('hello'); + wss.close(); + srv.close(); + done(); + }); + }); + }); + }); + + describe('hybi mode', function() { + describe('connection establishing', function() { + it('does not accept connections with no sec-websocket-key', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(400); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('does not accept connections with no sec-websocket-version', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(400); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('does not accept connections with invalid sec-websocket-version', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 12 + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(400); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('client can be denied', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o) { + return false; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 8, + 'Sec-WebSocket-Origin': 'http://foobar.com' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(401); + process.nextTick(function() { + wss.close(); + done(); + }); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('client can be accepted', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o) { + return true; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 13, + 'Origin': 'http://foobar.com' + } + }; + var req = http.request(options); + req.end(); + }); + wss.on('connection', function(ws) { + ws.terminate(); + wss.close(); + done(); + }); + wss.on('error', function() {}); + }); + + it('verifyClient gets client origin', function(done) { + var verifyClientCalled = false; + var wss = new WebSocketServer({port: ++port, verifyClient: function(info) { + info.origin.should.eql('http://foobarbaz.com'); + verifyClientCalled = true; + return false; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 13, + 'Origin': 'http://foobarbaz.com' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + verifyClientCalled.should.be.ok; + wss.close(); + done(); + }); + }); + wss.on('error', function() {}); + }); + + it('verifyClient gets original request', function(done) { + var verifyClientCalled = false; + var wss = new WebSocketServer({port: ++port, verifyClient: function(info) { + info.req.headers['sec-websocket-key'].should.eql('dGhlIHNhbXBsZSBub25jZQ=='); + verifyClientCalled = true; + return false; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 13, + 'Origin': 'http://foobarbaz.com' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + verifyClientCalled.should.be.ok; + wss.close(); + done(); + }); + }); + wss.on('error', function() {}); + }); + + it('verifyClient has secure:true for ssl connections', function(done) { + var options = { + key: fs.readFileSync('test/fixtures/key.pem'), + cert: fs.readFileSync('test/fixtures/certificate.pem') + }; + var app = https.createServer(options, function (req, res) { + res.writeHead(200); + res.end(); + }); + var success = false; + var wss = new WebSocketServer({ + server: app, + verifyClient: function(info) { + success = info.secure === true; + return true; + } + }); + app.listen(++port, function() { + var ws = new WebSocket('wss://localhost:' + port); + }); + wss.on('connection', function(ws) { + app.close(); + ws.terminate(); + wss.close(); + success.should.be.ok; + done(); + }); + }); + + it('verifyClient has secure:false for non-ssl connections', function(done) { + var app = http.createServer(function (req, res) { + res.writeHead(200); + res.end(); + }); + var success = false; + var wss = new WebSocketServer({ + server: app, + verifyClient: function(info) { + success = info.secure === false; + return true; + } + }); + app.listen(++port, function() { + var ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(ws) { + app.close(); + ws.terminate(); + wss.close(); + success.should.be.ok; + done(); + }); + }); + + it('client can be denied asynchronously', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o, cb) { + process.nextTick(function() { + cb(false); + }); + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 8, + 'Sec-WebSocket-Origin': 'http://foobar.com' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(401); + process.nextTick(function() { + wss.close(); + done(); + }); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('client can be accepted asynchronously', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o, cb) { + process.nextTick(function() { + cb(true); + }); + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 13, + 'Origin': 'http://foobar.com' + } + }; + var req = http.request(options); + req.end(); + }); + wss.on('connection', function(ws) { + ws.terminate(); + wss.close(); + done(); + }); + wss.on('error', function() {}); + }); + + it('handles messages passed along with the upgrade request (upgrade head)', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o) { + return true; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 13, + 'Origin': 'http://foobar.com' + } + }; + var req = http.request(options); + req.write(new Buffer([0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f], 'binary')); + req.end(); + }); + wss.on('connection', function(ws) { + ws.on('message', function(data) { + data.should.eql('Hello'); + ws.terminate(); + wss.close(); + done(); + }); + }); + wss.on('error', function() {}); + }); + + it('selects the first protocol by default', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'}); + ws.on('open', function(client) { + ws.protocol.should.eql('prot1'); + wss.close(); + done(); + }); + }); + }); + + it('selects the last protocol via protocol handler', function(done) { + var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) { + cb(true, ps[ps.length-1]); }}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'}); + ws.on('open', function(client) { + ws.protocol.should.eql('prot2'); + wss.close(); + done(); + }); + }); + }); + + it('client detects invalid server protocol', function(done) { + var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) { + cb(true, 'prot3'); }}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'}); + ws.on('open', function(client) { + done(new Error('connection must not be established')); + }); + ws.on('error', function() { + done(); + }); + }); + }); + + it('client detects no server protocol', function(done) { + var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) { + cb(true); }}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'}); + ws.on('open', function(client) { + done(new Error('connection must not be established')); + }); + ws.on('error', function() { + done(); + }); + }); + }); + + it('client refuses server protocols', function(done) { + var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) { + cb(false); }}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'}); + ws.on('open', function(client) { + done(new Error('connection must not be established')); + }); + ws.on('error', function() { + done(); + }); + }); + }); + + it('server detects invalid protocol handler', function(done) { + var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) { + // not calling callback is an error and shouldn't timeout + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 13, + 'Sec-WebSocket-Origin': 'http://foobar.com' + } + }; + options.port = port; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(501); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + }); + + describe('messaging', function() { + it('can send and receive data', function(done) { + var data = new Array(65*1024); + for (var i = 0; i < data.length; ++i) { + data[i] = String.fromCharCode(65 + ~~(25 * Math.random())); + } + data = data.join(''); + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('message', function(message, flags) { + ws.send(message); + }); + }); + wss.on('connection', function(client) { + client.on('message', function(message) { + message.should.eql(data); + wss.close(); + done(); + }); + client.send(data); + }); + }); + }); + }); + + describe('hixie mode', function() { + it('can be disabled', function(done) { + var wss = new WebSocketServer({port: ++port, disableHixie: true}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(401); + process.nextTick(function() { + wss.close(); + done(); + }); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + describe('connection establishing', function() { + it('does not accept connections with no sec-websocket-key1', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(400); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('does not accept connections with no sec-websocket-key2', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(400); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('accepts connections with valid handshake', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + }); + wss.on('connection', function(ws) { + ws.terminate(); + wss.close(); + done(); + }); + wss.on('error', function() {}); + }); + + it('client can be denied', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o) { + return false; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(401); + process.nextTick(function() { + wss.close(); + done(); + }); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('client can be accepted', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o) { + return true; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + }); + wss.on('connection', function(ws) { + ws.terminate(); + wss.close(); + done(); + }); + wss.on('error', function() {}); + }); + + it('verifyClient gets client origin', function(done) { + var verifyClientCalled = false; + var wss = new WebSocketServer({port: ++port, verifyClient: function(info) { + info.origin.should.eql('http://foobarbaz.com'); + verifyClientCalled = true; + return false; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Origin': 'http://foobarbaz.com', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + req.on('response', function(res) { + verifyClientCalled.should.be.ok; + wss.close(); + done(); + }); + }); + wss.on('error', function() {}); + }); + + it('verifyClient gets original request', function(done) { + var verifyClientCalled = false; + var wss = new WebSocketServer({port: ++port, verifyClient: function(info) { + info.req.headers['sec-websocket-key1'].should.eql('3e6b263 4 17 80'); + verifyClientCalled = true; + return false; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Origin': 'http://foobarbaz.com', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + req.on('response', function(res) { + verifyClientCalled.should.be.ok; + wss.close(); + done(); + }); + }); + wss.on('error', function() {}); + }); + + it('client can be denied asynchronously', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o, cb) { + cb(false); + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Origin': 'http://foobarbaz.com', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(401); + process.nextTick(function() { + wss.close(); + done(); + }); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('client can be accepted asynchronously', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o, cb) { + cb(true); + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Origin': 'http://foobarbaz.com', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + }); + wss.on('connection', function(ws) { + wss.close(); + done(); + }); + wss.on('error', function() {}); + }); + + it('handles messages passed along with the upgrade request (upgrade head)', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o) { + return true; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90', + 'Origin': 'http://foobar.com' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.write(new Buffer([0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff], 'binary')); + req.end(); + }); + wss.on('connection', function(ws) { + ws.on('message', function(data) { + data.should.eql('Hello'); + ws.terminate(); + wss.close(); + done(); + }); + }); + wss.on('error', function() {}); + }); + }); + }); + + describe('client properties', function() { + it('protocol is exposed', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocol: 'hi'}); + }); + wss.on('connection', function(client) { + client.protocol.should.eql('hi'); + wss.close(); + done(); + }); + }); + + it('protocolVersion is exposed', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocolVersion: 8}); + }); + wss.on('connection', function(client) { + client.protocolVersion.should.eql(8); + wss.close(); + done(); + }); + }); + + it('upgradeReq is the original request object', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocolVersion: 8}); + }); + wss.on('connection', function(client) { + client.upgradeReq.httpVersion.should.eql('1.1'); + wss.close(); + done(); + }); + }); + }); + +}); diff --git a/node_modules/ws/test/autobahn-server.js b/node_modules/ws/test/autobahn-server.js new file mode 100644 index 0000000..36fe0c2 --- /dev/null +++ b/node_modules/ws/test/autobahn-server.js @@ -0,0 +1,29 @@ +var WebSocketServer = require('../').Server; + +process.on('uncaughtException', function(err) { + console.log('Caught exception: ', err, err.stack); +}); + +process.on('SIGINT', function () { + try { + console.log('Updating reports and shutting down'); + var ws = new WebSocket('ws://localhost:9001/updateReports?agent=ws'); + ws.on('close', function() { + process.exit(); + }); + } + catch(e) { + process.exit(); + } +}); + +var wss = new WebSocketServer({port: 8181}); +wss.on('connection', function(ws) { + console.log('new connection'); + ws.on('message', function(data, flags) { + ws.send(flags.buffer, {binary: flags.binary === true}); + }); + ws.on('error', function() { + console.log('error', arguments); + }); +}); diff --git a/node_modules/ws/test/autobahn.js b/node_modules/ws/test/autobahn.js new file mode 100644 index 0000000..048cc90 --- /dev/null +++ b/node_modules/ws/test/autobahn.js @@ -0,0 +1,52 @@ +var WebSocket = require('../'); +var currentTest = 1; +var lastTest = -1; +var testCount = null; + +process.on('uncaughtException', function(err) { + console.log('Caught exception: ', err, err.stack); +}); + +process.on('SIGINT', function () { + try { + console.log('Updating reports and shutting down'); + var ws = new WebSocket('ws://localhost:9001/updateReports?agent=ws'); + ws.on('close', function() { + process.exit(); + }); + } + catch(e) { + process.exit(); + } +}); + +function nextTest() { + if (currentTest > testCount || (lastTest != -1 && currentTest > lastTest)) { + console.log('Updating reports and shutting down'); + var ws = new WebSocket('ws://localhost:9001/updateReports?agent=ws'); + ws.on('close', function() { + process.exit(); + }); + return; + }; + console.log('Running test case ' + currentTest + '/' + testCount); + var ws = new WebSocket('ws://localhost:9001/runCase?case=' + currentTest + '&agent=ws'); + ws.on('message', function(data, flags) { + ws.send(flags.buffer, {binary: flags.binary === true, mask: true}); + }); + ws.on('close', function(data) { + currentTest += 1; + process.nextTick(nextTest); + }); + ws.on('error', function(e) {}); +} + +var ws = new WebSocket('ws://localhost:9001/getCaseCount'); +ws.on('message', function(data, flags) { + testCount = parseInt(data); +}); +ws.on('close', function() { + if (testCount > 0) { + nextTest(); + } +}); \ No newline at end of file diff --git a/node_modules/ws/test/fixtures/agent1-cert.pem b/node_modules/ws/test/fixtures/agent1-cert.pem new file mode 100644 index 0000000..cccb9fb --- /dev/null +++ b/node_modules/ws/test/fixtures/agent1-cert.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICbjCCAdcCCQCVvok5oeLpqzANBgkqhkiG9w0BAQUFADB6MQswCQYDVQQGEwJV +UzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYDVQQKEwZKb3llbnQxEDAO +BgNVBAsTB05vZGUuanMxDDAKBgNVBAMTA2NhMTEgMB4GCSqGSIb3DQEJARYRcnlA +dGlueWNsb3Vkcy5vcmcwHhcNMTMwMzA4MDAzMDIyWhcNNDAwNzIzMDAzMDIyWjB9 +MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYDVQQK +EwZKb3llbnQxEDAOBgNVBAsTB05vZGUuanMxDzANBgNVBAMTBmFnZW50MTEgMB4G +CSqGSIb3DQEJARYRcnlAdGlueWNsb3Vkcy5vcmcwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBAL6GwKosYb0Yc3Qo0OtQVlCJ4208Idw11ij+t2W5sfYbCil5tyQo +jnhGM1CJhEXynQpXXwjKJuIeTQCkeUibTyFKa0bs8+li2FiGoKYbb4G81ovnqkmE +2iDVb8Gw3rrM4zeZ0ZdFnjMsAZac8h6+C4sB/pS9BiMOo6qTl15RQlcJAgMBAAEw +DQYJKoZIhvcNAQEFBQADgYEAOtmLo8DwTPnI4wfQbQ3hWlTS/9itww6IsxH2ODt9 +ggB7wi7N3uAdIWRZ54ke0NEAO5CW1xNTwsWcxQbiHrDOqX1vfVCjIenI76jVEEap +/Ay53ydHNBKdsKkib61Me14Mu0bA3lUul57VXwmH4NUEFB3w973Q60PschUhOEXj +7DY= +-----END CERTIFICATE----- diff --git a/node_modules/ws/test/fixtures/agent1-key.pem b/node_modules/ws/test/fixtures/agent1-key.pem new file mode 100644 index 0000000..cbd5f0c --- /dev/null +++ b/node_modules/ws/test/fixtures/agent1-key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC+hsCqLGG9GHN0KNDrUFZQieNtPCHcNdYo/rdlubH2Gwopebck +KI54RjNQiYRF8p0KV18IyibiHk0ApHlIm08hSmtG7PPpYthYhqCmG2+BvNaL56pJ +hNog1W/BsN66zOM3mdGXRZ4zLAGWnPIevguLAf6UvQYjDqOqk5deUUJXCQIDAQAB +AoGANu/CBA+SCyVOvRK70u4yRTzNMAUjukxnuSBhH1rg/pajYnwvG6T6F6IeT72n +P0gKkh3JUE6B0bds+p9yPUZTFUXghxjcF33wlIY44H6gFE4K5WutsFJ9c450wtuu +8rXZTsIg7lAXWjTFVmdtOEPetcGlO2Hpi1O7ZzkzHgB2w9ECQQDksCCYx78or1zY +ZSokm8jmpIjG3VLKdvI9HAoJRN40ldnwFoigrFa1AHwsFtWNe8bKyVRPDoLDUjpB +dkPWgweVAkEA1UfgqguQ2KIkbtp9nDBionu3QaajksrRHwIa8vdfRfLxszfHk2fh +NGY3dkRZF8HUAbzYLrd9poVhCBAEjWekpQJASOM6AHfpnXYHCZF01SYx6hEW5wsz +kARJQODm8f1ZNTlttO/5q/xBxn7ZFNRSTD3fJlL05B2j380ddC/Vf1FT4QJAP1BC +GliqnBSuGhZUWYxni3KMeTm9rzL0F29pjpzutHYlWB2D6ndY/FQnvL0XcZ0Bka58 +womIDGnl3x3aLBwLXQJBAJv6h5CHbXHx7VyDJAcNfppAqZGcEaiVg8yf2F33iWy2 +FLthhJucx7df7SO2aw5h06bRDRAhb9br0R9/3mLr7RE= +-----END RSA PRIVATE KEY----- diff --git a/node_modules/ws/test/fixtures/ca1-cert.pem b/node_modules/ws/test/fixtures/ca1-cert.pem new file mode 100644 index 0000000..1d0c0d6 --- /dev/null +++ b/node_modules/ws/test/fixtures/ca1-cert.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICazCCAdQCCQC9/g69HtxXRzANBgkqhkiG9w0BAQUFADB6MQswCQYDVQQGEwJV +UzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYDVQQKEwZKb3llbnQxEDAO +BgNVBAsTB05vZGUuanMxDDAKBgNVBAMTA2NhMTEgMB4GCSqGSIb3DQEJARYRcnlA +dGlueWNsb3Vkcy5vcmcwHhcNMTMwMzA4MDAzMDIyWhcNNDAwNzIzMDAzMDIyWjB6 +MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYDVQQK +EwZKb3llbnQxEDAOBgNVBAsTB05vZGUuanMxDDAKBgNVBAMTA2NhMTEgMB4GCSqG +SIb3DQEJARYRcnlAdGlueWNsb3Vkcy5vcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0A +MIGJAoGBAKxr1mARUcv7zaqx5y4AxJPK6c1jdbSg7StcL4vg8klaPAlfNO6o+/Cl +w5CdQD3ukaVUwUOJ4T/+b3Xf7785XcWBC33GdjVQkfbHATJYcka7j7JDw3qev5Jk +1rAbRw48hF6rYlSGcx1mccAjoLoa3I8jgxCNAYHIjUQXgdmU893rAgMBAAEwDQYJ +KoZIhvcNAQEFBQADgYEAis05yxjCtJRuv8uX/DK6TX/j9C9Lzp1rKDNFTaTZ0iRw +KCw1EcNx4OXSj9gNblW4PWxpDvygrt1AmH9h2cb8K859NSHa9JOBFw6MA5C2A4Sj +NQfNATqUl4T6cdORlcDEZwHtT8b6D4A6Er31G/eJF4Sen0TUFpjdjd+l9RBjHlo= +-----END CERTIFICATE----- diff --git a/node_modules/ws/test/fixtures/ca1-key.pem b/node_modules/ws/test/fixtures/ca1-key.pem new file mode 100644 index 0000000..df14950 --- /dev/null +++ b/node_modules/ws/test/fixtures/ca1-key.pem @@ -0,0 +1,17 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIFeWxJE1BrRECAggA +MBQGCCqGSIb3DQMHBAgu9PlMSQ+BOASCAoDEZN2tX0xWo/N+Jg+PrvCrFDk3P+3x +5xG/PEDjtMCAWPBEwbnaYHDzYmhNcAmxzGqEHGMDiWYs46LbO560VS3uMvFbEWPo +KYYVb13vkxl2poXdonCb5cHZA5GUYzTIVVJFptl4LHwBczHoMHtA4FqAhKlYvlWw +EOrdLB8XcwMmGPFabbbGxno0+EWWM27uNjlogfoxj35mQqSW4rOlhZ460XjOB1Zx +LjXMuZeONojkGYQRG5EUMchBoctQpCOM6cAi9r1B9BvtFCBpDV1c1zEZBzTEUd8o +kLn6tjLmY+QpTdylFjEWc7U3ppLY/pkoTBv4r85a2sEMWqkhSJboLaTboWzDJcU3 +Ke61pMpovt/3yCUd3TKgwduVwwQtDVTlBe0p66aN9QVj3CrFy/bKAGO3vxlli24H +aIjZf+OVoBY21ESlW3jLvNlBf7Ezf///2E7j4SCDLyZSFMTpFoAG/jDRyvi+wTKX +Kh485Bptnip6DCSuoH4u2SkOqwz3gJS/6s02YKe4m311QT4Pzne5/FwOFaS/HhQg +Xvyh2/d00OgJ0Y0PYQsHILPRgTUCKUXvj1O58opn3fxSacsPxIXwj6Z4FYAjUTaV +2B85k1lpant/JJEilDqMjqzx4pHZ/Z3Uto1lSM1JZs9SNL/0UR+6F0TXZTULVU9V +w8jYzz4sPr7LEyrrTbzmjQgnQFVbhAN/eKgRZK/SpLjxpmBV5MfpbPKsPUZqT4UC +4nXa8a/NYUQ9e+QKK8enq9E599c2W442W7Z1uFRZTWReMx/lF8wwA6G8zOPG0bdj +d+T5Gegzd5mvRiXMBklCo8RLxOOvgxun1n3PY4a63aH6mqBhdfhiLp5j +-----END ENCRYPTED PRIVATE KEY----- diff --git a/node_modules/ws/test/fixtures/certificate.pem b/node_modules/ws/test/fixtures/certificate.pem new file mode 100644 index 0000000..0efc2ef --- /dev/null +++ b/node_modules/ws/test/fixtures/certificate.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICATCCAWoCCQDPufXH86n2QzANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJu +bzETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTEyMDEwMTE0NDQwMFoXDTIwMDMxOTE0NDQwMFowRTELMAkG +A1UEBhMCbm8xEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtrQ7 ++r//2iV/B6F+4boH0XqFn7alcV9lpjvAmwRXNKnxAoa0f97AjYPGNLKrjpkNXXhB +JROIdbRbZnCNeC5fzX1a+JCo7KStzBXuGSZr27TtFmcV4H+9gIRIcNHtZmJLnxbJ +sIhkGR8yVYdmJZe4eT5ldk1zoB1adgPF1hZhCBMCAwEAATANBgkqhkiG9w0BAQUF +AAOBgQCeWBEHYJ4mCB5McwSSUox0T+/mJ4W48L/ZUE4LtRhHasU9hiW92xZkTa7E +QLcoJKQiWfiLX2ysAro0NX4+V8iqLziMqvswnPzz5nezaOLE/9U/QvH3l8qqNkXu +rNbsW1h/IO6FV8avWFYVFoutUwOaZ809k7iMh2F2JMgXQ5EymQ== +-----END CERTIFICATE----- diff --git a/node_modules/ws/test/fixtures/key.pem b/node_modules/ws/test/fixtures/key.pem new file mode 100644 index 0000000..176fe32 --- /dev/null +++ b/node_modules/ws/test/fixtures/key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC2tDv6v//aJX8HoX7hugfReoWftqVxX2WmO8CbBFc0qfEChrR/ +3sCNg8Y0squOmQ1deEElE4h1tFtmcI14Ll/NfVr4kKjspK3MFe4ZJmvbtO0WZxXg +f72AhEhw0e1mYkufFsmwiGQZHzJVh2Yll7h5PmV2TXOgHVp2A8XWFmEIEwIDAQAB +AoGAAlVY8sHi/aE+9xT77twWX3mGHV0SzdjfDnly40fx6S1Gc7bOtVdd9DC7pk6l +3ENeJVR02IlgU8iC5lMHq4JEHPE272jtPrLlrpWLTGmHEqoVFv9AITPqUDLhB9Kk +Hjl7h8NYBKbr2JHKICr3DIPKOT+RnXVb1PD4EORbJ3ooYmkCQQDfknUnVxPgxUGs +ouABw1WJIOVgcCY/IFt4Ihf6VWTsxBgzTJKxn3HtgvE0oqTH7V480XoH0QxHhjLq +DrgobWU9AkEA0TRJ8/ouXGnFEPAXjWr9GdPQRZ1Use2MrFjneH2+Sxc0CmYtwwqL +Kr5kS6mqJrxprJeluSjBd+3/ElxURrEXjwJAUvmlN1OPEhXDmRHd92mKnlkyKEeX +OkiFCiIFKih1S5Y/sRJTQ0781nyJjtJqO7UyC3pnQu1oFEePL+UEniRztQJAMfav +AtnpYKDSM+1jcp7uu9BemYGtzKDTTAYfoiNF42EzSJiGrWJDQn4eLgPjY0T0aAf/ +yGz3Z9ErbhMm/Ysl+QJBAL4kBxRT8gM4ByJw4sdOvSeCCANFq8fhbgm8pGWlCPb5 +JGmX3/GHFM8x2tbWMGpyZP1DLtiNEFz7eCGktWK5rqE= +-----END RSA PRIVATE KEY----- diff --git a/node_modules/ws/test/fixtures/request.pem b/node_modules/ws/test/fixtures/request.pem new file mode 100644 index 0000000..51bc7f6 --- /dev/null +++ b/node_modules/ws/test/fixtures/request.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBhDCB7gIBADBFMQswCQYDVQQGEwJubzETMBEGA1UECAwKU29tZS1TdGF0ZTEh +MB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQC2tDv6v//aJX8HoX7hugfReoWftqVxX2WmO8CbBFc0qfEC +hrR/3sCNg8Y0squOmQ1deEElE4h1tFtmcI14Ll/NfVr4kKjspK3MFe4ZJmvbtO0W +ZxXgf72AhEhw0e1mYkufFsmwiGQZHzJVh2Yll7h5PmV2TXOgHVp2A8XWFmEIEwID +AQABoAAwDQYJKoZIhvcNAQEFBQADgYEAjsUXEARgfxZNkMjuUcudgU2w4JXS0gGI +JQ0U1LmU0vMDSKwqndMlvCbKzEgPbJnGJDI8D4MeINCJHa5Ceyb8c+jaJYUcCabl +lQW5Psn3+eWp8ncKlIycDRj1Qk615XuXtV0fhkrgQM2ZCm9LaQ1O1Gd/CzLihLjF +W0MmgMKMMRk= +-----END CERTIFICATE REQUEST----- diff --git a/node_modules/ws/test/fixtures/textfile b/node_modules/ws/test/fixtures/textfile new file mode 100644 index 0000000..a10483b --- /dev/null +++ b/node_modules/ws/test/fixtures/textfile @@ -0,0 +1,9 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam egestas, massa at aliquam luctus, sapien erat viverra elit, nec pulvinar turpis eros sagittis urna. Pellentesque imperdiet tempor varius. Pellentesque blandit, ipsum in imperdiet venenatis, mi elit faucibus odio, id condimentum ante enim sed lectus. Aliquam et odio non odio pellentesque pulvinar. Vestibulum a erat dolor. Integer pretium risus sit amet nisl volutpat nec venenatis magna egestas. Ut bibendum felis eu tellus laoreet eleifend. Nam pulvinar auctor tortor, eu iaculis leo vestibulum quis. In euismod risus ac purus vehicula et fermentum ligula consectetur. Vivamus condimentum tempus lacinia. + +Curabitur sodales condimentum urna id dictum. Sed quis justo sit amet quam ultrices tincidunt vel laoreet nulla. Nullam quis ipsum sed nisi mollis bibendum at sit amet nisi. Donec laoreet consequat velit sit amet mollis. Nam sed sapien a massa iaculis dapibus. Sed dui nunc, ultricies et pellentesque ullamcorper, aliquet vitae ligula. Integer eu velit in neque iaculis venenatis. Ut rhoncus cursus est, ac dignissim leo vehicula a. Nulla ullamcorper vulputate mauris id blandit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque eleifend, nisi a tempor sollicitudin, odio massa pretium urna, quis congue sapien elit at tortor. Curabitur ipsum orci, vehicula non commodo molestie, laoreet id enim. Pellentesque convallis ultrices congue. Pellentesque nec iaculis lorem. In sagittis pharetra ipsum eget sodales. + +Fusce id nulla odio. Nunc nibh justo, placerat vel tincidunt sed, ornare et enim. Nulla vel urna vel ante commodo bibendum in vitae metus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis erat nunc, semper eget sagittis sit amet, ullamcorper eget lacus. Donec hendrerit ipsum vitae eros vestibulum eu gravida neque tincidunt. Ut molestie lacinia nulla. Donec mattis odio at magna egestas at pellentesque eros accumsan. Praesent interdum sem sit amet nibh commodo dignissim. Duis laoreet, enim ultricies fringilla suscipit, enim libero cursus nulla, sollicitudin adipiscing erat velit ut dui. Nulla eleifend mauris at velit fringilla a molestie lorem venenatis. + +Donec sit amet scelerisque metus. Cras ac felis a nulla venenatis vulputate. Duis porttitor eros ac neque rhoncus eget aliquet neque egestas. Quisque sed nunc est, vitae dapibus quam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In vehicula, est vitae posuere ultricies, diam purus pretium sapien, nec rhoncus dolor nisl eget arcu. Aliquam et nisi vitae risus tincidunt auctor. In vehicula, erat a cursus adipiscing, lorem orci congue est, nec ultricies elit dui in nunc. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Duis congue tempus elit sit amet auctor. Duis dignissim, risus ut sollicitudin ultricies, dolor ligula gravida odio, nec congue orci purus ut ligula. Fusce pretium dictum lectus at volutpat. Sed non auctor mauris. Etiam placerat vestibulum massa id blandit. Quisque consequat lacus ut nulla euismod facilisis. Sed aliquet ipsum nec mi imperdiet viverra. Pellentesque ullamcorper, lectus nec varius gravida, odio justo cursus risus, eu sagittis metus arcu quis felis. Phasellus consectetur vehicula libero, at condimentum orci euismod vel. Nunc purus tortor, suscipit nec fringilla nec, vulputate et nibh. Nam porta vehicula neque. Praesent porttitor, sapien eu auctor euismod, arcu quam elementum urna, sed hendrerit magna augue sed quam. \ No newline at end of file diff --git a/node_modules/ws/test/hybi-common.js b/node_modules/ws/test/hybi-common.js new file mode 100644 index 0000000..006f9c6 --- /dev/null +++ b/node_modules/ws/test/hybi-common.js @@ -0,0 +1,99 @@ +/** + * Returns a Buffer from a "ff 00 ff"-type hex string. + */ + +getBufferFromHexString = function(byteStr) { + var bytes = byteStr.split(' '); + var buf = new Buffer(bytes.length); + for (var i = 0; i < bytes.length; ++i) { + buf[i] = parseInt(bytes[i], 16); + } + return buf; +} + +/** + * Returns a hex string from a Buffer. + */ + +getHexStringFromBuffer = function(data) { + var s = ''; + for (var i = 0; i < data.length; ++i) { + s += padl(data[i].toString(16), 2, '0') + ' '; + } + return s.trim(); +} + +/** + * Splits a buffer in two parts. + */ + +splitBuffer = function(buffer) { + var b1 = new Buffer(Math.ceil(buffer.length / 2)); + buffer.copy(b1, 0, 0, b1.length); + var b2 = new Buffer(Math.floor(buffer.length / 2)); + buffer.copy(b2, 0, b1.length, b1.length + b2.length); + return [b1, b2]; +} + +/** + * Performs hybi07+ type masking on a hex string or buffer. + */ + +mask = function(buf, maskString) { + if (typeof buf == 'string') buf = new Buffer(buf); + var mask = getBufferFromHexString(maskString || '34 83 a8 68'); + for (var i = 0; i < buf.length; ++i) { + buf[i] ^= mask[i % 4]; + } + return buf; +} + +/** + * Returns a hex string representing the length of a message + */ + +getHybiLengthAsHexString = function(len, masked) { + if (len < 126) { + var buf = new Buffer(1); + buf[0] = (masked ? 0x80 : 0) | len; + } + else if (len < 65536) { + var buf = new Buffer(3); + buf[0] = (masked ? 0x80 : 0) | 126; + getBufferFromHexString(pack(4, len)).copy(buf, 1); + } + else { + var buf = new Buffer(9); + buf[0] = (masked ? 0x80 : 0) | 127; + getBufferFromHexString(pack(16, len)).copy(buf, 1); + } + return getHexStringFromBuffer(buf); +} + +/** + * Unpacks a Buffer into a number. + */ + +unpack = function(buffer) { + var n = 0; + for (var i = 0; i < buffer.length; ++i) { + n = (i == 0) ? buffer[i] : (n * 256) + buffer[i]; + } + return n; +} + +/** + * Returns a hex string, representing a specific byte count 'length', from a number. + */ + +pack = function(length, number) { + return padl(number.toString(16), length, '0').replace(/([0-9a-f][0-9a-f])/gi, '$1 ').trim(); +} + +/** + * Left pads the string 's' to a total length of 'n' with char 'c'. + */ + +padl = function(s, n, c) { + return new Array(1 + n - s.length).join(c) + s; +} diff --git a/node_modules/ws/test/testserver.js b/node_modules/ws/test/testserver.js new file mode 100644 index 0000000..3e7a966 --- /dev/null +++ b/node_modules/ws/test/testserver.js @@ -0,0 +1,180 @@ +var http = require('http') + , util = require('util') + , crypto = require('crypto') + , events = require('events') + , Sender = require('../lib/Sender') + , Receiver = require('../lib/Receiver'); + +module.exports = { + handlers: { + valid: validServer, + invalidKey: invalidRequestHandler, + closeAfterConnect: closeAfterConnectHandler, + return401: return401 + }, + createServer: function(port, handler, cb) { + if (handler && !cb) { + cb = handler; + handler = null; + } + var webServer = http.createServer(function (req, res) { + res.writeHead(200, {'Content-Type': 'text/plain'}); + res.end('okay'); + }); + var srv = new Server(webServer); + webServer.on('upgrade', function(req, socket) { + webServer._socket = socket; + (handler || validServer)(srv, req, socket); + }); + webServer.listen(port, '127.0.0.1', function() { cb(srv); }); + } +}; + +/** + * Test strategies + */ + +function validServer(server, req, socket) { + if (typeof req.headers.upgrade === 'undefined' || + req.headers.upgrade.toLowerCase() !== 'websocket') { + throw new Error('invalid headers'); + return; + } + + if (!req.headers['sec-websocket-key']) { + socket.end(); + throw new Error('websocket key is missing'); + } + + // calc key + var key = req.headers['sec-websocket-key']; + var shasum = crypto.createHash('sha1'); + shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); + key = shasum.digest('base64'); + + var headers = [ + 'HTTP/1.1 101 Switching Protocols' + , 'Upgrade: websocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Accept: ' + key + ]; + + socket.write(headers.concat('', '').join('\r\n')); + socket.setTimeout(0); + socket.setNoDelay(true); + + var sender = new Sender(socket); + var receiver = new Receiver(); + receiver.ontext = function (message, flags) { + server.emit('message', message, flags); + sender.send(message); + }; + receiver.onbinary = function (message, flags) { + flags = flags || {}; + flags.binary = true; + server.emit('message', message, flags); + sender.send(message, {binary: true}); + }; + receiver.onping = function (message, flags) { + flags = flags || {}; + server.emit('ping', message, flags); + }; + receiver.onpong = function (message, flags) { + flags = flags || {}; + server.emit('pong', message, flags); + }; + receiver.onclose = function (code, message, flags) { + flags = flags || {}; + server.emit('close', code, message, flags); + }; + socket.on('data', function (data) { + receiver.add(data); + }); + socket.on('end', function() { + socket.end(); + }); +} + +function invalidRequestHandler(server, req, socket) { + if (typeof req.headers.upgrade === 'undefined' || + req.headers.upgrade.toLowerCase() !== 'websocket') { + throw new Error('invalid headers'); + return; + } + + if (!req.headers['sec-websocket-key']) { + socket.end(); + throw new Error('websocket key is missing'); + } + + // calc key + var key = req.headers['sec-websocket-key']; + var shasum = crypto.createHash('sha1'); + shasum.update(key + "bogus"); + key = shasum.digest('base64'); + + var headers = [ + 'HTTP/1.1 101 Switching Protocols' + , 'Upgrade: websocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Accept: ' + key + ]; + + socket.write(headers.concat('', '').join('\r\n')); + socket.end(); +} + +function closeAfterConnectHandler(server, req, socket) { + if (typeof req.headers.upgrade === 'undefined' || + req.headers.upgrade.toLowerCase() !== 'websocket') { + throw new Error('invalid headers'); + return; + } + + if (!req.headers['sec-websocket-key']) { + socket.end(); + throw new Error('websocket key is missing'); + } + + // calc key + var key = req.headers['sec-websocket-key']; + var shasum = crypto.createHash('sha1'); + shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); + key = shasum.digest('base64'); + + var headers = [ + 'HTTP/1.1 101 Switching Protocols' + , 'Upgrade: websocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Accept: ' + key + ]; + + socket.write(headers.concat('', '').join('\r\n')); + socket.end(); +} + + +function return401(server, req, socket) { + var headers = [ + 'HTTP/1.1 401 Unauthorized' + , 'Content-type: text/html' + ]; + + socket.write(headers.concat('', '').join('\r\n')); + socket.end(); +} + +/** + * Server object, which will do the actual emitting + */ + +function Server(webServer) { + this.webServer = webServer; +} + +util.inherits(Server, events.EventEmitter); + +Server.prototype.close = function() { + this.webServer.close(); + if (this._socket) this._socket.end(); +} diff --git a/npm-debug.log b/npm-debug.log new file mode 100644 index 0000000..4a8e7f0 --- /dev/null +++ b/npm-debug.log @@ -0,0 +1,62 @@ +0 info it worked if it ends with ok +1 verbose cli [ 'C:\\Program Files (x86)\\nodejs\\\\node.exe', +1 verbose cli 'C:\\Program Files (x86)\\nodejs\\node_modules\\npm\\bin\\npm-cli.js', +1 verbose cli 'install', +1 verbose cli 'expressvalidator' ] +2 info using npm@1.3.5 +3 info using node@v0.10.15 +4 verbose node symlink C:\Program Files (x86)\nodejs\\node.exe +5 warn package.json MultiWebRTC@0.0.2-1 No repository field. +6 warn package.json MultiWebRTC@0.0.2-1 No README data +7 warn package.json consolidate@0.9.1 No repository field. +8 warn package.json mustache@0.7.2 No repository field. +9 verbose readDependencies using package.json deps +10 verbose cache add [ 'expressvalidator', null ] +11 verbose cache add name=undefined spec="expressvalidator" args=["expressvalidator",null] +12 verbose parsed url { protocol: null, +12 verbose parsed url slashes: null, +12 verbose parsed url auth: null, +12 verbose parsed url host: null, +12 verbose parsed url port: null, +12 verbose parsed url hostname: null, +12 verbose parsed url hash: null, +12 verbose parsed url search: null, +12 verbose parsed url query: null, +12 verbose parsed url pathname: 'expressvalidator', +12 verbose parsed url path: 'expressvalidator', +12 verbose parsed url href: 'expressvalidator' } +13 silly lockFile a5444023-expressvalidator expressvalidator +14 verbose lock expressvalidator C:\Users\Administrator\AppData\Roaming\npm-cache\a5444023-expressvalidator.lock +15 silly lockFile a5444023-expressvalidator expressvalidator +16 silly lockFile a5444023-expressvalidator expressvalidator +17 verbose addNamed [ 'expressvalidator', '' ] +18 verbose addNamed [ null, '*' ] +19 silly lockFile d3e19a5e-expressvalidator expressvalidator@ +20 verbose lock expressvalidator@ C:\Users\Administrator\AppData\Roaming\npm-cache\d3e19a5e-expressvalidator.lock +21 silly addNameRange { name: 'expressvalidator', range: '*', hasData: false } +22 verbose url raw expressvalidator +23 verbose url resolving [ 'https://registry.npmjs.org/', './expressvalidator' ] +24 verbose url resolved https://registry.npmjs.org/expressvalidator +25 info trying registry request attempt 1 at 07:59:33 +26 http GET https://registry.npmjs.org/expressvalidator +27 http 404 https://registry.npmjs.org/expressvalidator +28 silly registry.get cb [ 404, +28 silly registry.get { server: 'CouchDB/1.3.0 (Erlang OTP/R15B03)', +28 silly registry.get date: 'Wed, 07 Aug 2013 23:59:35 GMT', +28 silly registry.get 'content-type': 'application/json', +28 silly registry.get 'content-length': '52', +28 silly registry.get 'cache-control': 'must-revalidate' } ] +29 silly lockFile d3e19a5e-expressvalidator expressvalidator@ +30 silly lockFile d3e19a5e-expressvalidator expressvalidator@ +31 error 404 'expressvalidator' is not in the npm registry. +31 error 404 You should bug the author to publish it +31 error 404 +31 error 404 Note that you can also install from a +31 error 404 tarball, folder, or http url, or git url. +32 error System Windows_NT 6.1.7600 +33 error command "C:\\Program Files (x86)\\nodejs\\\\node.exe" "C:\\Program Files (x86)\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "expressvalidator" +34 error cwd C:\xampp\htdocs\demo +35 error node -v v0.10.15 +36 error npm -v 1.3.5 +37 error code E404 +38 verbose exit [ 1, true ] diff --git a/package.json b/package.json new file mode 100644 index 0000000..0ecc89d --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "ppWebRTC with video & audio", + "description": "multi user webrtc with video & audio", + "version": "0.1.0", + "engines": { + "node": ">= 0.6.0" + }, + "dependencies": { + "express": "3.1.0", + "ejs" : "latest", + "ws": "latest" + } +} diff --git a/public/css/styles.css b/public/css/styles.css new file mode 100644 index 0000000..79d51c8 --- /dev/null +++ b/public/css/styles.css @@ -0,0 +1,154 @@ +/* Essentials */ +body { + background-color:#3e8abc; +} +#login-content{ + width:721px; + height:650px; + margin:0 auto; + background:url("../images/login_bg.jpg") no-repeat center; +} +#login-content input[type=text] { + border: 1px solid #177ec1; + background:#177ec1; + position:relative; + height:32px; + width:207px; + font-size:24px; +} +#login-content input[type=text]:focus { + outline: 0; + outline-color: transparent; + outline-style: none; +} +#username{ + top:240px; + left:340px; +} +#roomname{ + top:275px; + left:340px; +} +#login-content .button { + font-family:Times New Roman; + font-size: 14px; + color: #fff; + cursor:pointer; + position: relative; + margin-left:10px; + top:350px; + left:440px; + padding: 7px; + padding-left:10px; + padding-right:10px; + text-decoration: none; + border: solid 1px #186f8f; + background-image: linear-gradient(bottom, rgb(23,126,193) 0%, rgb(127,181,217) 100%); + background-image: -o-linear-gradient(bottom, rgb(23,126,193) 0%, rgb(127,181,217) 100%); + background-image: -moz-linear-gradient(bottom, rgb(23,126,193) 0%, rgb(127,181,217) 100%); + background-image: -webkit-linear-gradient(bottom, rgb(23,126,193) 0%, rgb(127,181,217) 100%); + background-image: -ms-linear-gradient(bottom, rgb(23,126,193) 0%, rgb(127,181,217) 100%); + background-image: -webkit-gradient( linear, left bottom, left top, color-stop(0, rgb(23,126,193)), color-stop(1, rgb(127,181,217)) ); + -webkit-box-shadow: inset 0px 1px 0px #7fd2f1, 0px 1px 0px #fff; + -moz-box-shadow: inset 0px 1px 0px #7fd2f1, 0px 1px 0px #fff; + box-shadow: inset 0px 1px 0px #7fd2f1, 0px 1px 0px #fff; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; +} + +#login-content .button:active { + background-image: linear-gradient(bottom, rgb(127,181,217) 0%, rgb(23,126,193) 100%); + background-image: -o-linear-gradient(bottom, rgb(127,181,217) 0%, rgb(23,126,193) 100%); + background-image: -moz-linear-gradient(bottom, rgb(127,181,217) 0%, rgb(23,126,193) 100%); + background-image: -webkit-linear-gradient(bottom, rgb(127,181,217) 0%, rgb(23,126,193) 100%); + background-image: -ms-linear-gradient(bottom, rgb(127,181,217) 0%, rgb(23,126,193) 100%); + background-image: -webkit-gradient( + linear, + left bottom, + left top, + color-stop(0, rgb(127,181,217)), + color-stop(1, rgb(23,126,193)) + ); +} +#chat-wrapper{ + width:800px;height:600px;padding:1px; +} +.window-content{ + width:799px;height:561px; +} +#chat-toolbox{ + height:50px; +} +#chat-toolbox a{ + float:right; + position:relative; + top:15px; + margin-right:5px; +} +#chat-webcam{ + width:160px; +} +#chat-users{ + width:180px; +} +#chat-sendbox{ + overflow:hidden; +} +#chat-sendbox div{ + float:left; +} +#chat-sendbox{ + height:110px;padding:3px; +} +#chat-sendbox #sendtext{ + height:75px; + float:left; +} +#chat-sendbox .btnsend { + position:relative; + top:20px; + margin-left:20px; + float:left; +} +.sendbox-right +{ + width: 180px; + padding-top:5px; + height:90px; + display:block; +} +.sendbox-right video { + float:right; +} +.function_note{ + padding-left:10px; + color:#666; + font-size:12px; + font-style:italic; + float:left; +} +#users span{ + background:url("../images/user.png") no-repeat; + width:150px; + height:30px; + display:block; + padding-left:35px; + vertical-align:bottom; + font-size:15px; + font-weight:bold; +} +#users span:hover{ + cursor:pointer; +} +#users { + padding-left:15px; + padding-top:15px; +} +canvas { + display: none; +} +.icon-capture { + background: url("../images/capture.png") no-repeat center center; +} \ No newline at end of file diff --git a/public/images/capture.png b/public/images/capture.png new file mode 100644 index 0000000..7a84486 Binary files /dev/null and b/public/images/capture.png differ diff --git a/public/images/login_bg.jpg b/public/images/login_bg.jpg new file mode 100644 index 0000000..77bfba4 Binary files /dev/null and b/public/images/login_bg.jpg differ diff --git a/public/images/loginbt.png b/public/images/loginbt.png new file mode 100644 index 0000000..e1d97f3 Binary files /dev/null and b/public/images/loginbt.png differ diff --git a/public/images/offline.png b/public/images/offline.png new file mode 100644 index 0000000..737740b Binary files /dev/null and b/public/images/offline.png differ diff --git a/public/images/online.png b/public/images/online.png new file mode 100644 index 0000000..085dad2 Binary files /dev/null and b/public/images/online.png differ diff --git a/public/images/user.png b/public/images/user.png new file mode 100644 index 0000000..178fdd8 Binary files /dev/null and b/public/images/user.png differ diff --git a/public/javascripts/client.js b/public/javascripts/client.js new file mode 100644 index 0000000..793ae89 --- /dev/null +++ b/public/javascripts/client.js @@ -0,0 +1,249 @@ +var webcam_videos = []; +var chat_users = []; +var webcam_width = 130; +var webcam_height = 90; +var peerConnection; +var websocketChat = { + send: function (message) { + rtc._socket.send(message); + }, + recv: function (message) { + return message; + }, + event: 'receive_chat_msg' +}; +var dataChannelChat = { + broadcast: function(message) { + for(var connection in rtc.dataChannels) { + var channel = rtc.dataChannels[connection]; + if (rtc.connection_ok_to_send[connection]) { + channel.send(message); + } else { + console.log("unable to send message to " + connection); + } + } + }, + send: function(connection, message) { + var channel = rtc.dataChannels[connection]; + if (rtc.connection_ok_to_send[connection]) { + channel.send(message); + } else { + console.log("unable to send message to " + connection); + } + }, + recv: function(channel, message) { + return JSON.parse(message).data; + }, + event: 'data stream data' +}; + +var ppChat = { + init:function(){ + $('#chat-wrapper').window('open'); + }, + addmsg_to_board : function(username, msg, color) { + var messages = $('#msgboard'); + msg = ppChat.sanitize(msg); + if(color) { + msg = '' + username + ' : ' + '' + msg + ''; + } else { + msg = '' + username + ' : ' + '' + msg + ''; + } + messages.html(messages.html() + msg + '
    '); + messages.scrollTop(10000); + }, + dispsystemmessage : function(msg) { + var messages = $('#msgboard'); + msg = ppChat.sanitize(msg); + msg = '' + msg + ''; + messages.html(messages.html() + msg + '
    '); + messages.scrollTop(10000); + }, + sanitize : function(msg) { + /* this isn't actual security, just avoids accidential html input */ + return msg.replace(/ (data.chunk + 1)) { + /* only send the request for the next chunk if the number of chunks we have went up (ie. we saw a new chunk) */ + if (chunk_length < this.recieved_chunks[data.id].length) { + /* update the cointainer % */ + update_container_percentage(data.id, data.chunk, this.recieved_meta[data.id].numOfChunksInFile, this.recieved_meta[data.id].size); + /* request the next chunk */ + request_chunk(data.id, (data.chunk + 1)); + /* reset the timeout */ + clearTimeout(this.recieved_timeout[data.id]); + this.recieved_timeout[data.id] = setTimeout(resend_chunk_request_CB(data.id, (data.chunk + 1)),this.timeout); + } + } else { + console.log("done downloading file!"); + /* reset the timeout so we don't recieve the same packet twice */ + clearTimeout(this.recieved_timeout[data.id]); + /* now combine the chunks and form a link! */ + var combine_chunks = ''; + for (var i = 0; i < this.recieved_meta[data.id].numOfChunksInFile; i++) { + if (this.recieved_chunks[data.id][i] == ''){ + console.log("missing chunk! " + i); + } + combine_chunks += this.recieved_chunks[data.id][i]; + } + create_file_link (combine_chunks,this.recieved_meta[data.id], data.id, data.username); + } + + } else if (data.file_meta) { + /* if it contains file_meta, must be meta data! */ + this.recieved_meta[data.id] = data.file_meta; + console.log(this.recieved_meta[data.id]); + this.recieved_chunks[data.id] = []; //clear out our chunks + + /* create a download link */ + create_pre_file_link(this.recieved_meta[data.id], data.id, data.username); + + /* if auto-download, start the process */ + if ($("#auto_download").prop('checked')) { + download_file(data.id); + } + } else { + /* if it does not have file_params, must be request for next chunk, send it, don't broadcast */ + sendchunk(data.id, data.chunk); + } +} + +/* request chunk # chunk_num from id */ +function request_chunk(id, chunk_num) { + //console.log("requesting chunk " + chunk_num + " from " + id); + dataChannelChat.send(id, JSON.stringify({ + "eventName": "request_chunk", + "data": { + "chunk": chunk_num + } + })); +} + +/* request id's file by sending request for block 0 */ +function download_file(id) { + request_chunk(id, 0); +} + +/* creates an entry in our filelist for a user, if it doesn't exist already */ +function create_or_clear_container(id, username) { + var filelist = document.getElementById('filelist_cointainer'); + var filecontainer = document.getElementById(id); + + if (!filecontainer) { + /* if filecontainer doesn't exist, create it */ + var fs = '
    ' + username + ':
    '; + filelist.innerHTML = filelist.innerHTML + fs; + } else { + /* if filecontainer does exist, clear it */ + filecontainer.innerHTML = username + ": "; + } +} + +/* creates an entry in our filelist for a user, if it doesn't exist already */ +function remove_container(id) { + var filecontainer = document.getElementById(id); + if (filecontainer) { + filecontainer.remove(); + } +} + + +/* create a link that will let the user start the download */ +function create_pre_file_link(meta, id, username) { + + //create a place to store this if it does not already + create_or_clear_container(id, username); + var filecontainer = document.getElementById(id); + + //create the link + var a = document.createElement('a'); + a.download = meta.name; + a.id = id + '-download'; + a.href = 'javascript:void(0);'; + a.textContent = 'download ' + meta.name + ' ' + getReadableFileSizeString(meta.size); + a.draggable = true; + + //onclick, download the file! + a.setAttribute('onclick','javascript:download_file("' + id + '");'); + + //append link! + var messages = document.getElementById('messages'); + filecontainer.appendChild(a); + + //append to chat + systemMessage(username +" is now offering file " + meta.name); +} + +/* update a file container with a DL % */ +function update_container_percentage(id, chunk_num, chunk_total, total_size) { + + create_or_clear_container(id, username); + var filecontainer = document.getElementById(id); + + /* create file % based on chunk # downloaded */ + var percentage = (chunk_num / chunk_total) * 100; + filecontainer.innerHTML = filecontainer.innerHTML + percentage.toFixed(1) + "% of " + getReadableFileSizeString(total_size); +} + +/* -h */ +function getReadableFileSizeString(fileSizeInBytes) { + var i = -1; + var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB']; + do { + fileSizeInBytes = fileSizeInBytes / 1024; + i++; + } while (fileSizeInBytes > 1024); + return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i]; +}; + +/* create a link to this file */ +function create_file_link (combine_chunks, meta, id, username) { + //grab the file type, should probably use a pattern match... + var remove_base = meta.filetype.split(";"); + var remove_data = remove_base[0].split(":"); + var filetype = remove_data[1]; + + //now handle the data + var debase64_data = base64.decode(combine_chunks); + var bb = new Blob([new Uint8Array(debase64_data)], {type: filetype}); + + //create a place to store this if it does not already + create_or_clear_container(id, username); + var filecontainer = document.getElementById(id); + + //create the link + var a = document.createElement('a'); + a.download = meta.name; + a.href = window.URL.createObjectURL(bb); + a.textContent = 'save ' + meta.name; + a.dataset.downloadurl = [filetype, a.download, a.href].join(':'); + a.draggable = true; + + //append link! + var messages = document.getElementById('messages'); + filecontainer.appendChild(a); + + //append to chat + systemMessage(username +"'s file " + meta.name + " is ready to save locally"); +} + +/* devide the base64'd file into chunks, also process meta data */ +function chunkify(result, file) { + var split = result.split(','); + + /* meta data */ + this.meta.name = file.name; + this.meta.size = file.size; + this.meta.filetype = split[0]; + + /*chunkify */ + var file = split[1];//base64 + this.numOfChunksInFile = Math.ceil(file.length / this.CHUNK_SIZE); + this.meta.numOfChunksInFile = numOfChunksInFile; + console.log("number of chunks to send:"+this.numOfChunksInFile); + + for (var i = 0; i < this.numOfChunksInFile; i++) { + var start = i * this.CHUNK_SIZE; + this.chunks[i] = file.slice(start, start + this.CHUNK_SIZE); + } +} + +/* send out meta data, allow for id to be empty = broadcast */ +function send_meta(id) { + if (jQuery.isEmptyObject(this.meta)) { + return; + } + console.log("sending meta data"); + console.log(this.meta); + if (!id) { + dataChannelChat.broadcast(JSON.stringify({ + "eventName": "data_msg", + "data": { + "file_meta": this.meta + } + })); + } else { + dataChannelChat.send(id, JSON.stringify({ + "eventName": "data_msg", + "data": { + "file_meta": this.meta + } + })); + } +} + +/* Please note that this works by sending a chunk, then waiting for a request for the next one */ +function sendchunk(id, chunk_num) { + /* uncomment the following 6 lines and set breakpoints on them to similar an impaired connection */ + /* if (chunk_num == 30) { + console.log("30 reached, breakpoint this line"); + } + if (chunk_num == 50) { + console.log("30 reached"); + }*/ + //console.log("sending chunk " + chunk_num + " to " + id); + dataChannelChat.send(id, JSON.stringify({ + "eventName": "data_msg", + "data": { + "chunk": chunk_num, + "file": this.chunks[chunk_num] + } + })); +} \ No newline at end of file diff --git a/public/javascripts/jquery.easyui.min.js b/public/javascripts/jquery.easyui.min.js new file mode 100644 index 0000000..f2e69da --- /dev/null +++ b/public/javascripts/jquery.easyui.min.js @@ -0,0 +1,11839 @@ +/** + * jQuery EasyUI 1.3.3 + * + * Copyright (c) 2009-2013 www.jeasyui.com. All rights reserved. + * + * Licensed under the GPL or commercial licenses + * To use it on other terms please contact us: info@jeasyui.com + * http://www.gnu.org/licenses/gpl.txt + * http://www.jeasyui.com/license_commercial.php + * + */ +(function($){ +$.parser={auto:true,onComplete:function(_1){ +},plugins:["draggable","droppable","resizable","pagination","tooltip","linkbutton","menu","menubutton","splitbutton","progressbar","tree","combobox","combotree","combogrid","numberbox","validatebox","searchbox","numberspinner","timespinner","calendar","datebox","datetimebox","slider","layout","panel","datagrid","propertygrid","treegrid","tabs","accordion","window","dialog"],parse:function(_2){ +var aa=[]; +for(var i=0;i<$.parser.plugins.length;i++){ +var _3=$.parser.plugins[i]; +var r=$(".easyui-"+_3,_2); +if(r.length){ +if(r[_3]){ +r[_3](); +}else{ +aa.push({name:_3,jq:r}); +} +} +} +if(aa.length&&window.easyloader){ +var _4=[]; +for(var i=0;i").appendTo("body"); +$._boxModel=parseInt(d.width())==100; +d.remove(); +if(!window.easyloader&&$.parser.auto){ +$.parser.parse(); +} +}); +$.fn._outerWidth=function(_e){ +if(_e==undefined){ +if(this[0]==window){ +return this.width()||document.body.clientWidth; +} +return this.outerWidth()||0; +} +return this.each(function(){ +if($._boxModel){ +$(this).width(_e-($(this).outerWidth()-$(this).width())); +}else{ +$(this).width(_e); +} +}); +}; +$.fn._outerHeight=function(_f){ +if(_f==undefined){ +if(this[0]==window){ +return this.height()||document.body.clientHeight; +} +return this.outerHeight()||0; +} +return this.each(function(){ +if($._boxModel){ +$(this).height(_f-($(this).outerHeight()-$(this).height())); +}else{ +$(this).height(_f); +} +}); +}; +$.fn._scrollLeft=function(_10){ +if(_10==undefined){ +return this.scrollLeft(); +}else{ +return this.each(function(){ +$(this).scrollLeft(_10); +}); +} +}; +$.fn._propAttr=$.fn.prop||$.fn.attr; +$.fn._fit=function(fit){ +fit=fit==undefined?true:fit; +var t=this[0]; +var p=(t.tagName=="BODY"?t:this.parent()[0]); +var _11=p.fcount||0; +if(fit){ +if(!t.fitted){ +t.fitted=true; +p.fcount=_11+1; +$(p).addClass("panel-noscroll"); +if(p.tagName=="BODY"){ +$("html").addClass("panel-fit"); +} +} +}else{ +if(t.fitted){ +t.fitted=false; +p.fcount=_11-1; +if(p.fcount==0){ +$(p).removeClass("panel-noscroll"); +if(p.tagName=="BODY"){ +$("html").removeClass("panel-fit"); +} +} +} +} +return {width:$(p).width(),height:$(p).height()}; +}; +})(jQuery); +(function($){ +var _12=false; +function _13(e){ +var _14=$.data(e.data.target,"draggable"); +var _15=_14.options; +var _16=_14.proxy; +var _17=e.data; +var _18=_17.startLeft+e.pageX-_17.startX; +var top=_17.startTop+e.pageY-_17.startY; +if(_16){ +if(_16.parent()[0]==document.body){ +if(_15.deltaX!=null&&_15.deltaX!=undefined){ +_18=e.pageX+_15.deltaX; +}else{ +_18=e.pageX-e.data.offsetWidth; +} +if(_15.deltaY!=null&&_15.deltaY!=undefined){ +top=e.pageY+_15.deltaY; +}else{ +top=e.pageY-e.data.offsetHeight; +} +}else{ +if(_15.deltaX!=null&&_15.deltaX!=undefined){ +_18+=e.data.offsetWidth+_15.deltaX; +} +if(_15.deltaY!=null&&_15.deltaY!=undefined){ +top+=e.data.offsetHeight+_15.deltaY; +} +} +} +if(e.data.parent!=document.body){ +_18+=$(e.data.parent).scrollLeft(); +top+=$(e.data.parent).scrollTop(); +} +if(_15.axis=="h"){ +_17.left=_18; +}else{ +if(_15.axis=="v"){ +_17.top=top; +}else{ +_17.left=_18; +_17.top=top; +} +} +}; +function _19(e){ +var _1a=$.data(e.data.target,"draggable"); +var _1b=_1a.options; +var _1c=_1a.proxy; +if(!_1c){ +_1c=$(e.data.target); +} +_1c.css({left:e.data.left,top:e.data.top}); +$("body").css("cursor",_1b.cursor); +}; +function _1d(e){ +_12=true; +var _1e=$.data(e.data.target,"draggable"); +var _1f=_1e.options; +var _20=$(".droppable").filter(function(){ +return e.data.target!=this; +}).filter(function(){ +var _21=$.data(this,"droppable").options.accept; +if(_21){ +return $(_21).filter(function(){ +return this==e.data.target; +}).length>0; +}else{ +return true; +} +}); +_1e.droppables=_20; +var _22=_1e.proxy; +if(!_22){ +if(_1f.proxy){ +if(_1f.proxy=="clone"){ +_22=$(e.data.target).clone().insertAfter(e.data.target); +}else{ +_22=_1f.proxy.call(e.data.target,e.data.target); +} +_1e.proxy=_22; +}else{ +_22=$(e.data.target); +} +} +_22.css("position","absolute"); +_13(e); +_19(e); +_1f.onStartDrag.call(e.data.target,e); +return false; +}; +function _23(e){ +var _24=$.data(e.data.target,"draggable"); +_13(e); +if(_24.options.onDrag.call(e.data.target,e)!=false){ +_19(e); +} +var _25=e.data.target; +_24.droppables.each(function(){ +var _26=$(this); +if(_26.droppable("options").disabled){ +return; +} +var p2=_26.offset(); +if(e.pageX>p2.left&&e.pageXp2.top&&e.pageYp2.left&&e.pageXp2.top&&e.pageY_3b.options.edge; +}; +}); +}; +$.fn.draggable.methods={options:function(jq){ +return $.data(jq[0],"draggable").options; +},proxy:function(jq){ +return $.data(jq[0],"draggable").proxy; +},enable:function(jq){ +return jq.each(function(){ +$(this).draggable({disabled:false}); +}); +},disable:function(jq){ +return jq.each(function(){ +$(this).draggable({disabled:true}); +}); +}}; +$.fn.draggable.parseOptions=function(_40){ +var t=$(_40); +return $.extend({},$.parser.parseOptions(_40,["cursor","handle","axis",{"revert":"boolean","deltaX":"number","deltaY":"number","edge":"number"}]),{disabled:(t.attr("disabled")?true:undefined)}); +}; +$.fn.draggable.defaults={proxy:null,revert:false,cursor:"move",deltaX:null,deltaY:null,handle:null,disabled:false,edge:0,axis:null,onBeforeDrag:function(e){ +},onStartDrag:function(e){ +},onDrag:function(e){ +},onStopDrag:function(e){ +}}; +$(function(){ +function _41(e){ +var _42=e.changedTouches,_43=_42[0],_44=""; +switch(e.type){ +case "touchstart": +_44="mousedown"; +break; +case "touchmove": +_44="mousemove"; +break; +case "touchend": +_44="mouseup"; +break; +default: +return; +} +var _45=document.createEvent("MouseEvent"); +_45.initMouseEvent(_44,true,true,window,1,_43.screenX,_43.screenY,_43.clientX,_43.clientY,false,false,false,false,0,null); +_43.target.dispatchEvent(_45); +if(_12){ +e.preventDefault(); +} +}; +if(document.addEventListener){ +document.addEventListener("touchstart",_41,true); +document.addEventListener("touchmove",_41,true); +document.addEventListener("touchend",_41,true); +document.addEventListener("touchcancel",_41,true); +} +}); +})(jQuery); +(function($){ +function _46(_47){ +$(_47).addClass("droppable"); +$(_47).bind("_dragenter",function(e,_48){ +$.data(_47,"droppable").options.onDragEnter.apply(_47,[e,_48]); +}); +$(_47).bind("_dragleave",function(e,_49){ +$.data(_47,"droppable").options.onDragLeave.apply(_47,[e,_49]); +}); +$(_47).bind("_dragover",function(e,_4a){ +$.data(_47,"droppable").options.onDragOver.apply(_47,[e,_4a]); +}); +$(_47).bind("_drop",function(e,_4b){ +$.data(_47,"droppable").options.onDrop.apply(_47,[e,_4b]); +}); +}; +$.fn.droppable=function(_4c,_4d){ +if(typeof _4c=="string"){ +return $.fn.droppable.methods[_4c](this,_4d); +} +_4c=_4c||{}; +return this.each(function(){ +var _4e=$.data(this,"droppable"); +if(_4e){ +$.extend(_4e.options,_4c); +}else{ +_46(this); +$.data(this,"droppable",{options:$.extend({},$.fn.droppable.defaults,$.fn.droppable.parseOptions(this),_4c)}); +} +}); +}; +$.fn.droppable.methods={options:function(jq){ +return $.data(jq[0],"droppable").options; +},enable:function(jq){ +return jq.each(function(){ +$(this).droppable({disabled:false}); +}); +},disable:function(jq){ +return jq.each(function(){ +$(this).droppable({disabled:true}); +}); +}}; +$.fn.droppable.parseOptions=function(_4f){ +var t=$(_4f); +return $.extend({},$.parser.parseOptions(_4f,["accept"]),{disabled:(t.attr("disabled")?true:undefined)}); +}; +$.fn.droppable.defaults={accept:null,disabled:false,onDragEnter:function(e,_50){ +},onDragOver:function(e,_51){ +},onDragLeave:function(e,_52){ +},onDrop:function(e,_53){ +}}; +})(jQuery); +(function($){ +var _54=false; +$.fn.resizable=function(_55,_56){ +if(typeof _55=="string"){ +return $.fn.resizable.methods[_55](this,_56); +} +function _57(e){ +var _58=e.data; +var _59=$.data(_58.target,"resizable").options; +if(_58.dir.indexOf("e")!=-1){ +var _5a=_58.startWidth+e.pageX-_58.startX; +_5a=Math.min(Math.max(_5a,_59.minWidth),_59.maxWidth); +_58.width=_5a; +} +if(_58.dir.indexOf("s")!=-1){ +var _5b=_58.startHeight+e.pageY-_58.startY; +_5b=Math.min(Math.max(_5b,_59.minHeight),_59.maxHeight); +_58.height=_5b; +} +if(_58.dir.indexOf("w")!=-1){ +var _5a=_58.startWidth-e.pageX+_58.startX; +_5a=Math.min(Math.max(_5a,_59.minWidth),_59.maxWidth); +_58.width=_5a; +_58.left=_58.startLeft+_58.startWidth-_58.width; +} +if(_58.dir.indexOf("n")!=-1){ +var _5b=_58.startHeight-e.pageY+_58.startY; +_5b=Math.min(Math.max(_5b,_59.minHeight),_59.maxHeight); +_58.height=_5b; +_58.top=_58.startTop+_58.startHeight-_58.height; +} +}; +function _5c(e){ +var _5d=e.data; +var t=$(_5d.target); +t.css({left:_5d.left,top:_5d.top}); +if(t.outerWidth()!=_5d.width){ +t._outerWidth(_5d.width); +} +if(t.outerHeight()!=_5d.height){ +t._outerHeight(_5d.height); +} +}; +function _5e(e){ +_54=true; +$.data(e.data.target,"resizable").options.onStartResize.call(e.data.target,e); +return false; +}; +function _5f(e){ +_57(e); +if($.data(e.data.target,"resizable").options.onResize.call(e.data.target,e)!=false){ +_5c(e); +} +return false; +}; +function _60(e){ +_54=false; +_57(e,true); +_5c(e); +$.data(e.data.target,"resizable").options.onStopResize.call(e.data.target,e); +$(document).unbind(".resizable"); +$("body").css("cursor",""); +return false; +}; +return this.each(function(){ +var _61=null; +var _62=$.data(this,"resizable"); +if(_62){ +$(this).unbind(".resizable"); +_61=$.extend(_62.options,_55||{}); +}else{ +_61=$.extend({},$.fn.resizable.defaults,$.fn.resizable.parseOptions(this),_55||{}); +$.data(this,"resizable",{options:_61}); +} +if(_61.disabled==true){ +return; +} +$(this).bind("mousemove.resizable",{target:this},function(e){ +if(_54){ +return; +} +var dir=_63(e); +if(dir==""){ +$(e.data.target).css("cursor",""); +}else{ +$(e.data.target).css("cursor",dir+"-resize"); +} +}).bind("mouseleave.resizable",{target:this},function(e){ +$(e.data.target).css("cursor",""); +}).bind("mousedown.resizable",{target:this},function(e){ +var dir=_63(e); +if(dir==""){ +return; +} +function _64(css){ +var val=parseInt($(e.data.target).css(css)); +if(isNaN(val)){ +return 0; +}else{ +return val; +} +}; +var _65={target:e.data.target,dir:dir,startLeft:_64("left"),startTop:_64("top"),left:_64("left"),top:_64("top"),startX:e.pageX,startY:e.pageY,startWidth:$(e.data.target).outerWidth(),startHeight:$(e.data.target).outerHeight(),width:$(e.data.target).outerWidth(),height:$(e.data.target).outerHeight(),deltaWidth:$(e.data.target).outerWidth()-$(e.data.target).width(),deltaHeight:$(e.data.target).outerHeight()-$(e.data.target).height()}; +$(document).bind("mousedown.resizable",_65,_5e); +$(document).bind("mousemove.resizable",_65,_5f); +$(document).bind("mouseup.resizable",_65,_60); +$("body").css("cursor",dir+"-resize"); +}); +function _63(e){ +var tt=$(e.data.target); +var dir=""; +var _66=tt.offset(); +var _67=tt.outerWidth(); +var _68=tt.outerHeight(); +var _69=_61.edge; +if(e.pageY>_66.top&&e.pageY<_66.top+_69){ +dir+="n"; +}else{ +if(e.pageY<_66.top+_68&&e.pageY>_66.top+_68-_69){ +dir+="s"; +} +} +if(e.pageX>_66.left&&e.pageX<_66.left+_69){ +dir+="w"; +}else{ +if(e.pageX<_66.left+_67&&e.pageX>_66.left+_67-_69){ +dir+="e"; +} +} +var _6a=_61.handles.split(","); +for(var i=0;i<_6a.length;i++){ +var _6b=_6a[i].replace(/(^\s*)|(\s*$)/g,""); +if(_6b=="all"||_6b==dir){ +return dir; +} +} +return ""; +}; +}); +}; +$.fn.resizable.methods={options:function(jq){ +return $.data(jq[0],"resizable").options; +},enable:function(jq){ +return jq.each(function(){ +$(this).resizable({disabled:false}); +}); +},disable:function(jq){ +return jq.each(function(){ +$(this).resizable({disabled:true}); +}); +}}; +$.fn.resizable.parseOptions=function(_6c){ +var t=$(_6c); +return $.extend({},$.parser.parseOptions(_6c,["handles",{minWidth:"number",minHeight:"number",maxWidth:"number",maxHeight:"number",edge:"number"}]),{disabled:(t.attr("disabled")?true:undefined)}); +}; +$.fn.resizable.defaults={disabled:false,handles:"n, e, s, w, ne, se, sw, nw, all",minWidth:10,minHeight:10,maxWidth:10000,maxHeight:10000,edge:5,onStartResize:function(e){ +},onResize:function(e){ +},onStopResize:function(e){ +}}; +})(jQuery); +(function($){ +function _6d(_6e){ +var _6f=$.data(_6e,"linkbutton").options; +var t=$(_6e); +t.addClass("l-btn").removeClass("l-btn-plain l-btn-selected l-btn-plain-selected"); +if(_6f.plain){ +t.addClass("l-btn-plain"); +} +if(_6f.selected){ +t.addClass(_6f.plain?"l-btn-selected l-btn-plain-selected":"l-btn-selected"); +} +t.attr("group",_6f.group||""); +t.attr("id",_6f.id||""); +t.html(""+""+""); +if(_6f.text){ +t.find(".l-btn-text").html(_6f.text); +if(_6f.iconCls){ +t.find(".l-btn-text").addClass(_6f.iconCls).addClass(_6f.iconAlign=="left"?"l-btn-icon-left":"l-btn-icon-right"); +} +}else{ +t.find(".l-btn-text").html(" "); +if(_6f.iconCls){ +t.find(".l-btn-empty").addClass(_6f.iconCls); +} +} +t.unbind(".linkbutton").bind("focus.linkbutton",function(){ +if(!_6f.disabled){ +$(this).find(".l-btn-text").addClass("l-btn-focus"); +} +}).bind("blur.linkbutton",function(){ +$(this).find(".l-btn-text").removeClass("l-btn-focus"); +}); +if(_6f.toggle&&!_6f.disabled){ +t.bind("click.linkbutton",function(){ +if(_6f.selected){ +$(this).linkbutton("unselect"); +}else{ +$(this).linkbutton("select"); +} +}); +} +_70(_6e,_6f.selected); +_71(_6e,_6f.disabled); +}; +function _70(_72,_73){ +var _74=$.data(_72,"linkbutton").options; +if(_73){ +if(_74.group){ +$("a.l-btn[group=\""+_74.group+"\"]").each(function(){ +var o=$(this).linkbutton("options"); +if(o.toggle){ +$(this).removeClass("l-btn-selected l-btn-plain-selected"); +o.selected=false; +} +}); +} +$(_72).addClass(_74.plain?"l-btn-selected l-btn-plain-selected":"l-btn-selected"); +_74.selected=true; +}else{ +if(!_74.group){ +$(_72).removeClass("l-btn-selected l-btn-plain-selected"); +_74.selected=false; +} +} +}; +function _71(_75,_76){ +var _77=$.data(_75,"linkbutton"); +var _78=_77.options; +$(_75).removeClass("l-btn-disabled l-btn-plain-disabled"); +if(_76){ +_78.disabled=true; +var _79=$(_75).attr("href"); +if(_79){ +_77.href=_79; +$(_75).attr("href","javascript:void(0)"); +} +if(_75.onclick){ +_77.onclick=_75.onclick; +_75.onclick=null; +} +_78.plain?$(_75).addClass("l-btn-disabled l-btn-plain-disabled"):$(_75).addClass("l-btn-disabled"); +}else{ +_78.disabled=false; +if(_77.href){ +$(_75).attr("href",_77.href); +} +if(_77.onclick){ +_75.onclick=_77.onclick; +} +} +}; +$.fn.linkbutton=function(_7a,_7b){ +if(typeof _7a=="string"){ +return $.fn.linkbutton.methods[_7a](this,_7b); +} +_7a=_7a||{}; +return this.each(function(){ +var _7c=$.data(this,"linkbutton"); +if(_7c){ +$.extend(_7c.options,_7a); +}else{ +$.data(this,"linkbutton",{options:$.extend({},$.fn.linkbutton.defaults,$.fn.linkbutton.parseOptions(this),_7a)}); +$(this).removeAttr("disabled"); +} +_6d(this); +}); +}; +$.fn.linkbutton.methods={options:function(jq){ +return $.data(jq[0],"linkbutton").options; +},enable:function(jq){ +return jq.each(function(){ +_71(this,false); +}); +},disable:function(jq){ +return jq.each(function(){ +_71(this,true); +}); +},select:function(jq){ +return jq.each(function(){ +_70(this,true); +}); +},unselect:function(jq){ +return jq.each(function(){ +_70(this,false); +}); +}}; +$.fn.linkbutton.parseOptions=function(_7d){ +var t=$(_7d); +return $.extend({},$.parser.parseOptions(_7d,["id","iconCls","iconAlign","group",{plain:"boolean",toggle:"boolean",selected:"boolean"}]),{disabled:(t.attr("disabled")?true:undefined),text:$.trim(t.html()),iconCls:(t.attr("icon")||t.attr("iconCls"))}); +}; +$.fn.linkbutton.defaults={id:null,disabled:false,toggle:false,selected:false,group:null,plain:false,text:"",iconCls:null,iconAlign:"left"}; +})(jQuery); +(function($){ +function _7e(_7f){ +var _80=$.data(_7f,"pagination"); +var _81=_80.options; +var bb=_80.bb={}; +var _82=$(_7f).addClass("pagination").html("
    "); +var tr=_82.find("tr"); +function _83(_84){ +var btn=_81.nav[_84]; +var a=$("").appendTo(tr); +a.wrap(""); +a.linkbutton({iconCls:btn.iconCls,plain:true}).unbind(".pagination").bind("click.pagination",function(){ +btn.handler.call(_7f); +}); +return a; +}; +if(_81.showPageList){ +var ps=$(""); +ps.bind("change",function(){ +_81.pageSize=parseInt($(this).val()); +_81.onChangePageSize.call(_7f,_81.pageSize); +_86(_7f,_81.pageNumber); +}); +for(var i=0;i<_81.pageList.length;i++){ +$("").text(_81.pageList[i]).appendTo(ps); +} +$("").append(ps).appendTo(tr); +$("
    ").appendTo(tr); +} +bb.first=_83("first"); +bb.prev=_83("prev"); +$("
    ").appendTo(tr); +$("").html(_81.beforePageText).appendTo(tr).wrap(""); +bb.num=$("").appendTo(tr).wrap(""); +bb.num.unbind(".pagination").bind("keydown.pagination",function(e){ +if(e.keyCode==13){ +var _85=parseInt($(this).val())||1; +_86(_7f,_85); +return false; +} +}); +bb.after=$("").appendTo(tr).wrap(""); +$("
    ").appendTo(tr); +bb.next=_83("next"); +bb.last=_83("last"); +if(_81.showRefresh){ +$("
    ").appendTo(tr); +bb.refresh=_83("refresh"); +} +if(_81.buttons){ +$("
    ").appendTo(tr); +for(var i=0;i<_81.buttons.length;i++){ +var btn=_81.buttons[i]; +if(btn=="-"){ +$("
    ").appendTo(tr); +}else{ +var td=$("").appendTo(tr); +var a=$("").appendTo(td); +a[0].onclick=eval(btn.handler||function(){ +}); +a.linkbutton($.extend({},btn,{plain:true})); +} +} +} +$("
    ").appendTo(_82); +$("
    ").appendTo(_82); +}; +function _86(_87,_88){ +var _89=$.data(_87,"pagination").options; +var _8a=Math.ceil(_89.total/_89.pageSize)||1; +_89.pageNumber=_88; +if(_89.pageNumber<1){ +_89.pageNumber=1; +} +if(_89.pageNumber>_8a){ +_89.pageNumber=_8a; +} +_8b(_87,{pageNumber:_89.pageNumber}); +_89.onSelectPage.call(_87,_89.pageNumber,_89.pageSize); +}; +function _8b(_8c,_8d){ +var _8e=$.data(_8c,"pagination").options; +var bb=$.data(_8c,"pagination").bb; +$.extend(_8e,_8d||{}); +var ps=$(_8c).find("select.pagination-page-list"); +if(ps.length){ +ps.val(_8e.pageSize+""); +_8e.pageSize=parseInt(ps.val()); +} +var _8f=Math.ceil(_8e.total/_8e.pageSize)||1; +bb.num.val(_8e.pageNumber); +bb.after.html(_8e.afterPageText.replace(/{pages}/,_8f)); +var _90=_8e.displayMsg; +_90=_90.replace(/{from}/,_8e.total==0?0:_8e.pageSize*(_8e.pageNumber-1)+1); +_90=_90.replace(/{to}/,Math.min(_8e.pageSize*(_8e.pageNumber),_8e.total)); +_90=_90.replace(/{total}/,_8e.total); +$(_8c).find("div.pagination-info").html(_90); +bb.first.add(bb.prev).linkbutton({disabled:(_8e.pageNumber==1)}); +bb.next.add(bb.last).linkbutton({disabled:(_8e.pageNumber==_8f)}); +_91(_8c,_8e.loading); +}; +function _91(_92,_93){ +var _94=$.data(_92,"pagination").options; +var bb=$.data(_92,"pagination").bb; +_94.loading=_93; +if(_94.showRefresh){ +if(_94.loading){ +bb.refresh.linkbutton({iconCls:"pagination-loading"}); +}else{ +bb.refresh.linkbutton({iconCls:"pagination-load"}); +} +} +}; +$.fn.pagination=function(_95,_96){ +if(typeof _95=="string"){ +return $.fn.pagination.methods[_95](this,_96); +} +_95=_95||{}; +return this.each(function(){ +var _97; +var _98=$.data(this,"pagination"); +if(_98){ +_97=$.extend(_98.options,_95); +}else{ +_97=$.extend({},$.fn.pagination.defaults,$.fn.pagination.parseOptions(this),_95); +$.data(this,"pagination",{options:_97}); +} +_7e(this); +_8b(this); +}); +}; +$.fn.pagination.methods={options:function(jq){ +return $.data(jq[0],"pagination").options; +},loading:function(jq){ +return jq.each(function(){ +_91(this,true); +}); +},loaded:function(jq){ +return jq.each(function(){ +_91(this,false); +}); +},refresh:function(jq,_99){ +return jq.each(function(){ +_8b(this,_99); +}); +},select:function(jq,_9a){ +return jq.each(function(){ +_86(this,_9a); +}); +}}; +$.fn.pagination.parseOptions=function(_9b){ +var t=$(_9b); +return $.extend({},$.parser.parseOptions(_9b,[{total:"number",pageSize:"number",pageNumber:"number"},{loading:"boolean",showPageList:"boolean",showRefresh:"boolean"}]),{pageList:(t.attr("pageList")?eval(t.attr("pageList")):undefined)}); +}; +$.fn.pagination.defaults={total:1,pageSize:10,pageNumber:1,pageList:[10,20,30,50],loading:false,buttons:null,showPageList:true,showRefresh:true,onSelectPage:function(_9c,_9d){ +},onBeforeRefresh:function(_9e,_9f){ +},onRefresh:function(_a0,_a1){ +},onChangePageSize:function(_a2){ +},beforePageText:"Page",afterPageText:"of {pages}",displayMsg:"Displaying {from} to {to} of {total} items",nav:{first:{iconCls:"pagination-first",handler:function(){ +var _a3=$(this).pagination("options"); +if(_a3.pageNumber>1){ +$(this).pagination("select",1); +} +}},prev:{iconCls:"pagination-prev",handler:function(){ +var _a4=$(this).pagination("options"); +if(_a4.pageNumber>1){ +$(this).pagination("select",_a4.pageNumber-1); +} +}},next:{iconCls:"pagination-next",handler:function(){ +var _a5=$(this).pagination("options"); +var _a6=Math.ceil(_a5.total/_a5.pageSize); +if(_a5.pageNumber<_a6){ +$(this).pagination("select",_a5.pageNumber+1); +} +}},last:{iconCls:"pagination-last",handler:function(){ +var _a7=$(this).pagination("options"); +var _a8=Math.ceil(_a7.total/_a7.pageSize); +if(_a7.pageNumber<_a8){ +$(this).pagination("select",_a8); +} +}},refresh:{iconCls:"pagination-refresh",handler:function(){ +var _a9=$(this).pagination("options"); +if(_a9.onBeforeRefresh.call(this,_a9.pageNumber,_a9.pageSize)!=false){ +$(this).pagination("select",_a9.pageNumber); +_a9.onRefresh.call(this,_a9.pageNumber,_a9.pageSize); +} +}}}}; +})(jQuery); +(function($){ +function _aa(_ab){ +var _ac=$(_ab); +_ac.addClass("tree"); +return _ac; +}; +function _ad(_ae){ +var _af=[]; +_b0(_af,$(_ae)); +function _b0(aa,_b1){ +_b1.children("li").each(function(){ +var _b2=$(this); +var _b3=$.extend({},$.parser.parseOptions(this,["id","iconCls","state"]),{checked:(_b2.attr("checked")?true:undefined)}); +_b3.text=_b2.children("span").html(); +if(!_b3.text){ +_b3.text=_b2.html(); +} +var _b4=_b2.children("ul"); +if(_b4.length){ +_b3.children=[]; +_b0(_b3.children,_b4); +} +aa.push(_b3); +}); +}; +return _af; +}; +function _b5(_b6){ +var _b7=$.data(_b6,"tree").options; +$(_b6).unbind().bind("mouseover",function(e){ +var tt=$(e.target); +var _b8=tt.closest("div.tree-node"); +if(!_b8.length){ +return; +} +_b8.addClass("tree-node-hover"); +if(tt.hasClass("tree-hit")){ +if(tt.hasClass("tree-expanded")){ +tt.addClass("tree-expanded-hover"); +}else{ +tt.addClass("tree-collapsed-hover"); +} +} +e.stopPropagation(); +}).bind("mouseout",function(e){ +var tt=$(e.target); +var _b9=tt.closest("div.tree-node"); +if(!_b9.length){ +return; +} +_b9.removeClass("tree-node-hover"); +if(tt.hasClass("tree-hit")){ +if(tt.hasClass("tree-expanded")){ +tt.removeClass("tree-expanded-hover"); +}else{ +tt.removeClass("tree-collapsed-hover"); +} +} +e.stopPropagation(); +}).bind("click",function(e){ +var tt=$(e.target); +var _ba=tt.closest("div.tree-node"); +if(!_ba.length){ +return; +} +if(tt.hasClass("tree-hit")){ +_11f(_b6,_ba[0]); +return false; +}else{ +if(tt.hasClass("tree-checkbox")){ +_e2(_b6,_ba[0],!tt.hasClass("tree-checkbox1")); +return false; +}else{ +_15d(_b6,_ba[0]); +_b7.onClick.call(_b6,_bd(_b6,_ba[0])); +} +} +e.stopPropagation(); +}).bind("dblclick",function(e){ +var _bb=$(e.target).closest("div.tree-node"); +if(!_bb.length){ +return; +} +_15d(_b6,_bb[0]); +_b7.onDblClick.call(_b6,_bd(_b6,_bb[0])); +e.stopPropagation(); +}).bind("contextmenu",function(e){ +var _bc=$(e.target).closest("div.tree-node"); +if(!_bc.length){ +return; +} +_b7.onContextMenu.call(_b6,e,_bd(_b6,_bc[0])); +e.stopPropagation(); +}); +}; +function _be(_bf){ +var _c0=$(_bf).find("div.tree-node"); +_c0.draggable("disable"); +_c0.css("cursor","pointer"); +}; +function _c1(_c2){ +var _c3=$.data(_c2,"tree"); +var _c4=_c3.options; +var _c5=_c3.tree; +_c3.disabledNodes=[]; +_c5.find("div.tree-node").draggable({disabled:false,revert:true,cursor:"pointer",proxy:function(_c6){ +var p=$("
    ").appendTo("body"); +p.html(" "+$(_c6).find(".tree-title").html()); +p.hide(); +return p; +},deltaX:15,deltaY:15,onBeforeDrag:function(e){ +if(_c4.onBeforeDrag.call(_c2,_bd(_c2,this))==false){ +return false; +} +if($(e.target).hasClass("tree-hit")||$(e.target).hasClass("tree-checkbox")){ +return false; +} +if(e.which!=1){ +return false; +} +$(this).next("ul").find("div.tree-node").droppable({accept:"no-accept"}); +var _c7=$(this).find("span.tree-indent"); +if(_c7.length){ +e.data.offsetWidth-=_c7.length*_c7.width(); +} +},onStartDrag:function(){ +$(this).draggable("proxy").css({left:-10000,top:-10000}); +_c4.onStartDrag.call(_c2,_bd(_c2,this)); +var _c8=_bd(_c2,this); +if(_c8.id==undefined){ +_c8.id="easyui_tree_node_id_temp"; +_155(_c2,_c8); +} +_c3.draggingNodeId=_c8.id; +},onDrag:function(e){ +var x1=e.pageX,y1=e.pageY,x2=e.data.startX,y2=e.data.startY; +var d=Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); +if(d>3){ +$(this).draggable("proxy").show(); +} +this.pageY=e.pageY; +},onStopDrag:function(){ +$(this).next("ul").find("div.tree-node").droppable({accept:"div.tree-node"}); +for(var i=0;i<_c3.disabledNodes.length;i++){ +$(_c3.disabledNodes[i]).droppable("enable"); +} +_c3.disabledNodes=[]; +var _c9=_15b(_c2,_c3.draggingNodeId); +if(_c9&&_c9.id=="easyui_tree_node_id_temp"){ +_c9.id=""; +_155(_c2,_c9); +} +_c4.onStopDrag.call(_c2,_c9); +}}).droppable({accept:"div.tree-node",onDragEnter:function(e,_ca){ +if(_c4.onDragEnter.call(_c2,this,_bd(_c2,_ca))==false){ +_cb(_ca,false); +$(this).removeClass("tree-node-append tree-node-top tree-node-bottom"); +$(this).droppable("disable"); +_c3.disabledNodes.push(this); +} +},onDragOver:function(e,_cc){ +if($(this).droppable("options").disabled){ +return; +} +var _cd=_cc.pageY; +var top=$(this).offset().top; +var _ce=top+$(this).outerHeight(); +_cb(_cc,true); +$(this).removeClass("tree-node-append tree-node-top tree-node-bottom"); +if(_cd>top+(_ce-top)/2){ +if(_ce-_cd<5){ +$(this).addClass("tree-node-bottom"); +}else{ +$(this).addClass("tree-node-append"); +} +}else{ +if(_cd-top<5){ +$(this).addClass("tree-node-top"); +}else{ +$(this).addClass("tree-node-append"); +} +} +if(_c4.onDragOver.call(_c2,this,_bd(_c2,_cc))==false){ +_cb(_cc,false); +$(this).removeClass("tree-node-append tree-node-top tree-node-bottom"); +$(this).droppable("disable"); +_c3.disabledNodes.push(this); +} +},onDragLeave:function(e,_cf){ +_cb(_cf,false); +$(this).removeClass("tree-node-append tree-node-top tree-node-bottom"); +_c4.onDragLeave.call(_c2,this,_bd(_c2,_cf)); +},onDrop:function(e,_d0){ +var _d1=this; +var _d2,_d3; +if($(this).hasClass("tree-node-append")){ +_d2=_d4; +}else{ +_d2=_d5; +_d3=$(this).hasClass("tree-node-top")?"top":"bottom"; +} +if(_c4.onBeforeDrop.call(_c2,_d1,_14f(_c2,_d0),_d3)==false){ +$(this).removeClass("tree-node-append tree-node-top tree-node-bottom"); +return; +} +_d2(_d0,_d1,_d3); +$(this).removeClass("tree-node-append tree-node-top tree-node-bottom"); +}}); +function _cb(_d6,_d7){ +var _d8=$(_d6).draggable("proxy").find("span.tree-dnd-icon"); +_d8.removeClass("tree-dnd-yes tree-dnd-no").addClass(_d7?"tree-dnd-yes":"tree-dnd-no"); +}; +function _d4(_d9,_da){ +if(_bd(_c2,_da).state=="closed"){ +_117(_c2,_da,function(){ +_db(); +}); +}else{ +_db(); +} +function _db(){ +var _dc=$(_c2).tree("pop",_d9); +$(_c2).tree("append",{parent:_da,data:[_dc]}); +_c4.onDrop.call(_c2,_da,_dc,"append"); +}; +}; +function _d5(_dd,_de,_df){ +var _e0={}; +if(_df=="top"){ +_e0.before=_de; +}else{ +_e0.after=_de; +} +var _e1=$(_c2).tree("pop",_dd); +_e0.data=_e1; +$(_c2).tree("insert",_e0); +_c4.onDrop.call(_c2,_de,_e1,_df); +}; +}; +function _e2(_e3,_e4,_e5){ +var _e6=$.data(_e3,"tree").options; +if(!_e6.checkbox){ +return; +} +var _e7=_bd(_e3,_e4); +if(_e6.onBeforeCheck.call(_e3,_e7,_e5)==false){ +return; +} +var _e8=$(_e4); +var ck=_e8.find(".tree-checkbox"); +ck.removeClass("tree-checkbox0 tree-checkbox1 tree-checkbox2"); +if(_e5){ +ck.addClass("tree-checkbox1"); +}else{ +ck.addClass("tree-checkbox0"); +} +if(_e6.cascadeCheck){ +_e9(_e8); +_ea(_e8); +} +_e6.onCheck.call(_e3,_e7,_e5); +function _ea(_eb){ +var _ec=_eb.next().find(".tree-checkbox"); +_ec.removeClass("tree-checkbox0 tree-checkbox1 tree-checkbox2"); +if(_eb.find(".tree-checkbox").hasClass("tree-checkbox1")){ +_ec.addClass("tree-checkbox1"); +}else{ +_ec.addClass("tree-checkbox0"); +} +}; +function _e9(_ed){ +var _ee=_12a(_e3,_ed[0]); +if(_ee){ +var ck=$(_ee.target).find(".tree-checkbox"); +ck.removeClass("tree-checkbox0 tree-checkbox1 tree-checkbox2"); +if(_ef(_ed)){ +ck.addClass("tree-checkbox1"); +}else{ +if(_f0(_ed)){ +ck.addClass("tree-checkbox0"); +}else{ +ck.addClass("tree-checkbox2"); +} +} +_e9($(_ee.target)); +} +function _ef(n){ +var ck=n.find(".tree-checkbox"); +if(ck.hasClass("tree-checkbox0")||ck.hasClass("tree-checkbox2")){ +return false; +} +var b=true; +n.parent().siblings().each(function(){ +if(!$(this).children("div.tree-node").children(".tree-checkbox").hasClass("tree-checkbox1")){ +b=false; +} +}); +return b; +}; +function _f0(n){ +var ck=n.find(".tree-checkbox"); +if(ck.hasClass("tree-checkbox1")||ck.hasClass("tree-checkbox2")){ +return false; +} +var b=true; +n.parent().siblings().each(function(){ +if(!$(this).children("div.tree-node").children(".tree-checkbox").hasClass("tree-checkbox0")){ +b=false; +} +}); +return b; +}; +}; +}; +function _f1(_f2,_f3){ +var _f4=$.data(_f2,"tree").options; +var _f5=$(_f3); +if(_f6(_f2,_f3)){ +var ck=_f5.find(".tree-checkbox"); +if(ck.length){ +if(ck.hasClass("tree-checkbox1")){ +_e2(_f2,_f3,true); +}else{ +_e2(_f2,_f3,false); +} +}else{ +if(_f4.onlyLeafCheck){ +$("").insertBefore(_f5.find(".tree-title")); +} +} +}else{ +var ck=_f5.find(".tree-checkbox"); +if(_f4.onlyLeafCheck){ +ck.remove(); +}else{ +if(ck.hasClass("tree-checkbox1")){ +_e2(_f2,_f3,true); +}else{ +if(ck.hasClass("tree-checkbox2")){ +var _f7=true; +var _f8=true; +var _f9=_fa(_f2,_f3); +for(var i=0;i<_f9.length;i++){ +if(_f9[i].checked){ +_f8=false; +}else{ +_f7=false; +} +} +if(_f7){ +_e2(_f2,_f3,true); +} +if(_f8){ +_e2(_f2,_f3,false); +} +} +} +} +} +}; +function _fb(_fc,ul,_fd,_fe){ +var _ff=$.data(_fc,"tree").options; +_fd=_ff.loadFilter.call(_fc,_fd,$(ul).prev("div.tree-node")[0]); +if(!_fe){ +$(ul).empty(); +} +var _100=[]; +var _101=$(ul).prev("div.tree-node").find("span.tree-indent, span.tree-hit").length; +_102(ul,_fd,_101); +if(_ff.dnd){ +_c1(_fc); +}else{ +_be(_fc); +} +for(var i=0;i<_100.length;i++){ +_e2(_fc,_100[i],true); +} +setTimeout(function(){ +_107(_fc,_fc); +},0); +var _103=null; +if(_fc!=ul){ +var node=$(ul).prev(); +_103=_bd(_fc,node[0]); +} +_ff.onLoadSuccess.call(_fc,_103,_fd); +function _102(ul,_104,_105){ +for(var i=0;i<_104.length;i++){ +var li=$("
  • ").appendTo(ul); +var item=_104[i]; +if(item.state!="open"&&item.state!="closed"){ +item.state="open"; +} +var node=$("
    ").appendTo(li); +node.attr("node-id",item.id); +$.data(node[0],"tree-node",{id:item.id,text:item.text,iconCls:item.iconCls,attributes:item.attributes}); +$("").html(_ff.formatter.call(_fc,item)).appendTo(node); +if(_ff.checkbox){ +if(_ff.onlyLeafCheck){ +if(item.state=="open"&&(!item.children||!item.children.length)){ +if(item.checked){ +$("").prependTo(node); +}else{ +$("").prependTo(node); +} +} +}else{ +if(item.checked){ +$("").prependTo(node); +_100.push(node[0]); +}else{ +$("").prependTo(node); +} +} +} +if(item.children&&item.children.length){ +var _106=$("
      ").appendTo(li); +if(item.state=="open"){ +$("").addClass(item.iconCls).prependTo(node); +$("").prependTo(node); +}else{ +$("").addClass(item.iconCls).prependTo(node); +$("").prependTo(node); +_106.css("display","none"); +} +_102(_106,item.children,_105+1); +}else{ +if(item.state=="closed"){ +$("").addClass(item.iconCls).prependTo(node); +$("").prependTo(node); +}else{ +$("").addClass(item.iconCls).prependTo(node); +$("").prependTo(node); +} +} +for(var j=0;j<_105;j++){ +$("").prependTo(node); +} +} +}; +}; +function _107(_108,ul,_109){ +var opts=$.data(_108,"tree").options; +if(!opts.lines){ +return; +} +if(!_109){ +_109=true; +$(_108).find("span.tree-indent").removeClass("tree-line tree-join tree-joinbottom"); +$(_108).find("div.tree-node").removeClass("tree-node-last tree-root-first tree-root-one"); +var _10a=$(_108).tree("getRoots"); +if(_10a.length>1){ +$(_10a[0].target).addClass("tree-root-first"); +}else{ +if(_10a.length==1){ +$(_10a[0].target).addClass("tree-root-one"); +} +} +} +$(ul).children("li").each(function(){ +var node=$(this).children("div.tree-node"); +var ul=node.next("ul"); +if(ul.length){ +if($(this).next().length){ +_10b(node); +} +_107(_108,ul,_109); +}else{ +_10c(node); +} +}); +var _10d=$(ul).children("li:last").children("div.tree-node").addClass("tree-node-last"); +_10d.children("span.tree-join").removeClass("tree-join").addClass("tree-joinbottom"); +function _10c(node,_10e){ +var icon=node.find("span.tree-icon"); +icon.prev("span.tree-indent").addClass("tree-join"); +}; +function _10b(node){ +var _10f=node.find("span.tree-indent, span.tree-hit").length; +node.next().find("div.tree-node").each(function(){ +$(this).children("span:eq("+(_10f-1)+")").addClass("tree-line"); +}); +}; +}; +function _110(_111,ul,_112,_113){ +var opts=$.data(_111,"tree").options; +_112=_112||{}; +var _114=null; +if(_111!=ul){ +var node=$(ul).prev(); +_114=_bd(_111,node[0]); +} +if(opts.onBeforeLoad.call(_111,_114,_112)==false){ +return; +} +var _115=$(ul).prev().children("span.tree-folder"); +_115.addClass("tree-loading"); +var _116=opts.loader.call(_111,_112,function(data){ +_115.removeClass("tree-loading"); +_fb(_111,ul,data); +if(_113){ +_113(); +} +},function(){ +_115.removeClass("tree-loading"); +opts.onLoadError.apply(_111,arguments); +if(_113){ +_113(); +} +}); +if(_116==false){ +_115.removeClass("tree-loading"); +} +}; +function _117(_118,_119,_11a){ +var opts=$.data(_118,"tree").options; +var hit=$(_119).children("span.tree-hit"); +if(hit.length==0){ +return; +} +if(hit.hasClass("tree-expanded")){ +return; +} +var node=_bd(_118,_119); +if(opts.onBeforeExpand.call(_118,node)==false){ +return; +} +hit.removeClass("tree-collapsed tree-collapsed-hover").addClass("tree-expanded"); +hit.next().addClass("tree-folder-open"); +var ul=$(_119).next(); +if(ul.length){ +if(opts.animate){ +ul.slideDown("normal",function(){ +opts.onExpand.call(_118,node); +if(_11a){ +_11a(); +} +}); +}else{ +ul.css("display","block"); +opts.onExpand.call(_118,node); +if(_11a){ +_11a(); +} +} +}else{ +var _11b=$("
        ").insertAfter(_119); +_110(_118,_11b[0],{id:node.id},function(){ +if(_11b.is(":empty")){ +_11b.remove(); +} +if(opts.animate){ +_11b.slideDown("normal",function(){ +opts.onExpand.call(_118,node); +if(_11a){ +_11a(); +} +}); +}else{ +_11b.css("display","block"); +opts.onExpand.call(_118,node); +if(_11a){ +_11a(); +} +} +}); +} +}; +function _11c(_11d,_11e){ +var opts=$.data(_11d,"tree").options; +var hit=$(_11e).children("span.tree-hit"); +if(hit.length==0){ +return; +} +if(hit.hasClass("tree-collapsed")){ +return; +} +var node=_bd(_11d,_11e); +if(opts.onBeforeCollapse.call(_11d,node)==false){ +return; +} +hit.removeClass("tree-expanded tree-expanded-hover").addClass("tree-collapsed"); +hit.next().removeClass("tree-folder-open"); +var ul=$(_11e).next(); +if(opts.animate){ +ul.slideUp("normal",function(){ +opts.onCollapse.call(_11d,node); +}); +}else{ +ul.css("display","none"); +opts.onCollapse.call(_11d,node); +} +}; +function _11f(_120,_121){ +var hit=$(_121).children("span.tree-hit"); +if(hit.length==0){ +return; +} +if(hit.hasClass("tree-expanded")){ +_11c(_120,_121); +}else{ +_117(_120,_121); +} +}; +function _122(_123,_124){ +var _125=_fa(_123,_124); +if(_124){ +_125.unshift(_bd(_123,_124)); +} +for(var i=0;i<_125.length;i++){ +_117(_123,_125[i].target); +} +}; +function _126(_127,_128){ +var _129=[]; +var p=_12a(_127,_128); +while(p){ +_129.unshift(p); +p=_12a(_127,p.target); +} +for(var i=0;i<_129.length;i++){ +_117(_127,_129[i].target); +} +}; +function _12b(_12c,_12d){ +var _12e=_fa(_12c,_12d); +if(_12d){ +_12e.unshift(_bd(_12c,_12d)); +} +for(var i=0;i<_12e.length;i++){ +_11c(_12c,_12e[i].target); +} +}; +function _12f(_130){ +var _131=_132(_130); +if(_131.length){ +return _131[0]; +}else{ +return null; +} +}; +function _132(_133){ +var _134=[]; +$(_133).children("li").each(function(){ +var node=$(this).children("div.tree-node"); +_134.push(_bd(_133,node[0])); +}); +return _134; +}; +function _fa(_135,_136){ +var _137=[]; +if(_136){ +_138($(_136)); +}else{ +var _139=_132(_135); +for(var i=0;i<_139.length;i++){ +_137.push(_139[i]); +_138($(_139[i].target)); +} +} +function _138(node){ +node.next().find("div.tree-node").each(function(){ +_137.push(_bd(_135,this)); +}); +}; +return _137; +}; +function _12a(_13a,_13b){ +var ul=$(_13b).parent().parent(); +if(ul[0]==_13a){ +return null; +}else{ +return _bd(_13a,ul.prev()[0]); +} +}; +function _13c(_13d,_13e){ +_13e=_13e||"checked"; +var _13f=""; +if(_13e=="checked"){ +_13f="span.tree-checkbox1"; +}else{ +if(_13e=="unchecked"){ +_13f="span.tree-checkbox0"; +}else{ +if(_13e=="indeterminate"){ +_13f="span.tree-checkbox2"; +} +} +} +var _140=[]; +$(_13d).find(_13f).each(function(){ +var node=$(this).parent(); +_140.push(_bd(_13d,node[0])); +}); +return _140; +}; +function _141(_142){ +var node=$(_142).find("div.tree-node-selected"); +if(node.length){ +return _bd(_142,node[0]); +}else{ +return null; +} +}; +function _143(_144,_145){ +var node=$(_145.parent); +var ul; +if(node.length==0){ +ul=$(_144); +}else{ +ul=node.next(); +if(ul.length==0){ +ul=$("
          ").insertAfter(node); +} +} +if(_145.data&&_145.data.length){ +var _146=node.find("span.tree-icon"); +if(_146.hasClass("tree-file")){ +_146.removeClass("tree-file").addClass("tree-folder tree-folder-open"); +var hit=$("").insertBefore(_146); +if(hit.prev().length){ +hit.prev().remove(); +} +} +} +_fb(_144,ul[0],_145.data,true); +_f1(_144,ul.prev()); +}; +function _147(_148,_149){ +var ref=_149.before||_149.after; +var _14a=_12a(_148,ref); +var li; +if(_14a){ +_143(_148,{parent:_14a.target,data:[_149.data]}); +li=$(_14a.target).next().children("li:last"); +}else{ +_143(_148,{parent:null,data:[_149.data]}); +li=$(_148).children("li:last"); +} +if(_149.before){ +li.insertBefore($(ref).parent()); +}else{ +li.insertAfter($(ref).parent()); +} +}; +function _14b(_14c,_14d){ +var _14e=_12a(_14c,_14d); +var node=$(_14d); +var li=node.parent(); +var ul=li.parent(); +li.remove(); +if(ul.children("li").length==0){ +var node=ul.prev(); +node.find(".tree-icon").removeClass("tree-folder").addClass("tree-file"); +node.find(".tree-hit").remove(); +$("").prependTo(node); +if(ul[0]!=_14c){ +ul.remove(); +} +} +if(_14e){ +_f1(_14c,_14e.target); +} +_107(_14c,_14c); +}; +function _14f(_150,_151){ +function _152(aa,ul){ +ul.children("li").each(function(){ +var node=$(this).children("div.tree-node"); +var _153=_bd(_150,node[0]); +var sub=$(this).children("ul"); +if(sub.length){ +_153.children=[]; +_152(_153.children,sub); +} +aa.push(_153); +}); +}; +if(_151){ +var _154=_bd(_150,_151); +_154.children=[]; +_152(_154.children,$(_151).next()); +return _154; +}else{ +return null; +} +}; +function _155(_156,_157){ +var opts=$.data(_156,"tree").options; +var node=$(_157.target); +var _158=_bd(_156,_157.target); +if(_158.iconCls){ +node.find(".tree-icon").removeClass(_158.iconCls); +} +var data=$.extend({},_158,_157); +$.data(_157.target,"tree-node",data); +node.attr("node-id",data.id); +node.find(".tree-title").html(opts.formatter.call(_156,data)); +if(data.iconCls){ +node.find(".tree-icon").addClass(data.iconCls); +} +if(_158.checked!=data.checked){ +_e2(_156,_157.target,data.checked); +} +}; +function _bd(_159,_15a){ +var node=$.extend({},$.data(_15a,"tree-node"),{target:_15a,checked:$(_15a).find(".tree-checkbox").hasClass("tree-checkbox1")}); +if(!_f6(_159,_15a)){ +node.state=$(_15a).find(".tree-hit").hasClass("tree-expanded")?"open":"closed"; +} +return node; +}; +function _15b(_15c,id){ +var node=$(_15c).find("div.tree-node[node-id="+id+"]"); +if(node.length){ +return _bd(_15c,node[0]); +}else{ +return null; +} +}; +function _15d(_15e,_15f){ +var opts=$.data(_15e,"tree").options; +var node=_bd(_15e,_15f); +if(opts.onBeforeSelect.call(_15e,node)==false){ +return; +} +$("div.tree-node-selected",_15e).removeClass("tree-node-selected"); +$(_15f).addClass("tree-node-selected"); +opts.onSelect.call(_15e,node); +}; +function _f6(_160,_161){ +var node=$(_161); +var hit=node.children("span.tree-hit"); +return hit.length==0; +}; +function _162(_163,_164){ +var opts=$.data(_163,"tree").options; +var node=_bd(_163,_164); +if(opts.onBeforeEdit.call(_163,node)==false){ +return; +} +$(_164).css("position","relative"); +var nt=$(_164).find(".tree-title"); +var _165=nt.outerWidth(); +nt.empty(); +var _166=$("").appendTo(nt); +_166.val(node.text).focus(); +_166.width(_165+20); +_166.height(document.compatMode=="CSS1Compat"?(18-(_166.outerHeight()-_166.height())):18); +_166.bind("click",function(e){ +return false; +}).bind("mousedown",function(e){ +e.stopPropagation(); +}).bind("mousemove",function(e){ +e.stopPropagation(); +}).bind("keydown",function(e){ +if(e.keyCode==13){ +_167(_163,_164); +return false; +}else{ +if(e.keyCode==27){ +_16b(_163,_164); +return false; +} +} +}).bind("blur",function(e){ +e.stopPropagation(); +_167(_163,_164); +}); +}; +function _167(_168,_169){ +var opts=$.data(_168,"tree").options; +$(_169).css("position",""); +var _16a=$(_169).find("input.tree-editor"); +var val=_16a.val(); +_16a.remove(); +var node=_bd(_168,_169); +node.text=val; +_155(_168,node); +opts.onAfterEdit.call(_168,node); +}; +function _16b(_16c,_16d){ +var opts=$.data(_16c,"tree").options; +$(_16d).css("position",""); +$(_16d).find("input.tree-editor").remove(); +var node=_bd(_16c,_16d); +_155(_16c,node); +opts.onCancelEdit.call(_16c,node); +}; +$.fn.tree=function(_16e,_16f){ +if(typeof _16e=="string"){ +return $.fn.tree.methods[_16e](this,_16f); +} +var _16e=_16e||{}; +return this.each(function(){ +var _170=$.data(this,"tree"); +var opts; +if(_170){ +opts=$.extend(_170.options,_16e); +_170.options=opts; +}else{ +opts=$.extend({},$.fn.tree.defaults,$.fn.tree.parseOptions(this),_16e); +$.data(this,"tree",{options:opts,tree:_aa(this)}); +var data=_ad(this); +if(data.length&&!opts.data){ +opts.data=data; +} +} +_b5(this); +if(opts.lines){ +$(this).addClass("tree-lines"); +} +if(opts.data){ +_fb(this,this,opts.data); +}else{ +if(opts.dnd){ +_c1(this); +}else{ +_be(this); +} +} +_110(this,this); +}); +}; +$.fn.tree.methods={options:function(jq){ +return $.data(jq[0],"tree").options; +},loadData:function(jq,data){ +return jq.each(function(){ +_fb(this,this,data); +}); +},getNode:function(jq,_171){ +return _bd(jq[0],_171); +},getData:function(jq,_172){ +return _14f(jq[0],_172); +},reload:function(jq,_173){ +return jq.each(function(){ +if(_173){ +var node=$(_173); +var hit=node.children("span.tree-hit"); +hit.removeClass("tree-expanded tree-expanded-hover").addClass("tree-collapsed"); +node.next().remove(); +_117(this,_173); +}else{ +$(this).empty(); +_110(this,this); +} +}); +},getRoot:function(jq){ +return _12f(jq[0]); +},getRoots:function(jq){ +return _132(jq[0]); +},getParent:function(jq,_174){ +return _12a(jq[0],_174); +},getChildren:function(jq,_175){ +return _fa(jq[0],_175); +},getChecked:function(jq,_176){ +return _13c(jq[0],_176); +},getSelected:function(jq){ +return _141(jq[0]); +},isLeaf:function(jq,_177){ +return _f6(jq[0],_177); +},find:function(jq,id){ +return _15b(jq[0],id); +},select:function(jq,_178){ +return jq.each(function(){ +_15d(this,_178); +}); +},check:function(jq,_179){ +return jq.each(function(){ +_e2(this,_179,true); +}); +},uncheck:function(jq,_17a){ +return jq.each(function(){ +_e2(this,_17a,false); +}); +},collapse:function(jq,_17b){ +return jq.each(function(){ +_11c(this,_17b); +}); +},expand:function(jq,_17c){ +return jq.each(function(){ +_117(this,_17c); +}); +},collapseAll:function(jq,_17d){ +return jq.each(function(){ +_12b(this,_17d); +}); +},expandAll:function(jq,_17e){ +return jq.each(function(){ +_122(this,_17e); +}); +},expandTo:function(jq,_17f){ +return jq.each(function(){ +_126(this,_17f); +}); +},toggle:function(jq,_180){ +return jq.each(function(){ +_11f(this,_180); +}); +},append:function(jq,_181){ +return jq.each(function(){ +_143(this,_181); +}); +},insert:function(jq,_182){ +return jq.each(function(){ +_147(this,_182); +}); +},remove:function(jq,_183){ +return jq.each(function(){ +_14b(this,_183); +}); +},pop:function(jq,_184){ +var node=jq.tree("getData",_184); +jq.tree("remove",_184); +return node; +},update:function(jq,_185){ +return jq.each(function(){ +_155(this,_185); +}); +},enableDnd:function(jq){ +return jq.each(function(){ +_c1(this); +}); +},disableDnd:function(jq){ +return jq.each(function(){ +_be(this); +}); +},beginEdit:function(jq,_186){ +return jq.each(function(){ +_162(this,_186); +}); +},endEdit:function(jq,_187){ +return jq.each(function(){ +_167(this,_187); +}); +},cancelEdit:function(jq,_188){ +return jq.each(function(){ +_16b(this,_188); +}); +}}; +$.fn.tree.parseOptions=function(_189){ +var t=$(_189); +return $.extend({},$.parser.parseOptions(_189,["url","method",{checkbox:"boolean",cascadeCheck:"boolean",onlyLeafCheck:"boolean"},{animate:"boolean",lines:"boolean",dnd:"boolean"}])); +}; +$.fn.tree.defaults={url:null,method:"post",animate:false,checkbox:false,cascadeCheck:true,onlyLeafCheck:false,lines:false,dnd:false,data:null,formatter:function(node){ +return node.text; +},loader:function(_18a,_18b,_18c){ +var opts=$(this).tree("options"); +if(!opts.url){ +return false; +} +$.ajax({type:opts.method,url:opts.url,data:_18a,dataType:"json",success:function(data){ +_18b(data); +},error:function(){ +_18c.apply(this,arguments); +}}); +},loadFilter:function(data,_18d){ +return data; +},onBeforeLoad:function(node,_18e){ +},onLoadSuccess:function(node,data){ +},onLoadError:function(){ +},onClick:function(node){ +},onDblClick:function(node){ +},onBeforeExpand:function(node){ +},onExpand:function(node){ +},onBeforeCollapse:function(node){ +},onCollapse:function(node){ +},onBeforeCheck:function(node,_18f){ +},onCheck:function(node,_190){ +},onBeforeSelect:function(node){ +},onSelect:function(node){ +},onContextMenu:function(e,node){ +},onBeforeDrag:function(node){ +},onStartDrag:function(node){ +},onStopDrag:function(node){ +},onDragEnter:function(_191,_192){ +},onDragOver:function(_193,_194){ +},onDragLeave:function(_195,_196){ +},onBeforeDrop:function(_197,_198,_199){ +},onDrop:function(_19a,_19b,_19c){ +},onBeforeEdit:function(node){ +},onAfterEdit:function(node){ +},onCancelEdit:function(node){ +}}; +})(jQuery); +(function($){ +function init(_19d){ +$(_19d).addClass("progressbar"); +$(_19d).html("
          "); +return $(_19d); +}; +function _19e(_19f,_1a0){ +var opts=$.data(_19f,"progressbar").options; +var bar=$.data(_19f,"progressbar").bar; +if(_1a0){ +opts.width=_1a0; +} +bar._outerWidth(opts.width)._outerHeight(opts.height); +bar.find("div.progressbar-text").width(bar.width()); +bar.find("div.progressbar-text,div.progressbar-value").css({height:bar.height()+"px",lineHeight:bar.height()+"px"}); +}; +$.fn.progressbar=function(_1a1,_1a2){ +if(typeof _1a1=="string"){ +var _1a3=$.fn.progressbar.methods[_1a1]; +if(_1a3){ +return _1a3(this,_1a2); +} +} +_1a1=_1a1||{}; +return this.each(function(){ +var _1a4=$.data(this,"progressbar"); +if(_1a4){ +$.extend(_1a4.options,_1a1); +}else{ +_1a4=$.data(this,"progressbar",{options:$.extend({},$.fn.progressbar.defaults,$.fn.progressbar.parseOptions(this),_1a1),bar:init(this)}); +} +$(this).progressbar("setValue",_1a4.options.value); +_19e(this); +}); +}; +$.fn.progressbar.methods={options:function(jq){ +return $.data(jq[0],"progressbar").options; +},resize:function(jq,_1a5){ +return jq.each(function(){ +_19e(this,_1a5); +}); +},getValue:function(jq){ +return $.data(jq[0],"progressbar").options.value; +},setValue:function(jq,_1a6){ +if(_1a6<0){ +_1a6=0; +} +if(_1a6>100){ +_1a6=100; +} +return jq.each(function(){ +var opts=$.data(this,"progressbar").options; +var text=opts.text.replace(/{value}/,_1a6); +var _1a7=opts.value; +opts.value=_1a6; +$(this).find("div.progressbar-value").width(_1a6+"%"); +$(this).find("div.progressbar-text").html(text); +if(_1a7!=_1a6){ +opts.onChange.call(this,_1a6,_1a7); +} +}); +}}; +$.fn.progressbar.parseOptions=function(_1a8){ +return $.extend({},$.parser.parseOptions(_1a8,["width","height","text",{value:"number"}])); +}; +$.fn.progressbar.defaults={width:"auto",height:22,value:0,text:"{value}%",onChange:function(_1a9,_1aa){ +}}; +})(jQuery); +(function($){ +function init(_1ab){ +$(_1ab).addClass("tooltip-f"); +}; +function _1ac(_1ad){ +var opts=$.data(_1ad,"tooltip").options; +$(_1ad).unbind(".tooltip").bind(opts.showEvent+".tooltip",function(e){ +_1b4(_1ad,e); +}).bind(opts.hideEvent+".tooltip",function(e){ +_1ba(_1ad,e); +}).bind("mousemove.tooltip",function(e){ +if(opts.trackMouse){ +opts.trackMouseX=e.pageX; +opts.trackMouseY=e.pageY; +_1ae(_1ad); +} +}); +}; +function _1af(_1b0){ +var _1b1=$.data(_1b0,"tooltip"); +if(_1b1.showTimer){ +clearTimeout(_1b1.showTimer); +_1b1.showTimer=null; +} +if(_1b1.hideTimer){ +clearTimeout(_1b1.hideTimer); +_1b1.hideTimer=null; +} +}; +function _1ae(_1b2){ +var _1b3=$.data(_1b2,"tooltip"); +if(!_1b3||!_1b3.tip){ +return; +} +var opts=_1b3.options; +var tip=_1b3.tip; +if(opts.trackMouse){ +t=$(); +var left=opts.trackMouseX+opts.deltaX; +var top=opts.trackMouseY+opts.deltaY; +}else{ +var t=$(_1b2); +var left=t.offset().left+opts.deltaX; +var top=t.offset().top+opts.deltaY; +} +switch(opts.position){ +case "right": +left+=t._outerWidth()+12+(opts.trackMouse?12:0); +top-=(tip._outerHeight()-t._outerHeight())/2; +break; +case "left": +left-=tip._outerWidth()+12+(opts.trackMouse?12:0); +top-=(tip._outerHeight()-t._outerHeight())/2; +break; +case "top": +left-=(tip._outerWidth()-t._outerWidth())/2; +top-=tip._outerHeight()+12+(opts.trackMouse?12:0); +break; +case "bottom": +left-=(tip._outerWidth()-t._outerWidth())/2; +top+=t._outerHeight()+12+(opts.trackMouse?12:0); +break; +} +tip.css({left:left,top:top,zIndex:(opts.zIndex!=undefined?opts.zIndex:($.fn.window?$.fn.window.defaults.zIndex++:""))}); +opts.onPosition.call(_1b2,left,top); +}; +function _1b4(_1b5,e){ +var _1b6=$.data(_1b5,"tooltip"); +var opts=_1b6.options; +var tip=_1b6.tip; +if(!tip){ +tip=$("
          "+"
          "+"
          "+"
          "+"
          ").appendTo("body"); +_1b6.tip=tip; +_1b7(_1b5); +} +tip.removeClass("tooltip-top tooltip-bottom tooltip-left tooltip-right").addClass("tooltip-"+opts.position); +_1af(_1b5); +_1b6.showTimer=setTimeout(function(){ +_1ae(_1b5); +tip.show(); +opts.onShow.call(_1b5,e); +var _1b8=tip.children(".tooltip-arrow-outer"); +var _1b9=tip.children(".tooltip-arrow"); +var bc="border-"+opts.position+"-color"; +_1b8.add(_1b9).css({borderTopColor:"",borderBottomColor:"",borderLeftColor:"",borderRightColor:""}); +_1b8.css(bc,tip.css(bc)); +_1b9.css(bc,tip.css("backgroundColor")); +},opts.showDelay); +}; +function _1ba(_1bb,e){ +var _1bc=$.data(_1bb,"tooltip"); +if(_1bc&&_1bc.tip){ +_1af(_1bb); +_1bc.hideTimer=setTimeout(function(){ +_1bc.tip.hide(); +_1bc.options.onHide.call(_1bb,e); +},_1bc.options.hideDelay); +} +}; +function _1b7(_1bd,_1be){ +var _1bf=$.data(_1bd,"tooltip"); +var opts=_1bf.options; +if(_1be){ +opts.content=_1be; +} +if(!_1bf.tip){ +return; +} +var cc=typeof opts.content=="function"?opts.content.call(_1bd):opts.content; +_1bf.tip.children(".tooltip-content").html(cc); +opts.onUpdate.call(_1bd,cc); +}; +function _1c0(_1c1){ +var _1c2=$.data(_1c1,"tooltip"); +if(_1c2){ +_1af(_1c1); +var opts=_1c2.options; +if(_1c2.tip){ +_1c2.tip.remove(); +} +if(opts._title){ +$(_1c1).attr("title",opts._title); +} +$.removeData(_1c1,"tooltip"); +$(_1c1).unbind(".tooltip").removeClass("tooltip-f"); +opts.onDestroy.call(_1c1); +} +}; +$.fn.tooltip=function(_1c3,_1c4){ +if(typeof _1c3=="string"){ +return $.fn.tooltip.methods[_1c3](this,_1c4); +} +_1c3=_1c3||{}; +return this.each(function(){ +var _1c5=$.data(this,"tooltip"); +if(_1c5){ +$.extend(_1c5.options,_1c3); +}else{ +$.data(this,"tooltip",{options:$.extend({},$.fn.tooltip.defaults,$.fn.tooltip.parseOptions(this),_1c3)}); +init(this); +} +_1ac(this); +_1b7(this); +}); +}; +$.fn.tooltip.methods={options:function(jq){ +return $.data(jq[0],"tooltip").options; +},tip:function(jq){ +return $.data(jq[0],"tooltip").tip; +},arrow:function(jq){ +return jq.tooltip("tip").children(".tooltip-arrow-outer,.tooltip-arrow"); +},show:function(jq,e){ +return jq.each(function(){ +_1b4(this,e); +}); +},hide:function(jq,e){ +return jq.each(function(){ +_1ba(this,e); +}); +},update:function(jq,_1c6){ +return jq.each(function(){ +_1b7(this,_1c6); +}); +},reposition:function(jq){ +return jq.each(function(){ +_1ae(this); +}); +},destroy:function(jq){ +return jq.each(function(){ +_1c0(this); +}); +}}; +$.fn.tooltip.parseOptions=function(_1c7){ +var t=$(_1c7); +var opts=$.extend({},$.parser.parseOptions(_1c7,["position","showEvent","hideEvent","content",{deltaX:"number",deltaY:"number",showDelay:"number",hideDelay:"number"}]),{_title:t.attr("title")}); +t.attr("title",""); +if(!opts.content){ +opts.content=opts._title; +} +return opts; +}; +$.fn.tooltip.defaults={position:"bottom",content:null,trackMouse:false,deltaX:0,deltaY:0,showEvent:"mouseenter",hideEvent:"mouseleave",showDelay:200,hideDelay:100,onShow:function(e){ +},onHide:function(e){ +},onUpdate:function(_1c8){ +},onPosition:function(left,top){ +},onDestroy:function(){ +}}; +})(jQuery); +(function($){ +$.fn._remove=function(){ +return this.each(function(){ +$(this).remove(); +try{ +this.outerHTML=""; +} +catch(err){ +} +}); +}; +function _1c9(node){ +node._remove(); +}; +function _1ca(_1cb,_1cc){ +var opts=$.data(_1cb,"panel").options; +var _1cd=$.data(_1cb,"panel").panel; +var _1ce=_1cd.children("div.panel-header"); +var _1cf=_1cd.children("div.panel-body"); +if(_1cc){ +if(_1cc.width){ +opts.width=_1cc.width; +} +if(_1cc.height){ +opts.height=_1cc.height; +} +if(_1cc.left!=null){ +opts.left=_1cc.left; +} +if(_1cc.top!=null){ +opts.top=_1cc.top; +} +} +opts.fit?$.extend(opts,_1cd._fit()):_1cd._fit(false); +_1cd.css({left:opts.left,top:opts.top}); +if(!isNaN(opts.width)){ +_1cd._outerWidth(opts.width); +}else{ +_1cd.width("auto"); +} +_1ce.add(_1cf)._outerWidth(_1cd.width()); +if(!isNaN(opts.height)){ +_1cd._outerHeight(opts.height); +_1cf._outerHeight(_1cd.height()-_1ce._outerHeight()); +}else{ +_1cf.height("auto"); +} +_1cd.css("height",""); +opts.onResize.apply(_1cb,[opts.width,opts.height]); +_1cd.find(">div.panel-body>div").triggerHandler("_resize"); +}; +function _1d0(_1d1,_1d2){ +var opts=$.data(_1d1,"panel").options; +var _1d3=$.data(_1d1,"panel").panel; +if(_1d2){ +if(_1d2.left!=null){ +opts.left=_1d2.left; +} +if(_1d2.top!=null){ +opts.top=_1d2.top; +} +} +_1d3.css({left:opts.left,top:opts.top}); +opts.onMove.apply(_1d1,[opts.left,opts.top]); +}; +function _1d4(_1d5){ +$(_1d5).addClass("panel-body"); +var _1d6=$("
          ").insertBefore(_1d5); +_1d6[0].appendChild(_1d5); +_1d6.bind("_resize",function(){ +var opts=$.data(_1d5,"panel").options; +if(opts.fit==true){ +_1ca(_1d5); +} +return false; +}); +return _1d6; +}; +function _1d7(_1d8){ +var opts=$.data(_1d8,"panel").options; +var _1d9=$.data(_1d8,"panel").panel; +if(opts.tools&&typeof opts.tools=="string"){ +_1d9.find(">div.panel-header>div.panel-tool .panel-tool-a").appendTo(opts.tools); +} +_1c9(_1d9.children("div.panel-header")); +if(opts.title&&!opts.noheader){ +var _1da=$("
          "+opts.title+"
          ").prependTo(_1d9); +if(opts.iconCls){ +_1da.find(".panel-title").addClass("panel-with-icon"); +$("
          ").addClass(opts.iconCls).appendTo(_1da); +} +var tool=$("
          ").appendTo(_1da); +tool.bind("click",function(e){ +e.stopPropagation(); +}); +if(opts.tools){ +if(typeof opts.tools=="string"){ +$(opts.tools).children().each(function(){ +$(this).addClass($(this).attr("iconCls")).addClass("panel-tool-a").appendTo(tool); +}); +}else{ +for(var i=0;i").addClass(opts.tools[i].iconCls).appendTo(tool); +if(opts.tools[i].handler){ +t.bind("click",eval(opts.tools[i].handler)); +} +} +} +} +if(opts.collapsible){ +$("").appendTo(tool).bind("click",function(){ +if(opts.collapsed==true){ +_1f5(_1d8,true); +}else{ +_1ea(_1d8,true); +} +return false; +}); +} +if(opts.minimizable){ +$("").appendTo(tool).bind("click",function(){ +_1fb(_1d8); +return false; +}); +} +if(opts.maximizable){ +$("").appendTo(tool).bind("click",function(){ +if(opts.maximized==true){ +_1fe(_1d8); +}else{ +_1e9(_1d8); +} +return false; +}); +} +if(opts.closable){ +$("").appendTo(tool).bind("click",function(){ +_1db(_1d8); +return false; +}); +} +_1d9.children("div.panel-body").removeClass("panel-body-noheader"); +}else{ +_1d9.children("div.panel-body").addClass("panel-body-noheader"); +} +}; +function _1dc(_1dd){ +var _1de=$.data(_1dd,"panel"); +var opts=_1de.options; +if(opts.href){ +if(!_1de.isLoaded||!opts.cache){ +_1de.isLoaded=false; +_1df(_1dd); +if(opts.loadingMessage){ +$(_1dd).html($("
          ").html(opts.loadingMessage)); +} +$.ajax({url:opts.href,cache:false,dataType:"html",success:function(data){ +_1e0(opts.extractor.call(_1dd,data)); +opts.onLoad.apply(_1dd,arguments); +_1de.isLoaded=true; +}}); +} +}else{ +if(opts.content){ +if(!_1de.isLoaded){ +_1df(_1dd); +_1e0(opts.content); +_1de.isLoaded=true; +} +} +} +function _1e0(_1e1){ +$(_1dd).html(_1e1); +if($.parser){ +$.parser.parse($(_1dd)); +} +}; +}; +function _1df(_1e2){ +var t=$(_1e2); +t.find(".combo-f").each(function(){ +$(this).combo("destroy"); +}); +t.find(".m-btn").each(function(){ +$(this).menubutton("destroy"); +}); +t.find(".s-btn").each(function(){ +$(this).splitbutton("destroy"); +}); +t.find(".tooltip-f").tooltip("destroy"); +}; +function _1e3(_1e4){ +$(_1e4).find("div.panel:visible,div.accordion:visible,div.tabs-container:visible,div.layout:visible").each(function(){ +$(this).triggerHandler("_resize",[true]); +}); +}; +function _1e5(_1e6,_1e7){ +var opts=$.data(_1e6,"panel").options; +var _1e8=$.data(_1e6,"panel").panel; +if(_1e7!=true){ +if(opts.onBeforeOpen.call(_1e6)==false){ +return; +} +} +_1e8.show(); +opts.closed=false; +opts.minimized=false; +var tool=_1e8.children("div.panel-header").find("a.panel-tool-restore"); +if(tool.length){ +opts.maximized=true; +} +opts.onOpen.call(_1e6); +if(opts.maximized==true){ +opts.maximized=false; +_1e9(_1e6); +} +if(opts.collapsed==true){ +opts.collapsed=false; +_1ea(_1e6); +} +if(!opts.collapsed){ +_1dc(_1e6); +_1e3(_1e6); +} +}; +function _1db(_1eb,_1ec){ +var opts=$.data(_1eb,"panel").options; +var _1ed=$.data(_1eb,"panel").panel; +if(_1ec!=true){ +if(opts.onBeforeClose.call(_1eb)==false){ +return; +} +} +_1ed._fit(false); +_1ed.hide(); +opts.closed=true; +opts.onClose.call(_1eb); +}; +function _1ee(_1ef,_1f0){ +var opts=$.data(_1ef,"panel").options; +var _1f1=$.data(_1ef,"panel").panel; +if(_1f0!=true){ +if(opts.onBeforeDestroy.call(_1ef)==false){ +return; +} +} +_1df(_1ef); +_1c9(_1f1); +opts.onDestroy.call(_1ef); +}; +function _1ea(_1f2,_1f3){ +var opts=$.data(_1f2,"panel").options; +var _1f4=$.data(_1f2,"panel").panel; +var body=_1f4.children("div.panel-body"); +var tool=_1f4.children("div.panel-header").find("a.panel-tool-collapse"); +if(opts.collapsed==true){ +return; +} +body.stop(true,true); +if(opts.onBeforeCollapse.call(_1f2)==false){ +return; +} +tool.addClass("panel-tool-expand"); +if(_1f3==true){ +body.slideUp("normal",function(){ +opts.collapsed=true; +opts.onCollapse.call(_1f2); +}); +}else{ +body.hide(); +opts.collapsed=true; +opts.onCollapse.call(_1f2); +} +}; +function _1f5(_1f6,_1f7){ +var opts=$.data(_1f6,"panel").options; +var _1f8=$.data(_1f6,"panel").panel; +var body=_1f8.children("div.panel-body"); +var tool=_1f8.children("div.panel-header").find("a.panel-tool-collapse"); +if(opts.collapsed==false){ +return; +} +body.stop(true,true); +if(opts.onBeforeExpand.call(_1f6)==false){ +return; +} +tool.removeClass("panel-tool-expand"); +if(_1f7==true){ +body.slideDown("normal",function(){ +opts.collapsed=false; +opts.onExpand.call(_1f6); +_1dc(_1f6); +_1e3(_1f6); +}); +}else{ +body.show(); +opts.collapsed=false; +opts.onExpand.call(_1f6); +_1dc(_1f6); +_1e3(_1f6); +} +}; +function _1e9(_1f9){ +var opts=$.data(_1f9,"panel").options; +var _1fa=$.data(_1f9,"panel").panel; +var tool=_1fa.children("div.panel-header").find("a.panel-tool-max"); +if(opts.maximized==true){ +return; +} +tool.addClass("panel-tool-restore"); +if(!$.data(_1f9,"panel").original){ +$.data(_1f9,"panel").original={width:opts.width,height:opts.height,left:opts.left,top:opts.top,fit:opts.fit}; +} +opts.left=0; +opts.top=0; +opts.fit=true; +_1ca(_1f9); +opts.minimized=false; +opts.maximized=true; +opts.onMaximize.call(_1f9); +}; +function _1fb(_1fc){ +var opts=$.data(_1fc,"panel").options; +var _1fd=$.data(_1fc,"panel").panel; +_1fd._fit(false); +_1fd.hide(); +opts.minimized=true; +opts.maximized=false; +opts.onMinimize.call(_1fc); +}; +function _1fe(_1ff){ +var opts=$.data(_1ff,"panel").options; +var _200=$.data(_1ff,"panel").panel; +var tool=_200.children("div.panel-header").find("a.panel-tool-max"); +if(opts.maximized==false){ +return; +} +_200.show(); +tool.removeClass("panel-tool-restore"); +$.extend(opts,$.data(_1ff,"panel").original); +_1ca(_1ff); +opts.minimized=false; +opts.maximized=false; +$.data(_1ff,"panel").original=null; +opts.onRestore.call(_1ff); +}; +function _201(_202){ +var opts=$.data(_202,"panel").options; +var _203=$.data(_202,"panel").panel; +var _204=$(_202).panel("header"); +var body=$(_202).panel("body"); +_203.css(opts.style); +_203.addClass(opts.cls); +if(opts.border){ +_204.removeClass("panel-header-noborder"); +body.removeClass("panel-body-noborder"); +}else{ +_204.addClass("panel-header-noborder"); +body.addClass("panel-body-noborder"); +} +_204.addClass(opts.headerCls); +body.addClass(opts.bodyCls); +if(opts.id){ +$(_202).attr("id",opts.id); +}else{ +$(_202).attr("id",""); +} +}; +function _205(_206,_207){ +$.data(_206,"panel").options.title=_207; +$(_206).panel("header").find("div.panel-title").html(_207); +}; +var TO=false; +var _208=true; +$(window).unbind(".panel").bind("resize.panel",function(){ +if(!_208){ +return; +} +if(TO!==false){ +clearTimeout(TO); +} +TO=setTimeout(function(){ +_208=false; +var _209=$("body.layout"); +if(_209.length){ +_209.layout("resize"); +}else{ +$("body").children("div.panel,div.accordion,div.tabs-container,div.layout").triggerHandler("_resize"); +} +_208=true; +TO=false; +},200); +}); +$.fn.panel=function(_20a,_20b){ +if(typeof _20a=="string"){ +return $.fn.panel.methods[_20a](this,_20b); +} +_20a=_20a||{}; +return this.each(function(){ +var _20c=$.data(this,"panel"); +var opts; +if(_20c){ +opts=$.extend(_20c.options,_20a); +_20c.isLoaded=false; +}else{ +opts=$.extend({},$.fn.panel.defaults,$.fn.panel.parseOptions(this),_20a); +$(this).attr("title",""); +_20c=$.data(this,"panel",{options:opts,panel:_1d4(this),isLoaded:false}); +} +_1d7(this); +_201(this); +if(opts.doSize==true){ +_20c.panel.css("display","block"); +_1ca(this); +} +if(opts.closed==true||opts.minimized==true){ +_20c.panel.hide(); +}else{ +_1e5(this); +} +}); +}; +$.fn.panel.methods={options:function(jq){ +return $.data(jq[0],"panel").options; +},panel:function(jq){ +return $.data(jq[0],"panel").panel; +},header:function(jq){ +return $.data(jq[0],"panel").panel.find(">div.panel-header"); +},body:function(jq){ +return $.data(jq[0],"panel").panel.find(">div.panel-body"); +},setTitle:function(jq,_20d){ +return jq.each(function(){ +_205(this,_20d); +}); +},open:function(jq,_20e){ +return jq.each(function(){ +_1e5(this,_20e); +}); +},close:function(jq,_20f){ +return jq.each(function(){ +_1db(this,_20f); +}); +},destroy:function(jq,_210){ +return jq.each(function(){ +_1ee(this,_210); +}); +},refresh:function(jq,href){ +return jq.each(function(){ +$.data(this,"panel").isLoaded=false; +if(href){ +$.data(this,"panel").options.href=href; +} +_1dc(this); +}); +},resize:function(jq,_211){ +return jq.each(function(){ +_1ca(this,_211); +}); +},move:function(jq,_212){ +return jq.each(function(){ +_1d0(this,_212); +}); +},maximize:function(jq){ +return jq.each(function(){ +_1e9(this); +}); +},minimize:function(jq){ +return jq.each(function(){ +_1fb(this); +}); +},restore:function(jq){ +return jq.each(function(){ +_1fe(this); +}); +},collapse:function(jq,_213){ +return jq.each(function(){ +_1ea(this,_213); +}); +},expand:function(jq,_214){ +return jq.each(function(){ +_1f5(this,_214); +}); +}}; +$.fn.panel.parseOptions=function(_215){ +var t=$(_215); +return $.extend({},$.parser.parseOptions(_215,["id","width","height","left","top","title","iconCls","cls","headerCls","bodyCls","tools","href",{cache:"boolean",fit:"boolean",border:"boolean",noheader:"boolean"},{collapsible:"boolean",minimizable:"boolean",maximizable:"boolean"},{closable:"boolean",collapsed:"boolean",minimized:"boolean",maximized:"boolean",closed:"boolean"}]),{loadingMessage:(t.attr("loadingMessage")!=undefined?t.attr("loadingMessage"):undefined)}); +}; +$.fn.panel.defaults={id:null,title:null,iconCls:null,width:"auto",height:"auto",left:null,top:null,cls:null,headerCls:null,bodyCls:null,style:{},href:null,cache:true,fit:false,border:true,doSize:true,noheader:false,content:null,collapsible:false,minimizable:false,maximizable:false,closable:false,collapsed:false,minimized:false,maximized:false,closed:false,tools:null,href:null,loadingMessage:"Loading...",extractor:function(data){ +var _216=/]*>((.|[\n\r])*)<\/body>/im; +var _217=_216.exec(data); +if(_217){ +return _217[1]; +}else{ +return data; +} +},onLoad:function(){ +},onBeforeOpen:function(){ +},onOpen:function(){ +},onBeforeClose:function(){ +},onClose:function(){ +},onBeforeDestroy:function(){ +},onDestroy:function(){ +},onResize:function(_218,_219){ +},onMove:function(left,top){ +},onMaximize:function(){ +},onRestore:function(){ +},onMinimize:function(){ +},onBeforeCollapse:function(){ +},onBeforeExpand:function(){ +},onCollapse:function(){ +},onExpand:function(){ +}}; +})(jQuery); +(function($){ +function _21a(_21b,_21c){ +var opts=$.data(_21b,"window").options; +if(_21c){ +if(_21c.width){ +opts.width=_21c.width; +} +if(_21c.height){ +opts.height=_21c.height; +} +if(_21c.left!=null){ +opts.left=_21c.left; +} +if(_21c.top!=null){ +opts.top=_21c.top; +} +} +$(_21b).panel("resize",opts); +}; +function _21d(_21e,_21f){ +var _220=$.data(_21e,"window"); +if(_21f){ +if(_21f.left!=null){ +_220.options.left=_21f.left; +} +if(_21f.top!=null){ +_220.options.top=_21f.top; +} +} +$(_21e).panel("move",_220.options); +if(_220.shadow){ +_220.shadow.css({left:_220.options.left,top:_220.options.top}); +} +}; +function _221(_222,_223){ +var _224=$.data(_222,"window"); +var opts=_224.options; +var _225=opts.width; +if(isNaN(_225)){ +_225=_224.window._outerWidth(); +} +if(opts.inline){ +var _226=_224.window.parent(); +opts.left=(_226.width()-_225)/2+_226.scrollLeft(); +}else{ +opts.left=($(window)._outerWidth()-_225)/2+$(document).scrollLeft(); +} +if(_223){ +_21d(_222); +} +}; +function _227(_228,_229){ +var _22a=$.data(_228,"window"); +var opts=_22a.options; +var _22b=opts.height; +if(isNaN(_22b)){ +_22b=_22a.window._outerHeight(); +} +if(opts.inline){ +var _22c=_22a.window.parent(); +opts.top=(_22c.height()-_22b)/2+_22c.scrollTop(); +}else{ +opts.top=($(window)._outerHeight()-_22b)/2+$(document).scrollTop(); +} +if(_229){ +_21d(_228); +} +}; +function _22d(_22e){ +var _22f=$.data(_22e,"window"); +var win=$(_22e).panel($.extend({},_22f.options,{border:false,doSize:true,closed:true,cls:"window",headerCls:"window-header",bodyCls:"window-body "+(_22f.options.noheader?"window-body-noheader":""),onBeforeDestroy:function(){ +if(_22f.options.onBeforeDestroy.call(_22e)==false){ +return false; +} +if(_22f.shadow){ +_22f.shadow.remove(); +} +if(_22f.mask){ +_22f.mask.remove(); +} +},onClose:function(){ +if(_22f.shadow){ +_22f.shadow.hide(); +} +if(_22f.mask){ +_22f.mask.hide(); +} +_22f.options.onClose.call(_22e); +},onOpen:function(){ +if(_22f.mask){ +_22f.mask.css({display:"block",zIndex:$.fn.window.defaults.zIndex++}); +} +if(_22f.shadow){ +_22f.shadow.css({display:"block",zIndex:$.fn.window.defaults.zIndex++,left:_22f.options.left,top:_22f.options.top,width:_22f.window._outerWidth(),height:_22f.window._outerHeight()}); +} +_22f.window.css("z-index",$.fn.window.defaults.zIndex++); +_22f.options.onOpen.call(_22e); +},onResize:function(_230,_231){ +var opts=$(this).panel("options"); +$.extend(_22f.options,{width:opts.width,height:opts.height,left:opts.left,top:opts.top}); +if(_22f.shadow){ +_22f.shadow.css({left:_22f.options.left,top:_22f.options.top,width:_22f.window._outerWidth(),height:_22f.window._outerHeight()}); +} +_22f.options.onResize.call(_22e,_230,_231); +},onMinimize:function(){ +if(_22f.shadow){ +_22f.shadow.hide(); +} +if(_22f.mask){ +_22f.mask.hide(); +} +_22f.options.onMinimize.call(_22e); +},onBeforeCollapse:function(){ +if(_22f.options.onBeforeCollapse.call(_22e)==false){ +return false; +} +if(_22f.shadow){ +_22f.shadow.hide(); +} +},onExpand:function(){ +if(_22f.shadow){ +_22f.shadow.show(); +} +_22f.options.onExpand.call(_22e); +}})); +_22f.window=win.panel("panel"); +if(_22f.mask){ +_22f.mask.remove(); +} +if(_22f.options.modal==true){ +_22f.mask=$("
          ").insertAfter(_22f.window); +_22f.mask.css({width:(_22f.options.inline?_22f.mask.parent().width():_232().width),height:(_22f.options.inline?_22f.mask.parent().height():_232().height),display:"none"}); +} +if(_22f.shadow){ +_22f.shadow.remove(); +} +if(_22f.options.shadow==true){ +_22f.shadow=$("
          ").insertAfter(_22f.window); +_22f.shadow.css({display:"none"}); +} +if(_22f.options.left==null){ +_221(_22e); +} +if(_22f.options.top==null){ +_227(_22e); +} +_21d(_22e); +if(_22f.options.closed==false){ +win.window("open"); +} +}; +function _233(_234){ +var _235=$.data(_234,"window"); +_235.window.draggable({handle:">div.panel-header>div.panel-title",disabled:_235.options.draggable==false,onStartDrag:function(e){ +if(_235.mask){ +_235.mask.css("z-index",$.fn.window.defaults.zIndex++); +} +if(_235.shadow){ +_235.shadow.css("z-index",$.fn.window.defaults.zIndex++); +} +_235.window.css("z-index",$.fn.window.defaults.zIndex++); +if(!_235.proxy){ +_235.proxy=$("
          ").insertAfter(_235.window); +} +_235.proxy.css({display:"none",zIndex:$.fn.window.defaults.zIndex++,left:e.data.left,top:e.data.top}); +_235.proxy._outerWidth(_235.window._outerWidth()); +_235.proxy._outerHeight(_235.window._outerHeight()); +setTimeout(function(){ +if(_235.proxy){ +_235.proxy.show(); +} +},500); +},onDrag:function(e){ +_235.proxy.css({display:"block",left:e.data.left,top:e.data.top}); +return false; +},onStopDrag:function(e){ +_235.options.left=e.data.left; +_235.options.top=e.data.top; +$(_234).window("move"); +_235.proxy.remove(); +_235.proxy=null; +}}); +_235.window.resizable({disabled:_235.options.resizable==false,onStartResize:function(e){ +_235.pmask=$("
          ").insertAfter(_235.window); +_235.pmask.css({zIndex:$.fn.window.defaults.zIndex++,left:e.data.left,top:e.data.top,width:_235.window._outerWidth(),height:_235.window._outerHeight()}); +if(!_235.proxy){ +_235.proxy=$("
          ").insertAfter(_235.window); +} +_235.proxy.css({zIndex:$.fn.window.defaults.zIndex++,left:e.data.left,top:e.data.top}); +_235.proxy._outerWidth(e.data.width); +_235.proxy._outerHeight(e.data.height); +},onResize:function(e){ +_235.proxy.css({left:e.data.left,top:e.data.top}); +_235.proxy._outerWidth(e.data.width); +_235.proxy._outerHeight(e.data.height); +return false; +},onStopResize:function(e){ +$.extend(_235.options,{left:e.data.left,top:e.data.top,width:e.data.width,height:e.data.height}); +_21a(_234); +_235.pmask.remove(); +_235.pmask=null; +_235.proxy.remove(); +_235.proxy=null; +}}); +}; +function _232(){ +if(document.compatMode=="BackCompat"){ +return {width:Math.max(document.body.scrollWidth,document.body.clientWidth),height:Math.max(document.body.scrollHeight,document.body.clientHeight)}; +}else{ +return {width:Math.max(document.documentElement.scrollWidth,document.documentElement.clientWidth),height:Math.max(document.documentElement.scrollHeight,document.documentElement.clientHeight)}; +} +}; +$(window).resize(function(){ +$("body>div.window-mask").css({width:$(window)._outerWidth(),height:$(window)._outerHeight()}); +setTimeout(function(){ +$("body>div.window-mask").css({width:_232().width,height:_232().height}); +},50); +}); +$.fn.window=function(_236,_237){ +if(typeof _236=="string"){ +var _238=$.fn.window.methods[_236]; +if(_238){ +return _238(this,_237); +}else{ +return this.panel(_236,_237); +} +} +_236=_236||{}; +return this.each(function(){ +var _239=$.data(this,"window"); +if(_239){ +$.extend(_239.options,_236); +}else{ +_239=$.data(this,"window",{options:$.extend({},$.fn.window.defaults,$.fn.window.parseOptions(this),_236)}); +if(!_239.options.inline){ +document.body.appendChild(this); +} +} +_22d(this); +_233(this); +}); +}; +$.fn.window.methods={options:function(jq){ +var _23a=jq.panel("options"); +var _23b=$.data(jq[0],"window").options; +return $.extend(_23b,{closed:_23a.closed,collapsed:_23a.collapsed,minimized:_23a.minimized,maximized:_23a.maximized}); +},window:function(jq){ +return $.data(jq[0],"window").window; +},resize:function(jq,_23c){ +return jq.each(function(){ +_21a(this,_23c); +}); +},move:function(jq,_23d){ +return jq.each(function(){ +_21d(this,_23d); +}); +},hcenter:function(jq){ +return jq.each(function(){ +_221(this,true); +}); +},vcenter:function(jq){ +return jq.each(function(){ +_227(this,true); +}); +},center:function(jq){ +return jq.each(function(){ +_221(this); +_227(this); +_21d(this); +}); +}}; +$.fn.window.parseOptions=function(_23e){ +return $.extend({},$.fn.panel.parseOptions(_23e),$.parser.parseOptions(_23e,[{draggable:"boolean",resizable:"boolean",shadow:"boolean",modal:"boolean",inline:"boolean"}])); +}; +$.fn.window.defaults=$.extend({},$.fn.panel.defaults,{zIndex:9000,draggable:true,resizable:true,shadow:true,modal:false,inline:false,title:"New Window",collapsible:true,minimizable:true,maximizable:true,closable:true,closed:false}); +})(jQuery); +(function($){ +function _23f(_240){ +var cp=document.createElement("div"); +while(_240.firstChild){ +cp.appendChild(_240.firstChild); +} +_240.appendChild(cp); +var _241=$(cp); +_241.attr("style",$(_240).attr("style")); +$(_240).removeAttr("style").css("overflow","hidden"); +_241.panel({border:false,doSize:false,bodyCls:"dialog-content"}); +return _241; +}; +function _242(_243){ +var opts=$.data(_243,"dialog").options; +var _244=$.data(_243,"dialog").contentPanel; +if(opts.toolbar){ +if(typeof opts.toolbar=="string"){ +$(opts.toolbar).addClass("dialog-toolbar").prependTo(_243); +$(opts.toolbar).show(); +}else{ +$(_243).find("div.dialog-toolbar").remove(); +var _245=$("
          ").prependTo(_243); +var tr=_245.find("tr"); +for(var i=0;i
          ").appendTo(tr); +}else{ +var td=$("").appendTo(tr); +var tool=$("").appendTo(td); +tool[0].onclick=eval(btn.handler||function(){ +}); +tool.linkbutton($.extend({},btn,{plain:true})); +} +} +} +}else{ +$(_243).find("div.dialog-toolbar").remove(); +} +if(opts.buttons){ +if(typeof opts.buttons=="string"){ +$(opts.buttons).addClass("dialog-button").appendTo(_243); +$(opts.buttons).show(); +}else{ +$(_243).find("div.dialog-button").remove(); +var _246=$("
          ").appendTo(_243); +for(var i=0;i").appendTo(_246); +if(p.handler){ +_247[0].onclick=p.handler; +} +_247.linkbutton(p); +} +} +}else{ +$(_243).find("div.dialog-button").remove(); +} +var _248=opts.href; +var _249=opts.content; +opts.href=null; +opts.content=null; +_244.panel({closed:opts.closed,cache:opts.cache,href:_248,content:_249,onLoad:function(){ +if(opts.height=="auto"){ +$(_243).window("resize"); +} +opts.onLoad.apply(_243,arguments); +}}); +$(_243).window($.extend({},opts,{onOpen:function(){ +if(_244.panel("options").closed){ +_244.panel("open"); +} +if(opts.onOpen){ +opts.onOpen.call(_243); +} +},onResize:function(_24a,_24b){ +var _24c=$(_243); +_244.panel("panel").show(); +_244.panel("resize",{width:_24c.width(),height:(_24b=="auto")?"auto":_24c.height()-_24c.children("div.dialog-toolbar")._outerHeight()-_24c.children("div.dialog-button")._outerHeight()}); +if(opts.onResize){ +opts.onResize.call(_243,_24a,_24b); +} +}})); +opts.href=_248; +opts.content=_249; +}; +function _24d(_24e,href){ +var _24f=$.data(_24e,"dialog").contentPanel; +_24f.panel("refresh",href); +}; +$.fn.dialog=function(_250,_251){ +if(typeof _250=="string"){ +var _252=$.fn.dialog.methods[_250]; +if(_252){ +return _252(this,_251); +}else{ +return this.window(_250,_251); +} +} +_250=_250||{}; +return this.each(function(){ +var _253=$.data(this,"dialog"); +if(_253){ +$.extend(_253.options,_250); +}else{ +$.data(this,"dialog",{options:$.extend({},$.fn.dialog.defaults,$.fn.dialog.parseOptions(this),_250),contentPanel:_23f(this)}); +} +_242(this); +}); +}; +$.fn.dialog.methods={options:function(jq){ +var _254=$.data(jq[0],"dialog").options; +var _255=jq.panel("options"); +$.extend(_254,{closed:_255.closed,collapsed:_255.collapsed,minimized:_255.minimized,maximized:_255.maximized}); +var _256=$.data(jq[0],"dialog").contentPanel; +return _254; +},dialog:function(jq){ +return jq.window("window"); +},refresh:function(jq,href){ +return jq.each(function(){ +_24d(this,href); +}); +}}; +$.fn.dialog.parseOptions=function(_257){ +return $.extend({},$.fn.window.parseOptions(_257),$.parser.parseOptions(_257,["toolbar","buttons"])); +}; +$.fn.dialog.defaults=$.extend({},$.fn.window.defaults,{title:"New Dialog",collapsible:false,minimizable:false,maximizable:false,resizable:false,toolbar:null,buttons:null}); +})(jQuery); +(function($){ +function show(el,type,_258,_259){ +var win=$(el).window("window"); +if(!win){ +return; +} +switch(type){ +case null: +win.show(); +break; +case "slide": +win.slideDown(_258); +break; +case "fade": +win.fadeIn(_258); +break; +case "show": +win.show(_258); +break; +} +var _25a=null; +if(_259>0){ +_25a=setTimeout(function(){ +hide(el,type,_258); +},_259); +} +win.hover(function(){ +if(_25a){ +clearTimeout(_25a); +} +},function(){ +if(_259>0){ +_25a=setTimeout(function(){ +hide(el,type,_258); +},_259); +} +}); +}; +function hide(el,type,_25b){ +if(el.locked==true){ +return; +} +el.locked=true; +var win=$(el).window("window"); +if(!win){ +return; +} +switch(type){ +case null: +win.hide(); +break; +case "slide": +win.slideUp(_25b); +break; +case "fade": +win.fadeOut(_25b); +break; +case "show": +win.hide(_25b); +break; +} +setTimeout(function(){ +$(el).window("destroy"); +},_25b); +}; +function _25c(_25d){ +var opts=$.extend({},$.fn.window.defaults,{collapsible:false,minimizable:false,maximizable:false,shadow:false,draggable:false,resizable:false,closed:true,style:{left:"",top:"",right:0,zIndex:$.fn.window.defaults.zIndex++,bottom:-document.body.scrollTop-document.documentElement.scrollTop},onBeforeOpen:function(){ +show(this,opts.showType,opts.showSpeed,opts.timeout); +return false; +},onBeforeClose:function(){ +hide(this,opts.showType,opts.showSpeed); +return false; +}},{title:"",width:250,height:100,showType:"slide",showSpeed:600,msg:"",timeout:4000},_25d); +opts.style.zIndex=$.fn.window.defaults.zIndex++; +var win=$("
          ").html(opts.msg).appendTo("body"); +win.window(opts); +win.window("window").css(opts.style); +win.window("open"); +return win; +}; +function _25e(_25f,_260,_261){ +var win=$("
          ").appendTo("body"); +win.append(_260); +if(_261){ +var tb=$("
          ").appendTo(win); +for(var _262 in _261){ +$("").attr("href","javascript:void(0)").text(_262).css("margin-left",10).bind("click",eval(_261[_262])).appendTo(tb).linkbutton(); +} +} +win.window({title:_25f,noheader:(_25f?false:true),width:300,height:"auto",modal:true,collapsible:false,minimizable:false,maximizable:false,resizable:false,onClose:function(){ +setTimeout(function(){ +win.window("destroy"); +},100); +}}); +win.window("window").addClass("messager-window"); +win.children("div.messager-button").children("a:first").focus(); +return win; +}; +$.messager={show:function(_263){ +return _25c(_263); +},alert:function(_264,msg,icon,fn){ +var _265="
          "+msg+"
          "; +switch(icon){ +case "error": +_265="
          "+_265; +break; +case "info": +_265="
          "+_265; +break; +case "question": +_265="
          "+_265; +break; +case "warning": +_265="
          "+_265; +break; +} +_265+="
          "; +var _266={}; +_266[$.messager.defaults.ok]=function(){ +win.window("close"); +if(fn){ +fn(); +return false; +} +}; +var win=_25e(_264,_265,_266); +return win; +},confirm:function(_267,msg,fn){ +var _268="
          "+"
          "+msg+"
          "+"
          "; +var _269={}; +_269[$.messager.defaults.ok]=function(){ +win.window("close"); +if(fn){ +fn(true); +return false; +} +}; +_269[$.messager.defaults.cancel]=function(){ +win.window("close"); +if(fn){ +fn(false); +return false; +} +}; +var win=_25e(_267,_268,_269); +return win; +},prompt:function(_26a,msg,fn){ +var _26b="
          "+"
          "+msg+"
          "+"
          "+"
          "+"
          "; +var _26c={}; +_26c[$.messager.defaults.ok]=function(){ +win.window("close"); +if(fn){ +fn($(".messager-input",win).val()); +return false; +} +}; +_26c[$.messager.defaults.cancel]=function(){ +win.window("close"); +if(fn){ +fn(); +return false; +} +}; +var win=_25e(_26a,_26b,_26c); +win.children("input.messager-input").focus(); +return win; +},progress:function(_26d){ +var _26e={bar:function(){ +return $("body>div.messager-window").find("div.messager-p-bar"); +},close:function(){ +var win=$("body>div.messager-window>div.messager-body:has(div.messager-progress)"); +if(win.length){ +win.window("close"); +} +}}; +if(typeof _26d=="string"){ +var _26f=_26e[_26d]; +return _26f(); +} +var opts=$.extend({title:"",msg:"",text:undefined,interval:300},_26d||{}); +var _270="
          "; +var win=_25e(opts.title,_270,null); +win.find("div.messager-p-msg").html(opts.msg); +var bar=win.find("div.messager-p-bar"); +bar.progressbar({text:opts.text}); +win.window({closable:false,onClose:function(){ +if(this.timer){ +clearInterval(this.timer); +} +$(this).window("destroy"); +}}); +if(opts.interval){ +win[0].timer=setInterval(function(){ +var v=bar.progressbar("getValue"); +v+=10; +if(v>100){ +v=0; +} +bar.progressbar("setValue",v); +},opts.interval); +} +return win; +}}; +$.messager.defaults={ok:"Ok",cancel:"Cancel"}; +})(jQuery); +(function($){ +function _271(_272){ +var opts=$.data(_272,"accordion").options; +var _273=$.data(_272,"accordion").panels; +var cc=$(_272); +opts.fit?$.extend(opts,cc._fit()):cc._fit(false); +if(opts.width>0){ +cc._outerWidth(opts.width); +} +var _274="auto"; +if(opts.height>0){ +cc._outerHeight(opts.height); +var _275=_273.length?_273[0].panel("header").css("height","")._outerHeight():"auto"; +var _274=cc.height()-(_273.length-1)*_275; +} +for(var i=0;i<_273.length;i++){ +var _276=_273[i]; +var _277=_276.panel("header"); +_277._outerHeight(_275); +_276.panel("resize",{width:cc.width(),height:_274}); +} +}; +function _278(_279){ +var _27a=$.data(_279,"accordion").panels; +for(var i=0;i<_27a.length;i++){ +var _27b=_27a[i]; +if(_27b.panel("options").collapsed==false){ +return _27b; +} +} +return null; +}; +function _27c(_27d,_27e){ +var _27f=$.data(_27d,"accordion").panels; +for(var i=0;i<_27f.length;i++){ +if(_27f[i][0]==$(_27e)[0]){ +return i; +} +} +return -1; +}; +function _280(_281,_282,_283){ +var _284=$.data(_281,"accordion").panels; +if(typeof _282=="number"){ +if(_282<0||_282>=_284.length){ +return null; +}else{ +var _285=_284[_282]; +if(_283){ +_284.splice(_282,1); +} +return _285; +} +} +for(var i=0;i<_284.length;i++){ +var _285=_284[i]; +if(_285.panel("options").title==_282){ +if(_283){ +_284.splice(i,1); +} +return _285; +} +} +return null; +}; +function _286(_287){ +var opts=$.data(_287,"accordion").options; +var cc=$(_287); +if(opts.border){ +cc.removeClass("accordion-noborder"); +}else{ +cc.addClass("accordion-noborder"); +} +}; +function _288(_289){ +var cc=$(_289); +cc.addClass("accordion"); +var _28a=[]; +cc.children("div").each(function(){ +var opts=$.extend({},$.parser.parseOptions(this),{selected:($(this).attr("selected")?true:undefined)}); +var pp=$(this); +_28a.push(pp); +_28c(_289,pp,opts); +}); +cc.bind("_resize",function(e,_28b){ +var opts=$.data(_289,"accordion").options; +if(opts.fit==true||_28b){ +_271(_289); +} +return false; +}); +return {accordion:cc,panels:_28a}; +}; +function _28c(_28d,pp,_28e){ +pp.panel($.extend({},_28e,{collapsible:false,minimizable:false,maximizable:false,closable:false,doSize:false,collapsed:true,headerCls:"accordion-header",bodyCls:"accordion-body",onBeforeExpand:function(){ +var curr=_278(_28d); +if(curr){ +var _28f=$(curr).panel("header"); +_28f.removeClass("accordion-header-selected"); +_28f.find(".accordion-collapse").triggerHandler("click"); +} +var _28f=pp.panel("header"); +_28f.addClass("accordion-header-selected"); +_28f.find(".accordion-collapse").removeClass("accordion-expand"); +},onExpand:function(){ +var opts=$.data(_28d,"accordion").options; +opts.onSelect.call(_28d,pp.panel("options").title,_27c(_28d,this)); +},onBeforeCollapse:function(){ +var _290=pp.panel("header"); +_290.removeClass("accordion-header-selected"); +_290.find(".accordion-collapse").addClass("accordion-expand"); +}})); +var _291=pp.panel("header"); +var t=$("").appendTo(_291.children("div.panel-tool")); +t.bind("click",function(e){ +var _292=$.data(_28d,"accordion").options.animate; +_29d(_28d); +if(pp.panel("options").collapsed){ +pp.panel("expand",_292); +}else{ +pp.panel("collapse",_292); +} +return false; +}); +_291.click(function(){ +$(this).find(".accordion-collapse").triggerHandler("click"); +return false; +}); +}; +function _293(_294,_295){ +var _296=_280(_294,_295); +if(!_296){ +return; +} +var curr=_278(_294); +if(curr&&curr[0]==_296[0]){ +return; +} +_296.panel("header").triggerHandler("click"); +}; +function _297(_298){ +var _299=$.data(_298,"accordion").panels; +for(var i=0;i<_299.length;i++){ +if(_299[i].panel("options").selected){ +_29a(i); +return; +} +} +if(_299.length){ +_29a(0); +} +function _29a(_29b){ +var opts=$.data(_298,"accordion").options; +var _29c=opts.animate; +opts.animate=false; +_293(_298,_29b); +opts.animate=_29c; +}; +}; +function _29d(_29e){ +var _29f=$.data(_29e,"accordion").panels; +for(var i=0;i<_29f.length;i++){ +_29f[i].stop(true,true); +} +}; +function add(_2a0,_2a1){ +var opts=$.data(_2a0,"accordion").options; +var _2a2=$.data(_2a0,"accordion").panels; +if(_2a1.selected==undefined){ +_2a1.selected=true; +} +_29d(_2a0); +var pp=$("
          ").appendTo(_2a0); +_2a2.push(pp); +_28c(_2a0,pp,_2a1); +_271(_2a0); +opts.onAdd.call(_2a0,_2a1.title,_2a2.length-1); +if(_2a1.selected){ +_293(_2a0,_2a2.length-1); +} +}; +function _2a3(_2a4,_2a5){ +var opts=$.data(_2a4,"accordion").options; +var _2a6=$.data(_2a4,"accordion").panels; +_29d(_2a4); +var _2a7=_280(_2a4,_2a5); +var _2a8=_2a7.panel("options").title; +var _2a9=_27c(_2a4,_2a7); +if(opts.onBeforeRemove.call(_2a4,_2a8,_2a9)==false){ +return; +} +var _2a7=_280(_2a4,_2a5,true); +if(_2a7){ +_2a7.panel("destroy"); +if(_2a6.length){ +_271(_2a4); +var curr=_278(_2a4); +if(!curr){ +_293(_2a4,0); +} +} +} +opts.onRemove.call(_2a4,_2a8,_2a9); +}; +$.fn.accordion=function(_2aa,_2ab){ +if(typeof _2aa=="string"){ +return $.fn.accordion.methods[_2aa](this,_2ab); +} +_2aa=_2aa||{}; +return this.each(function(){ +var _2ac=$.data(this,"accordion"); +var opts; +if(_2ac){ +opts=$.extend(_2ac.options,_2aa); +_2ac.opts=opts; +}else{ +opts=$.extend({},$.fn.accordion.defaults,$.fn.accordion.parseOptions(this),_2aa); +var r=_288(this); +$.data(this,"accordion",{options:opts,accordion:r.accordion,panels:r.panels}); +} +_286(this); +_271(this); +_297(this); +}); +}; +$.fn.accordion.methods={options:function(jq){ +return $.data(jq[0],"accordion").options; +},panels:function(jq){ +return $.data(jq[0],"accordion").panels; +},resize:function(jq){ +return jq.each(function(){ +_271(this); +}); +},getSelected:function(jq){ +return _278(jq[0]); +},getPanel:function(jq,_2ad){ +return _280(jq[0],_2ad); +},getPanelIndex:function(jq,_2ae){ +return _27c(jq[0],_2ae); +},select:function(jq,_2af){ +return jq.each(function(){ +_293(this,_2af); +}); +},add:function(jq,_2b0){ +return jq.each(function(){ +add(this,_2b0); +}); +},remove:function(jq,_2b1){ +return jq.each(function(){ +_2a3(this,_2b1); +}); +}}; +$.fn.accordion.parseOptions=function(_2b2){ +var t=$(_2b2); +return $.extend({},$.parser.parseOptions(_2b2,["width","height",{fit:"boolean",border:"boolean",animate:"boolean"}])); +}; +$.fn.accordion.defaults={width:"auto",height:"auto",fit:false,border:true,animate:true,onSelect:function(_2b3,_2b4){ +},onAdd:function(_2b5,_2b6){ +},onBeforeRemove:function(_2b7,_2b8){ +},onRemove:function(_2b9,_2ba){ +}}; +})(jQuery); +(function($){ +function _2bb(_2bc){ +var opts=$.data(_2bc,"tabs").options; +if(opts.tabPosition=="left"||opts.tabPosition=="right"){ +return; +} +var _2bd=$(_2bc).children("div.tabs-header"); +var tool=_2bd.children("div.tabs-tool"); +var _2be=_2bd.children("div.tabs-scroller-left"); +var _2bf=_2bd.children("div.tabs-scroller-right"); +var wrap=_2bd.children("div.tabs-wrap"); +tool._outerHeight(_2bd.outerHeight()-(opts.plain?2:0)); +var _2c0=0; +$("ul.tabs li",_2bd).each(function(){ +_2c0+=$(this).outerWidth(true); +}); +var _2c1=_2bd.width()-tool._outerWidth(); +if(_2c0>_2c1){ +_2be.show(); +_2bf.show(); +if(opts.toolPosition=="left"){ +tool.css({left:_2be.outerWidth(),right:""}); +wrap.css({marginLeft:_2be.outerWidth()+tool._outerWidth(),marginRight:_2bf._outerWidth(),width:_2c1-_2be.outerWidth()-_2bf.outerWidth()}); +}else{ +tool.css({left:"",right:_2bf.outerWidth()}); +wrap.css({marginLeft:_2be.outerWidth(),marginRight:_2bf.outerWidth()+tool._outerWidth(),width:_2c1-_2be.outerWidth()-_2bf.outerWidth()}); +} +}else{ +_2be.hide(); +_2bf.hide(); +if(opts.toolPosition=="left"){ +tool.css({left:0,right:""}); +wrap.css({marginLeft:tool._outerWidth(),marginRight:0,width:_2c1}); +}else{ +tool.css({left:"",right:0}); +wrap.css({marginLeft:0,marginRight:tool._outerWidth(),width:_2c1}); +} +} +}; +function _2c2(_2c3){ +var opts=$.data(_2c3,"tabs").options; +var _2c4=$(_2c3).children("div.tabs-header"); +if(opts.tools){ +if(typeof opts.tools=="string"){ +$(opts.tools).addClass("tabs-tool").appendTo(_2c4); +$(opts.tools).show(); +}else{ +_2c4.children("div.tabs-tool").remove(); +var _2c5=$("
          ").appendTo(_2c4); +for(var i=0;i").appendTo(_2c5); +tool[0].onclick=eval(opts.tools[i].handler||function(){ +}); +tool.linkbutton($.extend({},opts.tools[i],{plain:true})); +} +} +}else{ +_2c4.children("div.tabs-tool").remove(); +} +}; +function _2c6(_2c7){ +var opts=$.data(_2c7,"tabs").options; +var cc=$(_2c7); +opts.fit?$.extend(opts,cc._fit()):cc._fit(false); +cc.width(opts.width).height(opts.height); +var _2c8=$(_2c7).children("div.tabs-header"); +var _2c9=$(_2c7).children("div.tabs-panels"); +if(opts.tabPosition=="left"||opts.tabPosition=="right"){ +_2c8._outerWidth(opts.headerWidth); +_2c9._outerWidth(cc.width()-opts.headerWidth); +_2c8.add(_2c9)._outerHeight(opts.height); +var wrap=_2c8.find("div.tabs-wrap"); +wrap._outerWidth(_2c8.width()); +_2c8.find(".tabs")._outerWidth(wrap.width()); +}else{ +_2c8.css("height",""); +_2c8.find("div.tabs-wrap").css("width",""); +_2c8.find(".tabs").css("width",""); +_2c8._outerWidth(opts.width); +_2bb(_2c7); +var _2ca=opts.height; +if(!isNaN(_2ca)){ +_2c9._outerHeight(_2ca-_2c8.outerHeight()); +}else{ +_2c9.height("auto"); +} +var _2cb=opts.width; +if(!isNaN(_2cb)){ +_2c9._outerWidth(_2cb); +}else{ +_2c9.width("auto"); +} +} +}; +function _2cc(_2cd){ +var opts=$.data(_2cd,"tabs").options; +var tab=_2ce(_2cd); +if(tab){ +var _2cf=$(_2cd).children("div.tabs-panels"); +var _2d0=opts.width=="auto"?"auto":_2cf.width(); +var _2d1=opts.height=="auto"?"auto":_2cf.height(); +tab.panel("resize",{width:_2d0,height:_2d1}); +} +}; +function _2d2(_2d3){ +var tabs=$.data(_2d3,"tabs").tabs; +var cc=$(_2d3); +cc.addClass("tabs-container"); +cc.wrapInner("
          "); +$("
          "+"
          "+"
          "+"
          "+"
            "+"
            "+"
            ").prependTo(_2d3); +cc.children("div.tabs-panels").children("div").each(function(i){ +var opts=$.extend({},$.parser.parseOptions(this),{selected:($(this).attr("selected")?true:undefined)}); +var pp=$(this); +tabs.push(pp); +_2d9(_2d3,pp,opts); +}); +cc.children("div.tabs-header").find(".tabs-scroller-left, .tabs-scroller-right").hover(function(){ +$(this).addClass("tabs-scroller-over"); +},function(){ +$(this).removeClass("tabs-scroller-over"); +}); +cc.bind("_resize",function(e,_2d4){ +var opts=$.data(_2d3,"tabs").options; +if(opts.fit==true||_2d4){ +_2c6(_2d3); +_2cc(_2d3); +} +return false; +}); +}; +function _2d5(_2d6){ +var opts=$.data(_2d6,"tabs").options; +var _2d7=$(_2d6).children("div.tabs-header"); +var _2d8=$(_2d6).children("div.tabs-panels"); +_2d7.removeClass("tabs-header-top tabs-header-bottom tabs-header-left tabs-header-right"); +_2d8.removeClass("tabs-panels-top tabs-panels-bottom tabs-panels-left tabs-panels-right"); +if(opts.tabPosition=="top"){ +_2d7.insertBefore(_2d8); +}else{ +if(opts.tabPosition=="bottom"){ +_2d7.insertAfter(_2d8); +_2d7.addClass("tabs-header-bottom"); +_2d8.addClass("tabs-panels-top"); +}else{ +if(opts.tabPosition=="left"){ +_2d7.addClass("tabs-header-left"); +_2d8.addClass("tabs-panels-right"); +}else{ +if(opts.tabPosition=="right"){ +_2d7.addClass("tabs-header-right"); +_2d8.addClass("tabs-panels-left"); +} +} +} +} +if(opts.plain==true){ +_2d7.addClass("tabs-header-plain"); +}else{ +_2d7.removeClass("tabs-header-plain"); +} +if(opts.border==true){ +_2d7.removeClass("tabs-header-noborder"); +_2d8.removeClass("tabs-panels-noborder"); +}else{ +_2d7.addClass("tabs-header-noborder"); +_2d8.addClass("tabs-panels-noborder"); +} +$(".tabs-scroller-left",_2d7).unbind(".tabs").bind("click.tabs",function(){ +$(_2d6).tabs("scrollBy",-opts.scrollIncrement); +}); +$(".tabs-scroller-right",_2d7).unbind(".tabs").bind("click.tabs",function(){ +$(_2d6).tabs("scrollBy",opts.scrollIncrement); +}); +}; +function _2d9(_2da,pp,_2db){ +var _2dc=$.data(_2da,"tabs"); +_2db=_2db||{}; +pp.panel($.extend({},_2db,{border:false,noheader:true,closed:true,doSize:false,iconCls:(_2db.icon?_2db.icon:undefined),onLoad:function(){ +if(_2db.onLoad){ +_2db.onLoad.call(this,arguments); +} +_2dc.options.onLoad.call(_2da,$(this)); +}})); +var opts=pp.panel("options"); +var tabs=$(_2da).children("div.tabs-header").find("ul.tabs"); +opts.tab=$("
          • ").appendTo(tabs); +opts.tab.append(""+""+""+""); +opts.tab.unbind(".tabs").bind("click.tabs",{p:pp},function(e){ +if($(this).hasClass("tabs-disabled")){ +return; +} +_2e1(_2da,_2dd(_2da,e.data.p)); +}).bind("contextmenu.tabs",{p:pp},function(e){ +if($(this).hasClass("tabs-disabled")){ +return; +} +_2dc.options.onContextMenu.call(_2da,e,$(this).find("span.tabs-title").html(),_2dd(_2da,e.data.p)); +}); +$(_2da).tabs("update",{tab:pp,options:opts}); +}; +function _2de(_2df,_2e0){ +var opts=$.data(_2df,"tabs").options; +var tabs=$.data(_2df,"tabs").tabs; +if(_2e0.selected==undefined){ +_2e0.selected=true; +} +var pp=$("
            ").appendTo($(_2df).children("div.tabs-panels")); +tabs.push(pp); +_2d9(_2df,pp,_2e0); +opts.onAdd.call(_2df,_2e0.title,tabs.length-1); +_2bb(_2df); +if(_2e0.selected){ +_2e1(_2df,tabs.length-1); +} +}; +function _2e2(_2e3,_2e4){ +var _2e5=$.data(_2e3,"tabs").selectHis; +var pp=_2e4.tab; +var _2e6=pp.panel("options").title; +pp.panel($.extend({},_2e4.options,{iconCls:(_2e4.options.icon?_2e4.options.icon:undefined)})); +var opts=pp.panel("options"); +var tab=opts.tab; +var _2e7=tab.find("span.tabs-title"); +var _2e8=tab.find("span.tabs-icon"); +_2e7.html(opts.title); +_2e8.attr("class","tabs-icon"); +tab.find("a.tabs-close").remove(); +if(opts.closable){ +_2e7.addClass("tabs-closable"); +var _2e9=$("").appendTo(tab); +_2e9.bind("click.tabs",{p:pp},function(e){ +if($(this).parent().hasClass("tabs-disabled")){ +return; +} +_2eb(_2e3,_2dd(_2e3,e.data.p)); +return false; +}); +}else{ +_2e7.removeClass("tabs-closable"); +} +if(opts.iconCls){ +_2e7.addClass("tabs-with-icon"); +_2e8.addClass(opts.iconCls); +}else{ +_2e7.removeClass("tabs-with-icon"); +} +if(_2e6!=opts.title){ +for(var i=0;i<_2e5.length;i++){ +if(_2e5[i]==_2e6){ +_2e5[i]=opts.title; +} +} +} +tab.find("span.tabs-p-tool").remove(); +if(opts.tools){ +var _2ea=$("").insertAfter(tab.find("a.tabs-inner")); +if(typeof opts.tools=="string"){ +$(opts.tools).children().appendTo(_2ea); +}else{ +for(var i=0;i").appendTo(_2ea); +t.addClass(opts.tools[i].iconCls); +if(opts.tools[i].handler){ +t.bind("click",{handler:opts.tools[i].handler},function(e){ +if($(this).parents("li").hasClass("tabs-disabled")){ +return; +} +e.data.handler.call(this); +}); +} +} +} +var pr=_2ea.children().length*12; +if(opts.closable){ +pr+=8; +}else{ +pr-=3; +_2ea.css("right","5px"); +} +_2e7.css("padding-right",pr+"px"); +} +_2bb(_2e3); +$.data(_2e3,"tabs").options.onUpdate.call(_2e3,opts.title,_2dd(_2e3,pp)); +}; +function _2eb(_2ec,_2ed){ +var opts=$.data(_2ec,"tabs").options; +var tabs=$.data(_2ec,"tabs").tabs; +var _2ee=$.data(_2ec,"tabs").selectHis; +if(!_2ef(_2ec,_2ed)){ +return; +} +var tab=_2f0(_2ec,_2ed); +var _2f1=tab.panel("options").title; +var _2f2=_2dd(_2ec,tab); +if(opts.onBeforeClose.call(_2ec,_2f1,_2f2)==false){ +return; +} +var tab=_2f0(_2ec,_2ed,true); +tab.panel("options").tab.remove(); +tab.panel("destroy"); +opts.onClose.call(_2ec,_2f1,_2f2); +_2bb(_2ec); +for(var i=0;i<_2ee.length;i++){ +if(_2ee[i]==_2f1){ +_2ee.splice(i,1); +i--; +} +} +var _2f3=_2ee.pop(); +if(_2f3){ +_2e1(_2ec,_2f3); +}else{ +if(tabs.length){ +_2e1(_2ec,0); +} +} +}; +function _2f0(_2f4,_2f5,_2f6){ +var tabs=$.data(_2f4,"tabs").tabs; +if(typeof _2f5=="number"){ +if(_2f5<0||_2f5>=tabs.length){ +return null; +}else{ +var tab=tabs[_2f5]; +if(_2f6){ +tabs.splice(_2f5,1); +} +return tab; +} +} +for(var i=0;idiv.tabs-header>div.tabs-wrap"); +var left=tab.position().left; +var _301=left+tab.outerWidth(); +if(left<0||_301>wrap.width()){ +var _302=left-(wrap.width()-tab.width())/2; +$(_2fb).tabs("scrollBy",_302); +}else{ +$(_2fb).tabs("scrollBy",0); +} +_2cc(_2fb); +opts.onSelect.call(_2fb,_300,_2dd(_2fb,_2fe)); +}; +function _2ef(_303,_304){ +return _2f0(_303,_304)!=null; +}; +$.fn.tabs=function(_305,_306){ +if(typeof _305=="string"){ +return $.fn.tabs.methods[_305](this,_306); +} +_305=_305||{}; +return this.each(function(){ +var _307=$.data(this,"tabs"); +var opts; +if(_307){ +opts=$.extend(_307.options,_305); +_307.options=opts; +}else{ +$.data(this,"tabs",{options:$.extend({},$.fn.tabs.defaults,$.fn.tabs.parseOptions(this),_305),tabs:[],selectHis:[]}); +_2d2(this); +} +_2c2(this); +_2d5(this); +_2c6(this); +_2f9(this); +}); +}; +$.fn.tabs.methods={options:function(jq){ +return $.data(jq[0],"tabs").options; +},tabs:function(jq){ +return $.data(jq[0],"tabs").tabs; +},resize:function(jq){ +return jq.each(function(){ +_2c6(this); +_2cc(this); +}); +},add:function(jq,_308){ +return jq.each(function(){ +_2de(this,_308); +}); +},close:function(jq,_309){ +return jq.each(function(){ +_2eb(this,_309); +}); +},getTab:function(jq,_30a){ +return _2f0(jq[0],_30a); +},getTabIndex:function(jq,tab){ +return _2dd(jq[0],tab); +},getSelected:function(jq){ +return _2ce(jq[0]); +},select:function(jq,_30b){ +return jq.each(function(){ +_2e1(this,_30b); +}); +},exists:function(jq,_30c){ +return _2ef(jq[0],_30c); +},update:function(jq,_30d){ +return jq.each(function(){ +_2e2(this,_30d); +}); +},enableTab:function(jq,_30e){ +return jq.each(function(){ +$(this).tabs("getTab",_30e).panel("options").tab.removeClass("tabs-disabled"); +}); +},disableTab:function(jq,_30f){ +return jq.each(function(){ +$(this).tabs("getTab",_30f).panel("options").tab.addClass("tabs-disabled"); +}); +},scrollBy:function(jq,_310){ +return jq.each(function(){ +var opts=$(this).tabs("options"); +var wrap=$(this).find(">div.tabs-header>div.tabs-wrap"); +var pos=Math.min(wrap._scrollLeft()+_310,_311()); +wrap.animate({scrollLeft:pos},opts.scrollDuration); +function _311(){ +var w=0; +var ul=wrap.children("ul"); +ul.children("li").each(function(){ +w+=$(this).outerWidth(true); +}); +return w-wrap.width()+(ul.outerWidth()-ul.width()); +}; +}); +}}; +$.fn.tabs.parseOptions=function(_312){ +return $.extend({},$.parser.parseOptions(_312,["width","height","tools","toolPosition","tabPosition",{fit:"boolean",border:"boolean",plain:"boolean",headerWidth:"number"}])); +}; +$.fn.tabs.defaults={width:"auto",height:"auto",headerWidth:150,plain:false,fit:false,border:true,tools:null,toolPosition:"right",tabPosition:"top",scrollIncrement:100,scrollDuration:400,onLoad:function(_313){ +},onSelect:function(_314,_315){ +},onBeforeClose:function(_316,_317){ +},onClose:function(_318,_319){ +},onAdd:function(_31a,_31b){ +},onUpdate:function(_31c,_31d){ +},onContextMenu:function(e,_31e,_31f){ +}}; +})(jQuery); +(function($){ +var _320=false; +function _321(_322){ +var _323=$.data(_322,"layout"); +var opts=_323.options; +var _324=_323.panels; +var cc=$(_322); +if(_322.tagName=="BODY"){ +cc._fit(); +}else{ +opts.fit?cc.css(cc._fit()):cc._fit(false); +} +var cpos={top:0,left:0,width:cc.width(),height:cc.height()}; +function _325(pp){ +if(pp.length==0){ +return; +} +var opts=pp.panel("options"); +var _326=Math.min(Math.max(opts.height,opts.minHeight),opts.maxHeight); +pp.panel("resize",{width:cc.width(),height:_326,left:0,top:0}); +cpos.top+=_326; +cpos.height-=_326; +}; +if(_32d(_324.expandNorth)){ +_325(_324.expandNorth); +}else{ +_325(_324.north); +} +function _327(pp){ +if(pp.length==0){ +return; +} +var opts=pp.panel("options"); +var _328=Math.min(Math.max(opts.height,opts.minHeight),opts.maxHeight); +pp.panel("resize",{width:cc.width(),height:_328,left:0,top:cc.height()-_328}); +cpos.height-=_328; +}; +if(_32d(_324.expandSouth)){ +_327(_324.expandSouth); +}else{ +_327(_324.south); +} +function _329(pp){ +if(pp.length==0){ +return; +} +var opts=pp.panel("options"); +var _32a=Math.min(Math.max(opts.width,opts.minWidth),opts.maxWidth); +pp.panel("resize",{width:_32a,height:cpos.height,left:cc.width()-_32a,top:cpos.top}); +cpos.width-=_32a; +}; +if(_32d(_324.expandEast)){ +_329(_324.expandEast); +}else{ +_329(_324.east); +} +function _32b(pp){ +if(pp.length==0){ +return; +} +var opts=pp.panel("options"); +var _32c=Math.min(Math.max(opts.width,opts.minWidth),opts.maxWidth); +pp.panel("resize",{width:_32c,height:cpos.height,left:0,top:cpos.top}); +cpos.left+=_32c; +cpos.width-=_32c; +}; +if(_32d(_324.expandWest)){ +_32b(_324.expandWest); +}else{ +_32b(_324.west); +} +_324.center.panel("resize",cpos); +}; +function init(_32e){ +var cc=$(_32e); +cc.addClass("layout"); +function _32f(cc){ +cc.children("div").each(function(){ +var opts=$.parser.parseOptions(this,["region",{split:"boolean",minWidth:"number",minHeight:"number",maxWidth:"number",maxHeight:"number"}]); +var r=opts.region; +if(r=="north"||r=="south"||r=="east"||r=="west"||r=="center"){ +_331(_32e,opts,this); +} +}); +}; +cc.children("form").length?_32f(cc.children("form")):_32f(cc); +$("
            ").appendTo(cc); +$("
            ").appendTo(cc); +cc.bind("_resize",function(e,_330){ +var opts=$.data(_32e,"layout").options; +if(opts.fit==true||_330){ +_321(_32e); +} +return false; +}); +}; +function _331(_332,_333,el){ +_333.region=_333.region||"center"; +var _334=$.data(_332,"layout").panels; +var cc=$(_332); +var dir=_333.region; +if(_334[dir].length){ +return; +} +var pp=$(el); +if(!pp.length){ +pp=$("
            ").appendTo(cc); +} +pp.panel($.extend({minWidth:10,minHeight:10,maxWidth:10000,maxHeight:10000},{width:(pp.length?parseInt(pp[0].style.width)||pp.outerWidth():"auto"),height:(pp.length?parseInt(pp[0].style.height)||pp.outerHeight():"auto"),doSize:false,collapsible:true,cls:("layout-panel layout-panel-"+dir),bodyCls:"layout-body",onOpen:function(){ +var tool=$(this).panel("header").children("div.panel-tool"); +tool.children("a.panel-tool-collapse").hide(); +var _335={north:"up",south:"down",east:"right",west:"left"}; +if(!_335[dir]){ +return; +} +var _336="layout-button-"+_335[dir]; +var t=tool.children("a."+_336); +if(!t.length){ +t=$("").addClass(_336).appendTo(tool); +t.bind("click",{dir:dir},function(e){ +_342(_332,e.data.dir); +return false; +}); +} +$(this).panel("options").collapsible?t.show():t.hide(); +}},_333)); +_334[dir]=pp; +if(pp.panel("options").split){ +var _337=pp.panel("panel"); +_337.addClass("layout-split-"+dir); +var _338=""; +if(dir=="north"){ +_338="s"; +} +if(dir=="south"){ +_338="n"; +} +if(dir=="east"){ +_338="w"; +} +if(dir=="west"){ +_338="e"; +} +_337.resizable($.extend({},{handles:_338,onStartResize:function(e){ +_320=true; +if(dir=="north"||dir=="south"){ +var _339=$(">div.layout-split-proxy-v",_332); +}else{ +var _339=$(">div.layout-split-proxy-h",_332); +} +var top=0,left=0,_33a=0,_33b=0; +var pos={display:"block"}; +if(dir=="north"){ +pos.top=parseInt(_337.css("top"))+_337.outerHeight()-_339.height(); +pos.left=parseInt(_337.css("left")); +pos.width=_337.outerWidth(); +pos.height=_339.height(); +}else{ +if(dir=="south"){ +pos.top=parseInt(_337.css("top")); +pos.left=parseInt(_337.css("left")); +pos.width=_337.outerWidth(); +pos.height=_339.height(); +}else{ +if(dir=="east"){ +pos.top=parseInt(_337.css("top"))||0; +pos.left=parseInt(_337.css("left"))||0; +pos.width=_339.width(); +pos.height=_337.outerHeight(); +}else{ +if(dir=="west"){ +pos.top=parseInt(_337.css("top"))||0; +pos.left=_337.outerWidth()-_339.width(); +pos.width=_339.width(); +pos.height=_337.outerHeight(); +} +} +} +} +_339.css(pos); +$("
            ").css({left:0,top:0,width:cc.width(),height:cc.height()}).appendTo(cc); +},onResize:function(e){ +if(dir=="north"||dir=="south"){ +var _33c=$(">div.layout-split-proxy-v",_332); +_33c.css("top",e.pageY-$(_332).offset().top-_33c.height()/2); +}else{ +var _33c=$(">div.layout-split-proxy-h",_332); +_33c.css("left",e.pageX-$(_332).offset().left-_33c.width()/2); +} +return false; +},onStopResize:function(){ +$(">div.layout-split-proxy-v",_332).css("display","none"); +$(">div.layout-split-proxy-h",_332).css("display","none"); +var opts=pp.panel("options"); +opts.width=_337.outerWidth(); +opts.height=_337.outerHeight(); +opts.left=_337.css("left"); +opts.top=_337.css("top"); +pp.panel("resize"); +_321(_332); +_320=false; +cc.find(">div.layout-mask").remove(); +}},_333)); +} +}; +function _33d(_33e,_33f){ +var _340=$.data(_33e,"layout").panels; +if(_340[_33f].length){ +_340[_33f].panel("destroy"); +_340[_33f]=$(); +var _341="expand"+_33f.substring(0,1).toUpperCase()+_33f.substring(1); +if(_340[_341]){ +_340[_341].panel("destroy"); +_340[_341]=undefined; +} +} +}; +function _342(_343,_344,_345){ +if(_345==undefined){ +_345="normal"; +} +var _346=$.data(_343,"layout").panels; +var p=_346[_344]; +if(p.panel("options").onBeforeCollapse.call(p)==false){ +return; +} +var _347="expand"+_344.substring(0,1).toUpperCase()+_344.substring(1); +if(!_346[_347]){ +_346[_347]=_348(_344); +_346[_347].panel("panel").click(function(){ +var _349=_34a(); +p.panel("expand",false).panel("open").panel("resize",_349.collapse); +p.panel("panel").animate(_349.expand,_345,function(){ +$(this).unbind(".layout").bind("mouseleave.layout",{region:_344},function(e){ +if(_320==true){ +return; +} +_342(_343,e.data.region); +}); +}); +return false; +}); +} +var _34b=_34a(); +if(!_32d(_346[_347])){ +_346.center.panel("resize",_34b.resizeC); +} +p.panel("panel").animate(_34b.collapse,_345,function(){ +p.panel("collapse",false).panel("close"); +_346[_347].panel("open").panel("resize",_34b.expandP); +$(this).unbind(".layout"); +}); +function _348(dir){ +var icon; +if(dir=="east"){ +icon="layout-button-left"; +}else{ +if(dir=="west"){ +icon="layout-button-right"; +}else{ +if(dir=="north"){ +icon="layout-button-down"; +}else{ +if(dir=="south"){ +icon="layout-button-up"; +} +} +} +} +var p=$("
            ").appendTo(_343).panel({cls:"layout-expand",title:" ",closed:true,doSize:false,tools:[{iconCls:icon,handler:function(){ +_34c(_343,_344); +return false; +}}]}); +p.panel("panel").hover(function(){ +$(this).addClass("layout-expand-over"); +},function(){ +$(this).removeClass("layout-expand-over"); +}); +return p; +}; +function _34a(){ +var cc=$(_343); +if(_344=="east"){ +return {resizeC:{width:_346.center.panel("options").width+_346["east"].panel("options").width-28},expand:{left:cc.width()-_346["east"].panel("options").width},expandP:{top:_346["east"].panel("options").top,left:cc.width()-28,width:28,height:_346["center"].panel("options").height},collapse:{left:cc.width()}}; +}else{ +if(_344=="west"){ +return {resizeC:{width:_346.center.panel("options").width+_346["west"].panel("options").width-28,left:28},expand:{left:0},expandP:{left:0,top:_346["west"].panel("options").top,width:28,height:_346["center"].panel("options").height},collapse:{left:-_346["west"].panel("options").width}}; +}else{ +if(_344=="north"){ +var hh=cc.height()-28; +if(_32d(_346.expandSouth)){ +hh-=_346.expandSouth.panel("options").height; +}else{ +if(_32d(_346.south)){ +hh-=_346.south.panel("options").height; +} +} +_346.east.panel("resize",{top:28,height:hh}); +_346.west.panel("resize",{top:28,height:hh}); +if(_32d(_346.expandEast)){ +_346.expandEast.panel("resize",{top:28,height:hh}); +} +if(_32d(_346.expandWest)){ +_346.expandWest.panel("resize",{top:28,height:hh}); +} +return {resizeC:{top:28,height:hh},expand:{top:0},expandP:{top:0,left:0,width:cc.width(),height:28},collapse:{top:-_346["north"].panel("options").height}}; +}else{ +if(_344=="south"){ +var hh=cc.height()-28; +if(_32d(_346.expandNorth)){ +hh-=_346.expandNorth.panel("options").height; +}else{ +if(_32d(_346.north)){ +hh-=_346.north.panel("options").height; +} +} +_346.east.panel("resize",{height:hh}); +_346.west.panel("resize",{height:hh}); +if(_32d(_346.expandEast)){ +_346.expandEast.panel("resize",{height:hh}); +} +if(_32d(_346.expandWest)){ +_346.expandWest.panel("resize",{height:hh}); +} +return {resizeC:{height:hh},expand:{top:cc.height()-_346["south"].panel("options").height},expandP:{top:cc.height()-28,left:0,width:cc.width(),height:28},collapse:{top:cc.height()}}; +} +} +} +} +}; +}; +function _34c(_34d,_34e){ +var _34f=$.data(_34d,"layout").panels; +var _350=_351(); +var p=_34f[_34e]; +if(p.panel("options").onBeforeExpand.call(p)==false){ +return; +} +var _352="expand"+_34e.substring(0,1).toUpperCase()+_34e.substring(1); +_34f[_352].panel("close"); +p.panel("panel").stop(true,true); +p.panel("expand",false).panel("open").panel("resize",_350.collapse); +p.panel("panel").animate(_350.expand,function(){ +_321(_34d); +}); +function _351(){ +var cc=$(_34d); +if(_34e=="east"&&_34f.expandEast){ +return {collapse:{left:cc.width()},expand:{left:cc.width()-_34f["east"].panel("options").width}}; +}else{ +if(_34e=="west"&&_34f.expandWest){ +return {collapse:{left:-_34f["west"].panel("options").width},expand:{left:0}}; +}else{ +if(_34e=="north"&&_34f.expandNorth){ +return {collapse:{top:-_34f["north"].panel("options").height},expand:{top:0}}; +}else{ +if(_34e=="south"&&_34f.expandSouth){ +return {collapse:{top:cc.height()},expand:{top:cc.height()-_34f["south"].panel("options").height}}; +} +} +} +} +}; +}; +function _32d(pp){ +if(!pp){ +return false; +} +if(pp.length){ +return pp.panel("panel").is(":visible"); +}else{ +return false; +} +}; +function _353(_354){ +var _355=$.data(_354,"layout").panels; +if(_355.east.length&&_355.east.panel("options").collapsed){ +_342(_354,"east",0); +} +if(_355.west.length&&_355.west.panel("options").collapsed){ +_342(_354,"west",0); +} +if(_355.north.length&&_355.north.panel("options").collapsed){ +_342(_354,"north",0); +} +if(_355.south.length&&_355.south.panel("options").collapsed){ +_342(_354,"south",0); +} +}; +$.fn.layout=function(_356,_357){ +if(typeof _356=="string"){ +return $.fn.layout.methods[_356](this,_357); +} +_356=_356||{}; +return this.each(function(){ +var _358=$.data(this,"layout"); +if(_358){ +$.extend(_358.options,_356); +}else{ +var opts=$.extend({},$.fn.layout.defaults,$.fn.layout.parseOptions(this),_356); +$.data(this,"layout",{options:opts,panels:{center:$(),north:$(),south:$(),east:$(),west:$()}}); +init(this); +} +_321(this); +_353(this); +}); +}; +$.fn.layout.methods={resize:function(jq){ +return jq.each(function(){ +_321(this); +}); +},panel:function(jq,_359){ +return $.data(jq[0],"layout").panels[_359]; +},collapse:function(jq,_35a){ +return jq.each(function(){ +_342(this,_35a); +}); +},expand:function(jq,_35b){ +return jq.each(function(){ +_34c(this,_35b); +}); +},add:function(jq,_35c){ +return jq.each(function(){ +_331(this,_35c); +_321(this); +if($(this).layout("panel",_35c.region).panel("options").collapsed){ +_342(this,_35c.region,0); +} +}); +},remove:function(jq,_35d){ +return jq.each(function(){ +_33d(this,_35d); +_321(this); +}); +}}; +$.fn.layout.parseOptions=function(_35e){ +return $.extend({},$.parser.parseOptions(_35e,[{fit:"boolean"}])); +}; +$.fn.layout.defaults={fit:false}; +})(jQuery); +(function($){ +function init(_35f){ +$(_35f).appendTo("body"); +$(_35f).addClass("menu-top"); +$(document).unbind(".menu").bind("mousedown.menu",function(e){ +var _360=$("body>div.menu:visible"); +var m=$(e.target).closest("div.menu",_360); +if(m.length){ +return; +} +$("body>div.menu-top:visible").menu("hide"); +}); +var _361=_362($(_35f)); +for(var i=0;i<_361.length;i++){ +_363(_361[i]); +} +function _362(menu){ +var _364=[]; +menu.addClass("menu"); +_364.push(menu); +if(!menu.hasClass("menu-content")){ +menu.children("div").each(function(){ +var _365=$(this).children("div"); +if(_365.length){ +_365.insertAfter(_35f); +this.submenu=_365; +var mm=_362(_365); +_364=_364.concat(mm); +} +}); +} +return _364; +}; +function _363(menu){ +var _366=$.parser.parseOptions(menu[0],["width"]).width; +if(menu.hasClass("menu-content")){ +menu[0].originalWidth=_366||menu._outerWidth(); +}else{ +menu[0].originalWidth=_366||0; +menu.children("div").each(function(){ +var item=$(this); +if(item.hasClass("menu-sep")){ +}else{ +var _367=$.extend({},$.parser.parseOptions(this,["name","iconCls","href"]),{disabled:(item.attr("disabled")?true:undefined)}); +item.attr("name",_367.name||"").attr("href",_367.href||""); +var text=item.addClass("menu-item").html(); +item.empty().append($("
            ").html(text)); +if(_367.iconCls){ +$("
            ").addClass(_367.iconCls).appendTo(item); +} +if(_367.disabled){ +_368(_35f,item[0],true); +} +if(item[0].submenu){ +$("
            ").appendTo(item); +} +_369(_35f,item); +} +}); +$("
            ").prependTo(menu); +} +_36a(_35f,menu); +menu.hide(); +_36b(_35f,menu); +}; +}; +function _36a(_36c,menu){ +var opts=$.data(_36c,"menu").options; +var d=menu.css("display"); +menu.css({display:"block",left:-10000}); +menu.find("div.menu-item")._outerHeight(22); +var _36d=0; +menu.find("div.menu-text").each(function(){ +if(_36d<$(this)._outerWidth()){ +_36d=$(this)._outerWidth(); +} +}); +_36d+=65; +menu._outerWidth(Math.max((menu[0].originalWidth||0),_36d,opts.minWidth)); +menu.css("display",d); +}; +function _36b(_36e,menu){ +var _36f=$.data(_36e,"menu"); +menu.unbind(".menu").bind("mouseenter.menu",function(){ +if(_36f.timer){ +clearTimeout(_36f.timer); +_36f.timer=null; +} +}).bind("mouseleave.menu",function(){ +_36f.timer=setTimeout(function(){ +_370(_36e); +},100); +}); +}; +function _369(_371,item){ +item.unbind(".menu"); +item.bind("click.menu",function(){ +if($(this).hasClass("menu-item-disabled")){ +return; +} +if(!this.submenu){ +_370(_371); +var href=$(this).attr("href"); +if(href){ +location.href=href; +} +} +var item=$(_371).menu("getItem",this); +$.data(_371,"menu").options.onClick.call(_371,item); +}).bind("mouseenter.menu",function(e){ +item.siblings().each(function(){ +if(this.submenu){ +_374(this.submenu); +} +$(this).removeClass("menu-active"); +}); +item.addClass("menu-active"); +if($(this).hasClass("menu-item-disabled")){ +item.addClass("menu-active-disabled"); +return; +} +var _372=item[0].submenu; +if(_372){ +$(_371).menu("show",{menu:_372,parent:item}); +} +}).bind("mouseleave.menu",function(e){ +item.removeClass("menu-active menu-active-disabled"); +var _373=item[0].submenu; +if(_373){ +if(e.pageX>=parseInt(_373.css("left"))){ +item.addClass("menu-active"); +}else{ +_374(_373); +} +}else{ +item.removeClass("menu-active"); +} +}); +}; +function _370(_375){ +var _376=$.data(_375,"menu"); +if(_376){ +if($(_375).is(":visible")){ +_374($(_375)); +_376.options.onHide.call(_375); +} +} +return false; +}; +function _377(_378,_379){ +var left,top; +var menu=$(_379.menu||_378); +if(menu.hasClass("menu-top")){ +var opts=$.data(_378,"menu").options; +left=opts.left; +top=opts.top; +if(_379.alignTo){ +var at=$(_379.alignTo); +left=at.offset().left; +top=at.offset().top+at._outerHeight(); +} +if(_379.left!=undefined){ +left=_379.left; +} +if(_379.top!=undefined){ +top=_379.top; +} +if(left+menu.outerWidth()>$(window)._outerWidth()+$(document)._scrollLeft()){ +left=$(window)._outerWidth()+$(document).scrollLeft()-menu.outerWidth()-5; +} +if(top+menu.outerHeight()>$(window)._outerHeight()+$(document).scrollTop()){ +top-=menu.outerHeight(); +} +}else{ +var _37a=_379.parent; +left=_37a.offset().left+_37a.outerWidth()-2; +if(left+menu.outerWidth()+5>$(window)._outerWidth()+$(document).scrollLeft()){ +left=_37a.offset().left-menu.outerWidth()+2; +} +var top=_37a.offset().top-3; +if(top+menu.outerHeight()>$(window)._outerHeight()+$(document).scrollTop()){ +top=$(window)._outerHeight()+$(document).scrollTop()-menu.outerHeight()-5; +} +} +menu.css({left:left,top:top}); +menu.show(0,function(){ +if(!menu[0].shadow){ +menu[0].shadow=$("
            ").insertAfter(menu); +} +menu[0].shadow.css({display:"block",zIndex:$.fn.menu.defaults.zIndex++,left:menu.css("left"),top:menu.css("top"),width:menu.outerWidth(),height:menu.outerHeight()}); +menu.css("z-index",$.fn.menu.defaults.zIndex++); +if(menu.hasClass("menu-top")){ +$.data(menu[0],"menu").options.onShow.call(menu[0]); +} +}); +}; +function _374(menu){ +if(!menu){ +return; +} +_37b(menu); +menu.find("div.menu-item").each(function(){ +if(this.submenu){ +_374(this.submenu); +} +$(this).removeClass("menu-active"); +}); +function _37b(m){ +m.stop(true,true); +if(m[0].shadow){ +m[0].shadow.hide(); +} +m.hide(); +}; +}; +function _37c(_37d,text){ +var _37e=null; +var tmp=$("
            "); +function find(menu){ +menu.children("div.menu-item").each(function(){ +var item=$(_37d).menu("getItem",this); +var s=tmp.empty().html(item.text).text(); +if(text==$.trim(s)){ +_37e=item; +}else{ +if(this.submenu&&!_37e){ +find(this.submenu); +} +} +}); +}; +find($(_37d)); +tmp.remove(); +return _37e; +}; +function _368(_37f,_380,_381){ +var t=$(_380); +if(_381){ +t.addClass("menu-item-disabled"); +if(_380.onclick){ +_380.onclick1=_380.onclick; +_380.onclick=null; +} +}else{ +t.removeClass("menu-item-disabled"); +if(_380.onclick1){ +_380.onclick=_380.onclick1; +_380.onclick1=null; +} +} +}; +function _382(_383,_384){ +var menu=$(_383); +if(_384.parent){ +if(!_384.parent.submenu){ +var _385=$("
            ").appendTo("body"); +_385.hide(); +_384.parent.submenu=_385; +$("
            ").appendTo(_384.parent); +} +menu=_384.parent.submenu; +} +var item=$("
            ").appendTo(menu); +$("
            ").html(_384.text).appendTo(item); +if(_384.iconCls){ +$("
            ").addClass(_384.iconCls).appendTo(item); +} +if(_384.id){ +item.attr("id",_384.id); +} +if(_384.href){ +item.attr("href",_384.href); +} +if(_384.name){ +item.attr("name",_384.name); +} +if(_384.onclick){ +if(typeof _384.onclick=="string"){ +item.attr("onclick",_384.onclick); +}else{ +item[0].onclick=eval(_384.onclick); +} +} +if(_384.handler){ +item[0].onclick=eval(_384.handler); +} +_369(_383,item); +if(_384.disabled){ +_368(_383,item[0],true); +} +_36b(_383,menu); +_36a(_383,menu); +}; +function _386(_387,_388){ +function _389(el){ +if(el.submenu){ +el.submenu.children("div.menu-item").each(function(){ +_389(this); +}); +var _38a=el.submenu[0].shadow; +if(_38a){ +_38a.remove(); +} +el.submenu.remove(); +} +$(el).remove(); +}; +_389(_388); +}; +function _38b(_38c){ +$(_38c).children("div.menu-item").each(function(){ +_386(_38c,this); +}); +if(_38c.shadow){ +_38c.shadow.remove(); +} +$(_38c).remove(); +}; +$.fn.menu=function(_38d,_38e){ +if(typeof _38d=="string"){ +return $.fn.menu.methods[_38d](this,_38e); +} +_38d=_38d||{}; +return this.each(function(){ +var _38f=$.data(this,"menu"); +if(_38f){ +$.extend(_38f.options,_38d); +}else{ +_38f=$.data(this,"menu",{options:$.extend({},$.fn.menu.defaults,$.fn.menu.parseOptions(this),_38d)}); +init(this); +} +$(this).css({left:_38f.options.left,top:_38f.options.top}); +}); +}; +$.fn.menu.methods={options:function(jq){ +return $.data(jq[0],"menu").options; +},show:function(jq,pos){ +return jq.each(function(){ +_377(this,pos); +}); +},hide:function(jq){ +return jq.each(function(){ +_370(this); +}); +},destroy:function(jq){ +return jq.each(function(){ +_38b(this); +}); +},setText:function(jq,_390){ +return jq.each(function(){ +$(_390.target).children("div.menu-text").html(_390.text); +}); +},setIcon:function(jq,_391){ +return jq.each(function(){ +var item=$(this).menu("getItem",_391.target); +if(item.iconCls){ +$(item.target).children("div.menu-icon").removeClass(item.iconCls).addClass(_391.iconCls); +}else{ +$("
            ").addClass(_391.iconCls).appendTo(_391.target); +} +}); +},getItem:function(jq,_392){ +var t=$(_392); +var item={target:_392,id:t.attr("id"),text:$.trim(t.children("div.menu-text").html()),disabled:t.hasClass("menu-item-disabled"),href:t.attr("href"),name:t.attr("name"),onclick:_392.onclick}; +var icon=t.children("div.menu-icon"); +if(icon.length){ +var cc=[]; +var aa=icon.attr("class").split(" "); +for(var i=0;i "})); +if(opts.menu){ +$(opts.menu).menu({onShow:function(){ +btn.addClass((opts.plain==true)?"m-btn-plain-active":"m-btn-active"); +},onHide:function(){ +btn.removeClass((opts.plain==true)?"m-btn-plain-active":"m-btn-active"); +}}); +} +_399(_398,opts.disabled); +}; +function _399(_39a,_39b){ +var opts=$.data(_39a,"menubutton").options; +opts.disabled=_39b; +var btn=$(_39a); +if(_39b){ +btn.linkbutton("disable"); +btn.unbind(".menubutton"); +}else{ +btn.linkbutton("enable"); +btn.unbind(".menubutton"); +btn.bind("click.menubutton",function(){ +_39c(); +return false; +}); +var _39d=null; +btn.bind("mouseenter.menubutton",function(){ +_39d=setTimeout(function(){ +_39c(); +},opts.duration); +return false; +}).bind("mouseleave.menubutton",function(){ +if(_39d){ +clearTimeout(_39d); +} +}); +} +function _39c(){ +if(!opts.menu){ +return; +} +$("body>div.menu-top").menu("hide"); +$(opts.menu).menu("show",{alignTo:btn}); +btn.blur(); +}; +}; +$.fn.menubutton=function(_39e,_39f){ +if(typeof _39e=="string"){ +return $.fn.menubutton.methods[_39e](this,_39f); +} +_39e=_39e||{}; +return this.each(function(){ +var _3a0=$.data(this,"menubutton"); +if(_3a0){ +$.extend(_3a0.options,_39e); +}else{ +$.data(this,"menubutton",{options:$.extend({},$.fn.menubutton.defaults,$.fn.menubutton.parseOptions(this),_39e)}); +$(this).removeAttr("disabled"); +} +init(this); +}); +}; +$.fn.menubutton.methods={options:function(jq){ +return $.data(jq[0],"menubutton").options; +},enable:function(jq){ +return jq.each(function(){ +_399(this,false); +}); +},disable:function(jq){ +return jq.each(function(){ +_399(this,true); +}); +},destroy:function(jq){ +return jq.each(function(){ +var opts=$(this).menubutton("options"); +if(opts.menu){ +$(opts.menu).menu("destroy"); +} +$(this).remove(); +}); +}}; +$.fn.menubutton.parseOptions=function(_3a1){ +var t=$(_3a1); +return $.extend({},$.fn.linkbutton.parseOptions(_3a1),$.parser.parseOptions(_3a1,["menu",{plain:"boolean",duration:"number"}])); +}; +$.fn.menubutton.defaults=$.extend({},$.fn.linkbutton.defaults,{plain:true,menu:null,duration:100}); +})(jQuery); +(function($){ +function init(_3a2){ +var opts=$.data(_3a2,"splitbutton").options; +var btn=$(_3a2); +btn.removeClass("s-btn-active s-btn-plain-active").addClass("s-btn"); +btn.linkbutton($.extend({},opts,{text:opts.text+" "})); +if(opts.menu){ +$(opts.menu).menu({onShow:function(){ +btn.addClass((opts.plain==true)?"s-btn-plain-active":"s-btn-active"); +},onHide:function(){ +btn.removeClass((opts.plain==true)?"s-btn-plain-active":"s-btn-active"); +}}); +} +_3a3(_3a2,opts.disabled); +}; +function _3a3(_3a4,_3a5){ +var opts=$.data(_3a4,"splitbutton").options; +opts.disabled=_3a5; +var btn=$(_3a4); +var _3a6=btn.find(".s-btn-downarrow"); +if(_3a5){ +btn.linkbutton("disable"); +_3a6.unbind(".splitbutton"); +}else{ +btn.linkbutton("enable"); +_3a6.unbind(".splitbutton"); +_3a6.bind("click.splitbutton",function(){ +_3a7(); +return false; +}); +var _3a8=null; +_3a6.bind("mouseenter.splitbutton",function(){ +_3a8=setTimeout(function(){ +_3a7(); +},opts.duration); +return false; +}).bind("mouseleave.splitbutton",function(){ +if(_3a8){ +clearTimeout(_3a8); +} +}); +} +function _3a7(){ +if(!opts.menu){ +return; +} +$("body>div.menu-top").menu("hide"); +$(opts.menu).menu("show",{alignTo:btn}); +btn.blur(); +}; +}; +$.fn.splitbutton=function(_3a9,_3aa){ +if(typeof _3a9=="string"){ +return $.fn.splitbutton.methods[_3a9](this,_3aa); +} +_3a9=_3a9||{}; +return this.each(function(){ +var _3ab=$.data(this,"splitbutton"); +if(_3ab){ +$.extend(_3ab.options,_3a9); +}else{ +$.data(this,"splitbutton",{options:$.extend({},$.fn.splitbutton.defaults,$.fn.splitbutton.parseOptions(this),_3a9)}); +$(this).removeAttr("disabled"); +} +init(this); +}); +}; +$.fn.splitbutton.methods={options:function(jq){ +return $.data(jq[0],"splitbutton").options; +},enable:function(jq){ +return jq.each(function(){ +_3a3(this,false); +}); +},disable:function(jq){ +return jq.each(function(){ +_3a3(this,true); +}); +},destroy:function(jq){ +return jq.each(function(){ +var opts=$(this).splitbutton("options"); +if(opts.menu){ +$(opts.menu).menu("destroy"); +} +$(this).remove(); +}); +}}; +$.fn.splitbutton.parseOptions=function(_3ac){ +var t=$(_3ac); +return $.extend({},$.fn.linkbutton.parseOptions(_3ac),$.parser.parseOptions(_3ac,["menu",{plain:"boolean",duration:"number"}])); +}; +$.fn.splitbutton.defaults=$.extend({},$.fn.linkbutton.defaults,{plain:true,menu:null,duration:100}); +})(jQuery); +(function($){ +function init(_3ad){ +$(_3ad).hide(); +var span=$("").insertAfter(_3ad); +var _3ae=$("").appendTo(span); +$("").appendTo(span); +var name=$(_3ad).attr("name"); +if(name){ +_3ae.attr("name",name); +$(_3ad).removeAttr("name").attr("searchboxName",name); +} +return span; +}; +function _3af(_3b0,_3b1){ +var opts=$.data(_3b0,"searchbox").options; +var sb=$.data(_3b0,"searchbox").searchbox; +if(_3b1){ +opts.width=_3b1; +} +sb.appendTo("body"); +if(isNaN(opts.width)){ +opts.width=sb._outerWidth(); +} +var _3b2=sb.find("span.searchbox-button"); +var menu=sb.find("a.searchbox-menu"); +var _3b3=sb.find("input.searchbox-text"); +sb._outerWidth(opts.width)._outerHeight(opts.height); +_3b3._outerWidth(sb.width()-menu._outerWidth()-_3b2._outerWidth()); +_3b3.css({height:sb.height()+"px",lineHeight:sb.height()+"px"}); +menu._outerHeight(sb.height()); +_3b2._outerHeight(sb.height()); +var _3b4=menu.find("span.l-btn-left"); +_3b4._outerHeight(sb.height()); +_3b4.find("span.l-btn-text,span.m-btn-downarrow").css({height:_3b4.height()+"px",lineHeight:_3b4.height()+"px"}); +sb.insertAfter(_3b0); +}; +function _3b5(_3b6){ +var _3b7=$.data(_3b6,"searchbox"); +var opts=_3b7.options; +if(opts.menu){ +_3b7.menu=$(opts.menu).menu({onClick:function(item){ +_3b8(item); +}}); +var item=_3b7.menu.children("div.menu-item:first"); +_3b7.menu.children("div.menu-item").each(function(){ +var _3b9=$.extend({},$.parser.parseOptions(this),{selected:($(this).attr("selected")?true:undefined)}); +if(_3b9.selected){ +item=$(this); +return false; +} +}); +item.triggerHandler("click"); +}else{ +_3b7.searchbox.find("a.searchbox-menu").remove(); +_3b7.menu=null; +} +function _3b8(item){ +_3b7.searchbox.find("a.searchbox-menu").remove(); +var mb=$("").html(item.text); +mb.prependTo(_3b7.searchbox).menubutton({menu:_3b7.menu,iconCls:item.iconCls}); +_3b7.searchbox.find("input.searchbox-text").attr("name",$(item.target).attr("name")||item.text); +_3af(_3b6); +}; +}; +function _3ba(_3bb){ +var _3bc=$.data(_3bb,"searchbox"); +var opts=_3bc.options; +var _3bd=_3bc.searchbox.find("input.searchbox-text"); +var _3be=_3bc.searchbox.find(".searchbox-button"); +_3bd.unbind(".searchbox").bind("blur.searchbox",function(e){ +opts.value=$(this).val(); +if(opts.value==""){ +$(this).val(opts.prompt); +$(this).addClass("searchbox-prompt"); +}else{ +$(this).removeClass("searchbox-prompt"); +} +}).bind("focus.searchbox",function(e){ +if($(this).val()!=opts.value){ +$(this).val(opts.value); +} +$(this).removeClass("searchbox-prompt"); +}).bind("keydown.searchbox",function(e){ +if(e.keyCode==13){ +e.preventDefault(); +var name=$.fn.prop?_3bd.prop("name"):_3bd.attr("name"); +opts.value=$(this).val(); +opts.searcher.call(_3bb,opts.value,name); +return false; +} +}); +_3be.unbind(".searchbox").bind("click.searchbox",function(){ +var name=$.fn.prop?_3bd.prop("name"):_3bd.attr("name"); +opts.searcher.call(_3bb,opts.value,name); +}).bind("mouseenter.searchbox",function(){ +$(this).addClass("searchbox-button-hover"); +}).bind("mouseleave.searchbox",function(){ +$(this).removeClass("searchbox-button-hover"); +}); +}; +function _3bf(_3c0){ +var _3c1=$.data(_3c0,"searchbox"); +var opts=_3c1.options; +var _3c2=_3c1.searchbox.find("input.searchbox-text"); +if(opts.value==""){ +_3c2.val(opts.prompt); +_3c2.addClass("searchbox-prompt"); +}else{ +_3c2.val(opts.value); +_3c2.removeClass("searchbox-prompt"); +} +}; +$.fn.searchbox=function(_3c3,_3c4){ +if(typeof _3c3=="string"){ +return $.fn.searchbox.methods[_3c3](this,_3c4); +} +_3c3=_3c3||{}; +return this.each(function(){ +var _3c5=$.data(this,"searchbox"); +if(_3c5){ +$.extend(_3c5.options,_3c3); +}else{ +_3c5=$.data(this,"searchbox",{options:$.extend({},$.fn.searchbox.defaults,$.fn.searchbox.parseOptions(this),_3c3),searchbox:init(this)}); +} +_3b5(this); +_3bf(this); +_3ba(this); +_3af(this); +}); +}; +$.fn.searchbox.methods={options:function(jq){ +return $.data(jq[0],"searchbox").options; +},menu:function(jq){ +return $.data(jq[0],"searchbox").menu; +},textbox:function(jq){ +return $.data(jq[0],"searchbox").searchbox.find("input.searchbox-text"); +},getValue:function(jq){ +return $.data(jq[0],"searchbox").options.value; +},setValue:function(jq,_3c6){ +return jq.each(function(){ +$(this).searchbox("options").value=_3c6; +$(this).searchbox("textbox").val(_3c6); +$(this).searchbox("textbox").blur(); +}); +},getName:function(jq){ +return $.data(jq[0],"searchbox").searchbox.find("input.searchbox-text").attr("name"); +},selectName:function(jq,name){ +return jq.each(function(){ +var menu=$.data(this,"searchbox").menu; +if(menu){ +menu.children("div.menu-item[name=\""+name+"\"]").triggerHandler("click"); +} +}); +},destroy:function(jq){ +return jq.each(function(){ +var menu=$(this).searchbox("menu"); +if(menu){ +menu.menu("destroy"); +} +$.data(this,"searchbox").searchbox.remove(); +$(this).remove(); +}); +},resize:function(jq,_3c7){ +return jq.each(function(){ +_3af(this,_3c7); +}); +}}; +$.fn.searchbox.parseOptions=function(_3c8){ +var t=$(_3c8); +return $.extend({},$.parser.parseOptions(_3c8,["width","height","prompt","menu"]),{value:t.val(),searcher:(t.attr("searcher")?eval(t.attr("searcher")):undefined)}); +}; +$.fn.searchbox.defaults={width:"auto",height:22,prompt:"",value:"",menu:null,searcher:function(_3c9,name){ +}}; +})(jQuery); +(function($){ +function init(_3ca){ +$(_3ca).addClass("validatebox-text"); +}; +function _3cb(_3cc){ +var _3cd=$.data(_3cc,"validatebox"); +_3cd.validating=false; +$(_3cc).tooltip("destroy"); +$(_3cc).unbind(); +$(_3cc).remove(); +}; +function _3ce(_3cf){ +var box=$(_3cf); +var _3d0=$.data(_3cf,"validatebox"); +box.unbind(".validatebox").bind("focus.validatebox",function(){ +_3d0.validating=true; +_3d0.value=undefined; +(function(){ +if(_3d0.validating){ +if(_3d0.value!=box.val()){ +_3d0.value=box.val(); +if(_3d0.timer){ +clearTimeout(_3d0.timer); +} +_3d0.timer=setTimeout(function(){ +$(_3cf).validatebox("validate"); +},_3d0.options.delay); +}else{ +_3d5(_3cf); +} +setTimeout(arguments.callee,200); +} +})(); +}).bind("blur.validatebox",function(){ +if(_3d0.timer){ +clearTimeout(_3d0.timer); +_3d0.timer=undefined; +} +_3d0.validating=false; +_3d1(_3cf); +}).bind("mouseenter.validatebox",function(){ +if(box.hasClass("validatebox-invalid")){ +_3d2(_3cf); +} +}).bind("mouseleave.validatebox",function(){ +if(!_3d0.validating){ +_3d1(_3cf); +} +}); +}; +function _3d2(_3d3){ +var _3d4=$.data(_3d3,"validatebox"); +var opts=_3d4.options; +$(_3d3).tooltip($.extend({},opts.tipOptions,{content:_3d4.message,position:opts.tipPosition,deltaX:opts.deltaX})).tooltip("show"); +_3d4.tip=true; +}; +function _3d5(_3d6){ +var _3d7=$.data(_3d6,"validatebox"); +if(_3d7&&_3d7.tip){ +$(_3d6).tooltip("reposition"); +} +}; +function _3d1(_3d8){ +var _3d9=$.data(_3d8,"validatebox"); +_3d9.tip=false; +$(_3d8).tooltip("hide"); +}; +function _3da(_3db){ +var _3dc=$.data(_3db,"validatebox"); +var opts=_3dc.options; +var box=$(_3db); +var _3dd=box.val(); +function _3de(msg){ +_3dc.message=msg; +}; +function _3df(_3e0){ +var _3e1=/([a-zA-Z_]+)(.*)/.exec(_3e0); +var rule=opts.rules[_3e1[1]]; +if(rule&&_3dd){ +var _3e2=eval(_3e1[2]); +if(!rule["validator"](_3dd,_3e2)){ +box.addClass("validatebox-invalid"); +var _3e3=rule["message"]; +if(_3e2){ +for(var i=0;i<_3e2.length;i++){ +_3e3=_3e3.replace(new RegExp("\\{"+i+"\\}","g"),_3e2[i]); +} +} +_3de(opts.invalidMessage||_3e3); +if(_3dc.validating){ +_3d2(_3db); +} +return false; +} +} +return true; +}; +if(opts.required){ +if(_3dd==""){ +box.addClass("validatebox-invalid"); +_3de(opts.missingMessage); +if(_3dc.validating){ +_3d2(_3db); +} +return false; +} +} +if(opts.validType){ +if(typeof opts.validType=="string"){ +if(!_3df(opts.validType)){ +return false; +} +}else{ +for(var i=0;i=_3eb[0]&&len<=_3eb[1]; +},message:"Please enter a value between {0} and {1}."},remote:{validator:function(_3ec,_3ed){ +var data={}; +data[_3ed[1]]=_3ec; +var _3ee=$.ajax({url:_3ed[0],dataType:"json",data:data,async:false,cache:false,type:"post"}).responseText; +return _3ee=="true"; +},message:"Please fix this field."}}}; +})(jQuery); +(function($){ +function _3ef(_3f0,_3f1){ +_3f1=_3f1||{}; +var _3f2={}; +if(_3f1.onSubmit){ +if(_3f1.onSubmit.call(_3f0,_3f2)==false){ +return; +} +} +var form=$(_3f0); +if(_3f1.url){ +form.attr("action",_3f1.url); +} +var _3f3="easyui_frame_"+(new Date().getTime()); +var _3f4=$("").attr("src",window.ActiveXObject?"javascript:false":"about:blank").css({position:"absolute",top:-1000,left:-1000}); +var t=form.attr("target"),a=form.attr("action"); +form.attr("target",_3f3); +var _3f5=$(); +try{ +_3f4.appendTo("body"); +_3f4.bind("load",cb); +for(var n in _3f2){ +var f=$("").val(_3f2[n]).appendTo(form); +_3f5=_3f5.add(f); +} +form[0].submit(); +} +finally{ +form.attr("action",a); +t?form.attr("target",t):form.removeAttr("target"); +_3f5.remove(); +} +var _3f6=10; +function cb(){ +_3f4.unbind(); +var body=$("#"+_3f3).contents().find("body"); +var data=body.html(); +if(data==""){ +if(--_3f6){ +setTimeout(cb,100); +return; +} +return; +} +var ta=body.find(">textarea"); +if(ta.length){ +data=ta.val(); +}else{ +var pre=body.find(">pre"); +if(pre.length){ +data=pre.html(); +} +} +if(_3f1.success){ +_3f1.success(data); +} +setTimeout(function(){ +_3f4.unbind(); +_3f4.remove(); +},100); +}; +}; +function load(_3f7,data){ +if(!$.data(_3f7,"form")){ +$.data(_3f7,"form",{options:$.extend({},$.fn.form.defaults)}); +} +var opts=$.data(_3f7,"form").options; +if(typeof data=="string"){ +var _3f8={}; +if(opts.onBeforeLoad.call(_3f7,_3f8)==false){ +return; +} +$.ajax({url:data,data:_3f8,dataType:"json",success:function(data){ +_3f9(data); +},error:function(){ +opts.onLoadError.apply(_3f7,arguments); +}}); +}else{ +_3f9(data); +} +function _3f9(data){ +var form=$(_3f7); +for(var name in data){ +var val=data[name]; +var rr=_3fa(name,val); +if(!rr.length){ +var f=form.find("input[numberboxName=\""+name+"\"]"); +if(f.length){ +f.numberbox("setValue",val); +}else{ +$("input[name=\""+name+"\"]",form).val(val); +$("textarea[name=\""+name+"\"]",form).val(val); +$("select[name=\""+name+"\"]",form).val(val); +} +} +_3fb(name,val); +} +opts.onLoadSuccess.call(_3f7,data); +_3fe(_3f7); +}; +function _3fa(name,val){ +var rr=$(_3f7).find("input[name=\""+name+"\"][type=radio], input[name=\""+name+"\"][type=checkbox]"); +rr._propAttr("checked",false); +rr.each(function(){ +var f=$(this); +if(f.val()==String(val)||$.inArray(f.val(),val)>=0){ +f._propAttr("checked",true); +} +}); +return rr; +}; +function _3fb(name,val){ +var form=$(_3f7); +var cc=["combobox","combotree","combogrid","datetimebox","datebox","combo"]; +var c=form.find("[comboName=\""+name+"\"]"); +if(c.length){ +for(var i=0;i").insertAfter(_40b); +var name=$(_40b).attr("name"); +if(name){ +v.attr("name",name); +$(_40b).removeAttr("name").attr("numberboxName",name); +} +return v; +}; +function _40c(_40d){ +var opts=$.data(_40d,"numberbox").options; +var fn=opts.onChange; +opts.onChange=function(){ +}; +_40e(_40d,opts.parser.call(_40d,opts.value)); +opts.onChange=fn; +opts.originalValue=_40f(_40d); +}; +function _40f(_410){ +return $.data(_410,"numberbox").field.val(); +}; +function _40e(_411,_412){ +var _413=$.data(_411,"numberbox"); +var opts=_413.options; +var _414=_40f(_411); +_412=opts.parser.call(_411,_412); +opts.value=_412; +_413.field.val(_412); +$(_411).val(opts.formatter.call(_411,_412)); +if(_414!=_412){ +opts.onChange.call(_411,_412,_414); +} +}; +function _415(_416){ +var opts=$.data(_416,"numberbox").options; +$(_416).unbind(".numberbox").bind("keypress.numberbox",function(e){ +return opts.filter.call(_416,e); +}).bind("blur.numberbox",function(){ +_40e(_416,$(this).val()); +$(this).val(opts.formatter.call(_416,_40f(_416))); +}).bind("focus.numberbox",function(){ +var vv=_40f(_416); +if(vv!=opts.parser.call(_416,$(this).val())){ +$(this).val(opts.formatter.call(_416,vv)); +} +}); +}; +function _417(_418){ +if($.fn.validatebox){ +var opts=$.data(_418,"numberbox").options; +$(_418).validatebox(opts); +} +}; +function _419(_41a,_41b){ +var opts=$.data(_41a,"numberbox").options; +if(_41b){ +opts.disabled=true; +$(_41a).attr("disabled",true); +}else{ +opts.disabled=false; +$(_41a).removeAttr("disabled"); +} +}; +$.fn.numberbox=function(_41c,_41d){ +if(typeof _41c=="string"){ +var _41e=$.fn.numberbox.methods[_41c]; +if(_41e){ +return _41e(this,_41d); +}else{ +return this.validatebox(_41c,_41d); +} +} +_41c=_41c||{}; +return this.each(function(){ +var _41f=$.data(this,"numberbox"); +if(_41f){ +$.extend(_41f.options,_41c); +}else{ +_41f=$.data(this,"numberbox",{options:$.extend({},$.fn.numberbox.defaults,$.fn.numberbox.parseOptions(this),_41c),field:init(this)}); +$(this).removeAttr("disabled"); +$(this).css({imeMode:"disabled"}); +} +_419(this,_41f.options.disabled); +_415(this); +_417(this); +_40c(this); +}); +}; +$.fn.numberbox.methods={options:function(jq){ +return $.data(jq[0],"numberbox").options; +},destroy:function(jq){ +return jq.each(function(){ +$.data(this,"numberbox").field.remove(); +$(this).validatebox("destroy"); +$(this).remove(); +}); +},disable:function(jq){ +return jq.each(function(){ +_419(this,true); +}); +},enable:function(jq){ +return jq.each(function(){ +_419(this,false); +}); +},fix:function(jq){ +return jq.each(function(){ +_40e(this,$(this).val()); +}); +},setValue:function(jq,_420){ +return jq.each(function(){ +_40e(this,_420); +}); +},getValue:function(jq){ +return _40f(jq[0]); +},clear:function(jq){ +return jq.each(function(){ +var _421=$.data(this,"numberbox"); +_421.field.val(""); +$(this).val(""); +}); +},reset:function(jq){ +return jq.each(function(){ +var opts=$(this).numberbox("options"); +$(this).numberbox("setValue",opts.originalValue); +}); +}}; +$.fn.numberbox.parseOptions=function(_422){ +var t=$(_422); +return $.extend({},$.fn.validatebox.parseOptions(_422),$.parser.parseOptions(_422,["decimalSeparator","groupSeparator","suffix",{min:"number",max:"number",precision:"number"}]),{prefix:(t.attr("prefix")?t.attr("prefix"):undefined),disabled:(t.attr("disabled")?true:undefined),value:(t.val()||undefined)}); +}; +$.fn.numberbox.defaults=$.extend({},$.fn.validatebox.defaults,{disabled:false,value:"",min:null,max:null,precision:0,decimalSeparator:".",groupSeparator:"",prefix:"",suffix:"",filter:function(e){ +var opts=$(this).numberbox("options"); +if(e.which==45){ +return ($(this).val().indexOf("-")==-1?true:false); +} +var c=String.fromCharCode(e.which); +if(c==opts.decimalSeparator){ +return ($(this).val().indexOf(c)==-1?true:false); +}else{ +if(c==opts.groupSeparator){ +return true; +}else{ +if((e.which>=48&&e.which<=57&&e.ctrlKey==false&&e.shiftKey==false)||e.which==0||e.which==8){ +return true; +}else{ +if(e.ctrlKey==true&&(e.which==99||e.which==118)){ +return true; +}else{ +return false; +} +} +} +} +},formatter:function(_423){ +if(!_423){ +return _423; +} +_423=_423+""; +var opts=$(this).numberbox("options"); +var s1=_423,s2=""; +var dpos=_423.indexOf("."); +if(dpos>=0){ +s1=_423.substring(0,dpos); +s2=_423.substring(dpos+1,_423.length); +} +if(opts.groupSeparator){ +var p=/(\d+)(\d{3})/; +while(p.test(s1)){ +s1=s1.replace(p,"$1"+opts.groupSeparator+"$2"); +} +} +if(s2){ +return opts.prefix+s1+opts.decimalSeparator+s2+opts.suffix; +}else{ +return opts.prefix+s1+opts.suffix; +} +},parser:function(s){ +s=s+""; +var opts=$(this).numberbox("options"); +if(parseFloat(s)!=s){ +if(opts.prefix){ +s=$.trim(s.replace(new RegExp("\\"+$.trim(opts.prefix),"g"),"")); +} +if(opts.suffix){ +s=$.trim(s.replace(new RegExp("\\"+$.trim(opts.suffix),"g"),"")); +} +if(opts.groupSeparator){ +s=$.trim(s.replace(new RegExp("\\"+opts.groupSeparator,"g"),"")); +} +if(opts.decimalSeparator){ +s=$.trim(s.replace(new RegExp("\\"+opts.decimalSeparator,"g"),".")); +} +s=s.replace(/\s/g,""); +} +var val=parseFloat(s).toFixed(opts.precision); +if(isNaN(val)){ +val=""; +}else{ +if(typeof (opts.min)=="number"&&valopts.max){ +val=opts.max.toFixed(opts.precision); +} +} +} +return val; +},onChange:function(_424,_425){ +}}); +})(jQuery); +(function($){ +function _426(_427){ +var opts=$.data(_427,"calendar").options; +var t=$(_427); +if(opts.fit==true){ +var p=t.parent(); +opts.width=p.width(); +opts.height=p.height(); +} +var _428=t.find(".calendar-header"); +t._outerWidth(opts.width); +t._outerHeight(opts.height); +t.find(".calendar-body")._outerHeight(t.height()-_428._outerHeight()); +}; +function init(_429){ +$(_429).addClass("calendar").html("
            "+"
            "+"
            "+"
            "+"
            "+"
            "+"Aprial 2010"+"
            "+"
            "+"
            "+"
            "+"
            "+""+""+""+"
            "+"
            "+"
            "+"
            "+"
            "); +$(_429).find(".calendar-title span").hover(function(){ +$(this).addClass("calendar-menu-hover"); +},function(){ +$(this).removeClass("calendar-menu-hover"); +}).click(function(){ +var menu=$(_429).find(".calendar-menu"); +if(menu.is(":visible")){ +menu.hide(); +}else{ +_430(_429); +} +}); +$(".calendar-prevmonth,.calendar-nextmonth,.calendar-prevyear,.calendar-nextyear",_429).hover(function(){ +$(this).addClass("calendar-nav-hover"); +},function(){ +$(this).removeClass("calendar-nav-hover"); +}); +$(_429).find(".calendar-nextmonth").click(function(){ +_42a(_429,1); +}); +$(_429).find(".calendar-prevmonth").click(function(){ +_42a(_429,-1); +}); +$(_429).find(".calendar-nextyear").click(function(){ +_42d(_429,1); +}); +$(_429).find(".calendar-prevyear").click(function(){ +_42d(_429,-1); +}); +$(_429).bind("_resize",function(){ +var opts=$.data(_429,"calendar").options; +if(opts.fit==true){ +_426(_429); +} +return false; +}); +}; +function _42a(_42b,_42c){ +var opts=$.data(_42b,"calendar").options; +opts.month+=_42c; +if(opts.month>12){ +opts.year++; +opts.month=1; +}else{ +if(opts.month<1){ +opts.year--; +opts.month=12; +} +} +show(_42b); +var menu=$(_42b).find(".calendar-menu-month-inner"); +menu.find("td.calendar-selected").removeClass("calendar-selected"); +menu.find("td:eq("+(opts.month-1)+")").addClass("calendar-selected"); +}; +function _42d(_42e,_42f){ +var opts=$.data(_42e,"calendar").options; +opts.year+=_42f; +show(_42e); +var menu=$(_42e).find(".calendar-menu-year"); +menu.val(opts.year); +}; +function _430(_431){ +var opts=$.data(_431,"calendar").options; +$(_431).find(".calendar-menu").show(); +if($(_431).find(".calendar-menu-month-inner").is(":empty")){ +$(_431).find(".calendar-menu-month-inner").empty(); +var t=$("
            ").appendTo($(_431).find(".calendar-menu-month-inner")); +var idx=0; +for(var i=0;i<3;i++){ +var tr=$("").appendTo(t); +for(var j=0;j<4;j++){ +$("").html(opts.months[idx++]).attr("abbr",idx).appendTo(tr); +} +} +$(_431).find(".calendar-menu-prev,.calendar-menu-next").hover(function(){ +$(this).addClass("calendar-menu-hover"); +},function(){ +$(this).removeClass("calendar-menu-hover"); +}); +$(_431).find(".calendar-menu-next").click(function(){ +var y=$(_431).find(".calendar-menu-year"); +if(!isNaN(y.val())){ +y.val(parseInt(y.val())+1); +} +}); +$(_431).find(".calendar-menu-prev").click(function(){ +var y=$(_431).find(".calendar-menu-year"); +if(!isNaN(y.val())){ +y.val(parseInt(y.val()-1)); +} +}); +$(_431).find(".calendar-menu-year").keypress(function(e){ +if(e.keyCode==13){ +_432(); +} +}); +$(_431).find(".calendar-menu-month").hover(function(){ +$(this).addClass("calendar-menu-hover"); +},function(){ +$(this).removeClass("calendar-menu-hover"); +}).click(function(){ +var menu=$(_431).find(".calendar-menu"); +menu.find(".calendar-selected").removeClass("calendar-selected"); +$(this).addClass("calendar-selected"); +_432(); +}); +} +function _432(){ +var menu=$(_431).find(".calendar-menu"); +var year=menu.find(".calendar-menu-year").val(); +var _433=menu.find(".calendar-selected").attr("abbr"); +if(!isNaN(year)){ +opts.year=parseInt(year); +opts.month=parseInt(_433); +show(_431); +} +menu.hide(); +}; +var body=$(_431).find(".calendar-body"); +var sele=$(_431).find(".calendar-menu"); +var _434=sele.find(".calendar-menu-year-inner"); +var _435=sele.find(".calendar-menu-month-inner"); +_434.find("input").val(opts.year).focus(); +_435.find("td.calendar-selected").removeClass("calendar-selected"); +_435.find("td:eq("+(opts.month-1)+")").addClass("calendar-selected"); +sele._outerWidth(body._outerWidth()); +sele._outerHeight(body._outerHeight()); +_435._outerHeight(sele.height()-_434._outerHeight()); +}; +function _436(_437,year,_438){ +var opts=$.data(_437,"calendar").options; +var _439=[]; +var _43a=new Date(year,_438,0).getDate(); +for(var i=1;i<=_43a;i++){ +_439.push([year,_438,i]); +} +var _43b=[],week=[]; +var _43c=-1; +while(_439.length>0){ +var date=_439.shift(); +week.push(date); +var day=new Date(date[0],date[1]-1,date[2]).getDay(); +if(_43c==day){ +day=0; +}else{ +if(day==(opts.firstDay==0?7:opts.firstDay)-1){ +_43b.push(week); +week=[]; +} +} +_43c=day; +} +if(week.length){ +_43b.push(week); +} +var _43d=_43b[0]; +if(_43d.length<7){ +while(_43d.length<7){ +var _43e=_43d[0]; +var date=new Date(_43e[0],_43e[1]-1,_43e[2]-1); +_43d.unshift([date.getFullYear(),date.getMonth()+1,date.getDate()]); +} +}else{ +var _43e=_43d[0]; +var week=[]; +for(var i=1;i<=7;i++){ +var date=new Date(_43e[0],_43e[1]-1,_43e[2]-i); +week.unshift([date.getFullYear(),date.getMonth()+1,date.getDate()]); +} +_43b.unshift(week); +} +var _43f=_43b[_43b.length-1]; +while(_43f.length<7){ +var _440=_43f[_43f.length-1]; +var date=new Date(_440[0],_440[1]-1,_440[2]+1); +_43f.push([date.getFullYear(),date.getMonth()+1,date.getDate()]); +} +if(_43b.length<6){ +var _440=_43f[_43f.length-1]; +var week=[]; +for(var i=1;i<=7;i++){ +var date=new Date(_440[0],_440[1]-1,_440[2]+i); +week.push([date.getFullYear(),date.getMonth()+1,date.getDate()]); +} +_43b.push(week); +} +return _43b; +}; +function show(_441){ +var opts=$.data(_441,"calendar").options; +$(_441).find(".calendar-title span").html(opts.months[opts.month-1]+" "+opts.year); +var body=$(_441).find("div.calendar-body"); +body.find(">table").remove(); +var t=$("
            ").prependTo(body); +var tr=$("").appendTo(t.find("thead")); +for(var i=opts.firstDay;i"+opts.weeks[i]+""); +} +for(var i=0;i"+opts.weeks[i]+""); +} +var _442=_436(_441,opts.year,opts.month); +for(var i=0;i<_442.length;i++){ +var week=_442[i]; +var tr=$("").appendTo(t.find("tbody")); +for(var j=0;j").attr("abbr",day[0]+","+day[1]+","+day[2]).html(day[2]).appendTo(tr); +} +} +t.find("td[abbr^=\""+opts.year+","+opts.month+"\"]").removeClass("calendar-other-month"); +var now=new Date(); +var _443=now.getFullYear()+","+(now.getMonth()+1)+","+now.getDate(); +t.find("td[abbr=\""+_443+"\"]").addClass("calendar-today"); +if(opts.current){ +t.find(".calendar-selected").removeClass("calendar-selected"); +var _444=opts.current.getFullYear()+","+(opts.current.getMonth()+1)+","+opts.current.getDate(); +t.find("td[abbr=\""+_444+"\"]").addClass("calendar-selected"); +} +var _445=6-opts.firstDay; +var _446=_445+1; +if(_445>=7){ +_445-=7; +} +if(_446>=7){ +_446-=7; +} +t.find("tr").find("td:eq("+_445+")").addClass("calendar-saturday"); +t.find("tr").find("td:eq("+_446+")").addClass("calendar-sunday"); +t.find("td").hover(function(){ +$(this).addClass("calendar-hover"); +},function(){ +$(this).removeClass("calendar-hover"); +}).click(function(){ +t.find(".calendar-selected").removeClass("calendar-selected"); +$(this).addClass("calendar-selected"); +var _447=$(this).attr("abbr").split(","); +opts.current=new Date(_447[0],parseInt(_447[1])-1,_447[2]); +opts.onSelect.call(_441,opts.current); +}); +}; +$.fn.calendar=function(_448,_449){ +if(typeof _448=="string"){ +return $.fn.calendar.methods[_448](this,_449); +} +_448=_448||{}; +return this.each(function(){ +var _44a=$.data(this,"calendar"); +if(_44a){ +$.extend(_44a.options,_448); +}else{ +_44a=$.data(this,"calendar",{options:$.extend({},$.fn.calendar.defaults,$.fn.calendar.parseOptions(this),_448)}); +init(this); +} +if(_44a.options.border==false){ +$(this).addClass("calendar-noborder"); +} +_426(this); +show(this); +$(this).find("div.calendar-menu").hide(); +}); +}; +$.fn.calendar.methods={options:function(jq){ +return $.data(jq[0],"calendar").options; +},resize:function(jq){ +return jq.each(function(){ +_426(this); +}); +},moveTo:function(jq,date){ +return jq.each(function(){ +$(this).calendar({year:date.getFullYear(),month:date.getMonth()+1,current:date}); +}); +}}; +$.fn.calendar.parseOptions=function(_44b){ +var t=$(_44b); +return $.extend({},$.parser.parseOptions(_44b,["width","height",{firstDay:"number",fit:"boolean",border:"boolean"}])); +}; +$.fn.calendar.defaults={width:180,height:180,fit:false,border:true,firstDay:0,weeks:["S","M","T","W","T","F","S"],months:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],year:new Date().getFullYear(),month:new Date().getMonth()+1,current:new Date(),onSelect:function(date){ +}}; +})(jQuery); +(function($){ +function init(_44c){ +var _44d=$(""+""+""+""+""+"").insertAfter(_44c); +$(_44c).addClass("spinner-text spinner-f").prependTo(_44d); +return _44d; +}; +function _44e(_44f,_450){ +var opts=$.data(_44f,"spinner").options; +var _451=$.data(_44f,"spinner").spinner; +if(_450){ +opts.width=_450; +} +var _452=$("
            ").insertBefore(_451); +_451.appendTo("body"); +if(isNaN(opts.width)){ +opts.width=$(_44f).outerWidth(); +} +var _453=_451.find(".spinner-arrow"); +_451._outerWidth(opts.width)._outerHeight(opts.height); +$(_44f)._outerWidth(_451.width()-_453.outerWidth()); +$(_44f).css({height:_451.height()+"px",lineHeight:_451.height()+"px"}); +_453._outerHeight(_451.height()); +_453.find("span")._outerHeight(_453.height()/2); +_451.insertAfter(_452); +_452.remove(); +}; +function _454(_455){ +var opts=$.data(_455,"spinner").options; +var _456=$.data(_455,"spinner").spinner; +_456.find(".spinner-arrow-up,.spinner-arrow-down").unbind(".spinner"); +if(!opts.disabled){ +_456.find(".spinner-arrow-up").bind("mouseenter.spinner",function(){ +$(this).addClass("spinner-arrow-hover"); +}).bind("mouseleave.spinner",function(){ +$(this).removeClass("spinner-arrow-hover"); +}).bind("click.spinner",function(){ +opts.spin.call(_455,false); +opts.onSpinUp.call(_455); +$(_455).validatebox("validate"); +}); +_456.find(".spinner-arrow-down").bind("mouseenter.spinner",function(){ +$(this).addClass("spinner-arrow-hover"); +}).bind("mouseleave.spinner",function(){ +$(this).removeClass("spinner-arrow-hover"); +}).bind("click.spinner",function(){ +opts.spin.call(_455,true); +opts.onSpinDown.call(_455); +$(_455).validatebox("validate"); +}); +} +}; +function _457(_458,_459){ +var opts=$.data(_458,"spinner").options; +if(_459){ +opts.disabled=true; +$(_458).attr("disabled",true); +}else{ +opts.disabled=false; +$(_458).removeAttr("disabled"); +} +}; +$.fn.spinner=function(_45a,_45b){ +if(typeof _45a=="string"){ +var _45c=$.fn.spinner.methods[_45a]; +if(_45c){ +return _45c(this,_45b); +}else{ +return this.validatebox(_45a,_45b); +} +} +_45a=_45a||{}; +return this.each(function(){ +var _45d=$.data(this,"spinner"); +if(_45d){ +$.extend(_45d.options,_45a); +}else{ +_45d=$.data(this,"spinner",{options:$.extend({},$.fn.spinner.defaults,$.fn.spinner.parseOptions(this),_45a),spinner:init(this)}); +$(this).removeAttr("disabled"); +} +_45d.options.originalValue=_45d.options.value; +$(this).val(_45d.options.value); +$(this).attr("readonly",!_45d.options.editable); +_457(this,_45d.options.disabled); +_44e(this); +$(this).validatebox(_45d.options); +_454(this); +}); +}; +$.fn.spinner.methods={options:function(jq){ +var opts=$.data(jq[0],"spinner").options; +return $.extend(opts,{value:jq.val()}); +},destroy:function(jq){ +return jq.each(function(){ +var _45e=$.data(this,"spinner").spinner; +$(this).validatebox("destroy"); +_45e.remove(); +}); +},resize:function(jq,_45f){ +return jq.each(function(){ +_44e(this,_45f); +}); +},enable:function(jq){ +return jq.each(function(){ +_457(this,false); +_454(this); +}); +},disable:function(jq){ +return jq.each(function(){ +_457(this,true); +_454(this); +}); +},getValue:function(jq){ +return jq.val(); +},setValue:function(jq,_460){ +return jq.each(function(){ +var opts=$.data(this,"spinner").options; +opts.value=_460; +$(this).val(_460); +}); +},clear:function(jq){ +return jq.each(function(){ +var opts=$.data(this,"spinner").options; +opts.value=""; +$(this).val(""); +}); +},reset:function(jq){ +return jq.each(function(){ +var opts=$(this).spinner("options"); +$(this).spinner("setValue",opts.originalValue); +}); +}}; +$.fn.spinner.parseOptions=function(_461){ +var t=$(_461); +return $.extend({},$.fn.validatebox.parseOptions(_461),$.parser.parseOptions(_461,["width","height","min","max",{increment:"number",editable:"boolean"}]),{value:(t.val()||undefined),disabled:(t.attr("disabled")?true:undefined)}); +}; +$.fn.spinner.defaults=$.extend({},$.fn.validatebox.defaults,{width:"auto",height:22,deltaX:19,value:"",min:null,max:null,increment:1,editable:true,disabled:false,spin:function(down){ +},onSpinUp:function(){ +},onSpinDown:function(){ +}}); +})(jQuery); +(function($){ +function _462(_463){ +$(_463).addClass("numberspinner-f"); +var opts=$.data(_463,"numberspinner").options; +$(_463).spinner(opts).numberbox(opts); +}; +function _464(_465,down){ +var opts=$.data(_465,"numberspinner").options; +var v=parseFloat($(_465).numberbox("getValue")||opts.value)||0; +if(down==true){ +v-=opts.increment; +}else{ +v+=opts.increment; +} +$(_465).numberbox("setValue",v); +}; +$.fn.numberspinner=function(_466,_467){ +if(typeof _466=="string"){ +var _468=$.fn.numberspinner.methods[_466]; +if(_468){ +return _468(this,_467); +}else{ +return this.spinner(_466,_467); +} +} +_466=_466||{}; +return this.each(function(){ +var _469=$.data(this,"numberspinner"); +if(_469){ +$.extend(_469.options,_466); +}else{ +$.data(this,"numberspinner",{options:$.extend({},$.fn.numberspinner.defaults,$.fn.numberspinner.parseOptions(this),_466)}); +} +_462(this); +}); +}; +$.fn.numberspinner.methods={options:function(jq){ +var opts=$.data(jq[0],"numberspinner").options; +return $.extend(opts,{value:jq.numberbox("getValue"),originalValue:jq.numberbox("options").originalValue}); +},setValue:function(jq,_46a){ +return jq.each(function(){ +$(this).numberbox("setValue",_46a); +}); +},getValue:function(jq){ +return jq.numberbox("getValue"); +},clear:function(jq){ +return jq.each(function(){ +$(this).spinner("clear"); +$(this).numberbox("clear"); +}); +},reset:function(jq){ +return jq.each(function(){ +var opts=$(this).numberspinner("options"); +$(this).numberspinner("setValue",opts.originalValue); +}); +}}; +$.fn.numberspinner.parseOptions=function(_46b){ +return $.extend({},$.fn.spinner.parseOptions(_46b),$.fn.numberbox.parseOptions(_46b),{}); +}; +$.fn.numberspinner.defaults=$.extend({},$.fn.spinner.defaults,$.fn.numberbox.defaults,{spin:function(down){ +_464(this,down); +}}); +})(jQuery); +(function($){ +function _46c(_46d){ +var opts=$.data(_46d,"timespinner").options; +$(_46d).addClass("timespinner-f"); +$(_46d).spinner(opts); +$(_46d).unbind(".timespinner"); +$(_46d).bind("click.timespinner",function(){ +var _46e=0; +if(this.selectionStart!=null){ +_46e=this.selectionStart; +}else{ +if(this.createTextRange){ +var _46f=_46d.createTextRange(); +var s=document.selection.createRange(); +s.setEndPoint("StartToStart",_46f); +_46e=s.text.length; +} +} +if(_46e>=0&&_46e<=2){ +opts.highlight=0; +}else{ +if(_46e>=3&&_46e<=5){ +opts.highlight=1; +}else{ +if(_46e>=6&&_46e<=8){ +opts.highlight=2; +} +} +} +_471(_46d); +}).bind("blur.timespinner",function(){ +_470(_46d); +}); +}; +function _471(_472){ +var opts=$.data(_472,"timespinner").options; +var _473=0,end=0; +if(opts.highlight==0){ +_473=0; +end=2; +}else{ +if(opts.highlight==1){ +_473=3; +end=5; +}else{ +if(opts.highlight==2){ +_473=6; +end=8; +} +} +} +if(_472.selectionStart!=null){ +_472.setSelectionRange(_473,end); +}else{ +if(_472.createTextRange){ +var _474=_472.createTextRange(); +_474.collapse(); +_474.moveEnd("character",end); +_474.moveStart("character",_473); +_474.select(); +} +} +$(_472).focus(); +}; +function _475(_476,_477){ +var opts=$.data(_476,"timespinner").options; +if(!_477){ +return null; +} +var vv=_477.split(opts.separator); +for(var i=0;itime){ +time=_47a; +} +if(_47b&&_47b"]; +for(var i=0;i<_48e.length;i++){ +_48d.cache[_48e[i][0]]={width:_48e[i][1]}; +} +var _48f=0; +for(var s in _48d.cache){ +var item=_48d.cache[s]; +item.index=_48f++; +ss.push(s+"{width:"+item.width+"}"); +} +ss.push(""); +$(ss.join("\n")).appendTo(cc); +setTimeout(function(){ +cc.children("style:not(:last)").remove(); +},0); +},getRule:function(_490){ +var _491=cc.children("style:last")[0]; +var _492=_491.styleSheet?_491.styleSheet:(_491.sheet||document.styleSheets[document.styleSheets.length-1]); +var _493=_492.cssRules||_492.rules; +return _493[_490]; +},set:function(_494,_495){ +var item=_48d.cache[_494]; +if(item){ +item.width=_495; +var rule=this.getRule(item.index); +if(rule){ +rule.style["width"]=_495; +} +} +},remove:function(_496){ +var tmp=[]; +for(var s in _48d.cache){ +if(s.indexOf(_496)==-1){ +tmp.push([s,_48d.cache[s].width]); +} +} +_48d.cache={}; +this.add(tmp); +},dirty:function(_497){ +if(_497){ +_48d.dirty.push(_497); +} +},clean:function(){ +for(var i=0;i<_48d.dirty.length;i++){ +this.remove(_48d.dirty[i]); +} +_48d.dirty=[]; +}}; +}; +function _498(_499,_49a){ +var opts=$.data(_499,"datagrid").options; +var _49b=$.data(_499,"datagrid").panel; +if(_49a){ +if(_49a.width){ +opts.width=_49a.width; +} +if(_49a.height){ +opts.height=_49a.height; +} +} +if(opts.fit==true){ +var p=_49b.panel("panel").parent(); +opts.width=p.width(); +opts.height=p.height(); +} +_49b.panel("resize",{width:opts.width,height:opts.height}); +}; +function _49c(_49d){ +var opts=$.data(_49d,"datagrid").options; +var dc=$.data(_49d,"datagrid").dc; +var wrap=$.data(_49d,"datagrid").panel; +var _49e=wrap.width(); +var _49f=wrap.height(); +var view=dc.view; +var _4a0=dc.view1; +var _4a1=dc.view2; +var _4a2=_4a0.children("div.datagrid-header"); +var _4a3=_4a1.children("div.datagrid-header"); +var _4a4=_4a2.find("table"); +var _4a5=_4a3.find("table"); +view.width(_49e); +var _4a6=_4a2.children("div.datagrid-header-inner").show(); +_4a0.width(_4a6.find("table").width()); +if(!opts.showHeader){ +_4a6.hide(); +} +_4a1.width(_49e-_4a0._outerWidth()); +_4a0.children("div.datagrid-header,div.datagrid-body,div.datagrid-footer").width(_4a0.width()); +_4a1.children("div.datagrid-header,div.datagrid-body,div.datagrid-footer").width(_4a1.width()); +var hh; +_4a2.css("height",""); +_4a3.css("height",""); +_4a4.css("height",""); +_4a5.css("height",""); +hh=Math.max(_4a4.height(),_4a5.height()); +_4a4.height(hh); +_4a5.height(hh); +_4a2.add(_4a3)._outerHeight(hh); +if(opts.height!="auto"){ +var _4a7=_49f-_4a1.children("div.datagrid-header")._outerHeight()-_4a1.children("div.datagrid-footer")._outerHeight()-wrap.children("div.datagrid-toolbar")._outerHeight(); +wrap.children("div.datagrid-pager").each(function(){ +_4a7-=$(this)._outerHeight(); +}); +dc.body1.add(dc.body2).children("table.datagrid-btable-frozen").css({position:"absolute",top:dc.header2._outerHeight()}); +var _4a8=dc.body2.children("table.datagrid-btable-frozen")._outerHeight(); +_4a0.add(_4a1).children("div.datagrid-body").css({marginTop:_4a8,height:(_4a7-_4a8)}); +} +view.height(_4a1.height()); +}; +function _4a9(_4aa,_4ab,_4ac){ +var rows=$.data(_4aa,"datagrid").data.rows; +var opts=$.data(_4aa,"datagrid").options; +var dc=$.data(_4aa,"datagrid").dc; +if(!dc.body1.is(":empty")&&(!opts.nowrap||opts.autoRowHeight||_4ac)){ +if(_4ab!=undefined){ +var tr1=opts.finder.getTr(_4aa,_4ab,"body",1); +var tr2=opts.finder.getTr(_4aa,_4ab,"body",2); +_4ad(tr1,tr2); +}else{ +var tr1=opts.finder.getTr(_4aa,0,"allbody",1); +var tr2=opts.finder.getTr(_4aa,0,"allbody",2); +_4ad(tr1,tr2); +if(opts.showFooter){ +var tr1=opts.finder.getTr(_4aa,0,"allfooter",1); +var tr2=opts.finder.getTr(_4aa,0,"allfooter",2); +_4ad(tr1,tr2); +} +} +} +_49c(_4aa); +if(opts.height=="auto"){ +var _4ae=dc.body1.parent(); +var _4af=dc.body2; +var _4b0=_4b1(_4af); +var _4b2=_4b0.height; +if(_4b0.width>_4af.width()){ +_4b2+=18; +} +_4ae.height(_4b2); +_4af.height(_4b2); +dc.view.height(dc.view2.height()); +} +dc.body2.triggerHandler("scroll"); +function _4ad(trs1,trs2){ +for(var i=0;i"); +} +_4ba(true); +_4ba(false); +_49c(_4b7); +function _4ba(_4bb){ +var _4bc=_4bb?1:2; +var tr=opts.finder.getTr(_4b7,_4b8,"body",_4bc); +(_4bb?dc.body1:dc.body2).children("table.datagrid-btable-frozen").append(tr); +}; +}; +function _4bd(_4be,_4bf){ +function _4c0(){ +var _4c1=[]; +var _4c2=[]; +$(_4be).children("thead").each(function(){ +var opt=$.parser.parseOptions(this,[{frozen:"boolean"}]); +$(this).find("tr").each(function(){ +var cols=[]; +$(this).find("th").each(function(){ +var th=$(this); +var col=$.extend({},$.parser.parseOptions(this,["field","align","halign","order",{sortable:"boolean",checkbox:"boolean",resizable:"boolean",fixed:"boolean"},{rowspan:"number",colspan:"number",width:"number"}]),{title:(th.html()||undefined),hidden:(th.attr("hidden")?true:undefined),formatter:(th.attr("formatter")?eval(th.attr("formatter")):undefined),styler:(th.attr("styler")?eval(th.attr("styler")):undefined),sorter:(th.attr("sorter")?eval(th.attr("sorter")):undefined)}); +if(th.attr("editor")){ +var s=$.trim(th.attr("editor")); +if(s.substr(0,1)=="{"){ +col.editor=eval("("+s+")"); +}else{ +col.editor=s; +} +} +cols.push(col); +}); +opt.frozen?_4c1.push(cols):_4c2.push(cols); +}); +}); +return [_4c1,_4c2]; +}; +var _4c3=$("
            "+"
            "+"
            "+"
            "+"
            "+"
            "+"
            "+"
            "+"
            "+"
            "+""+"
            "+"
            "+"
            "+"
            "+"
            "+"
            "+"
            "+"
            "+""+"
            "+"
            "+"
            "+"
            ").insertAfter(_4be); +_4c3.panel({doSize:false}); +_4c3.panel("panel").addClass("datagrid").bind("_resize",function(e,_4c4){ +var opts=$.data(_4be,"datagrid").options; +if(opts.fit==true||_4c4){ +_498(_4be); +setTimeout(function(){ +if($.data(_4be,"datagrid")){ +_4c5(_4be); +} +},0); +} +return false; +}); +$(_4be).hide().appendTo(_4c3.children("div.datagrid-view")); +var cc=_4c0(); +var view=_4c3.children("div.datagrid-view"); +var _4c6=view.children("div.datagrid-view1"); +var _4c7=view.children("div.datagrid-view2"); +var _4c8=_4c3.closest("div.datagrid-view"); +if(!_4c8.length){ +_4c8=view; +} +var ss=_48b(_4c8); +return {panel:_4c3,frozenColumns:cc[0],columns:cc[1],dc:{view:view,view1:_4c6,view2:_4c7,header1:_4c6.children("div.datagrid-header").children("div.datagrid-header-inner"),header2:_4c7.children("div.datagrid-header").children("div.datagrid-header-inner"),body1:_4c6.children("div.datagrid-body").children("div.datagrid-body-inner"),body2:_4c7.children("div.datagrid-body"),footer1:_4c6.children("div.datagrid-footer").children("div.datagrid-footer-inner"),footer2:_4c7.children("div.datagrid-footer").children("div.datagrid-footer-inner")},ss:ss}; +}; +function _4c9(_4ca){ +var _4cb=$.data(_4ca,"datagrid"); +var opts=_4cb.options; +var dc=_4cb.dc; +var _4cc=_4cb.panel; +_4cc.panel($.extend({},opts,{id:null,doSize:false,onResize:function(_4cd,_4ce){ +setTimeout(function(){ +if($.data(_4ca,"datagrid")){ +_49c(_4ca); +_4ef(_4ca); +opts.onResize.call(_4cc,_4cd,_4ce); +} +},0); +},onExpand:function(){ +_4a9(_4ca); +opts.onExpand.call(_4cc); +}})); +_4cb.rowIdPrefix="datagrid-row-r"+(++_486); +_4cb.cellClassPrefix="datagrid-cell-c"+_486; +_4cf(dc.header1,opts.frozenColumns,true); +_4cf(dc.header2,opts.columns,false); +_4d0(); +dc.header1.add(dc.header2).css("display",opts.showHeader?"block":"none"); +dc.footer1.add(dc.footer2).css("display",opts.showFooter?"block":"none"); +if(opts.toolbar){ +if(typeof opts.toolbar=="string"){ +$(opts.toolbar).addClass("datagrid-toolbar").prependTo(_4cc); +$(opts.toolbar).show(); +}else{ +$("div.datagrid-toolbar",_4cc).remove(); +var tb=$("
            ").prependTo(_4cc); +var tr=tb.find("tr"); +for(var i=0;i
            ").appendTo(tr); +}else{ +var td=$("").appendTo(tr); +var tool=$("").appendTo(td); +tool[0].onclick=eval(btn.handler||function(){ +}); +tool.linkbutton($.extend({},btn,{plain:true})); +} +} +} +}else{ +$("div.datagrid-toolbar",_4cc).remove(); +} +$("div.datagrid-pager",_4cc).remove(); +if(opts.pagination){ +var _4d1=$("
            "); +if(opts.pagePosition=="bottom"){ +_4d1.appendTo(_4cc); +}else{ +if(opts.pagePosition=="top"){ +_4d1.addClass("datagrid-pager-top").prependTo(_4cc); +}else{ +var ptop=$("
            ").prependTo(_4cc); +_4d1.appendTo(_4cc); +_4d1=_4d1.add(ptop); +} +} +_4d1.pagination({total:0,pageNumber:opts.pageNumber,pageSize:opts.pageSize,pageList:opts.pageList,onSelectPage:function(_4d2,_4d3){ +opts.pageNumber=_4d2; +opts.pageSize=_4d3; +_4d1.pagination("refresh",{pageNumber:_4d2,pageSize:_4d3}); +_5b0(_4ca); +}}); +opts.pageSize=_4d1.pagination("options").pageSize; +} +function _4cf(_4d4,_4d5,_4d6){ +if(!_4d5){ +return; +} +$(_4d4).show(); +$(_4d4).empty(); +var t=$("
            ").appendTo(_4d4); +for(var i=0;i<_4d5.length;i++){ +var tr=$("").appendTo($("tbody",t)); +var cols=_4d5[i]; +for(var j=0;j").appendTo(tr); +if(col.checkbox){ +td.attr("field",col.field); +$("
            ").html("").appendTo(td); +}else{ +if(col.field){ +td.attr("field",col.field); +td.append("
            "); +$("span",td).html(col.title); +$("span.datagrid-sort-icon",td).html(" "); +var cell=td.find("div.datagrid-cell"); +if(opts.sortName==col.field){ +cell.addClass("datagrid-sort-"+opts.sortOrder); +} +if(col.resizable==false){ +cell.attr("resizable","false"); +} +if(col.width){ +cell._outerWidth(col.width); +col.boxWidth=parseInt(cell[0].style.width); +}else{ +col.auto=true; +} +cell.css("text-align",(col.halign||col.align||"")); +col.cellClass=_4cb.cellClassPrefix+"-"+col.field.replace(/[\.|\s]/g,"-"); +}else{ +$("
            ").html(col.title).appendTo(td); +} +} +if(col.hidden){ +td.hide(); +} +} +} +if(_4d6&&opts.rownumbers){ +var td=$("
            "); +if($("tr",t).length==0){ +td.wrap("").parent().appendTo($("tbody",t)); +}else{ +td.prependTo($("tr:first",t)); +} +} +}; +function _4d0(){ +var _4d7=[]; +var _4d8=_4d9(_4ca,true).concat(_4d9(_4ca)); +for(var i=0;i<_4d8.length;i++){ +var col=_4da(_4ca,_4d8[i]); +if(col&&!col.checkbox){ +_4d7.push(["."+col.cellClass,col.boxWidth?col.boxWidth+"px":"auto"]); +} +} +_4cb.ss.add(_4d7); +_4cb.ss.dirty(_4cb.cellSelectorPrefix); +_4cb.cellSelectorPrefix="."+_4cb.cellClassPrefix; +}; +}; +function _4db(_4dc){ +var _4dd=$.data(_4dc,"datagrid"); +var _4de=_4dd.panel; +var opts=_4dd.options; +var dc=_4dd.dc; +var _4df=dc.header1.add(dc.header2); +_4df.find("input[type=checkbox]").unbind(".datagrid").bind("click.datagrid",function(e){ +if(opts.singleSelect&&opts.selectOnCheck){ +return false; +} +if($(this).is(":checked")){ +_54b(_4dc); +}else{ +_551(_4dc); +} +e.stopPropagation(); +}); +var _4e0=_4df.find("div.datagrid-cell"); +_4e0.closest("td").unbind(".datagrid").bind("mouseenter.datagrid",function(){ +if(_4dd.resizing){ +return; +} +$(this).addClass("datagrid-header-over"); +}).bind("mouseleave.datagrid",function(){ +$(this).removeClass("datagrid-header-over"); +}).bind("contextmenu.datagrid",function(e){ +var _4e1=$(this).attr("field"); +opts.onHeaderContextMenu.call(_4dc,e,_4e1); +}); +_4e0.unbind(".datagrid").bind("click.datagrid",function(e){ +var p1=$(this).offset().left+5; +var p2=$(this).offset().left+$(this)._outerWidth()-5; +if(e.pageXp1){ +var _4e2=$(this).parent().attr("field"); +var col=_4da(_4dc,_4e2); +if(!col.sortable||_4dd.resizing){ +return; +} +opts.sortName=_4e2; +opts.sortOrder=col.order||"asc"; +var cls="datagrid-sort-"+opts.sortOrder; +if($(this).hasClass("datagrid-sort-asc")){ +cls="datagrid-sort-desc"; +opts.sortOrder="desc"; +}else{ +if($(this).hasClass("datagrid-sort-desc")){ +cls="datagrid-sort-asc"; +opts.sortOrder="asc"; +} +} +_4e0.removeClass("datagrid-sort-asc datagrid-sort-desc"); +$(this).addClass(cls); +if(opts.remoteSort){ +_5b0(_4dc); +}else{ +var data=$.data(_4dc,"datagrid").data; +_51b(_4dc,data); +} +opts.onSortColumn.call(_4dc,opts.sortName,opts.sortOrder); +} +}).bind("dblclick.datagrid",function(e){ +var p1=$(this).offset().left+5; +var p2=$(this).offset().left+$(this)._outerWidth()-5; +var cond=opts.resizeHandle=="right"?(e.pageX>p2):(opts.resizeHandle=="left"?(e.pageXp2)); +if(cond){ +var _4e3=$(this).parent().attr("field"); +var col=_4da(_4dc,_4e3); +if(col.resizable==false){ +return; +} +$(_4dc).datagrid("autoSizeColumn",_4e3); +col.auto=false; +} +}); +var _4e4=opts.resizeHandle=="right"?"e":(opts.resizeHandle=="left"?"w":"e,w"); +_4e0.each(function(){ +$(this).resizable({handles:_4e4,disabled:($(this).attr("resizable")?$(this).attr("resizable")=="false":false),minWidth:25,onStartResize:function(e){ +_4dd.resizing=true; +_4df.css("cursor",$("body").css("cursor")); +if(!_4dd.proxy){ +_4dd.proxy=$("
            ").appendTo(dc.view); +} +_4dd.proxy.css({left:e.pageX-$(_4de).offset().left-1,display:"none"}); +setTimeout(function(){ +if(_4dd.proxy){ +_4dd.proxy.show(); +} +},500); +},onResize:function(e){ +_4dd.proxy.css({left:e.pageX-$(_4de).offset().left-1,display:"block"}); +return false; +},onStopResize:function(e){ +_4df.css("cursor",""); +$(this).css("height",""); +var _4e5=$(this).parent().attr("field"); +var col=_4da(_4dc,_4e5); +col.width=$(this)._outerWidth(); +col.boxWidth=parseInt(this.style.width); +col.auto=undefined; +_4c5(_4dc,_4e5); +_4dd.proxy.remove(); +_4dd.proxy=null; +if($(this).parents("div:first.datagrid-header").parent().hasClass("datagrid-view1")){ +_49c(_4dc); +} +_4ef(_4dc); +opts.onResizeColumn.call(_4dc,_4e5,col.width); +setTimeout(function(){ +_4dd.resizing=false; +},0); +}}); +}); +dc.body1.add(dc.body2).unbind().bind("mouseover",function(e){ +if(_4dd.resizing){ +return; +} +var tr=$(e.target).closest("tr.datagrid-row"); +if(!_4e6(tr)){ +return; +} +var _4e7=_4e8(tr); +_533(_4dc,_4e7); +e.stopPropagation(); +}).bind("mouseout",function(e){ +var tr=$(e.target).closest("tr.datagrid-row"); +if(!_4e6(tr)){ +return; +} +var _4e9=_4e8(tr); +opts.finder.getTr(_4dc,_4e9).removeClass("datagrid-row-over"); +e.stopPropagation(); +}).bind("click",function(e){ +var tt=$(e.target); +var tr=tt.closest("tr.datagrid-row"); +if(!_4e6(tr)){ +return; +} +var _4ea=_4e8(tr); +if(tt.parent().hasClass("datagrid-cell-check")){ +if(opts.singleSelect&&opts.selectOnCheck){ +if(!opts.checkOnSelect){ +_551(_4dc,true); +} +_53e(_4dc,_4ea); +}else{ +if(tt.is(":checked")){ +_53e(_4dc,_4ea); +}else{ +_545(_4dc,_4ea); +} +} +}else{ +var row=opts.finder.getRow(_4dc,_4ea); +var td=tt.closest("td[field]",tr); +if(td.length){ +var _4eb=td.attr("field"); +opts.onClickCell.call(_4dc,_4ea,_4eb,row[_4eb]); +} +if(opts.singleSelect==true){ +_537(_4dc,_4ea); +}else{ +if(tr.hasClass("datagrid-row-selected")){ +_53f(_4dc,_4ea); +}else{ +_537(_4dc,_4ea); +} +} +opts.onClickRow.call(_4dc,_4ea,row); +} +e.stopPropagation(); +}).bind("dblclick",function(e){ +var tt=$(e.target); +var tr=tt.closest("tr.datagrid-row"); +if(!_4e6(tr)){ +return; +} +var _4ec=_4e8(tr); +var row=opts.finder.getRow(_4dc,_4ec); +var td=tt.closest("td[field]",tr); +if(td.length){ +var _4ed=td.attr("field"); +opts.onDblClickCell.call(_4dc,_4ec,_4ed,row[_4ed]); +} +opts.onDblClickRow.call(_4dc,_4ec,row); +e.stopPropagation(); +}).bind("contextmenu",function(e){ +var tr=$(e.target).closest("tr.datagrid-row"); +if(!_4e6(tr)){ +return; +} +var _4ee=_4e8(tr); +var row=opts.finder.getRow(_4dc,_4ee); +opts.onRowContextMenu.call(_4dc,e,_4ee,row); +e.stopPropagation(); +}); +dc.body2.bind("scroll",function(){ +var b1=dc.view1.children("div.datagrid-body"); +b1.scrollTop($(this).scrollTop()); +var c1=dc.body1.children(":first"); +var c2=dc.body2.children(":first"); +if(c1.length&&c2.length){ +var top1=c1.offset().top; +var top2=c2.offset().top; +if(top1!=top2){ +b1.scrollTop(b1.scrollTop()+top1-top2); +} +} +dc.view2.children("div.datagrid-header,div.datagrid-footer")._scrollLeft($(this)._scrollLeft()); +dc.body2.children("table.datagrid-btable-frozen").css("left",-$(this)._scrollLeft()); +}); +function _4e8(tr){ +if(tr.attr("datagrid-row-index")){ +return parseInt(tr.attr("datagrid-row-index")); +}else{ +return tr.attr("node-id"); +} +}; +function _4e6(tr){ +return tr.length&&tr.parent().length; +}; +}; +function _4ef(_4f0){ +var opts=$.data(_4f0,"datagrid").options; +var dc=$.data(_4f0,"datagrid").dc; +dc.body2.css("overflow-x",opts.fitColumns?"hidden":""); +if(!opts.fitColumns){ +return; +} +var _4f1=dc.view2.children("div.datagrid-header"); +var _4f2=0; +var _4f3; +var _4f4=_4d9(_4f0,false); +for(var i=0;i<_4f4.length;i++){ +var col=_4da(_4f0,_4f4[i]); +if(_4f5(col)){ +_4f2+=col.width; +_4f3=col; +} +} +var _4f6=_4f1.children("div.datagrid-header-inner").show(); +var _4f7=_4f1.width()-_4f1.find("table").width()-opts.scrollbarSize; +var rate=_4f7/_4f2; +if(!opts.showHeader){ +_4f6.hide(); +} +for(var i=0;i<_4f4.length;i++){ +var col=_4da(_4f0,_4f4[i]); +if(_4f5(col)){ +var _4f8=Math.floor(col.width*rate); +_4f9(col,_4f8); +_4f7-=_4f8; +} +} +if(_4f7&&_4f3){ +_4f9(_4f3,_4f7); +} +_4c5(_4f0); +function _4f9(col,_4fa){ +col.width+=_4fa; +col.boxWidth+=_4fa; +_4f1.find("td[field=\""+col.field+"\"] div.datagrid-cell").width(col.boxWidth); +}; +function _4f5(col){ +if(!col.hidden&&!col.checkbox&&!col.auto&&!col.fixed){ +return true; +} +}; +}; +function _4fb(_4fc,_4fd){ +var opts=$.data(_4fc,"datagrid").options; +var dc=$.data(_4fc,"datagrid").dc; +if(_4fd){ +_498(_4fd); +if(opts.fitColumns){ +_49c(_4fc); +_4ef(_4fc); +} +}else{ +var _4fe=false; +var _4ff=_4d9(_4fc,true).concat(_4d9(_4fc,false)); +for(var i=0;i<_4ff.length;i++){ +var _4fd=_4ff[i]; +var col=_4da(_4fc,_4fd); +if(col.auto){ +_498(_4fd); +_4fe=true; +} +} +if(_4fe&&opts.fitColumns){ +_49c(_4fc); +_4ef(_4fc); +} +} +function _498(_500){ +var _501=dc.view.find("div.datagrid-header td[field=\""+_500+"\"] div.datagrid-cell"); +_501.css("width",""); +var col=$(_4fc).datagrid("getColumnOption",_500); +col.width=undefined; +col.boxWidth=undefined; +col.auto=true; +$(_4fc).datagrid("fixColumnSize",_500); +var _502=Math.max(_501._outerWidth(),_503("allbody"),_503("allfooter")); +_501._outerWidth(_502); +col.width=_502; +col.boxWidth=parseInt(_501[0].style.width); +$(_4fc).datagrid("fixColumnSize",_500); +opts.onResizeColumn.call(_4fc,_500,col.width); +function _503(type){ +var _504=0; +opts.finder.getTr(_4fc,0,type).find("td[field=\""+_500+"\"] div.datagrid-cell").each(function(){ +var w=$(this)._outerWidth(); +if(_504b?1:-1); +}; +data.rows.sort(function(r1,r2){ +return _51e(r1[opts.sortName],r2[opts.sortName])*(opts.sortOrder=="asc"?1:-1); +}); +} +} +if(opts.view.onBeforeRender){ +opts.view.onBeforeRender.call(opts.view,_51c,data.rows); +} +opts.view.render.call(opts.view,_51c,dc.body2,false); +opts.view.render.call(opts.view,_51c,dc.body1,true); +if(opts.showFooter){ +opts.view.renderFooter.call(opts.view,_51c,dc.footer2,false); +opts.view.renderFooter.call(opts.view,_51c,dc.footer1,true); +} +if(opts.view.onAfterRender){ +opts.view.onAfterRender.call(opts.view,_51c); +} +_51d.ss.clean(); +opts.onLoadSuccess.call(_51c,data); +var _51f=$(_51c).datagrid("getPager"); +if(_51f.length){ +if(_51f.pagination("options").total!=data.total){ +_51f.pagination("refresh",{total:data.total}); +} +} +_4a9(_51c); +dc.body2.triggerHandler("scroll"); +_520(); +$(_51c).datagrid("autoSizeColumn"); +function _520(){ +if(opts.idField){ +for(var i=0;i_531.height()-18){ +_531.scrollTop(_531.scrollTop()+top+tr._outerHeight()-_531.height()+18); +} +} +} +}; +function _533(_534,_535){ +var _536=$.data(_534,"datagrid"); +var opts=_536.options; +opts.finder.getTr(_534,_536.highlightIndex).removeClass("datagrid-row-over"); +opts.finder.getTr(_534,_535).addClass("datagrid-row-over"); +_536.highlightIndex=_535; +}; +function _537(_538,_539,_53a){ +var _53b=$.data(_538,"datagrid"); +var dc=_53b.dc; +var opts=_53b.options; +var _53c=_53b.selectedRows; +if(opts.singleSelect){ +_53d(_538); +_53c.splice(0,_53c.length); +} +if(!_53a&&opts.checkOnSelect){ +_53e(_538,_539,true); +} +var row=opts.finder.getRow(_538,_539); +if(opts.idField){ +_48a(_53c,opts.idField,row); +} +opts.finder.getTr(_538,_539).addClass("datagrid-row-selected"); +opts.onSelect.call(_538,_539,row); +_52c(_538,_539); +}; +function _53f(_540,_541,_542){ +var _543=$.data(_540,"datagrid"); +var dc=_543.dc; +var opts=_543.options; +var _544=$.data(_540,"datagrid").selectedRows; +if(!_542&&opts.checkOnSelect){ +_545(_540,_541,true); +} +opts.finder.getTr(_540,_541).removeClass("datagrid-row-selected"); +var row=opts.finder.getRow(_540,_541); +if(opts.idField){ +_488(_544,opts.idField,row[opts.idField]); +} +opts.onUnselect.call(_540,_541,row); +}; +function _546(_547,_548){ +var _549=$.data(_547,"datagrid"); +var opts=_549.options; +var rows=_549.data.rows; +var _54a=$.data(_547,"datagrid").selectedRows; +if(!_548&&opts.checkOnSelect){ +_54b(_547,true); +} +opts.finder.getTr(_547,"","allbody").addClass("datagrid-row-selected"); +if(opts.idField){ +for(var _54c=0;_54c"); +cell.children("table").bind("click dblclick contextmenu",function(e){ +e.stopPropagation(); +}); +$.data(cell[0],"datagrid.editor",{actions:_581,target:_581.init(cell.find("td"),_580),field:_57e,type:_57f,oldHtml:_582}); +} +} +}); +_4a9(_57c,_57d,true); +}; +function _573(_584,_585){ +var opts=$.data(_584,"datagrid").options; +var tr=opts.finder.getTr(_584,_585); +tr.children("td").each(function(){ +var cell=$(this).find("div.datagrid-editable"); +if(cell.length){ +var ed=$.data(cell[0],"datagrid.editor"); +if(ed.actions.destroy){ +ed.actions.destroy(ed.target); +} +cell.html(ed.oldHtml); +$.removeData(cell[0],"datagrid.editor"); +cell.removeClass("datagrid-editable"); +cell.css("width",""); +} +}); +}; +function _568(_586,_587){ +var tr=$.data(_586,"datagrid").options.finder.getTr(_586,_587); +if(!tr.hasClass("datagrid-row-editing")){ +return true; +} +var vbox=tr.find(".validatebox-text"); +vbox.validatebox("validate"); +vbox.trigger("mouseleave"); +var _588=tr.find(".validatebox-invalid"); +return _588.length==0; +}; +function _589(_58a,_58b){ +var _58c=$.data(_58a,"datagrid").insertedRows; +var _58d=$.data(_58a,"datagrid").deletedRows; +var _58e=$.data(_58a,"datagrid").updatedRows; +if(!_58b){ +var rows=[]; +rows=rows.concat(_58c); +rows=rows.concat(_58d); +rows=rows.concat(_58e); +return rows; +}else{ +if(_58b=="inserted"){ +return _58c; +}else{ +if(_58b=="deleted"){ +return _58d; +}else{ +if(_58b=="updated"){ +return _58e; +} +} +} +} +return []; +}; +function _58f(_590,_591){ +var _592=$.data(_590,"datagrid"); +var opts=_592.options; +var data=_592.data; +var _593=_592.insertedRows; +var _594=_592.deletedRows; +$(_590).datagrid("cancelEdit",_591); +var row=data.rows[_591]; +if(_487(_593,row)>=0){ +_488(_593,row); +}else{ +_594.push(row); +} +_488(_592.selectedRows,opts.idField,data.rows[_591][opts.idField]); +_488(_592.checkedRows,opts.idField,data.rows[_591][opts.idField]); +opts.view.deleteRow.call(opts.view,_590,_591); +if(opts.height=="auto"){ +_4a9(_590); +} +$(_590).datagrid("getPager").pagination("refresh",{total:data.total}); +}; +function _595(_596,_597){ +var data=$.data(_596,"datagrid").data; +var view=$.data(_596,"datagrid").options.view; +var _598=$.data(_596,"datagrid").insertedRows; +view.insertRow.call(view,_596,_597.index,_597.row); +_598.push(_597.row); +$(_596).datagrid("getPager").pagination("refresh",{total:data.total}); +}; +function _599(_59a,row){ +var data=$.data(_59a,"datagrid").data; +var view=$.data(_59a,"datagrid").options.view; +var _59b=$.data(_59a,"datagrid").insertedRows; +view.insertRow.call(view,_59a,null,row); +_59b.push(row); +$(_59a).datagrid("getPager").pagination("refresh",{total:data.total}); +}; +function _59c(_59d){ +var _59e=$.data(_59d,"datagrid"); +var data=_59e.data; +var rows=data.rows; +var _59f=[]; +for(var i=0;i=0){ +(_5ac=="s"?_537:_53e)(_5a3,_5ad,true); +} +} +}; +for(var i=0;i0){ +_51b(this,data); +_59c(this); +} +} +_498(this); +_5b0(this); +_4db(this); +}); +}; +var _5be={text:{init:function(_5bf,_5c0){ +var _5c1=$("").appendTo(_5bf); +return _5c1; +},getValue:function(_5c2){ +return $(_5c2).val(); +},setValue:function(_5c3,_5c4){ +$(_5c3).val(_5c4); +},resize:function(_5c5,_5c6){ +$(_5c5)._outerWidth(_5c6); +}},textarea:{init:function(_5c7,_5c8){ +var _5c9=$("").appendTo(_5c7); +return _5c9; +},getValue:function(_5ca){ +return $(_5ca).val(); +},setValue:function(_5cb,_5cc){ +$(_5cb).val(_5cc); +},resize:function(_5cd,_5ce){ +$(_5cd)._outerWidth(_5ce); +}},checkbox:{init:function(_5cf,_5d0){ +var _5d1=$("").appendTo(_5cf); +_5d1.val(_5d0.on); +_5d1.attr("offval",_5d0.off); +return _5d1; +},getValue:function(_5d2){ +if($(_5d2).is(":checked")){ +return $(_5d2).val(); +}else{ +return $(_5d2).attr("offval"); +} +},setValue:function(_5d3,_5d4){ +var _5d5=false; +if($(_5d3).val()==_5d4){ +_5d5=true; +} +$(_5d3)._propAttr("checked",_5d5); +}},numberbox:{init:function(_5d6,_5d7){ +var _5d8=$("").appendTo(_5d6); +_5d8.numberbox(_5d7); +return _5d8; +},destroy:function(_5d9){ +$(_5d9).numberbox("destroy"); +},getValue:function(_5da){ +$(_5da).blur(); +return $(_5da).numberbox("getValue"); +},setValue:function(_5db,_5dc){ +$(_5db).numberbox("setValue",_5dc); +},resize:function(_5dd,_5de){ +$(_5dd)._outerWidth(_5de); +}},validatebox:{init:function(_5df,_5e0){ +var _5e1=$("").appendTo(_5df); +_5e1.validatebox(_5e0); +return _5e1; +},destroy:function(_5e2){ +$(_5e2).validatebox("destroy"); +},getValue:function(_5e3){ +return $(_5e3).val(); +},setValue:function(_5e4,_5e5){ +$(_5e4).val(_5e5); +},resize:function(_5e6,_5e7){ +$(_5e6)._outerWidth(_5e7); +}},datebox:{init:function(_5e8,_5e9){ +var _5ea=$("").appendTo(_5e8); +_5ea.datebox(_5e9); +return _5ea; +},destroy:function(_5eb){ +$(_5eb).datebox("destroy"); +},getValue:function(_5ec){ +return $(_5ec).datebox("getValue"); +},setValue:function(_5ed,_5ee){ +$(_5ed).datebox("setValue",_5ee); +},resize:function(_5ef,_5f0){ +$(_5ef).datebox("resize",_5f0); +}},combobox:{init:function(_5f1,_5f2){ +var _5f3=$("").appendTo(_5f1); +_5f3.combobox(_5f2||{}); +return _5f3; +},destroy:function(_5f4){ +$(_5f4).combobox("destroy"); +},getValue:function(_5f5){ +return $(_5f5).combobox("getValue"); +},setValue:function(_5f6,_5f7){ +$(_5f6).combobox("setValue",_5f7); +},resize:function(_5f8,_5f9){ +$(_5f8).combobox("resize",_5f9); +}},combotree:{init:function(_5fa,_5fb){ +var _5fc=$("").appendTo(_5fa); +_5fc.combotree(_5fb); +return _5fc; +},destroy:function(_5fd){ +$(_5fd).combotree("destroy"); +},getValue:function(_5fe){ +return $(_5fe).combotree("getValue"); +},setValue:function(_5ff,_600){ +$(_5ff).combotree("setValue",_600); +},resize:function(_601,_602){ +$(_601).combotree("resize",_602); +}}}; +$.fn.datagrid.methods={options:function(jq){ +var _603=$.data(jq[0],"datagrid").options; +var _604=$.data(jq[0],"datagrid").panel.panel("options"); +var opts=$.extend(_603,{width:_604.width,height:_604.height,closed:_604.closed,collapsed:_604.collapsed,minimized:_604.minimized,maximized:_604.maximized}); +return opts; +},getPanel:function(jq){ +return $.data(jq[0],"datagrid").panel; +},getPager:function(jq){ +return $.data(jq[0],"datagrid").panel.children("div.datagrid-pager"); +},getColumnFields:function(jq,_605){ +return _4d9(jq[0],_605); +},getColumnOption:function(jq,_606){ +return _4da(jq[0],_606); +},resize:function(jq,_607){ +return jq.each(function(){ +_498(this,_607); +}); +},load:function(jq,_608){ +return jq.each(function(){ +var opts=$(this).datagrid("options"); +opts.pageNumber=1; +var _609=$(this).datagrid("getPager"); +_609.pagination({pageNumber:1}); +_5b0(this,_608); +}); +},reload:function(jq,_60a){ +return jq.each(function(){ +_5b0(this,_60a); +}); +},reloadFooter:function(jq,_60b){ +return jq.each(function(){ +var opts=$.data(this,"datagrid").options; +var dc=$.data(this,"datagrid").dc; +if(_60b){ +$.data(this,"datagrid").footer=_60b; +} +if(opts.showFooter){ +opts.view.renderFooter.call(opts.view,this,dc.footer2,false); +opts.view.renderFooter.call(opts.view,this,dc.footer1,true); +if(opts.view.onAfterRender){ +opts.view.onAfterRender.call(opts.view,this); +} +$(this).datagrid("fixRowHeight"); +} +}); +},loading:function(jq){ +return jq.each(function(){ +var opts=$.data(this,"datagrid").options; +$(this).datagrid("getPager").pagination("loading"); +if(opts.loadMsg){ +var _60c=$(this).datagrid("getPanel"); +$("
            ").appendTo(_60c); +var msg=$("
            ").html(opts.loadMsg).appendTo(_60c); +msg.css("marginLeft",-msg.outerWidth()/2); +} +}); +},loaded:function(jq){ +return jq.each(function(){ +$(this).datagrid("getPager").pagination("loaded"); +var _60d=$(this).datagrid("getPanel"); +_60d.children("div.datagrid-mask-msg").remove(); +_60d.children("div.datagrid-mask").remove(); +}); +},fitColumns:function(jq){ +return jq.each(function(){ +_4ef(this); +}); +},fixColumnSize:function(jq,_60e){ +return jq.each(function(){ +_4c5(this,_60e); +}); +},fixRowHeight:function(jq,_60f){ +return jq.each(function(){ +_4a9(this,_60f); +}); +},freezeRow:function(jq,_610){ +return jq.each(function(){ +_4b6(this,_610); +}); +},autoSizeColumn:function(jq,_611){ +return jq.each(function(){ +_4fb(this,_611); +}); +},loadData:function(jq,data){ +return jq.each(function(){ +_51b(this,data); +_59c(this); +}); +},getData:function(jq){ +return $.data(jq[0],"datagrid").data; +},getRows:function(jq){ +return $.data(jq[0],"datagrid").data.rows; +},getFooterRows:function(jq){ +return $.data(jq[0],"datagrid").footer; +},getRowIndex:function(jq,id){ +return _522(jq[0],id); +},getChecked:function(jq){ +return _529(jq[0]); +},getSelected:function(jq){ +var rows=_525(jq[0]); +return rows.length>0?rows[0]:null; +},getSelections:function(jq){ +return _525(jq[0]); +},clearSelections:function(jq){ +return jq.each(function(){ +var _612=$.data(this,"datagrid").selectedRows; +_612.splice(0,_612.length); +_53d(this); +}); +},clearChecked:function(jq){ +return jq.each(function(){ +var _613=$.data(this,"datagrid").checkedRows; +_613.splice(0,_613.length); +_551(this); +}); +},scrollTo:function(jq,_614){ +return jq.each(function(){ +_52c(this,_614); +}); +},highlightRow:function(jq,_615){ +return jq.each(function(){ +_533(this,_615); +_52c(this,_615); +}); +},selectAll:function(jq){ +return jq.each(function(){ +_546(this); +}); +},unselectAll:function(jq){ +return jq.each(function(){ +_53d(this); +}); +},selectRow:function(jq,_616){ +return jq.each(function(){ +_537(this,_616); +}); +},selectRecord:function(jq,id){ +return jq.each(function(){ +var opts=$.data(this,"datagrid").options; +if(opts.idField){ +var _617=_522(this,id); +if(_617>=0){ +$(this).datagrid("selectRow",_617); +} +} +}); +},unselectRow:function(jq,_618){ +return jq.each(function(){ +_53f(this,_618); +}); +},checkRow:function(jq,_619){ +return jq.each(function(){ +_53e(this,_619); +}); +},uncheckRow:function(jq,_61a){ +return jq.each(function(){ +_545(this,_61a); +}); +},checkAll:function(jq){ +return jq.each(function(){ +_54b(this); +}); +},uncheckAll:function(jq){ +return jq.each(function(){ +_551(this); +}); +},beginEdit:function(jq,_61b){ +return jq.each(function(){ +_563(this,_61b); +}); +},endEdit:function(jq,_61c){ +return jq.each(function(){ +_569(this,_61c,false); +}); +},cancelEdit:function(jq,_61d){ +return jq.each(function(){ +_569(this,_61d,true); +}); +},getEditors:function(jq,_61e){ +return _574(jq[0],_61e); +},getEditor:function(jq,_61f){ +return _578(jq[0],_61f); +},refreshRow:function(jq,_620){ +return jq.each(function(){ +var opts=$.data(this,"datagrid").options; +opts.view.refreshRow.call(opts.view,this,_620); +}); +},validateRow:function(jq,_621){ +return _568(jq[0],_621); +},updateRow:function(jq,_622){ +return jq.each(function(){ +var opts=$.data(this,"datagrid").options; +opts.view.updateRow.call(opts.view,this,_622.index,_622.row); +}); +},appendRow:function(jq,row){ +return jq.each(function(){ +_599(this,row); +}); +},insertRow:function(jq,_623){ +return jq.each(function(){ +_595(this,_623); +}); +},deleteRow:function(jq,_624){ +return jq.each(function(){ +_58f(this,_624); +}); +},getChanges:function(jq,_625){ +return _589(jq[0],_625); +},acceptChanges:function(jq){ +return jq.each(function(){ +_5a0(this); +}); +},rejectChanges:function(jq){ +return jq.each(function(){ +_5a2(this); +}); +},mergeCells:function(jq,_626){ +return jq.each(function(){ +_5b6(this,_626); +}); +},showColumn:function(jq,_627){ +return jq.each(function(){ +var _628=$(this).datagrid("getPanel"); +_628.find("td[field=\""+_627+"\"]").show(); +$(this).datagrid("getColumnOption",_627).hidden=false; +$(this).datagrid("fitColumns"); +}); +},hideColumn:function(jq,_629){ +return jq.each(function(){ +var _62a=$(this).datagrid("getPanel"); +_62a.find("td[field=\""+_629+"\"]").hide(); +$(this).datagrid("getColumnOption",_629).hidden=true; +$(this).datagrid("fitColumns"); +}); +}}; +$.fn.datagrid.parseOptions=function(_62b){ +var t=$(_62b); +return $.extend({},$.fn.panel.parseOptions(_62b),$.parser.parseOptions(_62b,["url","toolbar","idField","sortName","sortOrder","pagePosition","resizeHandle",{fitColumns:"boolean",autoRowHeight:"boolean",striped:"boolean",nowrap:"boolean"},{rownumbers:"boolean",singleSelect:"boolean",checkOnSelect:"boolean",selectOnCheck:"boolean"},{pagination:"boolean",pageSize:"number",pageNumber:"number"},{remoteSort:"boolean",showHeader:"boolean",showFooter:"boolean"},{scrollbarSize:"number"}]),{pageList:(t.attr("pageList")?eval(t.attr("pageList")):undefined),loadMsg:(t.attr("loadMsg")!=undefined?t.attr("loadMsg"):undefined),rowStyler:(t.attr("rowStyler")?eval(t.attr("rowStyler")):undefined)}); +}; +$.fn.datagrid.parseData=function(_62c){ +var t=$(_62c); +var data={total:0,rows:[]}; +var _62d=t.datagrid("getColumnFields",true).concat(t.datagrid("getColumnFields",false)); +t.find("tbody tr").each(function(){ +data.total++; +var row={}; +$.extend(row,$.parser.parseOptions(this,["iconCls","state"])); +for(var i=0;i<_62d.length;i++){ +row[_62d[i]]=$(this).find("td:eq("+i+")").html(); +} +data.rows.push(row); +}); +return data; +}; +var _62e={render:function(_62f,_630,_631){ +var _632=$.data(_62f,"datagrid"); +var opts=_632.options; +var rows=_632.data.rows; +var _633=$(_62f).datagrid("getColumnFields",_631); +if(_631){ +if(!(opts.rownumbers||(opts.frozenColumns&&opts.frozenColumns.length))){ +return; +} +} +var _634=[""]; +for(var i=0;i"); +_634.push(this.renderRow.call(this,_62f,_633,_631,i,rows[i])); +_634.push(""); +} +_634.push("
            "); +$(_630).html(_634.join("")); +},renderFooter:function(_638,_639,_63a){ +var opts=$.data(_638,"datagrid").options; +var rows=$.data(_638,"datagrid").footer||[]; +var _63b=$(_638).datagrid("getColumnFields",_63a); +var _63c=[""]; +for(var i=0;i"); +_63c.push(this.renderRow.call(this,_638,_63b,_63a,i,rows[i])); +_63c.push(""); +} +_63c.push("
            "); +$(_639).html(_63c.join("")); +},renderRow:function(_63d,_63e,_63f,_640,_641){ +var opts=$.data(_63d,"datagrid").options; +var cc=[]; +if(_63f&&opts.rownumbers){ +var _642=_640+1; +if(opts.pagination){ +_642+=(opts.pageNumber-1)*opts.pageSize; +} +cc.push("
            "+_642+"
            "); +} +for(var i=0;i<_63e.length;i++){ +var _643=_63e[i]; +var col=$(_63d).datagrid("getColumnOption",_643); +if(col){ +var _644=_641[_643]; +var _645=col.styler?(col.styler(_644,_641,_640)||""):""; +var _646=col.hidden?"style=\"display:none;"+_645+"\"":(_645?"style=\""+_645+"\"":""); +cc.push(""); +if(col.checkbox){ +var _646=""; +}else{ +var _646=_645; +if(col.align){ +_646+=";text-align:"+col.align+";"; +} +if(!opts.nowrap){ +_646+=";white-space:normal;height:auto;"; +}else{ +if(opts.autoRowHeight){ +_646+=";height:auto;"; +} +} +} +cc.push("
            "); +if(col.checkbox){ +cc.push(""); +}else{ +if(col.formatter){ +cc.push(col.formatter(_644,_641,_640)); +}else{ +cc.push(_644); +} +} +cc.push("
            "); +cc.push(""); +} +} +return cc.join(""); +},refreshRow:function(_647,_648){ +this.updateRow.call(this,_647,_648,{}); +},updateRow:function(_649,_64a,row){ +var opts=$.data(_649,"datagrid").options; +var rows=$(_649).datagrid("getRows"); +$.extend(rows[_64a],row); +var _64b=opts.rowStyler?opts.rowStyler.call(_649,_64a,rows[_64a]):""; +function _64c(_64d){ +var _64e=$(_649).datagrid("getColumnFields",_64d); +var tr=opts.finder.getTr(_649,_64a,"body",(_64d?1:2)); +var _64f=tr.find("div.datagrid-cell-check input[type=checkbox]").is(":checked"); +tr.html(this.renderRow.call(this,_649,_64e,_64d,_64a,rows[_64a])); +tr.attr("style",_64b||""); +if(_64f){ +tr.find("div.datagrid-cell-check input[type=checkbox]")._propAttr("checked",true); +} +}; +_64c.call(this,true); +_64c.call(this,false); +$(_649).datagrid("fixRowHeight",_64a); +},insertRow:function(_650,_651,row){ +var _652=$.data(_650,"datagrid"); +var opts=_652.options; +var dc=_652.dc; +var data=_652.data; +if(_651==undefined||_651==null){ +_651=data.rows.length; +} +if(_651>data.rows.length){ +_651=data.rows.length; +} +function _653(_654){ +var _655=_654?1:2; +for(var i=data.rows.length-1;i>=_651;i--){ +var tr=opts.finder.getTr(_650,i,"body",_655); +tr.attr("datagrid-row-index",i+1); +tr.attr("id",_652.rowIdPrefix+"-"+_655+"-"+(i+1)); +if(_654&&opts.rownumbers){ +var _656=i+2; +if(opts.pagination){ +_656+=(opts.pageNumber-1)*opts.pageSize; +} +tr.find("div.datagrid-cell-rownumber").html(_656); +} +} +}; +function _657(_658){ +var _659=_658?1:2; +var _65a=$(_650).datagrid("getColumnFields",_658); +var _65b=_652.rowIdPrefix+"-"+_659+"-"+_651; +var tr=""; +if(_651>=data.rows.length){ +if(data.rows.length){ +opts.finder.getTr(_650,"","last",_659).after(tr); +}else{ +var cc=_658?dc.body1:dc.body2; +cc.html(""+tr+"
            "); +} +}else{ +opts.finder.getTr(_650,_651+1,"body",_659).before(tr); +} +}; +_653.call(this,true); +_653.call(this,false); +_657.call(this,true); +_657.call(this,false); +data.total+=1; +data.rows.splice(_651,0,row); +this.refreshRow.call(this,_650,_651); +},deleteRow:function(_65c,_65d){ +var _65e=$.data(_65c,"datagrid"); +var opts=_65e.options; +var data=_65e.data; +function _65f(_660){ +var _661=_660?1:2; +for(var i=_65d+1;itable>tbody>tr[datagrid-row-index="+_66c+"]"); +} +return tr; +}else{ +if(type=="footer"){ +return (_66d==1?dc.footer1:dc.footer2).find(">table>tbody>tr[datagrid-row-index="+_66c+"]"); +}else{ +if(type=="selected"){ +return (_66d==1?dc.body1:dc.body2).find(">table>tbody>tr.datagrid-row-selected"); +}else{ +if(type=="highlight"){ +return (_66d==1?dc.body1:dc.body2).find(">table>tbody>tr.datagrid-row-over"); +}else{ +if(type=="checked"){ +return (_66d==1?dc.body1:dc.body2).find(">table>tbody>tr.datagrid-row:has(div.datagrid-cell-check input:checked)"); +}else{ +if(type=="last"){ +return (_66d==1?dc.body1:dc.body2).find(">table>tbody>tr[datagrid-row-index]:last"); +}else{ +if(type=="allbody"){ +return (_66d==1?dc.body1:dc.body2).find(">table>tbody>tr[datagrid-row-index]"); +}else{ +if(type=="allfooter"){ +return (_66d==1?dc.footer1:dc.footer2).find(">table>tbody>tr[datagrid-row-index]"); +} +} +} +} +} +} +} +} +} +},getRow:function(_66f,p){ +var _670=(typeof p=="object")?p.attr("datagrid-row-index"):p; +return $.data(_66f,"datagrid").data.rows[parseInt(_670)]; +}},view:_62e,onBeforeLoad:function(_671){ +},onLoadSuccess:function(){ +},onLoadError:function(){ +},onClickRow:function(_672,_673){ +},onDblClickRow:function(_674,_675){ +},onClickCell:function(_676,_677,_678){ +},onDblClickCell:function(_679,_67a,_67b){ +},onSortColumn:function(sort,_67c){ +},onResizeColumn:function(_67d,_67e){ +},onSelect:function(_67f,_680){ +},onUnselect:function(_681,_682){ +},onSelectAll:function(rows){ +},onUnselectAll:function(rows){ +},onCheck:function(_683,_684){ +},onUncheck:function(_685,_686){ +},onCheckAll:function(rows){ +},onUncheckAll:function(rows){ +},onBeforeEdit:function(_687,_688){ +},onAfterEdit:function(_689,_68a,_68b){ +},onCancelEdit:function(_68c,_68d){ +},onHeaderContextMenu:function(e,_68e){ +},onRowContextMenu:function(e,_68f,_690){ +}}); +})(jQuery); +(function($){ +var _691; +function _692(_693){ +var _694=$.data(_693,"propertygrid"); +var opts=$.data(_693,"propertygrid").options; +$(_693).datagrid($.extend({},opts,{cls:"propertygrid",view:(opts.showGroup?_695:undefined),onClickRow:function(_696,row){ +if(_691!=this){ +_697(_691); +_691=this; +} +if(opts.editIndex!=_696&&row.editor){ +var col=$(this).datagrid("getColumnOption","value"); +col.editor=row.editor; +_697(_691); +$(this).datagrid("beginEdit",_696); +$(this).datagrid("getEditors",_696)[0].target.focus(); +opts.editIndex=_696; +} +opts.onClickRow.call(_693,_696,row); +},loadFilter:function(data){ +_697(this); +return opts.loadFilter.call(this,data); +},onLoadSuccess:function(data){ +$(_693).datagrid("getPanel").find("div.datagrid-group").attr("style",""); +opts.onLoadSuccess.call(_693,data); +}})); +$(document).unbind(".propertygrid").bind("mousedown.propertygrid",function(e){ +var p=$(e.target).closest("div.datagrid-view,div.combo-panel"); +if(p.length){ +return; +} +_697(_691); +_691=undefined; +}); +}; +function _697(_698){ +var t=$(_698); +if(!t.length){ +return; +} +var opts=$.data(_698,"propertygrid").options; +var _699=opts.editIndex; +if(_699==undefined){ +return; +} +var ed=t.datagrid("getEditors",_699)[0]; +if(ed){ +ed.target.blur(); +if(t.datagrid("validateRow",_699)){ +t.datagrid("endEdit",_699); +}else{ +t.datagrid("cancelEdit",_699); +} +} +opts.editIndex=undefined; +}; +$.fn.propertygrid=function(_69a,_69b){ +if(typeof _69a=="string"){ +var _69c=$.fn.propertygrid.methods[_69a]; +if(_69c){ +return _69c(this,_69b); +}else{ +return this.datagrid(_69a,_69b); +} +} +_69a=_69a||{}; +return this.each(function(){ +var _69d=$.data(this,"propertygrid"); +if(_69d){ +$.extend(_69d.options,_69a); +}else{ +var opts=$.extend({},$.fn.propertygrid.defaults,$.fn.propertygrid.parseOptions(this),_69a); +opts.frozenColumns=$.extend(true,[],opts.frozenColumns); +opts.columns=$.extend(true,[],opts.columns); +$.data(this,"propertygrid",{options:opts}); +} +_692(this); +}); +}; +$.fn.propertygrid.methods={options:function(jq){ +return $.data(jq[0],"propertygrid").options; +}}; +$.fn.propertygrid.parseOptions=function(_69e){ +var t=$(_69e); +return $.extend({},$.fn.datagrid.parseOptions(_69e),$.parser.parseOptions(_69e,[{showGroup:"boolean"}])); +}; +var _695=$.extend({},$.fn.datagrid.defaults.view,{render:function(_69f,_6a0,_6a1){ +var _6a2=$.data(_69f,"datagrid"); +var opts=_6a2.options; +var rows=_6a2.data.rows; +var _6a3=$(_69f).datagrid("getColumnFields",_6a1); +var _6a4=[]; +var _6a5=0; +var _6a6=this.groups; +for(var i=0;i<_6a6.length;i++){ +var _6a7=_6a6[i]; +_6a4.push("
            "); +_6a4.push(""); +_6a4.push(""); +_6a4.push(""); +_6a4.push(""); +_6a4.push("
            "); +if(!_6a1){ +_6a4.push(""); +_6a4.push(opts.groupFormatter.call(_69f,_6a7.fvalue,_6a7.rows)); +_6a4.push(""); +} +_6a4.push("
            "); +_6a4.push("
            "); +_6a4.push(""); +for(var j=0;j<_6a7.rows.length;j++){ +var cls=(_6a5%2&&opts.striped)?"class=\"datagrid-row datagrid-row-alt\"":"class=\"datagrid-row\""; +var _6a8=opts.rowStyler?opts.rowStyler.call(_69f,_6a5,_6a7.rows[j]):""; +var _6a9=_6a8?"style=\""+_6a8+"\"":""; +var _6aa=_6a2.rowIdPrefix+"-"+(_6a1?1:2)+"-"+_6a5; +_6a4.push(""); +_6a4.push(this.renderRow.call(this,_69f,_6a3,_6a1,_6a5,_6a7.rows[j])); +_6a4.push(""); +_6a5++; +} +_6a4.push("
            "); +} +$(_6a0).html(_6a4.join("")); +},onAfterRender:function(_6ab){ +var opts=$.data(_6ab,"datagrid").options; +var dc=$.data(_6ab,"datagrid").dc; +var view=dc.view; +var _6ac=dc.view1; +var _6ad=dc.view2; +$.fn.datagrid.defaults.view.onAfterRender.call(this,_6ab); +if(opts.rownumbers||opts.frozenColumns.length){ +var _6ae=_6ac.find("div.datagrid-group"); +}else{ +var _6ae=_6ad.find("div.datagrid-group"); +} +$(" ").insertBefore(_6ae.find("td")); +view.find("div.datagrid-group").each(function(){ +var _6af=$(this).attr("group-index"); +$(this).find("span.datagrid-row-expander").bind("click",{groupIndex:_6af},function(e){ +if($(this).hasClass("datagrid-row-collapse")){ +$(_6ab).datagrid("collapseGroup",e.data.groupIndex); +}else{ +$(_6ab).datagrid("expandGroup",e.data.groupIndex); +} +}); +}); +},onBeforeRender:function(_6b0,rows){ +var opts=$.data(_6b0,"datagrid").options; +var _6b1=[]; +for(var i=0;i"+""+"
            "+""+"").insertAfter(tr); +}; +}; +function _6ed(_6ee,_6ef,data,_6f0){ +var _6f1=$.data(_6ee,"treegrid"); +var opts=_6f1.options; +var dc=_6f1.dc; +data=opts.loadFilter.call(_6ee,data,_6ef); +var node=find(_6ee,_6ef); +if(node){ +var _6f2=opts.finder.getTr(_6ee,_6ef,"body",1); +var _6f3=opts.finder.getTr(_6ee,_6ef,"body",2); +var cc1=_6f2.next("tr.treegrid-tr-tree").children("td").children("div"); +var cc2=_6f3.next("tr.treegrid-tr-tree").children("td").children("div"); +if(!_6f0){ +node.children=[]; +} +}else{ +var cc1=dc.body1; +var cc2=dc.body2; +if(!_6f0){ +_6f1.data=[]; +} +} +if(!_6f0){ +cc1.empty(); +cc2.empty(); +} +if(opts.view.onBeforeRender){ +opts.view.onBeforeRender.call(opts.view,_6ee,_6ef,data); +} +opts.view.render.call(opts.view,_6ee,cc1,true); +opts.view.render.call(opts.view,_6ee,cc2,false); +if(opts.showFooter){ +opts.view.renderFooter.call(opts.view,_6ee,dc.footer1,true); +opts.view.renderFooter.call(opts.view,_6ee,dc.footer2,false); +} +if(opts.view.onAfterRender){ +opts.view.onAfterRender.call(opts.view,_6ee); +} +opts.onLoadSuccess.call(_6ee,node,data); +if(!_6ef&&opts.pagination){ +var _6f4=$.data(_6ee,"treegrid").total; +var _6f5=$(_6ee).datagrid("getPager"); +if(_6f5.pagination("options").total!=_6f4){ +_6f5.pagination({total:_6f4}); +} +} +_6d8(_6ee); +_6e0(_6ee); +$(_6ee).treegrid("autoSizeColumn"); +}; +function _6d7(_6f6,_6f7,_6f8,_6f9,_6fa){ +var opts=$.data(_6f6,"treegrid").options; +var body=$(_6f6).datagrid("getPanel").find("div.datagrid-body"); +if(_6f8){ +opts.queryParams=_6f8; +} +var _6fb=$.extend({},opts.queryParams); +if(opts.pagination){ +$.extend(_6fb,{page:opts.pageNumber,rows:opts.pageSize}); +} +if(opts.sortName){ +$.extend(_6fb,{sort:opts.sortName,order:opts.sortOrder}); +} +var row=find(_6f6,_6f7); +if(opts.onBeforeLoad.call(_6f6,row,_6fb)==false){ +return; +} +var _6fc=body.find("tr[node-id="+_6f7+"] span.tree-folder"); +_6fc.addClass("tree-loading"); +$(_6f6).treegrid("loading"); +var _6fd=opts.loader.call(_6f6,_6fb,function(data){ +_6fc.removeClass("tree-loading"); +$(_6f6).treegrid("loaded"); +_6ed(_6f6,_6f7,data,_6f9); +if(_6fa){ +_6fa(); +} +},function(){ +_6fc.removeClass("tree-loading"); +$(_6f6).treegrid("loaded"); +opts.onLoadError.apply(_6f6,arguments); +if(_6fa){ +_6fa(); +} +}); +if(_6fd==false){ +_6fc.removeClass("tree-loading"); +$(_6f6).treegrid("loaded"); +} +}; +function _6fe(_6ff){ +var rows=_700(_6ff); +if(rows.length){ +return rows[0]; +}else{ +return null; +} +}; +function _700(_701){ +return $.data(_701,"treegrid").data; +}; +function _702(_703,_704){ +var row=find(_703,_704); +if(row._parentId){ +return find(_703,row._parentId); +}else{ +return null; +} +}; +function _6dc(_705,_706){ +var opts=$.data(_705,"treegrid").options; +var body=$(_705).datagrid("getPanel").find("div.datagrid-view2 div.datagrid-body"); +var _707=[]; +if(_706){ +_708(_706); +}else{ +var _709=_700(_705); +for(var i=0;i<_709.length;i++){ +_707.push(_709[i]); +_708(_709[i][opts.idField]); +} +} +function _708(_70a){ +var _70b=find(_705,_70a); +if(_70b&&_70b.children){ +for(var i=0,len=_70b.children.length;i").insertBefore(_72f); +if(hit.prev().length){ +hit.prev().remove(); +} +} +} +_6ed(_72d,_72e.parent,_72e.data,true); +}; +function _730(_731,_732){ +var ref=_732.before||_732.after; +var opts=$.data(_731,"treegrid").options; +var _733=_702(_731,ref); +_72c(_731,{parent:(_733?_733[opts.idField]:null),data:[_732.data]}); +_734(true); +_734(false); +_6e0(_731); +function _734(_735){ +var _736=_735?1:2; +var tr=opts.finder.getTr(_731,_732.data[opts.idField],"body",_736); +var _737=tr.closest("table.datagrid-btable"); +tr=tr.parent().children(); +var dest=opts.finder.getTr(_731,ref,"body",_736); +if(_732.before){ +tr.insertBefore(dest); +}else{ +var sub=dest.next("tr.treegrid-tr-tree"); +tr.insertAfter(sub.length?sub:dest); +} +_737.remove(); +}; +}; +function _738(_739,_73a){ +var opts=$.data(_739,"treegrid").options; +var tr=opts.finder.getTr(_739,_73a); +tr.next("tr.treegrid-tr-tree").remove(); +tr.remove(); +var _73b=del(_73a); +if(_73b){ +if(_73b.children.length==0){ +tr=opts.finder.getTr(_739,_73b[opts.idField]); +tr.next("tr.treegrid-tr-tree").remove(); +var cell=tr.children("td[field="+opts.treeField+"]").children("div.datagrid-cell"); +cell.find(".tree-icon").removeClass("tree-folder").addClass("tree-file"); +cell.find(".tree-hit").remove(); +$("").prependTo(cell); +} +} +_6e0(_739); +function del(id){ +var cc; +var _73c=_702(_739,_73a); +if(_73c){ +cc=_73c.children; +}else{ +cc=$(_739).treegrid("getData"); +} +for(var i=0;i"]; +for(var i=0;i<_753.length;i++){ +var row=_753[i]; +if(row.state!="open"&&row.state!="closed"){ +row.state="open"; +} +var cls=(_74e++%2&&opts.striped)?"class=\"datagrid-row datagrid-row-alt\"":"class=\"datagrid-row\""; +var _755=opts.rowStyler?opts.rowStyler.call(_749,row):""; +var _756=_755?"style=\""+_755+"\"":""; +var _757=_74d+"-"+(_751?1:2)+"-"+row[opts.idField]; +_754.push(""); +_754=_754.concat(view.renderRow.call(view,_749,_74c,_751,_752,row)); +_754.push(""); +if(row.children&&row.children.length){ +var tt=_750(_751,_752+1,row.children); +var v=row.state=="closed"?"none":"block"; +_754.push("
            "); +_754=_754.concat(tt); +_754.push("
            "); +} +} +_754.push(""); +return _754; +}; +},renderFooter:function(_758,_759,_75a){ +var opts=$.data(_758,"treegrid").options; +var rows=$.data(_758,"treegrid").footer||[]; +var _75b=$(_758).datagrid("getColumnFields",_75a); +var _75c=[""]; +for(var i=0;i"); +_75c.push(this.renderRow.call(this,_758,_75b,_75a,0,row)); +_75c.push(""); +} +_75c.push("
            "); +$(_759).html(_75c.join("")); +},renderRow:function(_75d,_75e,_75f,_760,row){ +var opts=$.data(_75d,"treegrid").options; +var cc=[]; +if(_75f&&opts.rownumbers){ +cc.push("
            0
            "); +} +for(var i=0;i<_75e.length;i++){ +var _761=_75e[i]; +var col=$(_75d).datagrid("getColumnOption",_761); +if(col){ +var _762=col.styler?(col.styler(row[_761],row)||""):""; +var _763=col.hidden?"style=\"display:none;"+_762+"\"":(_762?"style=\""+_762+"\"":""); +cc.push(""); +if(col.checkbox){ +var _763=""; +}else{ +var _763=_762; +if(col.align){ +_763+=";text-align:"+col.align+";"; +} +if(!opts.nowrap){ +_763+=";white-space:normal;height:auto;"; +}else{ +if(opts.autoRowHeight){ +_763+=";height:auto;"; +} +} +} +cc.push("
            "); +if(col.checkbox){ +if(row.checked){ +cc.push(""); +}else{ +var val=null; +if(col.formatter){ +val=col.formatter(row[_761],row); +}else{ +val=row[_761]; +} +if(_761==opts.treeField){ +for(var j=0;j<_760;j++){ +cc.push(""); +} +if(row.state=="closed"){ +cc.push(""); +cc.push(""); +}else{ +if(row.children&&row.children.length){ +cc.push(""); +cc.push(""); +}else{ +cc.push(""); +cc.push(""); +} +} +cc.push(""+val+""); +}else{ +cc.push(val); +} +} +cc.push("
            "); +cc.push(""); +} +} +return cc.join(""); +},refreshRow:function(_764,id){ +this.updateRow.call(this,_764,id,{}); +},updateRow:function(_765,id,row){ +var opts=$.data(_765,"treegrid").options; +var _766=$(_765).treegrid("find",id); +$.extend(_766,row); +var _767=$(_765).treegrid("getLevel",id)-1; +var _768=opts.rowStyler?opts.rowStyler.call(_765,_766):""; +function _769(_76a){ +var _76b=$(_765).treegrid("getColumnFields",_76a); +var tr=opts.finder.getTr(_765,id,"body",(_76a?1:2)); +var _76c=tr.find("div.datagrid-cell-rownumber").html(); +var _76d=tr.find("div.datagrid-cell-check input[type=checkbox]").is(":checked"); +tr.html(this.renderRow(_765,_76b,_76a,_767,_766)); +tr.attr("style",_768||""); +tr.find("div.datagrid-cell-rownumber").html(_76c); +if(_76d){ +tr.find("div.datagrid-cell-check input[type=checkbox]")._propAttr("checked",true); +} +}; +_769.call(this,true); +_769.call(this,false); +$(_765).treegrid("fixRowHeight",id); +},onBeforeRender:function(_76e,_76f,data){ +if($.isArray(_76f)){ +data={total:_76f.length,rows:_76f}; +_76f=null; +} +if(!data){ +return false; +} +var _770=$.data(_76e,"treegrid"); +var opts=_770.options; +if(data.length==undefined){ +if(data.footer){ +_770.footer=data.footer; +} +if(data.total){ +_770.total=data.total; +} +data=this.transfer(_76e,_76f,data.rows); +}else{ +function _771(_772,_773){ +for(var i=0;i<_772.length;i++){ +var row=_772[i]; +row._parentId=_773; +if(row.children&&row.children.length){ +_771(row.children,row[opts.idField]); +} +} +}; +_771(data,_76f); +} +var node=find(_76e,_76f); +if(node){ +if(node.children){ +node.children=node.children.concat(data); +}else{ +node.children=data; +} +}else{ +_770.data=_770.data.concat(data); +} +if(!opts.remoteSort){ +this.sort(_76e,data); +} +this.treeNodes=data; +this.treeLevel=$(_76e).treegrid("getLevel",_76f); +},sort:function(_774,data){ +var opts=$.data(_774,"treegrid").options; +var opt=$(_774).treegrid("getColumnOption",opts.sortName); +if(opt){ +var _775=opt.sorter||function(a,b){ +return (a>b?1:-1); +}; +_776(data); +} +function _776(rows){ +rows.sort(function(r1,r2){ +return _775(r1[opts.sortName],r2[opts.sortName])*(opts.sortOrder=="asc"?1:-1); +}); +for(var i=0;i").insertAfter(_78e); +var _78f=$("").appendTo(span); +$("").appendTo(span); +$("").appendTo(span); +var _790=$("
            ").appendTo("body"); +_790.panel({doSize:false,closed:true,cls:"combo-p",style:{position:"absolute",zIndex:10},onOpen:function(){ +$(this).panel("resize"); +},onClose:function(){ +var _791=$.data(_78e,"combo"); +if(_791){ +_791.options.onHidePanel.call(_78e); +} +}}); +var name=$(_78e).attr("name"); +if(name){ +span.find("input.combo-value").attr("name",name); +$(_78e).removeAttr("name").attr("comboName",name); +} +_78f.attr("autocomplete","off"); +return {combo:span,panel:_790}; +}; +function _792(_793){ +var _794=$.data(_793,"combo"); +var opts=_794.options; +var _795=_794.combo; +if(opts.hasDownArrow){ +_795.find(".combo-arrow").show(); +}else{ +_795.find(".combo-arrow").hide(); +} +_796(_793,opts.disabled); +_797(_793,opts.readonly); +}; +function _798(_799){ +var _79a=$.data(_799,"combo"); +var _79b=_79a.combo.find("input.combo-text"); +_79b.validatebox("destroy"); +_79a.panel.panel("destroy"); +_79a.combo.remove(); +$(_799).remove(); +}; +function _79c(_79d){ +var _79e=$.data(_79d,"combo"); +var opts=_79e.options; +var _79f=_79e.panel; +var _7a0=_79e.combo; +var _7a1=_7a0.find(".combo-text"); +var _7a2=_7a0.find(".combo-arrow"); +$(document).unbind(".combo").bind("mousedown.combo",function(e){ +var p=$(e.target).closest("span.combo,div.combo-panel"); +if(p.length){ +return; +} +$("body>div.combo-p>div.combo-panel:visible").panel("close"); +}); +_7a1.unbind(".combo"); +_7a2.unbind(".combo"); +if(!opts.disabled&&!opts.readonly){ +_7a1.bind("mousedown.combo",function(e){ +$("div.combo-panel").not(_79f).panel("close"); +e.stopPropagation(); +}).bind("keydown.combo",function(e){ +switch(e.keyCode){ +case 38: +opts.keyHandler.up.call(_79d); +break; +case 40: +opts.keyHandler.down.call(_79d); +break; +case 13: +e.preventDefault(); +opts.keyHandler.enter.call(_79d); +return false; +case 9: +case 27: +_7a9(_79d); +break; +default: +if(opts.editable){ +if(_79e.timer){ +clearTimeout(_79e.timer); +} +_79e.timer=setTimeout(function(){ +var q=_7a1.val(); +if(_79e.previousValue!=q){ +_79e.previousValue=q; +$(_79d).combo("showPanel"); +opts.keyHandler.query.call(_79d,_7a1.val()); +_7ac(_79d,true); +} +},opts.delay); +} +} +}); +_7a2.bind("click.combo",function(){ +if(_79f.is(":visible")){ +_7a9(_79d); +}else{ +$("div.combo-panel:visible").panel("close"); +$(_79d).combo("showPanel"); +} +_7a1.focus(); +}).bind("mouseenter.combo",function(){ +$(this).addClass("combo-arrow-hover"); +}).bind("mouseleave.combo",function(){ +$(this).removeClass("combo-arrow-hover"); +}); +} +}; +function _7a3(_7a4){ +var opts=$.data(_7a4,"combo").options; +var _7a5=$.data(_7a4,"combo").combo; +var _7a6=$.data(_7a4,"combo").panel; +if($.fn.window){ +_7a6.panel("panel").css("z-index",$.fn.window.defaults.zIndex++); +} +_7a6.panel("move",{left:_7a5.offset().left,top:_7a7()}); +if(_7a6.panel("options").closed){ +_7a6.panel("open"); +opts.onShowPanel.call(_7a4); +} +(function(){ +if(_7a6.is(":visible")){ +_7a6.panel("move",{left:_7a8(),top:_7a7()}); +setTimeout(arguments.callee,200); +} +})(); +function _7a8(){ +var left=_7a5.offset().left; +if(left+_7a6._outerWidth()>$(window)._outerWidth()+$(document).scrollLeft()){ +left=$(window)._outerWidth()+$(document).scrollLeft()-_7a6._outerWidth(); +} +if(left<0){ +left=0; +} +return left; +}; +function _7a7(){ +var top=_7a5.offset().top+_7a5._outerHeight(); +if(top+_7a6._outerHeight()>$(window)._outerHeight()+$(document).scrollTop()){ +top=_7a5.offset().top-_7a6._outerHeight(); +} +if(top<$(document).scrollTop()){ +top=_7a5.offset().top+_7a5._outerHeight(); +} +return top; +}; +}; +function _7a9(_7aa){ +var _7ab=$.data(_7aa,"combo").panel; +_7ab.panel("close"); +}; +function _7ac(_7ad,doit){ +var opts=$.data(_7ad,"combo").options; +var _7ae=$.data(_7ad,"combo").combo.find("input.combo-text"); +_7ae.validatebox($.extend({},opts,{deltaX:(opts.hasDownArrow?opts.deltaX:(opts.deltaX>0?1:-1))})); +if(doit){ +_7ae.validatebox("validate"); +} +}; +function _796(_7af,_7b0){ +var _7b1=$.data(_7af,"combo"); +var opts=_7b1.options; +var _7b2=_7b1.combo; +if(_7b0){ +opts.disabled=true; +$(_7af).attr("disabled",true); +_7b2.find(".combo-value").attr("disabled",true); +_7b2.find(".combo-text").attr("disabled",true); +}else{ +opts.disabled=false; +$(_7af).removeAttr("disabled"); +_7b2.find(".combo-value").removeAttr("disabled"); +_7b2.find(".combo-text").removeAttr("disabled"); +} +}; +function _797(_7b3,mode){ +var _7b4=$.data(_7b3,"combo"); +var opts=_7b4.options; +opts.readonly=mode==undefined?true:mode; +_7b4.combo.find(".combo-text").attr("readonly",opts.readonly?true:(!opts.editable)); +}; +function _7b5(_7b6){ +var _7b7=$.data(_7b6,"combo"); +var opts=_7b7.options; +var _7b8=_7b7.combo; +if(opts.multiple){ +_7b8.find("input.combo-value").remove(); +}else{ +_7b8.find("input.combo-value").val(""); +} +_7b8.find("input.combo-text").val(""); +}; +function _7b9(_7ba){ +var _7bb=$.data(_7ba,"combo").combo; +return _7bb.find("input.combo-text").val(); +}; +function _7bc(_7bd,text){ +var _7be=$.data(_7bd,"combo").combo; +_7be.find("input.combo-text").val(text); +_7ac(_7bd,true); +$.data(_7bd,"combo").previousValue=text; +}; +function _7bf(_7c0){ +var _7c1=[]; +var _7c2=$.data(_7c0,"combo").combo; +_7c2.find("input.combo-value").each(function(){ +_7c1.push($(this).val()); +}); +return _7c1; +}; +function _7c3(_7c4,_7c5){ +var opts=$.data(_7c4,"combo").options; +var _7c6=_7bf(_7c4); +var _7c7=$.data(_7c4,"combo").combo; +_7c7.find("input.combo-value").remove(); +var name=$(_7c4).attr("comboName"); +for(var i=0;i<_7c5.length;i++){ +var _7c8=$("").appendTo(_7c7); +if(name){ +_7c8.attr("name",name); +} +_7c8.val(_7c5[i]); +} +var tmp=[]; +for(var i=0;i<_7c6.length;i++){ +tmp[i]=_7c6[i]; +} +var aa=[]; +for(var i=0;i<_7c5.length;i++){ +for(var j=0;j_7e0.height()){ +var h=_7e0.scrollTop()+item.position().top+item.outerHeight()-_7e0.height(); +_7e0.scrollTop(h); +} +} +} +}; +function nav(_7e1,dir){ +var opts=$(_7e1).combobox("options"); +var _7e2=$(_7e1).combobox("panel"); +var item=_7e2.children("div.combobox-item-hover"); +if(!item.length){ +item=_7e2.children("div.combobox-item-selected"); +} +item.removeClass("combobox-item-hover"); +if(!item.length){ +item=_7e2.children("div.combobox-item:visible:"+(dir=="next"?"first":"last")); +}else{ +if(dir=="next"){ +item=item.nextAll(":visible:first"); +if(!item.length){ +item=_7e2.children("div.combobox-item:visible:first"); +} +}else{ +item=item.prevAll(":visible:first"); +if(!item.length){ +item=_7e2.children("div.combobox-item:visible:last"); +} +} +} +if(item.length){ +item.addClass("combobox-item-hover"); +_7dd(_7e1,item.attr("value")); +if(opts.selectOnNavigation){ +_7e3(_7e1,item.attr("value")); +} +} +}; +function _7e3(_7e4,_7e5){ +var opts=$.data(_7e4,"combobox").options; +var data=$.data(_7e4,"combobox").data; +if(opts.multiple){ +var _7e6=$(_7e4).combo("getValues"); +for(var i=0;i<_7e6.length;i++){ +if(_7e6[i]==_7e5){ +return; +} +} +_7e6.push(_7e5); +_7e7(_7e4,_7e6); +}else{ +_7e7(_7e4,[_7e5]); +} +var item=_7db(data,opts.valueField,_7e5); +if(item){ +opts.onSelect.call(_7e4,item); +} +}; +function _7e8(_7e9,_7ea){ +var _7eb=$.data(_7e9,"combobox"); +var opts=_7eb.options; +var _7ec=$(_7e9).combo("getValues"); +var _7ed=_7ec.indexOf(_7ea+""); +if(_7ed>=0){ +_7ec.splice(_7ed,1); +_7e7(_7e9,_7ec); +} +var item=_7db(_7eb.data,opts.valueField,_7ea); +if(item){ +opts.onUnselect.call(_7e9,item); +} +}; +function _7e7(_7ee,_7ef,_7f0){ +var opts=$.data(_7ee,"combobox").options; +var data=$.data(_7ee,"combobox").data; +var _7f1=$(_7ee).combo("panel"); +_7f1.find("div.combobox-item-selected").removeClass("combobox-item-selected"); +var vv=[],ss=[]; +for(var i=0;i<_7ef.length;i++){ +var v=_7ef[i]; +var s=v; +var item=_7db(data,opts.valueField,v); +if(item){ +s=item[opts.textField]; +} +vv.push(v); +ss.push(s); +_7f1.find("div.combobox-item[value=\""+v+"\"]").addClass("combobox-item-selected"); +} +$(_7ee).combo("setValues",vv); +if(!_7f0){ +$(_7ee).combo("setText",ss.join(opts.separator)); +} +}; +function _7f2(_7f3,data,_7f4){ +var opts=$.data(_7f3,"combobox").options; +var _7f5=$(_7f3).combo("panel"); +data=opts.loadFilter.call(_7f3,data); +$.data(_7f3,"combobox").data=data; +var _7f6=$(_7f3).combobox("getValues"); +_7f5.empty(); +for(var i=0;i
            ").appendTo(_7f5); +item.attr("value",v); +if(opts.formatter){ +item.html(opts.formatter.call(_7f3,data[i])); +}else{ +item.html(s); +} +if(data[i]["selected"]){ +(function(){ +for(var i=0;i<_7f6.length;i++){ +if(v==_7f6[i]){ +return; +} +} +_7f6.push(v); +})(); +} +} +if(opts.multiple){ +_7e7(_7f3,_7f6,_7f4); +}else{ +if(_7f6.length){ +_7e7(_7f3,[_7f6[_7f6.length-1]],_7f4); +}else{ +_7e7(_7f3,[],_7f4); +} +} +opts.onLoadSuccess.call(_7f3,data); +}; +function _7f7(_7f8,url,_7f9,_7fa){ +var opts=$.data(_7f8,"combobox").options; +if(url){ +opts.url=url; +} +_7f9=_7f9||{}; +if(opts.onBeforeLoad.call(_7f8,_7f9)==false){ +return; +} +opts.loader.call(_7f8,_7f9,function(data){ +_7f2(_7f8,data,_7fa); +},function(){ +opts.onLoadError.apply(this,arguments); +}); +}; +function _7fb(_7fc,q){ +var opts=$.data(_7fc,"combobox").options; +if(opts.multiple&&!q){ +_7e7(_7fc,[],true); +}else{ +_7e7(_7fc,[q],true); +} +if(opts.mode=="remote"){ +_7f7(_7fc,null,{q:q},true); +}else{ +var _7fd=$(_7fc).combo("panel"); +_7fd.find("div.combobox-item").hide(); +var data=$.data(_7fc,"combobox").data; +for(var i=0;i").appendTo(_819); +$.data(_818,"combotree").tree=tree; +} +tree.tree($.extend({},opts,{checkbox:opts.multiple,onLoadSuccess:function(node,data){ +var _81a=$(_818).combotree("getValues"); +if(opts.multiple){ +var _81b=tree.tree("getChecked"); +for(var i=0;i<_81b.length;i++){ +var id=_81b[i].id; +(function(){ +for(var i=0;i<_81a.length;i++){ +if(id==_81a[i]){ +return; +} +} +_81a.push(id); +})(); +} +} +$(_818).combotree("setValues",_81a); +opts.onLoadSuccess.call(this,node,data); +},onClick:function(node){ +_81d(_818); +$(_818).combo("hidePanel"); +opts.onClick.call(this,node); +},onCheck:function(node,_81c){ +_81d(_818); +opts.onCheck.call(this,node,_81c); +}})); +}; +function _81d(_81e){ +var opts=$.data(_81e,"combotree").options; +var tree=$.data(_81e,"combotree").tree; +var vv=[],ss=[]; +if(opts.multiple){ +var _81f=tree.tree("getChecked"); +for(var i=0;i<_81f.length;i++){ +vv.push(_81f[i].id); +ss.push(_81f[i].text); +} +}else{ +var node=tree.tree("getSelected"); +if(node){ +vv.push(node.id); +ss.push(node.text); +} +} +$(_81e).combo("setValues",vv).combo("setText",ss.join(opts.separator)); +}; +function _820(_821,_822){ +var opts=$.data(_821,"combotree").options; +var tree=$.data(_821,"combotree").tree; +tree.find("span.tree-checkbox").addClass("tree-checkbox0").removeClass("tree-checkbox1 tree-checkbox2"); +var vv=[],ss=[]; +for(var i=0;i<_822.length;i++){ +var v=_822[i]; +var s=v; +var node=tree.tree("find",v); +if(node){ +s=node.text; +tree.tree("check",node.target); +tree.tree("select",node.target); +} +vv.push(v); +ss.push(s); +} +$(_821).combo("setValues",vv).combo("setText",ss.join(opts.separator)); +}; +$.fn.combotree=function(_823,_824){ +if(typeof _823=="string"){ +var _825=$.fn.combotree.methods[_823]; +if(_825){ +return _825(this,_824); +}else{ +return this.combo(_823,_824); +} +} +_823=_823||{}; +return this.each(function(){ +var _826=$.data(this,"combotree"); +if(_826){ +$.extend(_826.options,_823); +}else{ +$.data(this,"combotree",{options:$.extend({},$.fn.combotree.defaults,$.fn.combotree.parseOptions(this),_823)}); +} +_817(this); +}); +}; +$.fn.combotree.methods={options:function(jq){ +var _827=jq.combo("options"); +return $.extend($.data(jq[0],"combotree").options,{originalValue:_827.originalValue,disabled:_827.disabled,readonly:_827.readonly}); +},tree:function(jq){ +return $.data(jq[0],"combotree").tree; +},loadData:function(jq,data){ +return jq.each(function(){ +var opts=$.data(this,"combotree").options; +opts.data=data; +var tree=$.data(this,"combotree").tree; +tree.tree("loadData",data); +}); +},reload:function(jq,url){ +return jq.each(function(){ +var opts=$.data(this,"combotree").options; +var tree=$.data(this,"combotree").tree; +if(url){ +opts.url=url; +} +tree.tree({url:opts.url}); +}); +},setValues:function(jq,_828){ +return jq.each(function(){ +_820(this,_828); +}); +},setValue:function(jq,_829){ +return jq.each(function(){ +_820(this,[_829]); +}); +},clear:function(jq){ +return jq.each(function(){ +var tree=$.data(this,"combotree").tree; +tree.find("div.tree-node-selected").removeClass("tree-node-selected"); +var cc=tree.tree("getChecked"); +for(var i=0;i").appendTo(_82e); +_82d.grid=grid; +} +grid.datagrid($.extend({},opts,{border:false,fit:true,singleSelect:(!opts.multiple),onLoadSuccess:function(data){ +var _82f=$(_82c).combo("getValues"); +var _830=opts.onSelect; +opts.onSelect=function(){ +}; +_83a(_82c,_82f,_82d.remainText); +opts.onSelect=_830; +opts.onLoadSuccess.apply(_82c,arguments); +},onClickRow:_831,onSelect:function(_832,row){ +_833(); +opts.onSelect.call(this,_832,row); +},onUnselect:function(_834,row){ +_833(); +opts.onUnselect.call(this,_834,row); +},onSelectAll:function(rows){ +_833(); +opts.onSelectAll.call(this,rows); +},onUnselectAll:function(rows){ +if(opts.multiple){ +_833(); +} +opts.onUnselectAll.call(this,rows); +}})); +function _831(_835,row){ +_82d.remainText=false; +_833(); +if(!opts.multiple){ +$(_82c).combo("hidePanel"); +} +opts.onClickRow.call(this,_835,row); +}; +function _833(){ +var rows=grid.datagrid("getSelections"); +var vv=[],ss=[]; +for(var i=0;i=_838){ +_839=0; +} +} +grid.datagrid("highlightRow",_839); +if(opts.selectOnNavigation){ +_837.remainText=false; +grid.datagrid("selectRow",_839); +} +}; +function _83a(_83b,_83c,_83d){ +var _83e=$.data(_83b,"combogrid"); +var opts=_83e.options; +var grid=_83e.grid; +var rows=grid.datagrid("getRows"); +var ss=[]; +var _83f=$(_83b).combo("getValues"); +var _840=$(_83b).combo("options"); +var _841=_840.onChange; +_840.onChange=function(){ +}; +grid.datagrid("clearSelections"); +for(var i=0;i<_83c.length;i++){ +var _842=grid.datagrid("getRowIndex",_83c[i]); +if(_842>=0){ +grid.datagrid("selectRow",_842); +ss.push(rows[_842][opts.textField]); +}else{ +ss.push(_83c[i]); +} +} +$(_83b).combo("setValues",_83f); +_840.onChange=_841; +$(_83b).combo("setValues",_83c); +if(!_83d){ +var s=ss.join(opts.separator); +if($(_83b).combo("getText")!=s){ +$(_83b).combo("setText",s); +} +} +}; +function _843(_844,q){ +var _845=$.data(_844,"combogrid"); +var opts=_845.options; +var grid=_845.grid; +_845.remainText=true; +if(opts.multiple&&!q){ +_83a(_844,[],true); +}else{ +_83a(_844,[q],true); +} +if(opts.mode=="remote"){ +grid.datagrid("clearSelections"); +grid.datagrid("load",$.extend({},opts.queryParams,{q:q})); +}else{ +if(!q){ +return; +} +var rows=grid.datagrid("getRows"); +for(var i=0;i
            ").appendTo(_856).wrap("
            "); +_854.calendar.calendar({fit:true,border:false,onSelect:function(date){ +var _857=opts.formatter(date); +_85b(_853,_857); +$(_853).combo("hidePanel"); +opts.onSelect.call(_853,date); +}}); +_85b(_853,opts.value); +var _858=$("
            ").appendTo(_856); +$("").html(opts.currentText).appendTo(_858); +$("").html(opts.closeText).appendTo(_858); +_858.find(".datebox-current,.datebox-close").hover(function(){ +$(this).addClass("datebox-button-hover"); +},function(){ +$(this).removeClass("datebox-button-hover"); +}); +_858.find(".datebox-current").click(function(){ +_854.calendar.calendar({year:new Date().getFullYear(),month:new Date().getMonth()+1,current:new Date()}); +}); +_858.find(".datebox-close").click(function(){ +$(_853).combo("hidePanel"); +}); +}; +}; +function _859(_85a,q){ +_85b(_85a,q); +}; +function _85c(_85d){ +var opts=$.data(_85d,"datebox").options; +var c=$.data(_85d,"datebox").calendar; +var _85e=opts.formatter(c.calendar("options").current); +_85b(_85d,_85e); +$(_85d).combo("hidePanel"); +}; +function _85b(_85f,_860){ +var _861=$.data(_85f,"datebox"); +var opts=_861.options; +$(_85f).combo("setValue",_860).combo("setText",_860); +_861.calendar.calendar("moveTo",opts.parser(_860)); +}; +$.fn.datebox=function(_862,_863){ +if(typeof _862=="string"){ +var _864=$.fn.datebox.methods[_862]; +if(_864){ +return _864(this,_863); +}else{ +return this.combo(_862,_863); +} +} +_862=_862||{}; +return this.each(function(){ +var _865=$.data(this,"datebox"); +if(_865){ +$.extend(_865.options,_862); +}else{ +$.data(this,"datebox",{options:$.extend({},$.fn.datebox.defaults,$.fn.datebox.parseOptions(this),_862)}); +} +_852(this); +}); +}; +$.fn.datebox.methods={options:function(jq){ +var _866=jq.combo("options"); +return $.extend($.data(jq[0],"datebox").options,{originalValue:_866.originalValue,disabled:_866.disabled,readonly:_866.readonly}); +},calendar:function(jq){ +return $.data(jq[0],"datebox").calendar; +},setValue:function(jq,_867){ +return jq.each(function(){ +_85b(this,_867); +}); +},reset:function(jq){ +return jq.each(function(){ +var opts=$(this).datebox("options"); +$(this).datebox("setValue",opts.originalValue); +}); +}}; +$.fn.datebox.parseOptions=function(_868){ +var t=$(_868); +return $.extend({},$.fn.combo.parseOptions(_868),{}); +}; +$.fn.datebox.defaults=$.extend({},$.fn.combo.defaults,{panelWidth:180,panelHeight:"auto",keyHandler:{up:function(){ +},down:function(){ +},enter:function(){ +_85c(this); +},query:function(q){ +_859(this,q); +}},currentText:"Today",closeText:"Close",okText:"Ok",formatter:function(date){ +var y=date.getFullYear(); +var m=date.getMonth()+1; +var d=date.getDate(); +return m+"/"+d+"/"+y; +},parser:function(s){ +var t=Date.parse(s); +if(!isNaN(t)){ +return new Date(t); +}else{ +return new Date(); +} +},onSelect:function(date){ +}}); +})(jQuery); +(function($){ +function _869(_86a){ +var _86b=$.data(_86a,"datetimebox"); +var opts=_86b.options; +$(_86a).datebox($.extend({},opts,{onShowPanel:function(){ +var _86c=$(_86a).datetimebox("getValue"); +_86f(_86a,_86c,true); +opts.onShowPanel.call(_86a); +},formatter:$.fn.datebox.defaults.formatter,parser:$.fn.datebox.defaults.parser})); +$(_86a).removeClass("datebox-f").addClass("datetimebox-f"); +$(_86a).datebox("calendar").calendar({onSelect:function(date){ +opts.onSelect.call(_86a,date); +}}); +var _86d=$(_86a).datebox("panel"); +if(!_86b.spinner){ +var p=$("
            ").insertAfter(_86d.children("div.datebox-calendar-inner")); +_86b.spinner=p.children("input"); +var _86e=_86d.children("div.datebox-button"); +var ok=$("").html(opts.okText).appendTo(_86e); +ok.hover(function(){ +$(this).addClass("datebox-button-hover"); +},function(){ +$(this).removeClass("datebox-button-hover"); +}).click(function(){ +_874(_86a); +}); +} +_86b.spinner.timespinner({showSeconds:opts.showSeconds,separator:opts.timeSeparator}).unbind(".datetimebox").bind("mousedown.datetimebox",function(e){ +e.stopPropagation(); +}); +_86f(_86a,opts.value); +}; +function _870(_871){ +var c=$(_871).datetimebox("calendar"); +var t=$(_871).datetimebox("spinner"); +var date=c.calendar("options").current; +return new Date(date.getFullYear(),date.getMonth(),date.getDate(),t.timespinner("getHours"),t.timespinner("getMinutes"),t.timespinner("getSeconds")); +}; +function _872(_873,q){ +_86f(_873,q,true); +}; +function _874(_875){ +var opts=$.data(_875,"datetimebox").options; +var date=_870(_875); +_86f(_875,opts.formatter.call(_875,date)); +$(_875).combo("hidePanel"); +}; +function _86f(_876,_877,_878){ +var opts=$.data(_876,"datetimebox").options; +$(_876).combo("setValue",_877); +if(!_878){ +if(_877){ +var date=opts.parser.call(_876,_877); +$(_876).combo("setValue",opts.formatter.call(_876,date)); +$(_876).combo("setText",opts.formatter.call(_876,date)); +}else{ +$(_876).combo("setText",_877); +} +} +var date=opts.parser.call(_876,_877); +$(_876).datetimebox("calendar").calendar("moveTo",date); +$(_876).datetimebox("spinner").timespinner("setValue",_879(date)); +function _879(date){ +function _87a(_87b){ +return (_87b<10?"0":"")+_87b; +}; +var tt=[_87a(date.getHours()),_87a(date.getMinutes())]; +if(opts.showSeconds){ +tt.push(_87a(date.getSeconds())); +} +return tt.join($(_876).datetimebox("spinner").timespinner("options").separator); +}; +}; +$.fn.datetimebox=function(_87c,_87d){ +if(typeof _87c=="string"){ +var _87e=$.fn.datetimebox.methods[_87c]; +if(_87e){ +return _87e(this,_87d); +}else{ +return this.datebox(_87c,_87d); +} +} +_87c=_87c||{}; +return this.each(function(){ +var _87f=$.data(this,"datetimebox"); +if(_87f){ +$.extend(_87f.options,_87c); +}else{ +$.data(this,"datetimebox",{options:$.extend({},$.fn.datetimebox.defaults,$.fn.datetimebox.parseOptions(this),_87c)}); +} +_869(this); +}); +}; +$.fn.datetimebox.methods={options:function(jq){ +var _880=jq.datebox("options"); +return $.extend($.data(jq[0],"datetimebox").options,{originalValue:_880.originalValue,disabled:_880.disabled,readonly:_880.readonly}); +},spinner:function(jq){ +return $.data(jq[0],"datetimebox").spinner; +},setValue:function(jq,_881){ +return jq.each(function(){ +_86f(this,_881); +}); +},reset:function(jq){ +return jq.each(function(){ +var opts=$(this).datetimebox("options"); +$(this).datetimebox("setValue",opts.originalValue); +}); +}}; +$.fn.datetimebox.parseOptions=function(_882){ +var t=$(_882); +return $.extend({},$.fn.datebox.parseOptions(_882),$.parser.parseOptions(_882,["timeSeparator",{showSeconds:"boolean"}])); +}; +$.fn.datetimebox.defaults=$.extend({},$.fn.datebox.defaults,{showSeconds:true,timeSeparator:":",keyHandler:{up:function(){ +},down:function(){ +},enter:function(){ +_874(this); +},query:function(q){ +_872(this,q); +}},formatter:function(date){ +var h=date.getHours(); +var M=date.getMinutes(); +var s=date.getSeconds(); +function _883(_884){ +return (_884<10?"0":"")+_884; +}; +var _885=$(this).datetimebox("spinner").timespinner("options").separator; +var r=$.fn.datebox.defaults.formatter(date)+" "+_883(h)+_885+_883(M); +if($(this).datetimebox("options").showSeconds){ +r+=_885+_883(s); +} +return r; +},parser:function(s){ +if($.trim(s)==""){ +return new Date(); +} +var dt=s.split(" "); +var d=$.fn.datebox.defaults.parser(dt[0]); +if(dt.length<2){ +return d; +} +var _886=$(this).datetimebox("spinner").timespinner("options").separator; +var tt=dt[1].split(_886); +var hour=parseInt(tt[0],10)||0; +var _887=parseInt(tt[1],10)||0; +var _888=parseInt(tt[2],10)||0; +return new Date(d.getFullYear(),d.getMonth(),d.getDate(),hour,_887,_888); +}}); +})(jQuery); +(function($){ +function init(_889){ +var _88a=$("
            "+"
            "+""+""+"
            "+"
            "+"
            "+"
            "+""+"
            ").insertAfter(_889); +var name=$(_889).hide().attr("name"); +if(name){ +_88a.find("input.slider-value").attr("name",name); +$(_889).removeAttr("name").attr("sliderName",name); +} +return _88a; +}; +function _88b(_88c,_88d){ +var _88e=$.data(_88c,"slider"); +var opts=_88e.options; +var _88f=_88e.slider; +if(_88d){ +if(_88d.width){ +opts.width=_88d.width; +} +if(_88d.height){ +opts.height=_88d.height; +} +} +if(opts.mode=="h"){ +_88f.css("height",""); +_88f.children("div").css("height",""); +if(!isNaN(opts.width)){ +_88f.width(opts.width); +} +}else{ +_88f.css("width",""); +_88f.children("div").css("width",""); +if(!isNaN(opts.height)){ +_88f.height(opts.height); +_88f.find("div.slider-rule").height(opts.height); +_88f.find("div.slider-rulelabel").height(opts.height); +_88f.find("div.slider-inner")._outerHeight(opts.height); +} +} +_890(_88c); +}; +function _891(_892){ +var _893=$.data(_892,"slider"); +var opts=_893.options; +var _894=_893.slider; +var aa=opts.mode=="h"?opts.rule:opts.rule.slice(0).reverse(); +if(opts.reversed){ +aa=aa.slice(0).reverse(); +} +_895(aa); +function _895(aa){ +var rule=_894.find("div.slider-rule"); +var _896=_894.find("div.slider-rulelabel"); +rule.empty(); +_896.empty(); +for(var i=0;i").appendTo(rule); +span.css((opts.mode=="h"?"left":"top"),_897); +if(aa[i]!="|"){ +span=$("").appendTo(_896); +span.html(aa[i]); +if(opts.mode=="h"){ +span.css({left:_897,marginLeft:-Math.round(span.outerWidth()/2)}); +}else{ +span.css({top:_897,marginTop:-Math.round(span.outerHeight()/2)}); +} +} +} +}; +}; +function _898(_899){ +var _89a=$.data(_899,"slider"); +var opts=_89a.options; +var _89b=_89a.slider; +_89b.removeClass("slider-h slider-v slider-disabled"); +_89b.addClass(opts.mode=="h"?"slider-h":"slider-v"); +_89b.addClass(opts.disabled?"slider-disabled":""); +_89b.find("a.slider-handle").draggable({axis:opts.mode,cursor:"pointer",disabled:opts.disabled,onDrag:function(e){ +var left=e.data.left; +var _89c=_89b.width(); +if(opts.mode!="h"){ +left=e.data.top; +_89c=_89b.height(); +} +if(left<0||left>_89c){ +return false; +}else{ +var _89d=_8ae(_899,left); +_89e(_89d); +return false; +} +},onStartDrag:function(){ +opts.onSlideStart.call(_899,opts.value); +},onStopDrag:function(e){ +var _89f=_8ae(_899,(opts.mode=="h"?e.data.left:e.data.top)); +_89e(_89f); +opts.onSlideEnd.call(_899,opts.value); +}}); +function _89e(_8a0){ +var s=Math.abs(_8a0%opts.step); +if(sopts.max){ +_8a3=opts.max; +} +opts.value=_8a3; +$(_8a2).val(_8a3); +_8a5.find("input.slider-value").val(_8a3); +var pos=_8a7(_8a2,_8a3); +var tip=_8a5.find(".slider-tip"); +if(opts.showTip){ +tip.show(); +tip.html(opts.tipFormatter.call(_8a2,opts.value)); +}else{ +tip.hide(); +} +if(opts.mode=="h"){ +var _8a8="left:"+pos+"px;"; +_8a5.find(".slider-handle").attr("style",_8a8); +tip.attr("style",_8a8+"margin-left:"+(-Math.round(tip.outerWidth()/2))+"px"); +}else{ +var _8a8="top:"+pos+"px;"; +_8a5.find(".slider-handle").attr("style",_8a8); +tip.attr("style",_8a8+"margin-left:"+(-Math.round(tip.outerWidth()))+"px"); +} +if(_8a6!=_8a3){ +opts.onChange.call(_8a2,_8a3,_8a6); +} +}; +function _890(_8a9){ +var opts=$.data(_8a9,"slider").options; +var fn=opts.onChange; +opts.onChange=function(){ +}; +_8a1(_8a9,opts.value); +opts.onChange=fn; +}; +function _8a7(_8aa,_8ab){ +var _8ac=$.data(_8aa,"slider"); +var opts=_8ac.options; +var _8ad=_8ac.slider; +if(opts.mode=="h"){ +var pos=(_8ab-opts.min)/(opts.max-opts.min)*_8ad.width(); +if(opts.reversed){ +pos=_8ad.width()-pos; +} +}else{ +var pos=_8ad.height()-(_8ab-opts.min)/(opts.max-opts.min)*_8ad.height(); +if(opts.reversed){ +pos=_8ad.height()-pos; +} +} +return pos.toFixed(0); +}; +function _8ae(_8af,pos){ +var _8b0=$.data(_8af,"slider"); +var opts=_8b0.options; +var _8b1=_8b0.slider; +if(opts.mode=="h"){ +var _8b2=opts.min+(opts.max-opts.min)*(pos/_8b1.width()); +}else{ +var _8b2=opts.min+(opts.max-opts.min)*((_8b1.height()-pos)/_8b1.height()); +} +return opts.reversed?opts.max-_8b2.toFixed(0):_8b2.toFixed(0); +}; +$.fn.slider=function(_8b3,_8b4){ +if(typeof _8b3=="string"){ +return $.fn.slider.methods[_8b3](this,_8b4); +} +_8b3=_8b3||{}; +return this.each(function(){ +var _8b5=$.data(this,"slider"); +if(_8b5){ +$.extend(_8b5.options,_8b3); +}else{ +_8b5=$.data(this,"slider",{options:$.extend({},$.fn.slider.defaults,$.fn.slider.parseOptions(this),_8b3),slider:init(this)}); +$(this).removeAttr("disabled"); +} +var opts=_8b5.options; +opts.min=parseFloat(opts.min); +opts.max=parseFloat(opts.max); +opts.value=parseFloat(opts.value); +opts.step=parseFloat(opts.step); +_898(this); +_891(this); +_88b(this); +}); +}; +$.fn.slider.methods={options:function(jq){ +return $.data(jq[0],"slider").options; +},destroy:function(jq){ +return jq.each(function(){ +$.data(this,"slider").slider.remove(); +$(this).remove(); +}); +},resize:function(jq,_8b6){ +return jq.each(function(){ +_88b(this,_8b6); +}); +},getValue:function(jq){ +return jq.slider("options").value; +},setValue:function(jq,_8b7){ +return jq.each(function(){ +_8a1(this,_8b7); +}); +},enable:function(jq){ +return jq.each(function(){ +$.data(this,"slider").options.disabled=false; +_898(this); +}); +},disable:function(jq){ +return jq.each(function(){ +$.data(this,"slider").options.disabled=true; +_898(this); +}); +}}; +$.fn.slider.parseOptions=function(_8b8){ +var t=$(_8b8); +return $.extend({},$.parser.parseOptions(_8b8,["width","height","mode",{reversed:"boolean",showTip:"boolean",min:"number",max:"number",step:"number"}]),{value:(t.val()||undefined),disabled:(t.attr("disabled")?true:undefined),rule:(t.attr("rule")?eval(t.attr("rule")):undefined)}); +}; +$.fn.slider.defaults={width:"auto",height:"auto",mode:"h",reversed:false,showTip:false,disabled:false,value:0,min:0,max:100,step:1,rule:[],tipFormatter:function(_8b9){ +return _8b9; +},onChange:function(_8ba,_8bb){ +},onSlideStart:function(_8bc){ +},onSlideEnd:function(_8bd){ +}}; +})(jQuery); + diff --git a/public/javascripts/jquery.min.js b/public/javascripts/jquery.min.js new file mode 100644 index 0000000..b18e05a --- /dev/null +++ b/public/javascripts/jquery.min.js @@ -0,0 +1,6 @@ +/*! jQuery v2.0.0 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license +//@ sourceMappingURL=jquery.min.map +*/ +(function(e,undefined){var t,n,r=typeof undefined,i=e.location,o=e.document,s=o.documentElement,a=e.jQuery,u=e.$,l={},c=[],f="2.0.0",p=c.concat,h=c.push,d=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=f.trim,x=function(e,n){return new x.fn.init(e,n,t)},b=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^-ms-/,N=/-([\da-z])/gi,E=function(e,t){return t.toUpperCase()},S=function(){o.removeEventListener("DOMContentLoaded",S,!1),e.removeEventListener("load",S,!1),x.ready()};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,t,n){var r,i;if(!e)return this;if("string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:T.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof x?t[0]:t,x.merge(this,x.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:o,!0)),C.test(r[1])&&x.isPlainObject(t))for(r in t)x.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=o.getElementById(r[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?n.ready(e):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return d.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,t,n,r,i,o,s=arguments[0]||{},a=1,u=arguments.length,l=!1;for("boolean"==typeof s&&(l=s,s=arguments[1]||{},a=2),"object"==typeof s||x.isFunction(s)||(s={}),u===a&&(s=this,--a);u>a;a++)if(null!=(e=arguments[a]))for(t in e)n=s[t],r=e[t],s!==r&&(l&&r&&(x.isPlainObject(r)||(i=x.isArray(r)))?(i?(i=!1,o=n&&x.isArray(n)?n:[]):o=n&&x.isPlainObject(n)?n:{},s[t]=x.extend(l,o,r)):r!==undefined&&(s[t]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=a),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){(e===!0?--x.readyWait:x.isReady)||(x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(o,[x]),x.fn.trigger&&x(o).trigger("ready").off("ready")))},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if("object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}return!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:JSON.parse,parseXML:function(e){var t,n;if(!e||"string"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,"text/xml")}catch(r){t=undefined}return(!t||t.getElementsByTagName("parsererror").length)&&x.error("Invalid XML: "+e),t},noop:function(){},globalEval:function(e){var t,n=eval;e=x.trim(e),e&&(1===e.indexOf("use strict")?(t=o.createElement("script"),t.text=e,o.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(k,"ms-").replace(N,E)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,s=j(e);if(n){if(s){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(s){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:function(e){return null==e?"":v.call(e)},makeArray:function(e,t){var n=t||[];return null!=e&&(j(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:g.call(t,e,n)},merge:function(e,t){var n=t.length,r=e.length,i=0;if("number"==typeof n)for(;n>i;i++)e[r++]=t[i];else while(t[i]!==undefined)e[r++]=t[i++];return e.length=r,e},grep:function(e,t,n){var r,i=[],o=0,s=e.length;for(n=!!n;s>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,s=j(e),a=[];if(s)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(a[a.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(a[a.length]=r);return p.apply([],a)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),x.isFunction(e)?(r=d.call(arguments,2),i=function(){return e.apply(t||this,r.concat(d.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):undefined},access:function(e,t,n,r,i,o,s){var a=0,u=e.length,l=null==n;if("object"===x.type(n)){i=!0;for(a in n)x.access(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,x.isFunction(r)||(s=!0),l&&(s?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(x(e),n)})),t))for(;u>a;a++)t(e[a],n,s?r:r.call(e[a],a,t(e[a],n)));return i?e:l?t.call(e):u?t(e[0],n):o},now:Date.now,swap:function(e,t,n,r){var i,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=s[o];return i}}),x.ready.promise=function(t){return n||(n=x.Deferred(),"complete"===o.readyState?setTimeout(x.ready):(o.addEventListener("DOMContentLoaded",S,!1),e.addEventListener("load",S,!1))),n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function j(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}t=x(o),function(e,undefined){var t,n,r,i,o,s,a,u,l,c,f,p,h,d,g,m,y="sizzle"+-new Date,v=e.document,b={},w=0,T=0,C=ot(),k=ot(),N=ot(),E=!1,S=function(){return 0},j=typeof undefined,D=1<<31,A=[],L=A.pop,q=A.push,H=A.push,O=A.slice,F=A.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},P="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",R="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=M.replace("w","w#"),$="\\["+R+"*("+M+")"+R+"*(?:([*^$|!~]?=)"+R+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+R+"*\\]",B=":("+M+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",I=RegExp("^"+R+"+|((?:^|[^\\\\])(?:\\\\.)*)"+R+"+$","g"),z=RegExp("^"+R+"*,"+R+"*"),_=RegExp("^"+R+"*([>+~]|"+R+")"+R+"*"),X=RegExp(R+"*[+~]"),U=RegExp("="+R+"*([^\\]'\"]*)"+R+"*\\]","g"),Y=RegExp(B),V=RegExp("^"+W+"$"),G={ID:RegExp("^#("+M+")"),CLASS:RegExp("^\\.("+M+")"),TAG:RegExp("^("+M.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+B),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+R+"*(even|odd|(([+-]|)(\\d*)n|)"+R+"*(?:([+-]|)"+R+"*(\\d+)|))"+R+"*\\)|)","i"),"boolean":RegExp("^(?:"+P+")$","i"),needsContext:RegExp("^"+R+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+R+"*((?:-\\d)?\\d*)"+R+"*\\)|)(?=[^-]|$)","i")},J=/^[^{]+\{\s*\[native \w/,Q=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,et=/'|\\/g,tt=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,nt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{H.apply(A=O.call(v.childNodes),v.childNodes),A[v.childNodes.length].nodeType}catch(rt){H={apply:A.length?function(e,t){q.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function it(e){return J.test(e+"")}function ot(){var e,t=[];return e=function(n,i){return t.push(n+=" ")>r.cacheLength&&delete e[t.shift()],e[n]=i}}function st(e){return e[y]=!0,e}function at(e){var t=c.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ut(e,t,n,r){var i,o,s,a,u,f,d,g,x,w;if((t?t.ownerDocument||t:v)!==c&&l(t),t=t||c,n=n||[],!e||"string"!=typeof e)return n;if(1!==(a=t.nodeType)&&9!==a)return[];if(p&&!r){if(i=Q.exec(e))if(s=i[1]){if(9===a){if(o=t.getElementById(s),!o||!o.parentNode)return n;if(o.id===s)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(s))&&m(t,o)&&o.id===s)return n.push(o),n}else{if(i[2])return H.apply(n,t.getElementsByTagName(e)),n;if((s=i[3])&&b.getElementsByClassName&&t.getElementsByClassName)return H.apply(n,t.getElementsByClassName(s)),n}if(b.qsa&&(!h||!h.test(e))){if(g=d=y,x=t,w=9===a&&e,1===a&&"object"!==t.nodeName.toLowerCase()){f=gt(e),(d=t.getAttribute("id"))?g=d.replace(et,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=f.length;while(u--)f[u]=g+mt(f[u]);x=X.test(e)&&t.parentNode||t,w=f.join(",")}if(w)try{return H.apply(n,x.querySelectorAll(w)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(I,"$1"),t,n,r)}o=ut.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},l=ut.setDocument=function(e){var t=e?e.ownerDocument||e:v;return t!==c&&9===t.nodeType&&t.documentElement?(c=t,f=t.documentElement,p=!o(t),b.getElementsByTagName=at(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),b.attributes=at(function(e){return e.className="i",!e.getAttribute("className")}),b.getElementsByClassName=at(function(e){return e.innerHTML="
            ",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),b.sortDetached=at(function(e){return 1&e.compareDocumentPosition(c.createElement("div"))}),b.getById=at(function(e){return f.appendChild(e).id=y,!t.getElementsByName||!t.getElementsByName(y).length}),b.getById?(r.find.ID=function(e,t){if(typeof t.getElementById!==j&&p){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},r.filter.ID=function(e){var t=e.replace(tt,nt);return function(e){return e.getAttribute("id")===t}}):(r.find.ID=function(e,t){if(typeof t.getElementById!==j&&p){var n=t.getElementById(e);return n?n.id===e||typeof n.getAttributeNode!==j&&n.getAttributeNode("id").value===e?[n]:undefined:[]}},r.filter.ID=function(e){var t=e.replace(tt,nt);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),r.find.TAG=b.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==j?t.getElementsByTagName(e):undefined}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=b.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==j&&p?t.getElementsByClassName(e):undefined},d=[],h=[],(b.qsa=it(t.querySelectorAll))&&(at(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||h.push("\\["+R+"*(?:value|"+P+")"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){var t=c.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&h.push("[*^$]="+R+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(b.matchesSelector=it(g=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){b.disconnectedMatch=g.call(e,"div"),g.call(e,"[s!='']:x"),d.push("!=",B)}),h=h.length&&RegExp(h.join("|")),d=d.length&&RegExp(d.join("|")),m=it(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},S=f.compareDocumentPosition?function(e,n){if(e===n)return E=!0,0;var r=n.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(n);return r?1&r||!b.sortDetached&&n.compareDocumentPosition(e)===r?e===t||m(v,e)?-1:n===t||m(v,n)?1:u?F.call(u,e)-F.call(u,n):0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,o=e.parentNode,s=n.parentNode,a=[e],l=[n];if(e===n)return E=!0,0;if(!o||!s)return e===t?-1:n===t?1:o?-1:s?1:u?F.call(u,e)-F.call(u,n):0;if(o===s)return lt(e,n);r=e;while(r=r.parentNode)a.unshift(r);r=n;while(r=r.parentNode)l.unshift(r);while(a[i]===l[i])i++;return i?lt(a[i],l[i]):a[i]===v?-1:l[i]===v?1:0},c):c},ut.matches=function(e,t){return ut(e,null,null,t)},ut.matchesSelector=function(e,t){if((e.ownerDocument||e)!==c&&l(e),t=t.replace(U,"='$1']"),!(!b.matchesSelector||!p||d&&d.test(t)||h&&h.test(t)))try{var n=g.call(e,t);if(n||b.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return ut(t,c,null,[e]).length>0},ut.contains=function(e,t){return(e.ownerDocument||e)!==c&&l(e),m(e,t)},ut.attr=function(e,t){(e.ownerDocument||e)!==c&&l(e);var n=r.attrHandle[t.toLowerCase()],i=n&&n(e,t,!p);return i===undefined?b.attributes||!p?e.getAttribute(t):(i=e.getAttributeNode(t))&&i.specified?i.value:null:i},ut.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ut.uniqueSort=function(e){var t,n=[],r=0,i=0;if(E=!b.detectDuplicates,u=!b.sortStable&&e.slice(0),e.sort(S),E){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return e};function lt(e,t){var n=t&&e,r=n&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ct(e,t,n){var r;return n?undefined:(r=e.getAttributeNode(t))&&r.specified?r.value:e[t]===!0?t.toLowerCase():null}function ft(e,t,n){var r;return n?undefined:r=e.getAttribute(t,"type"===t.toLowerCase()?1:2)}function pt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ht(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function dt(e){return st(function(t){return t=+t,st(function(n,r){var i,o=e([],n.length,t),s=o.length;while(s--)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}i=ut.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else for(;t=e[r];r++)n+=i(t);return n},r=ut.selectors={cacheLength:50,createPseudo:st,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(tt,nt),e[3]=(e[4]||e[5]||"").replace(tt,nt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ut.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ut.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return G.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&Y.test(n)&&(t=gt(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(tt,nt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=C[e+" "];return t||(t=RegExp("(^|"+R+")"+e+"("+R+"|$)"))&&C(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ut.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,h,d,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,v=a&&t.nodeName.toLowerCase(),x=!u&&!a;if(m){if(o){while(g){f=t;while(f=f[g])if(a?f.nodeName.toLowerCase()===v:1===f.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&x){c=m[y]||(m[y]={}),l=c[e]||[],h=l[0]===w&&l[1],p=l[0]===w&&l[2],f=h&&m.childNodes[h];while(f=++h&&f&&f[g]||(p=h=0)||d.pop())if(1===f.nodeType&&++p&&f===t){c[e]=[w,h,p];break}}else if(x&&(l=(t[y]||(t[y]={}))[e])&&l[0]===w)p=l[1];else while(f=++h&&f&&f[g]||(p=h=0)||d.pop())if((a?f.nodeName.toLowerCase()===v:1===f.nodeType)&&++p&&(x&&((f[y]||(f[y]={}))[e]=[w,p]),f===t))break;return p-=i,p===r||0===p%r&&p/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||ut.error("unsupported pseudo: "+e);return i[y]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?st(function(e,n){var r,o=i(e,t),s=o.length;while(s--)r=F.call(e,o[s]),e[r]=!(n[r]=o[s])}):function(e){return i(e,0,n)}):i}},pseudos:{not:st(function(e){var t=[],n=[],r=s(e.replace(I,"$1"));return r[y]?st(function(e,t,n,i){var o,s=r(e,null,i,[]),a=e.length;while(a--)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:st(function(e){return function(t){return ut(e,t).length>0}}),contains:st(function(e){return function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:st(function(e){return V.test(e||"")||ut.error("unsupported lang: "+e),e=e.replace(tt,nt).toLowerCase(),function(t){var n;do if(n=p?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===c.activeElement&&(!c.hasFocus||c.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Z.test(e.nodeName)},input:function(e){return K.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:dt(function(){return[0]}),last:dt(function(e,t){return[t-1]}),eq:dt(function(e,t,n){return[0>n?n+t:n]}),even:dt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:dt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:dt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:dt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})r.pseudos[t]=pt(t);for(t in{submit:!0,reset:!0})r.pseudos[t]=ht(t);function gt(e,t){var n,i,o,s,a,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);a=e,u=[],l=r.preFilter;while(a){(!n||(i=z.exec(a)))&&(i&&(a=a.slice(i[0].length)||a),u.push(o=[])),n=!1,(i=_.exec(a))&&(n=i.shift(),o.push({value:n,type:i[0].replace(I," ")}),a=a.slice(n.length));for(s in r.filter)!(i=G[s].exec(a))||l[s]&&!(i=l[s](i))||(n=i.shift(),o.push({value:n,type:s,matches:i}),a=a.slice(n.length));if(!n)break}return t?a.length:a?ut.error(e):k(e,u).slice(0)}function mt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function yt(e,t,r){var i=t.dir,o=r&&"parentNode"===i,s=T++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,r,a){var u,l,c,f=w+" "+s;if(a){while(t=t[i])if((1===t.nodeType||o)&&e(t,r,a))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[y]||(t[y]={}),(l=c[i])&&l[0]===f){if((u=l[1])===!0||u===n)return u===!0}else if(l=c[i]=[f],l[1]=e(t,r,a)||n,l[1]===!0)return!0}}function vt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,s=[],a=0,u=e.length,l=null!=t;for(;u>a;a++)(o=e[a])&&(!n||n(o,r,i))&&(s.push(o),l&&t.push(a));return s}function bt(e,t,n,r,i,o){return r&&!r[y]&&(r=bt(r)),i&&!i[y]&&(i=bt(i,o)),st(function(o,s,a,u){var l,c,f,p=[],h=[],d=s.length,g=o||Ct(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:xt(g,p,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=xt(y,h),r(l,[],a,u),c=l.length;while(c--)(f=l[c])&&(y[h[c]]=!(m[h[c]]=f))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(f=y[c])&&l.push(m[c]=f);i(null,y=[],l,u)}c=y.length;while(c--)(f=y[c])&&(l=i?F.call(o,f):p[c])>-1&&(o[l]=!(s[l]=f))}}else y=xt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):H.apply(s,y)})}function wt(e){var t,n,i,o=e.length,s=r.relative[e[0].type],u=s||r.relative[" "],l=s?1:0,c=yt(function(e){return e===t},u,!0),f=yt(function(e){return F.call(t,e)>-1},u,!0),p=[function(e,n,r){return!s&&(r||n!==a)||((t=n).nodeType?c(e,n,r):f(e,n,r))}];for(;o>l;l++)if(n=r.relative[e[l].type])p=[yt(vt(p),n)];else{if(n=r.filter[e[l].type].apply(null,e[l].matches),n[y]){for(i=++l;o>i;i++)if(r.relative[e[i].type])break;return bt(l>1&&vt(p),l>1&&mt(e.slice(0,l-1)).replace(I,"$1"),n,i>l&&wt(e.slice(l,i)),o>i&&wt(e=e.slice(i)),o>i&&mt(e))}p.push(n)}return vt(p)}function Tt(e,t){var i=0,o=t.length>0,s=e.length>0,u=function(u,l,f,p,h){var d,g,m,y=[],v=0,x="0",b=u&&[],T=null!=h,C=a,k=u||s&&r.find.TAG("*",h&&l.parentNode||l),N=w+=null==C?1:Math.random()||.1;for(T&&(a=l!==c&&l,n=i);null!=(d=k[x]);x++){if(s&&d){g=0;while(m=e[g++])if(m(d,l,f)){p.push(d);break}T&&(w=N,n=++i)}o&&((d=!m&&d)&&v--,u&&b.push(d))}if(v+=x,o&&x!==v){g=0;while(m=t[g++])m(b,y,l,f);if(u){if(v>0)while(x--)b[x]||y[x]||(y[x]=L.call(p));y=xt(y)}H.apply(p,y),T&&!u&&y.length>0&&v+t.length>1&&ut.uniqueSort(p)}return T&&(w=N,a=C),b};return o?st(u):u}s=ut.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=gt(e)),n=t.length;while(n--)o=wt(t[n]),o[y]?r.push(o):i.push(o);o=N(e,Tt(i,r))}return o};function Ct(e,t,n){var r=0,i=t.length;for(;i>r;r++)ut(e,t[r],n);return n}function kt(e,t,n,i){var o,a,u,l,c,f=gt(e);if(!i&&1===f.length){if(a=f[0]=f[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&p&&r.relative[a[1].type]){if(t=(r.find.ID(u.matches[0].replace(tt,nt),t)||[])[0],!t)return n;e=e.slice(a.shift().value.length)}o=G.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],r.relative[l=u.type])break;if((c=r.find[l])&&(i=c(u.matches[0].replace(tt,nt),X.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=i.length&&mt(a),!e)return H.apply(n,i),n;break}}}return s(e,f)(i,t,!p,n,X.test(e)),n}r.pseudos.nth=r.pseudos.eq;function Nt(){}Nt.prototype=r.filters=r.pseudos,r.setFilters=new Nt,b.sortStable=y.split("").sort(S).join("")===y,l(),[0,0].sort(S),b.detectDuplicates=E,at(function(e){if(e.innerHTML="","#"!==e.firstChild.getAttribute("href")){var t="type|href|height|width".split("|"),n=t.length;while(n--)r.attrHandle[t[n]]=ft}}),at(function(e){if(null!=e.getAttribute("disabled")){var t=P.split("|"),n=t.length;while(n--)r.attrHandle[t[n]]=ct}}),x.find=ut,x.expr=ut.selectors,x.expr[":"]=x.expr.pseudos,x.unique=ut.uniqueSort,x.text=ut.getText,x.isXMLDoc=ut.isXML,x.contains=ut.contains}(e);var D={};function A(e){var t=D[e]={};return x.each(e.match(w)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?D[e]||A(e):x.extend({},e);var t,n,r,i,o,s,a=[],u=!e.once&&[],l=function(f){for(t=e.memory&&f,n=!0,s=i||0,i=0,o=a.length,r=!0;a&&o>s;s++)if(a[s].apply(f[0],f[1])===!1&&e.stopOnFalse){t=!1;break}r=!1,a&&(u?u.length&&l(u.shift()):t?a=[]:c.disable())},c={add:function(){if(a){var n=a.length;(function s(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&c.has(n)||a.push(n):n&&n.length&&"string"!==r&&s(n)})})(arguments),r?o=a.length:t&&(i=n,l(t))}return this},remove:function(){return a&&x.each(arguments,function(e,t){var n;while((n=x.inArray(t,a,n))>-1)a.splice(n,1),r&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?x.inArray(e,a)>-1:!(!a||!a.length)},empty:function(){return a=[],o=0,this},disable:function(){return a=u=t=undefined,this},disabled:function(){return!a},lock:function(){return u=undefined,t||c.disable(),this},locked:function(){return!u},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!a||n&&!u||(r?u.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var s=o[0],a=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var s=o[2],a=o[3];r[o[1]]=s.add,a&&s.add(function(){n=a},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=s.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=d.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),s=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?d.call(arguments):r,n===a?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},a,u,l;if(r>1)for(a=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(s(t,l,n)).fail(o.reject).progress(s(t,u,a)):--i;return i||o.resolveWith(l,n),o.promise()}}),x.support=function(t){var n=o.createElement("input"),r=o.createDocumentFragment(),i=o.createElement("div"),s=o.createElement("select"),a=s.appendChild(o.createElement("option"));return n.type?(n.type="checkbox",t.checkOn=""!==n.value,t.optSelected=a.selected,t.reliableMarginRight=!0,t.boxSizingReliable=!0,t.pixelPosition=!1,n.checked=!0,t.noCloneChecked=n.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!a.disabled,n=o.createElement("input"),n.value="t",n.type="radio",t.radioValue="t"===n.value,n.setAttribute("checked","t"),n.setAttribute("name","t"),r.appendChild(n),t.checkClone=r.cloneNode(!0).cloneNode(!0).lastChild.checked,t.focusinBubbles="onfocusin"in e,i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===i.style.backgroundClip,x(function(){var n,r,s="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",a=o.getElementsByTagName("body")[0];a&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",a.appendChild(n).appendChild(i),i.innerHTML="",i.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",x.swap(a,null!=a.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===i.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(i,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(i,null)||{width:"4px"}).width,r=i.appendChild(o.createElement("div")),r.style.cssText=i.style.cssText=s,r.style.marginRight=r.style.width="0",i.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),a.removeChild(n))}),t):t}({});var L,q,H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,O=/([A-Z])/g;function F(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=x.expando+Math.random()}F.uid=1,F.accepts=function(e){return e.nodeType?1===e.nodeType||9===e.nodeType:!0},F.prototype={key:function(e){if(!F.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=F.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(r){t[this.expando]=n,x.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var r,i=this.key(e),o=this.cache[i];if("string"==typeof t)o[t]=n;else if(x.isEmptyObject(o))this.cache[i]=t;else for(r in t)o[r]=t[r]},get:function(e,t){var n=this.cache[this.key(e)];return t===undefined?n:n[t]},access:function(e,t,n){return t===undefined||t&&"string"==typeof t&&n===undefined?this.get(e,t):(this.set(e,t,n),n!==undefined?n:t)},remove:function(e,t){var n,r,i=this.key(e),o=this.cache[i];if(t===undefined)this.cache[i]={};else{x.isArray(t)?r=t.concat(t.map(x.camelCase)):t in o?r=[t]:(r=x.camelCase(t),r=r in o?[r]:r.match(w)||[]),n=r.length;while(n--)delete o[r[n]]}},hasData:function(e){return!x.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){delete this.cache[this.key(e)]}},L=new F,q=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||q.hasData(e)},data:function(e,t,n){return L.access(e,t,n)},removeData:function(e,t){L.remove(e,t)},_data:function(e,t,n){return q.access(e,t,n)},_removeData:function(e,t){q.remove(e,t)}}),x.fn.extend({data:function(e,t){var n,r,i=this[0],o=0,s=null;if(e===undefined){if(this.length&&(s=L.get(i),1===i.nodeType&&!q.get(i,"hasDataAttrs"))){for(n=i.attributes;n.length>o;o++)r=n[o].name,0===r.indexOf("data-")&&(r=x.camelCase(r.substring(5)),P(i,r,s[r]));q.set(i,"hasDataAttrs",!0)}return s}return"object"==typeof e?this.each(function(){L.set(this,e)}):x.access(this,function(t){var n,r=x.camelCase(e);if(i&&t===undefined){if(n=L.get(i,e),n!==undefined)return n;if(n=L.get(i,r),n!==undefined)return n;if(n=P(i,r,undefined),n!==undefined)return n}else this.each(function(){var n=L.get(this,r);L.set(this,r,t),-1!==e.indexOf("-")&&n!==undefined&&L.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){L.remove(this,e)})}});function P(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(O,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:H.test(n)?JSON.parse(n):n}catch(i){}L.set(e,t,n)}else n=undefined;return n}x.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=q.get(e,t),n&&(!r||x.isArray(n)?r=q.access(e,t,x.makeArray(n)):r.push(n)),r||[]):undefined},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),s=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return q.get(e,n)||q.access(e,n,{empty:x.Callbacks("once memory").add(function(){q.remove(e,[t+"queue",n])})})}}),x.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),n>arguments.length?x.queue(this[0],e):t===undefined?this:this.each(function(){var n=x.queue(this,e,t); +x._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=x.Deferred(),o=this,s=this.length,a=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=undefined),e=e||"fx";while(s--)n=q.get(o[s],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(a));return a(),i.promise(t)}});var R,M,W=/[\t\r\n]/g,$=/\r/g,B=/^(?:input|select|textarea|button)$/i;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[x.propFix[e]||e]})},addClass:function(e){var t,n,r,i,o,s=0,a=this.length,u="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,s=0,a=this.length,u=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,i="boolean"==typeof t;return x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,s=0,a=x(this),u=t,l=e.match(w)||[];while(o=l[s++])u=i?u:!a.hasClass(o),a[u?"addClass":"removeClass"](o)}else(n===r||"boolean"===n)&&(this.className&&q.set(this,"__className__",this.className),this.className=this.className||e===!1?"":q.get(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(W," ").indexOf(t)>=0)return!0;return!1},val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=x.isFunction(e),this.each(function(n){var i,o=x(this);1===this.nodeType&&(i=r?e.call(this,n,o.val()):e,null==i?i="":"number"==typeof i?i+="":x.isArray(i)&&(i=x.map(i,function(e){return null==e?"":e+""})),t=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return t=x.valHooks[i.type]||x.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace($,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,s=o?null:[],a=o?i+1:r.length,u=0>i?a:o?i:0;for(;a>u;u++)if(n=r[u],!(!n.selected&&u!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),s=i.length;while(s--)r=i[s],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,t,n){var i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===r?x.prop(e,t,n):(1===s&&x.isXMLDoc(e)||(t=t.toLowerCase(),i=x.attrHooks[t]||(x.expr.match.boolean.test(t)?M:R)),n===undefined?i&&"get"in i&&null!==(o=i.get(e,t))?o:(o=x.find.attr(e,t),null==o?undefined:o):null!==n?i&&"set"in i&&(o=i.set(e,n,t))!==undefined?o:(e.setAttribute(t,n+""),n):(x.removeAttr(e,t),undefined))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.boolean.test(n)&&(e[r]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return o=1!==s||!x.isXMLDoc(e),o&&(t=x.propFix[t]||t,i=x.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute("tabindex")||B.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),M={set:function(e,t,n){return t===!1?x.removeAttr(e,n):e.setAttribute(n,n),n}},x.each(x.expr.match.boolean.source.match(/\w+/g),function(e,t){var n=x.expr.attrHandle[t]||x.find.attr;x.expr.attrHandle[t]=function(e,t,r){var i=x.expr.attrHandle[t],o=r?undefined:(x.expr.attrHandle[t]=undefined)!=n(e,t,r)?t.toLowerCase():null;return x.expr.attrHandle[t]=i,o}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,t){return x.isArray(t)?e.checked=x.inArray(x(e).val(),t)>=0:undefined}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var I=/^key/,z=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,X=/^([^.]*)(?:\.(.+)|)$/;function U(){return!0}function Y(){return!1}function V(){try{return o.activeElement}catch(e){}}x.event={global:{},add:function(e,t,n,i,o){var s,a,u,l,c,f,p,h,d,g,m,y=q.get(e);if(y){n.handler&&(s=n,n=s.handler,o=s.selector),n.guid||(n.guid=x.guid++),(l=y.events)||(l=y.events={}),(a=y.handle)||(a=y.handle=function(e){return typeof x===r||e&&x.event.triggered===e.type?undefined:x.event.dispatch.apply(a.elem,arguments)},a.elem=e),t=(t||"").match(w)||[""],c=t.length;while(c--)u=X.exec(t[c])||[],d=m=u[1],g=(u[2]||"").split(".").sort(),d&&(p=x.event.special[d]||{},d=(o?p.delegateType:p.bindType)||d,p=x.event.special[d]||{},f=x.extend({type:d,origType:m,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&x.expr.match.needsContext.test(o),namespace:g.join(".")},s),(h=l[d])||(h=l[d]=[],h.delegateCount=0,p.setup&&p.setup.call(e,i,g,a)!==!1||e.addEventListener&&e.addEventListener(d,a,!1)),p.add&&(p.add.call(e,f),f.handler.guid||(f.handler.guid=n.guid)),o?h.splice(h.delegateCount++,0,f):h.push(f),x.event.global[d]=!0);e=null}},remove:function(e,t,n,r,i){var o,s,a,u,l,c,f,p,h,d,g,m=q.hasData(e)&&q.get(e);if(m&&(u=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(a=X.exec(t[l])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){f=x.event.special[h]||{},h=(r?f.delegateType:f.bindType)||h,p=u[h]||[],a=a[2]&&RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));s&&!p.length&&(f.teardown&&f.teardown.call(e,d,m.handle)!==!1||x.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)x.event.remove(e,h+t[l],n,r,!0);x.isEmptyObject(u)&&(delete m.handle,q.remove(e,"events"))}},trigger:function(t,n,r,i){var s,a,u,l,c,f,p,h=[r||o],d=y.call(t,"type")?t.type:t,g=y.call(t,"namespace")?t.namespace.split("."):[];if(a=u=r=r||o,3!==r.nodeType&&8!==r.nodeType&&!_.test(d+x.event.triggered)&&(d.indexOf(".")>=0&&(g=d.split("."),d=g.shift(),g.sort()),c=0>d.indexOf(":")&&"on"+d,t=t[x.expando]?t:new x.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.namespace_re=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:x.makeArray(n,[t]),p=x.event.special[d]||{},i||!p.trigger||p.trigger.apply(r,n)!==!1)){if(!i&&!p.noBubble&&!x.isWindow(r)){for(l=p.delegateType||d,_.test(l+d)||(a=a.parentNode);a;a=a.parentNode)h.push(a),u=a;u===(r.ownerDocument||o)&&h.push(u.defaultView||u.parentWindow||e)}s=0;while((a=h[s++])&&!t.isPropagationStopped())t.type=s>1?l:p.bindType||d,f=(q.get(a,"events")||{})[t.type]&&q.get(a,"handle"),f&&f.apply(a,n),f=c&&a[c],f&&x.acceptData(a)&&f.apply&&f.apply(a,n)===!1&&t.preventDefault();return t.type=d,i||t.isDefaultPrevented()||p._default&&p._default.apply(h.pop(),n)!==!1||!x.acceptData(r)||c&&x.isFunction(r[d])&&!x.isWindow(r)&&(u=r[c],u&&(r[c]=null),x.event.triggered=d,r[d](),x.event.triggered=undefined,u&&(r[c]=u)),t.result}},dispatch:function(e){e=x.event.fix(e);var t,n,r,i,o,s=[],a=d.call(arguments),u=(q.get(this,"events")||{})[e.type]||[],l=x.event.special[e.type]||{};if(a[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),t=0;while((i=s[t++])&&!e.isPropagationStopped()){e.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(o.namespace))&&(e.handleObj=o,e.data=o.data,r=((x.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,a),r!==undefined&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,s=[],a=t.delegateCount,u=e.target;if(a&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!==this;u=u.parentNode||this)if(u.disabled!==!0||"click"!==e.type){for(r=[],n=0;a>n;n++)o=t[n],i=o.selector+" ",r[i]===undefined&&(r[i]=o.needsContext?x(i,this).index(u)>=0:x.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&s.push({elem:u,handlers:r})}return t.length>a&&s.push({elem:this,handlers:t.slice(a)}),s},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,s=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||o,r=n.documentElement,i=n.body,e.pageX=t.clientX+(r&&r.scrollLeft||i&&i.scrollLeft||0)-(r&&r.clientLeft||i&&i.clientLeft||0),e.pageY=t.clientY+(r&&r.scrollTop||i&&i.scrollTop||0)-(r&&r.clientTop||i&&i.clientTop||0)),e.which||s===undefined||(e.which=1&s?1:2&s?3:4&s?2:0),e}},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=z.test(i)?this.mouseHooks:I.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return 3===e.target.nodeType&&(e.target=e.target.parentNode),s.filter?s.filter(e,o):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==V()&&this.focus?(this.focus(),!1):undefined},delegateType:"focusin"},blur:{trigger:function(){return this===V()&&this.blur?(this.blur(),!1):undefined},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&x.nodeName(this,"input")?(this.click(),!1):undefined},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==undefined&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},x.Event=function(e,t){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.getPreventDefault&&e.getPreventDefault()?U:Y):this.type=e,t&&x.extend(this,t),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,undefined):new x.Event(e,t)},x.Event.prototype={isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=U,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=U,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=U,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,t,n,r,i){var o,s;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=undefined);for(s in e)this.on(s,t,n,e[s],i);return this}if(null==n&&null==r?(r=t,n=t=undefined):null==r&&("string"==typeof t?(r=n,n=undefined):(r=n,n=t,t=undefined)),r===!1)r=Y;else if(!r)return this;return 1===i&&(o=r,r=function(e){return x().off(e),o.apply(this,arguments)},r.guid=o.guid||(o.guid=x.guid++)),this.each(function(){x.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,x(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=undefined),n===!1&&(n=Y),this.each(function(){x.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?x.event.trigger(e,t,n,!0):undefined}});var G=/^.[^:#\[\.,]*$/,J=x.expr.match.needsContext,Q={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return t=this,this.pushStack(x(e).filter(function(){for(r=0;i>r;r++)if(x.contains(t[r],this))return!0}));for(n=[],r=0;i>r;r++)x.find(e,this[r],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t=x(e,this),n=t.length;return this.filter(function(){var e=0;for(;n>e;e++)if(x.contains(this,t[e]))return!0})},not:function(e){return this.pushStack(Z(this,e||[],!0))},filter:function(e){return this.pushStack(Z(this,e||[],!1))},is:function(e){return!!e&&("string"==typeof e?J.test(e)?x(e,this.context).index(this[0])>=0:x.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],s=J.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(s?s.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?g.call(x(e),this[0]):g.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function K(e,t){while((e=e[t])&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return K(e,"nextSibling")},prev:function(e){return K(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(Q[e]||x.unique(i),"p"===e[0]&&i.reverse()),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,t,n){var r=[],i=n!==undefined;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&x(e).is(n))break;r.push(e)}return r},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function Z(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(G.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return g.call(t,e)>=0!==n})}var et=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,tt=/<([\w:]+)/,nt=/<|&#?\w+;/,rt=/<(?:script|style|link)/i,it=/^(?:checkbox|radio)$/i,ot=/checked\s*(?:[^=]|=\s*.checked.)/i,st=/^$|\/(?:java|ecma)script/i,at=/^true\/(.*)/,ut=/^\s*\s*$/g,lt={option:[1,""],thead:[1,"","
            "],tr:[2,"","
            "],td:[3,"","
            "],_default:[0,"",""]};lt.optgroup=lt.option,lt.tbody=lt.tfoot=lt.colgroup=lt.caption=lt.col=lt.thead,lt.th=lt.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===undefined?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=ct(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=ct(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(gt(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&ht(gt(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++)1===e.nodeType&&(x.cleanData(gt(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!rt.test(e)&&!lt[(tt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(et,"<$1>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(x.cleanData(gt(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=p.apply([],e);var r,i,o,s,a,u,l=0,c=this.length,f=this,h=c-1,d=e[0],g=x.isFunction(d);if(g||!(1>=c||"string"!=typeof d||x.support.checkClone)&&ot.test(d))return this.each(function(r){var i=f.eq(r);g&&(e[0]=d.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(r=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),i=r.firstChild,1===r.childNodes.length&&(r=i),i)){for(o=x.map(gt(r,"script"),ft),s=o.length;c>l;l++)a=r,l!==h&&(a=x.clone(a,!0,!0),s&&x.merge(o,gt(a,"script"))),t.call(this[l],a,l);if(s)for(u=o[o.length-1].ownerDocument,x.map(o,pt),l=0;s>l;l++)a=o[l],st.test(a.type||"")&&!q.access(a,"globalEval")&&x.contains(u,a)&&(a.src?x._evalUrl(a.src):x.globalEval(a.textContent.replace(ut,"")))}return this}}),x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=[],i=x(e),o=i.length-1,s=0;for(;o>=s;s++)n=s===o?this:this.clone(!0),x(i[s])[t](n),h.apply(r,n.get());return this.pushStack(r)}}),x.extend({clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=x.contains(e.ownerDocument,e);if(!(x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(s=gt(a),o=gt(e),r=0,i=o.length;i>r;r++)mt(o[r],s[r]);if(t)if(n)for(o=o||gt(e),s=s||gt(a),r=0,i=o.length;i>r;r++)dt(o[r],s[r]);else dt(e,a);return s=gt(a,"script"),s.length>0&&ht(s,!u&>(e,"script")),a},buildFragment:function(e,t,n,r){var i,o,s,a,u,l,c=0,f=e.length,p=t.createDocumentFragment(),h=[];for(;f>c;c++)if(i=e[c],i||0===i)if("object"===x.type(i))x.merge(h,i.nodeType?[i]:i);else if(nt.test(i)){o=o||p.appendChild(t.createElement("div")),s=(tt.exec(i)||["",""])[1].toLowerCase(),a=lt[s]||lt._default,o.innerHTML=a[1]+i.replace(et,"<$1>")+a[2],l=a[0];while(l--)o=o.firstChild;x.merge(h,o.childNodes),o=p.firstChild,o.textContent=""}else h.push(t.createTextNode(i));p.textContent="",c=0;while(i=h[c++])if((!r||-1===x.inArray(i,r))&&(u=x.contains(i.ownerDocument,i),o=gt(p.appendChild(i),"script"),u&&ht(o),n)){l=0;while(i=o[l++])st.test(i.type||"")&&n.push(i)}return p},cleanData:function(e){var t,n,r,i=e.length,o=0,s=x.event.special;for(;i>o;o++){if(n=e[o],x.acceptData(n)&&(t=q.access(n)))for(r in t.events)s[r]?x.event.remove(n,r):x.removeEvent(n,r,t.handle);L.discard(n),q.discard(n)}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"text",async:!1,global:!1,success:x.globalEval})}});function ct(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function ft(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function pt(e){var t=at.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function ht(e,t){var n=e.length,r=0;for(;n>r;r++)q.set(e[r],"globalEval",!t||q.get(t[r],"globalEval"))}function dt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(q.hasData(e)&&(o=q.access(e),s=x.extend({},o),l=o.events,q.set(t,s),l)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)x.event.add(t,i,l[i][n])}L.hasData(e)&&(a=L.access(e),u=x.extend({},a),L.set(t,u))}}function gt(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return t===undefined||t&&x.nodeName(e,t)?x.merge([e],n):n}function mt(e,t){var n=t.nodeName.toLowerCase();"input"===n&&it.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}x.fn.extend({wrapAll:function(e){var t;return x.isFunction(e)?this.each(function(t){x(this).wrapAll(e.call(this,t))}):(this[0]&&(t=x(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var yt,vt,xt=/^(none|table(?!-c[ea]).+)/,bt=/^margin/,wt=RegExp("^("+b+")(.*)$","i"),Tt=RegExp("^("+b+")(?!px)[a-z%]+$","i"),Ct=RegExp("^([+-])=("+b+")","i"),kt={BODY:"block"},Nt={position:"absolute",visibility:"hidden",display:"block"},Et={letterSpacing:0,fontWeight:400},St=["Top","Right","Bottom","Left"],jt=["Webkit","O","Moz","ms"];function Dt(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=jt.length;while(i--)if(t=jt[i]+n,t in e)return t;return r}function At(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function Lt(t){return e.getComputedStyle(t,null)}function qt(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=q.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&At(r)&&(o[s]=q.access(r,"olddisplay",Pt(r.nodeName)))):o[s]||(i=At(r),(n&&"none"!==n||!i)&&q.set(r,"olddisplay",i?n:x.css(r,"display"))));for(s=0;a>s;s++)r=e[s],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[s]||"":"none"));return e}x.fn.extend({css:function(e,t){return x.access(this,function(e,t,n){var r,i,o={},s=0;if(x.isArray(t)){for(r=Lt(e),i=t.length;i>s;s++)o[t[s]]=x.css(e,t[s],!1,r);return o}return n!==undefined?x.style(e,t,n):x.css(e,t)},e,t,arguments.length>1)},show:function(){return qt(this,!0)},hide:function(){return qt(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:At(this))?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=yt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=x.camelCase(t),u=e.style;return t=x.cssProps[a]||(x.cssProps[a]=Dt(u,a)),s=x.cssHooks[t]||x.cssHooks[a],n===undefined?s&&"get"in s&&(i=s.get(e,!1,r))!==undefined?i:u[t]:(o=typeof n,"string"===o&&(i=Ct.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(x.css(e,t)),o="number"),null==n||"number"===o&&isNaN(n)||("number"!==o||x.cssNumber[a]||(n+="px"),x.support.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&(n=s.set(e,n,r))===undefined||(u[t]=n)),undefined)}},css:function(e,t,n,r){var i,o,s,a=x.camelCase(t);return t=x.cssProps[a]||(x.cssProps[a]=Dt(e.style,a)),s=x.cssHooks[t]||x.cssHooks[a],s&&"get"in s&&(i=s.get(e,!0,n)),i===undefined&&(i=yt(e,t,r)),"normal"===i&&t in Et&&(i=Et[t]),""===n||n?(o=parseFloat(i),n===!0||x.isNumeric(o)?o||0:i):i}}),yt=function(e,t,n){var r,i,o,s=n||Lt(e),a=s?s.getPropertyValue(t)||s[t]:undefined,u=e.style;return s&&(""!==a||x.contains(e.ownerDocument,e)||(a=x.style(e,t)),Tt.test(a)&&bt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=s.width,u.width=r,u.minWidth=i,u.maxWidth=o)),a};function Ht(e,t,n){var r=wt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function Ot(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,s=0;for(;4>o;o+=2)"margin"===n&&(s+=x.css(e,n+St[o],!0,i)),r?("content"===n&&(s-=x.css(e,"padding"+St[o],!0,i)),"margin"!==n&&(s-=x.css(e,"border"+St[o]+"Width",!0,i))):(s+=x.css(e,"padding"+St[o],!0,i),"padding"!==n&&(s+=x.css(e,"border"+St[o]+"Width",!0,i)));return s}function Ft(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Lt(e),s=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=yt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Tt.test(i))return i;r=s&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+Ot(e,t,n||(s?"border":"content"),r,o)+"px"}function Pt(e){var t=o,n=kt[e];return n||(n=Rt(e,t),"none"!==n&&n||(vt=(vt||x("