From 4df1a4d20e0c79c02c88dde88d8735ff75257977 Mon Sep 17 00:00:00 2001 From: Brannon Dorsey Date: Sat, 5 Oct 2013 04:01:20 +0000 Subject: [PATCH 1/2] My version of Coder with node.js v0.10.9 --- .gitignore | 0 LICENSE | 0 README.md | 0 coder-base/apps/auth/app.js | 0 coder-base/apps/auth/meta.json | 0 coder-base/apps/boilerplate/app.js | 0 coder-base/apps/boilerplate/meta.json | 0 coder-base/apps/coder/app.js | 0 coder-base/apps/coder/meta.json | 0 coder-base/apps/coderlib/app.js | 0 coder-base/apps/coderlib/meta.json | 0 coder-base/apps/editor/app.js | 0 coder-base/apps/editor/meta.json | 0 coder-base/apps/eyeball/app.js | 0 coder-base/apps/eyeball/meta.json | 0 coder-base/apps/game2d/app.js | 0 coder-base/apps/game2d/meta.json | 0 coder-base/apps/hello_coder/app.js | 0 coder-base/apps/hello_coder/meta.json | 0 coder-base/apps/node_js_tests/app.js | 30 + coder-base/apps/node_js_tests/meta.json | 8 + coder-base/apps/space_rocks_/app.js | 0 coder-base/apps/space_rocks_/meta.json | 0 coder-base/apps/wifi/app.js | 0 coder-base/apps/wifi/meta.json | 0 coder-base/certs/.placeholder | 0 coder-base/config.js | 0 coder-base/device.json | 4 +- coder-base/device.json.reset | 0 coder-base/node_modules_orig/.bin/express | 1 + coder-base/node_modules_orig/.bin/nodezip | 1 + .../node_modules_orig/bcrypt/.lock-wscript | 9 + .../node_modules_orig/bcrypt/.npmignore | 5 + .../node_modules_orig/bcrypt/.travis.yml | 4 + coder-base/node_modules_orig/bcrypt/CHANGELOG | 46 + coder-base/node_modules_orig/bcrypt/LICENSE | 19 + coder-base/node_modules_orig/bcrypt/Makefile | 22 + coder-base/node_modules_orig/bcrypt/README.md | 243 +++ coder-base/node_modules_orig/bcrypt/bcrypt.js | 189 ++ .../node_modules_orig/bcrypt/binding.gyp | 42 + .../bcrypt/build/.conf_check_0/test.cpp | 5 + .../.conf_check_0/testbuild/.wafpickle-7 | Bin 0 -> 794 bytes .../.conf_check_0/testbuild/Release/test_1.o | Bin 0 -> 2584 bytes .../.conf_check_0/testbuild/Release/testprog | Bin 0 -> 6242 bytes .../bcrypt/build/.wafpickle-7 | Bin 0 -> 1374 bytes .../bcrypt/build/Release/bcrypt_lib.node | Bin 0 -> 182602 bytes .../bcrypt/build/Release/src/bcrypt_1.o | Bin 0 -> 13164 bytes .../bcrypt/build/Release/src/bcrypt_node_1.o | Bin 0 -> 179808 bytes .../bcrypt/build/Release/src/blowfish_1.o | Bin 0 -> 24856 bytes .../bcrypt/build/c4che/Release.cache.py | 54 + .../bcrypt/build/c4che/build.config.py | 2 + .../node_modules_orig/bcrypt/build/config.log | 52 + .../bcrypt/examples/async_compare.js | 21 + .../bcrypt/examples/forever_gen_salt.js | 8 + .../node_modules_orig/bcrypt/package.json | 124 ++ .../node_modules_orig/bcrypt/src/bcrypt.cc | 322 ++++ .../bcrypt/src/bcrypt_node.cc | 477 +++++ .../node_modules_orig/bcrypt/src/blowfish.cc | 686 +++++++ .../node_modules_orig/bcrypt/src/node_blf.h | 111 ++ .../node_modules_orig/bcrypt/test/async.js | 137 ++ .../bcrypt/test/deprecated.js | 34 + .../bcrypt/test/repetitions.js | 118 ++ .../node_modules_orig/bcrypt/test/sync.js | 109 ++ coder-base/node_modules_orig/bcrypt/wscript | 60 + .../node_modules_orig/consolidate/.npmignore | 4 + .../node_modules_orig/consolidate/History.md | 66 + .../node_modules_orig/consolidate/Makefile | 9 + .../node_modules_orig/consolidate/Readme.md | 153 ++ .../node_modules_orig/consolidate/index.js | 1 + .../consolidate/lib/consolidate.js | 676 +++++++ .../consolidate/package.json | 60 + .../express-params/.npmignore | 4 + .../express-params/History.md | 16 + .../node_modules_orig/express-params/Makefile | 6 + .../express-params/Readme.md | 115 ++ .../node_modules_orig/express-params/index.js | 2 + .../express-params/lib/express-params.js | 89 + .../express-params/package.json | 32 + .../node_modules_orig/express/.npmignore | 9 + .../node_modules_orig/express/.travis.yml | 4 + .../node_modules_orig/express/History.md | 1091 +++++++++++ coder-base/node_modules_orig/express/LICENSE | 22 + coder-base/node_modules_orig/express/Makefile | 33 + .../node_modules_orig/express/Readme.md | 179 ++ .../node_modules_orig/express/bin/express | 422 +++++ .../node_modules_orig/express/client.js | 25 + coder-base/node_modules_orig/express/index.js | 4 + .../express/lib/application.js | 534 ++++++ .../node_modules_orig/express/lib/express.js | 92 + .../express/lib/middleware.js | 33 + .../node_modules_orig/express/lib/request.js | 493 +++++ .../node_modules_orig/express/lib/response.js | 754 ++++++++ .../express/lib/router/index.js | 273 +++ .../express/lib/router/route.js | 72 + .../node_modules_orig/express/lib/utils.js | 282 +++ .../node_modules_orig/express/lib/view.js | 76 + .../node_modules_orig/express/package.json | 87 + coder-base/node_modules_orig/express/test.js | 14 + .../node_modules_orig/mustache/.jshintrc | 5 + .../node_modules_orig/mustache/.npmignore | 10 + .../node_modules_orig/mustache/.travis.yml | 4 + coder-base/node_modules_orig/mustache/CHANGES | 34 + coder-base/node_modules_orig/mustache/LICENSE | 10 + .../node_modules_orig/mustache/README.md | 400 ++++ .../node_modules_orig/mustache/Rakefile | 68 + .../node_modules_orig/mustache/mustache.js | 610 ++++++ .../mustache/mustache.js.nuspec | 14 + .../node_modules_orig/mustache/package.json | 39 + .../mustache/test/_files/ampersand_escape.js | 3 + .../test/_files/ampersand_escape.mustache | 1 + .../mustache/test/_files/ampersand_escape.txt | 1 + .../mustache/test/_files/apostrophe.js | 4 + .../mustache/test/_files/apostrophe.mustache | 1 + .../mustache/test/_files/apostrophe.txt | 1 + .../mustache/test/_files/array_of_strings.js | 3 + .../test/_files/array_of_strings.mustache | 1 + .../mustache/test/_files/array_of_strings.txt | 1 + .../mustache/test/_files/backslashes.js | 3 + .../mustache/test/_files/backslashes.mustache | 7 + .../mustache/test/_files/backslashes.txt | 7 + .../test/_files/bug_11_eating_whitespace.js | 3 + .../_files/bug_11_eating_whitespace.mustache | 1 + .../test/_files/bug_11_eating_whitespace.txt | 1 + .../test/_files/changing_delimiters.js | 4 + .../test/_files/changing_delimiters.mustache | 1 + .../test/_files/changing_delimiters.txt | 1 + .../mustache/test/_files/check_falsy.js | 7 + .../mustache/test/_files/check_falsy.mustache | 1 + .../mustache/test/_files/check_falsy.txt | 1 + .../mustache/test/_files/comments.js | 5 + .../mustache/test/_files/comments.mustache | 1 + .../mustache/test/_files/comments.txt | 1 + .../mustache/test/_files/complex.js | 19 + .../mustache/test/_files/complex.mustache | 16 + .../mustache/test/_files/complex.txt | 6 + .../mustache/test/_files/context_lookup.js | 8 + .../test/_files/context_lookup.mustache | 1 + .../mustache/test/_files/context_lookup.txt | 1 + .../mustache/test/_files/delimiters.js | 6 + .../mustache/test/_files/delimiters.mustache | 7 + .../mustache/test/_files/delimiters.txt | 5 + .../test/_files/disappearing_whitespace.js | 4 + .../_files/disappearing_whitespace.mustache | 1 + .../test/_files/disappearing_whitespace.txt | 1 + .../mustache/test/_files/dot_notation.js | 23 + .../test/_files/dot_notation.mustache | 9 + .../mustache/test/_files/dot_notation.txt | 9 + .../mustache/test/_files/double_render.js | 5 + .../test/_files/double_render.mustache | 1 + .../mustache/test/_files/double_render.txt | 1 + .../mustache/test/_files/empty_list.js | 3 + .../mustache/test/_files/empty_list.mustache | 4 + .../mustache/test/_files/empty_list.txt | 1 + .../mustache/test/_files/empty_sections.js | 1 + .../test/_files/empty_sections.mustache | 1 + .../mustache/test/_files/empty_sections.txt | 1 + .../mustache/test/_files/empty_string.js | 6 + .../test/_files/empty_string.mustache | 1 + .../mustache/test/_files/empty_string.txt | 1 + .../mustache/test/_files/empty_template.js | 1 + .../test/_files/empty_template.mustache | 1 + .../mustache/test/_files/empty_template.txt | 1 + .../mustache/test/_files/error_not_found.js | 3 + .../test/_files/error_not_found.mustache | 1 + .../mustache/test/_files/error_not_found.txt | 0 .../mustache/test/_files/escaped.js | 6 + .../mustache/test/_files/escaped.mustache | 2 + .../mustache/test/_files/escaped.txt | 2 + .../mustache/test/_files/falsy.js | 8 + .../mustache/test/_files/falsy.mustache | 12 + .../mustache/test/_files/falsy.txt | 12 + .../test/_files/grandparent_context.js | 19 + .../test/_files/grandparent_context.mustache | 10 + .../test/_files/grandparent_context.txt | 17 + .../test/_files/higher_order_sections.js | 9 + .../_files/higher_order_sections.mustache | 1 + .../test/_files/higher_order_sections.txt | 1 + .../mustache/test/_files/included_tag.js | 3 + .../test/_files/included_tag.mustache | 1 + .../mustache/test/_files/included_tag.txt | 1 + .../mustache/test/_files/inverted_section.js | 3 + .../test/_files/inverted_section.mustache | 3 + .../mustache/test/_files/inverted_section.txt | 3 + .../test/_files/keys_with_questionmarks.js | 5 + .../_files/keys_with_questionmarks.mustache | 3 + .../test/_files/keys_with_questionmarks.txt | 1 + .../test/_files/malicious_template.js | 1 + .../test/_files/malicious_template.mustache | 5 + .../test/_files/malicious_template.txt | 2 + .../mustache/test/_files/multiline_comment.js | 1 + .../test/_files/multiline_comment.mustache | 6 + .../test/_files/multiline_comment.txt | 1 + .../_files/nested_higher_order_sections.js | 8 + .../nested_higher_order_sections.mustache | 1 + .../_files/nested_higher_order_sections.txt | 1 + .../mustache/test/_files/nested_iterating.js | 8 + .../test/_files/nested_iterating.mustache | 1 + .../mustache/test/_files/nested_iterating.txt | 1 + .../mustache/test/_files/nesting.js | 7 + .../mustache/test/_files/nesting.mustache | 5 + .../mustache/test/_files/nesting.txt | 3 + .../mustache/test/_files/nesting_same_name.js | 8 + .../test/_files/nesting_same_name.mustache | 1 + .../test/_files/nesting_same_name.txt | 1 + .../mustache/test/_files/null_string.js | 10 + .../mustache/test/_files/null_string.mustache | 6 + .../mustache/test/_files/null_string.txt | 6 + .../mustache/test/_files/null_view.js | 4 + .../mustache/test/_files/null_view.mustache | 1 + .../mustache/test/_files/null_view.txt | 1 + .../mustache/test/_files/partial_array.js | 3 + .../test/_files/partial_array.mustache | 1 + .../test/_files/partial_array.partial | 4 + .../mustache/test/_files/partial_array.txt | 5 + .../test/_files/partial_array_of_partials.js | 8 + .../_files/partial_array_of_partials.mustache | 4 + .../_files/partial_array_of_partials.partial | 1 + .../test/_files/partial_array_of_partials.txt | 5 + .../partial_array_of_partials_implicit.js | 3 + ...artial_array_of_partials_implicit.mustache | 4 + ...partial_array_of_partials_implicit.partial | 1 + .../partial_array_of_partials_implicit.txt | 5 + .../mustache/test/_files/partial_empty.js | 3 + .../test/_files/partial_empty.mustache | 2 + .../test/_files/partial_empty.partial | 0 .../mustache/test/_files/partial_empty.txt | 1 + .../mustache/test/_files/partial_template.js | 6 + .../test/_files/partial_template.mustache | 2 + .../test/_files/partial_template.partial | 1 + .../mustache/test/_files/partial_template.txt | 2 + .../mustache/test/_files/partial_view.js | 14 + .../test/_files/partial_view.mustache | 3 + .../mustache/test/_files/partial_view.partial | 5 + .../mustache/test/_files/partial_view.txt | 5 + .../test/_files/partial_whitespace.js | 14 + .../test/_files/partial_whitespace.mustache | 3 + .../test/_files/partial_whitespace.partial | 5 + .../test/_files/partial_whitespace.txt | 5 + .../test/_files/recursion_with_same_names.js | 8 + .../_files/recursion_with_same_names.mustache | 7 + .../test/_files/recursion_with_same_names.txt | 7 + .../test/_files/reuse_of_enumerables.js | 6 + .../test/_files/reuse_of_enumerables.mustache | 8 + .../test/_files/reuse_of_enumerables.txt | 8 + .../test/_files/section_as_context.js | 10 + .../test/_files/section_as_context.mustache | 9 + .../test/_files/section_as_context.txt | 6 + .../mustache/test/_files/simple.js | 8 + .../mustache/test/_files/simple.mustache | 5 + .../mustache/test/_files/simple.txt | 3 + .../mustache/test/_files/string_as_context.js | 4 + .../test/_files/string_as_context.mustache | 5 + .../test/_files/string_as_context.txt | 5 + .../mustache/test/_files/two_in_a_row.js | 4 + .../test/_files/two_in_a_row.mustache | 1 + .../mustache/test/_files/two_in_a_row.txt | 1 + .../mustache/test/_files/two_sections.js | 1 + .../test/_files/two_sections.mustache | 4 + .../mustache/test/_files/two_sections.txt | 0 .../mustache/test/_files/unescaped.js | 5 + .../mustache/test/_files/unescaped.mustache | 1 + .../mustache/test/_files/unescaped.txt | 1 + .../mustache/test/_files/whitespace.js | 4 + .../mustache/test/_files/whitespace.mustache | 4 + .../mustache/test/_files/whitespace.txt | 4 + .../mustache/test/context-test.js | 51 + .../node_modules_orig/mustache/test/helper.js | 2 + .../mustache/test/parse-test.js | 106 ++ .../mustache/test/render-test.js | 68 + .../mustache/test/scanner-test.js | 78 + .../mustache/test/writer-test.js | 43 + .../mustache/wrappers/dojo/mustache.js.post | 4 + .../mustache/wrappers/dojo/mustache.js.pre | 9 + .../mustache/wrappers/jquery/mustache.js.post | 14 + .../mustache/wrappers/jquery/mustache.js.pre | 9 + .../wrappers/mootools/mustache.js.post | 5 + .../wrappers/mootools/mustache.js.pre | 2 + .../wrappers/qooxdoo/mustache.js.post | 9 + .../mustache/wrappers/qooxdoo/mustache.js.pre | 134 ++ coder-base/node_modules_orig/redis/.npmignore | 1 + coder-base/node_modules_orig/redis/README.md | 691 +++++++ .../redis/benches/buffer_bench.js | 89 + .../redis/benches/hiredis_parser.js | 38 + .../redis/benches/re_sub_test.js | 14 + .../redis/benches/reconnect_test.js | 29 + .../redis/benches/stress/codec.js | 16 + .../redis/benches/stress/pubsub/pub.js | 38 + .../redis/benches/stress/pubsub/run | 10 + .../redis/benches/stress/pubsub/server.js | 23 + .../redis/benches/stress/rpushblpop/pub.js | 49 + .../redis/benches/stress/rpushblpop/run | 6 + .../redis/benches/stress/rpushblpop/server.js | 30 + .../redis/benches/stress/speed/00 | 13 + .../redis/benches/stress/speed/plot | 13 + .../redis/benches/stress/speed/size-rate.png | Bin 0 -> 6672 bytes .../redis/benches/stress/speed/speed.js | 84 + .../redis/benches/sub_quit_test.js | 18 + .../node_modules_orig/redis/changelog.md | 240 +++ .../redis/diff_multi_bench_output.js | 87 + .../node_modules_orig/redis/examples/auth.js | 5 + .../redis/examples/backpressure_drain.js | 33 + .../node_modules_orig/redis/examples/eval.js | 9 + .../redis/examples/extend.js | 24 + .../node_modules_orig/redis/examples/file.js | 32 + .../node_modules_orig/redis/examples/mget.js | 5 + .../redis/examples/monitor.js | 10 + .../node_modules_orig/redis/examples/multi.js | 46 + .../redis/examples/multi2.js | 29 + .../redis/examples/psubscribe.js | 33 + .../redis/examples/pub_sub.js | 41 + .../redis/examples/simple.js | 24 + .../node_modules_orig/redis/examples/sort.js | 17 + .../redis/examples/subqueries.js | 15 + .../redis/examples/subquery.js | 19 + .../redis/examples/unix_socket.js | 29 + .../redis/examples/web_server.js | 31 + .../redis/generate_commands.js | 39 + coder-base/node_modules_orig/redis/index.js | 1113 +++++++++++ .../node_modules_orig/redis/lib/commands.js | 147 ++ .../redis/lib/parser/hiredis.js | 46 + .../redis/lib/parser/javascript.js | 298 +++ .../node_modules_orig/redis/lib/queue.js | 59 + .../node_modules_orig/redis/lib/to_array.js | 12 + .../node_modules_orig/redis/lib/util.js | 11 + .../node_modules_orig/redis/multi_bench.js | 222 +++ .../node_modules_orig/redis/package.json | 38 + coder-base/node_modules_orig/redis/test.js | 1675 +++++++++++++++++ coder-base/node_modules_orig/redis/test3.js | 18 + .../node_modules_orig/socket.io/.npmignore | 3 + .../node_modules_orig/socket.io/.travis.yml | 6 + .../node_modules_orig/socket.io/History.md | 310 +++ .../node_modules_orig/socket.io/LICENSE | 22 + .../node_modules_orig/socket.io/Makefile | 31 + .../node_modules_orig/socket.io/Readme.md | 364 ++++ .../socket.io/benchmarks/decode.bench.js | 64 + .../socket.io/benchmarks/encode.bench.js | 90 + .../socket.io/benchmarks/runner.js | 55 + .../node_modules_orig/socket.io/index.js | 8 + .../node_modules_orig/socket.io/lib/index.js | 131 ++ .../node_modules_orig/socket.io/lib/logger.js | 97 + .../socket.io/lib/manager.js | 1026 ++++++++++ .../socket.io/lib/namespace.js | 355 ++++ .../node_modules_orig/socket.io/lib/parser.js | 249 +++ .../socket.io/lib/socket.io.js | 143 ++ .../node_modules_orig/socket.io/lib/socket.js | 369 ++++ .../node_modules_orig/socket.io/lib/static.js | 395 ++++ .../node_modules_orig/socket.io/lib/store.js | 98 + .../socket.io/lib/stores/memory.js | 143 ++ .../socket.io/lib/stores/redis.js | 269 +++ .../socket.io/lib/transport.js | 534 ++++++ .../socket.io/lib/transports/flashsocket.js | 129 ++ .../socket.io/lib/transports/htmlfile.js | 82 + .../socket.io/lib/transports/http-polling.js | 147 ++ .../socket.io/lib/transports/http.js | 121 ++ .../socket.io/lib/transports/index.js | 12 + .../socket.io/lib/transports/jsonp-polling.js | 97 + .../socket.io/lib/transports/websocket.js | 36 + .../lib/transports/websocket/default.js | 362 ++++ .../lib/transports/websocket/hybi-07-12.js | 622 ++++++ .../lib/transports/websocket/hybi-16.js | 622 ++++++ .../lib/transports/websocket/index.js | 11 + .../socket.io/lib/transports/xhr-polling.js | 69 + .../node_modules_orig/socket.io/lib/util.js | 50 + .../node_modules_orig/socket.io/package.json | 72 + coder-base/package.json | 26 +- coder-base/server.js | 0 coder-base/static/apps/auth/css/index.css | 0 coder-base/static/apps/auth/js/index.js | 0 .../static/apps/boilerplate/css/index.css | 0 .../static/apps/boilerplate/js/index.js | 0 coder-base/static/apps/coder/css/index.css | 0 coder-base/static/apps/coder/js/index.js | 0 .../static/apps/coder/media/myapps_tip.png | Bin .../static/apps/coder/media/newapp_tip.png | Bin .../static/apps/coder/media/settings_tip.png | Bin coder-base/static/apps/coderlib/css/index.css | 0 coder-base/static/apps/coderlib/js/index.js | 0 coder-base/static/apps/editor/css/index.css | 0 coder-base/static/apps/editor/js/index.js | 0 coder-base/static/apps/eyeball/css/index.css | 0 coder-base/static/apps/eyeball/js/index.js | 0 coder-base/static/apps/game2d/css/index.css | 0 coder-base/static/apps/game2d/js/index.js | 0 .../static/apps/hello_coder/css/index.css | 0 .../static/apps/hello_coder/js/index.js | 0 .../static/apps/node_js_tests/css/index.css | 4 + .../static/apps/node_js_tests/js/index.js | 6 + .../static/apps/space_rocks_/css/index.css | 0 .../static/apps/space_rocks_/js/index.js | 0 .../apps/space_rocks_/media/die_ship.mp3 | Bin .../apps/space_rocks_/media/die_ship.ogg | Bin .../apps/space_rocks_/media/die_ship.wav | Bin .../apps/space_rocks_/media/die_spacerock.mp3 | Bin .../apps/space_rocks_/media/die_spacerock.ogg | Bin .../apps/space_rocks_/media/die_spacerock.wav | Bin .../space_rocks_/media/spacerocks_shoot.mp3 | Bin .../space_rocks_/media/spacerocks_shoot.ogg | Bin .../space_rocks_/media/spacerocks_shoot.wav | Bin .../static/apps/space_rocks_/media/thrust.mp3 | Bin .../static/apps/space_rocks_/media/thrust.ogg | Bin .../static/apps/space_rocks_/media/thrust.wav | Bin coder-base/static/apps/wifi/css/index.css | 0 coder-base/static/apps/wifi/js/index.js | 0 coder-base/static/common/ace-min/LICENSE | 0 coder-base/static/common/ace-min/ace.js | 0 .../common/ace-min/ext-static_highlight.js | 0 .../static/common/ace-min/ext-textarea.js | 0 .../static/common/ace-min/keybinding-emacs.js | 0 .../static/common/ace-min/keybinding-vim.js | 0 .../static/common/ace-min/mode-asciidoc.js | 0 .../static/common/ace-min/mode-c9search.js | 0 .../static/common/ace-min/mode-c_cpp.js | 0 .../static/common/ace-min/mode-clojure.js | 0 .../static/common/ace-min/mode-coffee.js | 0 .../static/common/ace-min/mode-coldfusion.js | 0 .../static/common/ace-min/mode-csharp.js | 0 coder-base/static/common/ace-min/mode-css.js | 0 coder-base/static/common/ace-min/mode-diff.js | 0 coder-base/static/common/ace-min/mode-glsl.js | 0 .../static/common/ace-min/mode-golang.js | 0 .../static/common/ace-min/mode-groovy.js | 0 coder-base/static/common/ace-min/mode-haxe.js | 0 coder-base/static/common/ace-min/mode-html.js | 0 coder-base/static/common/ace-min/mode-jade.js | 0 coder-base/static/common/ace-min/mode-java.js | 0 .../static/common/ace-min/mode-javascript.js | 0 coder-base/static/common/ace-min/mode-json.js | 0 coder-base/static/common/ace-min/mode-jsp.js | 0 coder-base/static/common/ace-min/mode-jsx.js | 0 .../static/common/ace-min/mode-latex.js | 0 coder-base/static/common/ace-min/mode-less.js | 0 .../static/common/ace-min/mode-liquid.js | 0 coder-base/static/common/ace-min/mode-lua.js | 0 .../static/common/ace-min/mode-luapage.js | 0 .../static/common/ace-min/mode-markdown.js | 0 .../static/common/ace-min/mode-ocaml.js | 0 coder-base/static/common/ace-min/mode-perl.js | 0 .../static/common/ace-min/mode-pgsql.js | 0 coder-base/static/common/ace-min/mode-php.js | 0 .../static/common/ace-min/mode-powershell.js | 0 .../static/common/ace-min/mode-python.js | 0 coder-base/static/common/ace-min/mode-ruby.js | 0 coder-base/static/common/ace-min/mode-scad.js | 0 .../static/common/ace-min/mode-scala.js | 0 coder-base/static/common/ace-min/mode-scss.js | 0 coder-base/static/common/ace-min/mode-sh.js | 0 coder-base/static/common/ace-min/mode-sql.js | 0 coder-base/static/common/ace-min/mode-svg.js | 0 coder-base/static/common/ace-min/mode-tcl.js | 0 coder-base/static/common/ace-min/mode-text.js | 0 .../static/common/ace-min/mode-textile.js | 0 .../static/common/ace-min/mode-typescript.js | 0 coder-base/static/common/ace-min/mode-xml.js | 0 .../static/common/ace-min/mode-xquery.js | 0 coder-base/static/common/ace-min/mode-yaml.js | 0 .../static/common/ace-min/theme-ambiance.js | 0 .../static/common/ace-min/theme-chrome.js | 0 .../static/common/ace-min/theme-clouds.js | 0 .../common/ace-min/theme-clouds_midnight.js | 0 .../static/common/ace-min/theme-cobalt.js | 0 .../static/common/ace-min/theme-coder.js | 0 .../common/ace-min/theme-crimson_editor.js | 0 .../static/common/ace-min/theme-dawn.js | 0 .../common/ace-min/theme-dreamweaver.js | 0 .../static/common/ace-min/theme-eclipse.js | 0 .../static/common/ace-min/theme-github.js | 0 .../common/ace-min/theme-idle_fingers.js | 0 coder-base/static/common/ace-min/theme-kr.js | 0 .../static/common/ace-min/theme-merbivore.js | 0 .../common/ace-min/theme-merbivore_soft.js | 0 .../common/ace-min/theme-mono_industrial.js | 0 .../static/common/ace-min/theme-monokai.js | 0 .../common/ace-min/theme-pastel_on_dark.js | 0 .../common/ace-min/theme-solarized_dark.js | 0 .../common/ace-min/theme-solarized_light.js | 0 .../static/common/ace-min/theme-textmate.js | 0 .../static/common/ace-min/theme-tomorrow.js | 0 .../common/ace-min/theme-tomorrow_night.js | 0 .../ace-min/theme-tomorrow_night_blue.js | 0 .../ace-min/theme-tomorrow_night_bright.js | 0 .../ace-min/theme-tomorrow_night_eighties.js | 0 .../static/common/ace-min/theme-twilight.js | 0 .../common/ace-min/theme-vibrant_ink.js | 0 .../static/common/ace-min/theme-xcode.js | 0 .../static/common/ace-min/worker-coffee.js | 0 .../static/common/ace-min/worker-css.js | 0 .../common/ace-min/worker-javascript.js | 0 .../static/common/ace-min/worker-json.js | 0 .../static/common/ace-min/worker-xquery.js | 0 .../static/common/js/jquery.fileupload.js | 0 .../common/js/jquery.iframe-transport.js | 0 coder-base/static/common/js/jquery.min.js | 0 .../static/common/js/jquery.ui.widget.js | 0 .../static/common/media/coder_icons.png | Bin coder-base/tmp/.placeholder | 0 coder-base/views/404.html | 0 coder-base/views/apps/auth/index.html | 0 coder-base/views/apps/boilerplate/index.html | 0 coder-base/views/apps/coder/index.html | 0 coder-base/views/apps/coderlib/index.html | 0 coder-base/views/apps/editor/index.html | 0 coder-base/views/apps/eyeball/index.html | 0 coder-base/views/apps/game2d/index.html | 0 coder-base/views/apps/hello_coder/index.html | 0 .../views/apps/node_js_tests/index.html | 32 + coder-base/views/apps/space_rocks_/index.html | 0 coder-base/views/apps/wifi/index.html | 0 coder-base/views/index.html | 0 findcoder-appengine/api/__init__.py | 0 findcoder-appengine/api/coder.py | 0 findcoder-appengine/app.yaml | 0 findcoder-appengine/index.py | 0 .../static/assets/css/index.css | 0 findcoder-appengine/static/assets/js/index.js | 0 .../static/assets/js/jquery.min.js | 0 findcoder-appengine/views/index.html | 0 installer/macosx/CoderSetup.py | 0 installer/macosx/buildcmd.txt | 0 installer/macosx/clonesdcard.txt | 0 installer/macosx/codersd.icns | Bin installer/macosx/formatsdcard.py | 0 installer/macosx/installerlogo.gif | Bin installer/macosx/setup.py | 0 raspbian-addons/etc/default/coder-daemon | 0 raspbian-addons/etc/default/isc-dhcp-server | 0 raspbian-addons/etc/dhcp/dhcpd.conf | 0 raspbian-addons/etc/iptables.up.rules | 0 raspbian-addons/etc/network/interfaces | 0 raspbian-addons/etc/ssh/sshd_config | 0 raspbian-addons/etc/sudoers | 0 .../etc/wpa_supplicant/wpa_supplicant.conf | 0 .../wpa_supplicant/wpa_supplicant.conf.reset | 0 532 files changed, 23883 insertions(+), 15 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 coder-base/apps/auth/app.js mode change 100644 => 100755 coder-base/apps/auth/meta.json mode change 100644 => 100755 coder-base/apps/boilerplate/app.js mode change 100644 => 100755 coder-base/apps/boilerplate/meta.json mode change 100644 => 100755 coder-base/apps/coder/app.js mode change 100644 => 100755 coder-base/apps/coder/meta.json mode change 100644 => 100755 coder-base/apps/coderlib/app.js mode change 100644 => 100755 coder-base/apps/coderlib/meta.json mode change 100644 => 100755 coder-base/apps/editor/app.js mode change 100644 => 100755 coder-base/apps/editor/meta.json mode change 100644 => 100755 coder-base/apps/eyeball/app.js mode change 100644 => 100755 coder-base/apps/eyeball/meta.json mode change 100644 => 100755 coder-base/apps/game2d/app.js mode change 100644 => 100755 coder-base/apps/game2d/meta.json mode change 100644 => 100755 coder-base/apps/hello_coder/app.js mode change 100644 => 100755 coder-base/apps/hello_coder/meta.json create mode 100755 coder-base/apps/node_js_tests/app.js create mode 100755 coder-base/apps/node_js_tests/meta.json mode change 100644 => 100755 coder-base/apps/space_rocks_/app.js mode change 100644 => 100755 coder-base/apps/space_rocks_/meta.json mode change 100644 => 100755 coder-base/apps/wifi/app.js mode change 100644 => 100755 coder-base/apps/wifi/meta.json mode change 100644 => 100755 coder-base/certs/.placeholder mode change 100644 => 100755 coder-base/config.js mode change 100644 => 100755 coder-base/device.json mode change 100644 => 100755 coder-base/device.json.reset create mode 120000 coder-base/node_modules_orig/.bin/express create mode 120000 coder-base/node_modules_orig/.bin/nodezip create mode 100755 coder-base/node_modules_orig/bcrypt/.lock-wscript create mode 100755 coder-base/node_modules_orig/bcrypt/.npmignore create mode 100755 coder-base/node_modules_orig/bcrypt/.travis.yml create mode 100755 coder-base/node_modules_orig/bcrypt/CHANGELOG create mode 100755 coder-base/node_modules_orig/bcrypt/LICENSE create mode 100755 coder-base/node_modules_orig/bcrypt/Makefile create mode 100755 coder-base/node_modules_orig/bcrypt/README.md create mode 100755 coder-base/node_modules_orig/bcrypt/bcrypt.js create mode 100755 coder-base/node_modules_orig/bcrypt/binding.gyp create mode 100755 coder-base/node_modules_orig/bcrypt/build/.conf_check_0/test.cpp create mode 100755 coder-base/node_modules_orig/bcrypt/build/.conf_check_0/testbuild/.wafpickle-7 create mode 100755 coder-base/node_modules_orig/bcrypt/build/.conf_check_0/testbuild/Release/test_1.o create mode 100755 coder-base/node_modules_orig/bcrypt/build/.conf_check_0/testbuild/Release/testprog create mode 100755 coder-base/node_modules_orig/bcrypt/build/.wafpickle-7 create mode 100755 coder-base/node_modules_orig/bcrypt/build/Release/bcrypt_lib.node create mode 100755 coder-base/node_modules_orig/bcrypt/build/Release/src/bcrypt_1.o create mode 100755 coder-base/node_modules_orig/bcrypt/build/Release/src/bcrypt_node_1.o create mode 100755 coder-base/node_modules_orig/bcrypt/build/Release/src/blowfish_1.o create mode 100755 coder-base/node_modules_orig/bcrypt/build/c4che/Release.cache.py create mode 100755 coder-base/node_modules_orig/bcrypt/build/c4che/build.config.py create mode 100755 coder-base/node_modules_orig/bcrypt/build/config.log create mode 100755 coder-base/node_modules_orig/bcrypt/examples/async_compare.js create mode 100755 coder-base/node_modules_orig/bcrypt/examples/forever_gen_salt.js create mode 100755 coder-base/node_modules_orig/bcrypt/package.json create mode 100755 coder-base/node_modules_orig/bcrypt/src/bcrypt.cc create mode 100755 coder-base/node_modules_orig/bcrypt/src/bcrypt_node.cc create mode 100755 coder-base/node_modules_orig/bcrypt/src/blowfish.cc create mode 100755 coder-base/node_modules_orig/bcrypt/src/node_blf.h create mode 100755 coder-base/node_modules_orig/bcrypt/test/async.js create mode 100755 coder-base/node_modules_orig/bcrypt/test/deprecated.js create mode 100755 coder-base/node_modules_orig/bcrypt/test/repetitions.js create mode 100755 coder-base/node_modules_orig/bcrypt/test/sync.js create mode 100755 coder-base/node_modules_orig/bcrypt/wscript create mode 100755 coder-base/node_modules_orig/consolidate/.npmignore create mode 100755 coder-base/node_modules_orig/consolidate/History.md create mode 100755 coder-base/node_modules_orig/consolidate/Makefile create mode 100755 coder-base/node_modules_orig/consolidate/Readme.md create mode 100755 coder-base/node_modules_orig/consolidate/index.js create mode 100755 coder-base/node_modules_orig/consolidate/lib/consolidate.js create mode 100755 coder-base/node_modules_orig/consolidate/package.json create mode 100755 coder-base/node_modules_orig/express-params/.npmignore create mode 100755 coder-base/node_modules_orig/express-params/History.md create mode 100755 coder-base/node_modules_orig/express-params/Makefile create mode 100755 coder-base/node_modules_orig/express-params/Readme.md create mode 100755 coder-base/node_modules_orig/express-params/index.js create mode 100755 coder-base/node_modules_orig/express-params/lib/express-params.js create mode 100755 coder-base/node_modules_orig/express-params/package.json create mode 100755 coder-base/node_modules_orig/express/.npmignore create mode 100755 coder-base/node_modules_orig/express/.travis.yml create mode 100755 coder-base/node_modules_orig/express/History.md create mode 100755 coder-base/node_modules_orig/express/LICENSE create mode 100755 coder-base/node_modules_orig/express/Makefile create mode 100755 coder-base/node_modules_orig/express/Readme.md create mode 100755 coder-base/node_modules_orig/express/bin/express create mode 100755 coder-base/node_modules_orig/express/client.js create mode 100755 coder-base/node_modules_orig/express/index.js create mode 100755 coder-base/node_modules_orig/express/lib/application.js create mode 100755 coder-base/node_modules_orig/express/lib/express.js create mode 100755 coder-base/node_modules_orig/express/lib/middleware.js create mode 100755 coder-base/node_modules_orig/express/lib/request.js create mode 100755 coder-base/node_modules_orig/express/lib/response.js create mode 100755 coder-base/node_modules_orig/express/lib/router/index.js create mode 100755 coder-base/node_modules_orig/express/lib/router/route.js create mode 100755 coder-base/node_modules_orig/express/lib/utils.js create mode 100755 coder-base/node_modules_orig/express/lib/view.js create mode 100755 coder-base/node_modules_orig/express/package.json create mode 100755 coder-base/node_modules_orig/express/test.js create mode 100755 coder-base/node_modules_orig/mustache/.jshintrc create mode 100755 coder-base/node_modules_orig/mustache/.npmignore create mode 100755 coder-base/node_modules_orig/mustache/.travis.yml create mode 100755 coder-base/node_modules_orig/mustache/CHANGES create mode 100755 coder-base/node_modules_orig/mustache/LICENSE create mode 100755 coder-base/node_modules_orig/mustache/README.md create mode 100755 coder-base/node_modules_orig/mustache/Rakefile create mode 100755 coder-base/node_modules_orig/mustache/mustache.js create mode 100755 coder-base/node_modules_orig/mustache/mustache.js.nuspec create mode 100755 coder-base/node_modules_orig/mustache/package.json create mode 100755 coder-base/node_modules_orig/mustache/test/_files/ampersand_escape.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/ampersand_escape.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/ampersand_escape.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/apostrophe.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/apostrophe.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/apostrophe.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/array_of_strings.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/array_of_strings.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/array_of_strings.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/backslashes.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/backslashes.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/backslashes.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/bug_11_eating_whitespace.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/bug_11_eating_whitespace.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/bug_11_eating_whitespace.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/changing_delimiters.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/changing_delimiters.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/changing_delimiters.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/check_falsy.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/check_falsy.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/check_falsy.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/comments.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/comments.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/comments.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/complex.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/complex.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/complex.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/context_lookup.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/context_lookup.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/context_lookup.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/delimiters.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/delimiters.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/delimiters.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/disappearing_whitespace.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/disappearing_whitespace.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/disappearing_whitespace.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/dot_notation.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/dot_notation.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/dot_notation.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/double_render.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/double_render.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/double_render.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/empty_list.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/empty_list.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/empty_list.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/empty_sections.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/empty_sections.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/empty_sections.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/empty_string.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/empty_string.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/empty_string.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/empty_template.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/empty_template.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/empty_template.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/error_not_found.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/error_not_found.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/error_not_found.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/escaped.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/escaped.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/escaped.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/falsy.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/falsy.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/falsy.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/grandparent_context.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/grandparent_context.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/grandparent_context.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/higher_order_sections.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/higher_order_sections.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/higher_order_sections.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/included_tag.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/included_tag.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/included_tag.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/inverted_section.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/inverted_section.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/inverted_section.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/keys_with_questionmarks.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/keys_with_questionmarks.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/keys_with_questionmarks.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/malicious_template.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/malicious_template.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/malicious_template.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/multiline_comment.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/multiline_comment.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/multiline_comment.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/nested_higher_order_sections.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/nested_higher_order_sections.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/nested_higher_order_sections.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/nested_iterating.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/nested_iterating.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/nested_iterating.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/nesting.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/nesting.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/nesting.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/nesting_same_name.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/nesting_same_name.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/nesting_same_name.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/null_string.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/null_string.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/null_string.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/null_view.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/null_view.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/null_view.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_array.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_array.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_array.partial create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_array.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.partial create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.partial create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_empty.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_empty.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_empty.partial create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_empty.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_template.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_template.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_template.partial create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_template.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_view.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_view.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_view.partial create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_view.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.partial create mode 100755 coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/recursion_with_same_names.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/recursion_with_same_names.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/recursion_with_same_names.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/reuse_of_enumerables.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/reuse_of_enumerables.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/reuse_of_enumerables.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/section_as_context.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/section_as_context.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/section_as_context.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/simple.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/simple.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/simple.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/string_as_context.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/string_as_context.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/string_as_context.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/two_in_a_row.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/two_in_a_row.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/two_in_a_row.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/two_sections.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/two_sections.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/two_sections.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/unescaped.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/unescaped.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/unescaped.txt create mode 100755 coder-base/node_modules_orig/mustache/test/_files/whitespace.js create mode 100755 coder-base/node_modules_orig/mustache/test/_files/whitespace.mustache create mode 100755 coder-base/node_modules_orig/mustache/test/_files/whitespace.txt create mode 100755 coder-base/node_modules_orig/mustache/test/context-test.js create mode 100755 coder-base/node_modules_orig/mustache/test/helper.js create mode 100755 coder-base/node_modules_orig/mustache/test/parse-test.js create mode 100755 coder-base/node_modules_orig/mustache/test/render-test.js create mode 100755 coder-base/node_modules_orig/mustache/test/scanner-test.js create mode 100755 coder-base/node_modules_orig/mustache/test/writer-test.js create mode 100755 coder-base/node_modules_orig/mustache/wrappers/dojo/mustache.js.post create mode 100755 coder-base/node_modules_orig/mustache/wrappers/dojo/mustache.js.pre create mode 100755 coder-base/node_modules_orig/mustache/wrappers/jquery/mustache.js.post create mode 100755 coder-base/node_modules_orig/mustache/wrappers/jquery/mustache.js.pre create mode 100755 coder-base/node_modules_orig/mustache/wrappers/mootools/mustache.js.post create mode 100755 coder-base/node_modules_orig/mustache/wrappers/mootools/mustache.js.pre create mode 100755 coder-base/node_modules_orig/mustache/wrappers/qooxdoo/mustache.js.post create mode 100755 coder-base/node_modules_orig/mustache/wrappers/qooxdoo/mustache.js.pre create mode 100755 coder-base/node_modules_orig/redis/.npmignore create mode 100755 coder-base/node_modules_orig/redis/README.md create mode 100755 coder-base/node_modules_orig/redis/benches/buffer_bench.js create mode 100755 coder-base/node_modules_orig/redis/benches/hiredis_parser.js create mode 100755 coder-base/node_modules_orig/redis/benches/re_sub_test.js create mode 100755 coder-base/node_modules_orig/redis/benches/reconnect_test.js create mode 100755 coder-base/node_modules_orig/redis/benches/stress/codec.js create mode 100755 coder-base/node_modules_orig/redis/benches/stress/pubsub/pub.js create mode 100755 coder-base/node_modules_orig/redis/benches/stress/pubsub/run create mode 100755 coder-base/node_modules_orig/redis/benches/stress/pubsub/server.js create mode 100755 coder-base/node_modules_orig/redis/benches/stress/rpushblpop/pub.js create mode 100755 coder-base/node_modules_orig/redis/benches/stress/rpushblpop/run create mode 100755 coder-base/node_modules_orig/redis/benches/stress/rpushblpop/server.js create mode 100755 coder-base/node_modules_orig/redis/benches/stress/speed/00 create mode 100755 coder-base/node_modules_orig/redis/benches/stress/speed/plot create mode 100755 coder-base/node_modules_orig/redis/benches/stress/speed/size-rate.png create mode 100755 coder-base/node_modules_orig/redis/benches/stress/speed/speed.js create mode 100755 coder-base/node_modules_orig/redis/benches/sub_quit_test.js create mode 100755 coder-base/node_modules_orig/redis/changelog.md create mode 100755 coder-base/node_modules_orig/redis/diff_multi_bench_output.js create mode 100755 coder-base/node_modules_orig/redis/examples/auth.js create mode 100755 coder-base/node_modules_orig/redis/examples/backpressure_drain.js create mode 100755 coder-base/node_modules_orig/redis/examples/eval.js create mode 100755 coder-base/node_modules_orig/redis/examples/extend.js create mode 100755 coder-base/node_modules_orig/redis/examples/file.js create mode 100755 coder-base/node_modules_orig/redis/examples/mget.js create mode 100755 coder-base/node_modules_orig/redis/examples/monitor.js create mode 100755 coder-base/node_modules_orig/redis/examples/multi.js create mode 100755 coder-base/node_modules_orig/redis/examples/multi2.js create mode 100755 coder-base/node_modules_orig/redis/examples/psubscribe.js create mode 100755 coder-base/node_modules_orig/redis/examples/pub_sub.js create mode 100755 coder-base/node_modules_orig/redis/examples/simple.js create mode 100755 coder-base/node_modules_orig/redis/examples/sort.js create mode 100755 coder-base/node_modules_orig/redis/examples/subqueries.js create mode 100755 coder-base/node_modules_orig/redis/examples/subquery.js create mode 100755 coder-base/node_modules_orig/redis/examples/unix_socket.js create mode 100755 coder-base/node_modules_orig/redis/examples/web_server.js create mode 100755 coder-base/node_modules_orig/redis/generate_commands.js create mode 100755 coder-base/node_modules_orig/redis/index.js create mode 100755 coder-base/node_modules_orig/redis/lib/commands.js create mode 100755 coder-base/node_modules_orig/redis/lib/parser/hiredis.js create mode 100755 coder-base/node_modules_orig/redis/lib/parser/javascript.js create mode 100755 coder-base/node_modules_orig/redis/lib/queue.js create mode 100755 coder-base/node_modules_orig/redis/lib/to_array.js create mode 100755 coder-base/node_modules_orig/redis/lib/util.js create mode 100755 coder-base/node_modules_orig/redis/multi_bench.js create mode 100755 coder-base/node_modules_orig/redis/package.json create mode 100755 coder-base/node_modules_orig/redis/test.js create mode 100755 coder-base/node_modules_orig/redis/test3.js create mode 100755 coder-base/node_modules_orig/socket.io/.npmignore create mode 100755 coder-base/node_modules_orig/socket.io/.travis.yml create mode 100755 coder-base/node_modules_orig/socket.io/History.md create mode 100755 coder-base/node_modules_orig/socket.io/LICENSE create mode 100755 coder-base/node_modules_orig/socket.io/Makefile create mode 100755 coder-base/node_modules_orig/socket.io/Readme.md create mode 100755 coder-base/node_modules_orig/socket.io/benchmarks/decode.bench.js create mode 100755 coder-base/node_modules_orig/socket.io/benchmarks/encode.bench.js create mode 100755 coder-base/node_modules_orig/socket.io/benchmarks/runner.js create mode 100755 coder-base/node_modules_orig/socket.io/index.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/index.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/logger.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/manager.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/namespace.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/parser.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/socket.io.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/socket.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/static.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/store.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/stores/memory.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/stores/redis.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/transport.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/transports/flashsocket.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/transports/htmlfile.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/transports/http-polling.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/transports/http.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/transports/index.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/transports/jsonp-polling.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/transports/websocket.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/transports/websocket/default.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/transports/websocket/hybi-07-12.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/transports/websocket/hybi-16.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/transports/websocket/index.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/transports/xhr-polling.js create mode 100755 coder-base/node_modules_orig/socket.io/lib/util.js create mode 100755 coder-base/node_modules_orig/socket.io/package.json mode change 100644 => 100755 coder-base/package.json mode change 100644 => 100755 coder-base/server.js mode change 100644 => 100755 coder-base/static/apps/auth/css/index.css mode change 100644 => 100755 coder-base/static/apps/auth/js/index.js mode change 100644 => 100755 coder-base/static/apps/boilerplate/css/index.css mode change 100644 => 100755 coder-base/static/apps/boilerplate/js/index.js mode change 100644 => 100755 coder-base/static/apps/coder/css/index.css mode change 100644 => 100755 coder-base/static/apps/coder/js/index.js mode change 100644 => 100755 coder-base/static/apps/coder/media/myapps_tip.png mode change 100644 => 100755 coder-base/static/apps/coder/media/newapp_tip.png mode change 100644 => 100755 coder-base/static/apps/coder/media/settings_tip.png mode change 100644 => 100755 coder-base/static/apps/coderlib/css/index.css mode change 100644 => 100755 coder-base/static/apps/coderlib/js/index.js mode change 100644 => 100755 coder-base/static/apps/editor/css/index.css mode change 100644 => 100755 coder-base/static/apps/editor/js/index.js mode change 100644 => 100755 coder-base/static/apps/eyeball/css/index.css mode change 100644 => 100755 coder-base/static/apps/eyeball/js/index.js mode change 100644 => 100755 coder-base/static/apps/game2d/css/index.css mode change 100644 => 100755 coder-base/static/apps/game2d/js/index.js mode change 100644 => 100755 coder-base/static/apps/hello_coder/css/index.css mode change 100644 => 100755 coder-base/static/apps/hello_coder/js/index.js create mode 100755 coder-base/static/apps/node_js_tests/css/index.css create mode 100755 coder-base/static/apps/node_js_tests/js/index.js mode change 100644 => 100755 coder-base/static/apps/space_rocks_/css/index.css mode change 100644 => 100755 coder-base/static/apps/space_rocks_/js/index.js mode change 100644 => 100755 coder-base/static/apps/space_rocks_/media/die_ship.mp3 mode change 100644 => 100755 coder-base/static/apps/space_rocks_/media/die_ship.ogg mode change 100644 => 100755 coder-base/static/apps/space_rocks_/media/die_ship.wav mode change 100644 => 100755 coder-base/static/apps/space_rocks_/media/die_spacerock.mp3 mode change 100644 => 100755 coder-base/static/apps/space_rocks_/media/die_spacerock.ogg mode change 100644 => 100755 coder-base/static/apps/space_rocks_/media/die_spacerock.wav mode change 100644 => 100755 coder-base/static/apps/space_rocks_/media/spacerocks_shoot.mp3 mode change 100644 => 100755 coder-base/static/apps/space_rocks_/media/spacerocks_shoot.ogg mode change 100644 => 100755 coder-base/static/apps/space_rocks_/media/spacerocks_shoot.wav mode change 100644 => 100755 coder-base/static/apps/space_rocks_/media/thrust.mp3 mode change 100644 => 100755 coder-base/static/apps/space_rocks_/media/thrust.ogg mode change 100644 => 100755 coder-base/static/apps/space_rocks_/media/thrust.wav mode change 100644 => 100755 coder-base/static/apps/wifi/css/index.css mode change 100644 => 100755 coder-base/static/apps/wifi/js/index.js mode change 100644 => 100755 coder-base/static/common/ace-min/LICENSE mode change 100644 => 100755 coder-base/static/common/ace-min/ace.js mode change 100644 => 100755 coder-base/static/common/ace-min/ext-static_highlight.js mode change 100644 => 100755 coder-base/static/common/ace-min/ext-textarea.js mode change 100644 => 100755 coder-base/static/common/ace-min/keybinding-emacs.js mode change 100644 => 100755 coder-base/static/common/ace-min/keybinding-vim.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-asciidoc.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-c9search.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-c_cpp.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-clojure.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-coffee.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-coldfusion.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-csharp.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-css.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-diff.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-glsl.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-golang.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-groovy.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-haxe.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-html.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-jade.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-java.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-javascript.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-json.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-jsp.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-jsx.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-latex.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-less.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-liquid.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-lua.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-luapage.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-markdown.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-ocaml.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-perl.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-pgsql.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-php.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-powershell.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-python.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-ruby.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-scad.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-scala.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-scss.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-sh.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-sql.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-svg.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-tcl.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-text.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-textile.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-typescript.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-xml.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-xquery.js mode change 100644 => 100755 coder-base/static/common/ace-min/mode-yaml.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-ambiance.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-chrome.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-clouds.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-clouds_midnight.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-cobalt.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-coder.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-crimson_editor.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-dawn.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-dreamweaver.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-eclipse.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-github.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-idle_fingers.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-kr.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-merbivore.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-merbivore_soft.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-mono_industrial.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-monokai.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-pastel_on_dark.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-solarized_dark.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-solarized_light.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-textmate.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-tomorrow.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-tomorrow_night.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-tomorrow_night_blue.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-tomorrow_night_bright.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-tomorrow_night_eighties.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-twilight.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-vibrant_ink.js mode change 100644 => 100755 coder-base/static/common/ace-min/theme-xcode.js mode change 100644 => 100755 coder-base/static/common/ace-min/worker-coffee.js mode change 100644 => 100755 coder-base/static/common/ace-min/worker-css.js mode change 100644 => 100755 coder-base/static/common/ace-min/worker-javascript.js mode change 100644 => 100755 coder-base/static/common/ace-min/worker-json.js mode change 100644 => 100755 coder-base/static/common/ace-min/worker-xquery.js mode change 100644 => 100755 coder-base/static/common/js/jquery.fileupload.js mode change 100644 => 100755 coder-base/static/common/js/jquery.iframe-transport.js mode change 100644 => 100755 coder-base/static/common/js/jquery.min.js mode change 100644 => 100755 coder-base/static/common/js/jquery.ui.widget.js mode change 100644 => 100755 coder-base/static/common/media/coder_icons.png mode change 100644 => 100755 coder-base/tmp/.placeholder mode change 100644 => 100755 coder-base/views/404.html mode change 100644 => 100755 coder-base/views/apps/auth/index.html mode change 100644 => 100755 coder-base/views/apps/boilerplate/index.html mode change 100644 => 100755 coder-base/views/apps/coder/index.html mode change 100644 => 100755 coder-base/views/apps/coderlib/index.html mode change 100644 => 100755 coder-base/views/apps/editor/index.html mode change 100644 => 100755 coder-base/views/apps/eyeball/index.html mode change 100644 => 100755 coder-base/views/apps/game2d/index.html mode change 100644 => 100755 coder-base/views/apps/hello_coder/index.html create mode 100755 coder-base/views/apps/node_js_tests/index.html mode change 100644 => 100755 coder-base/views/apps/space_rocks_/index.html mode change 100644 => 100755 coder-base/views/apps/wifi/index.html mode change 100644 => 100755 coder-base/views/index.html mode change 100644 => 100755 findcoder-appengine/api/__init__.py mode change 100644 => 100755 findcoder-appengine/api/coder.py mode change 100644 => 100755 findcoder-appengine/app.yaml mode change 100644 => 100755 findcoder-appengine/index.py mode change 100644 => 100755 findcoder-appengine/static/assets/css/index.css mode change 100644 => 100755 findcoder-appengine/static/assets/js/index.js mode change 100644 => 100755 findcoder-appengine/static/assets/js/jquery.min.js mode change 100644 => 100755 findcoder-appengine/views/index.html mode change 100644 => 100755 installer/macosx/CoderSetup.py mode change 100644 => 100755 installer/macosx/buildcmd.txt mode change 100644 => 100755 installer/macosx/clonesdcard.txt mode change 100644 => 100755 installer/macosx/codersd.icns mode change 100644 => 100755 installer/macosx/formatsdcard.py mode change 100644 => 100755 installer/macosx/installerlogo.gif mode change 100644 => 100755 installer/macosx/setup.py mode change 100644 => 100755 raspbian-addons/etc/default/coder-daemon mode change 100644 => 100755 raspbian-addons/etc/default/isc-dhcp-server mode change 100644 => 100755 raspbian-addons/etc/dhcp/dhcpd.conf mode change 100644 => 100755 raspbian-addons/etc/iptables.up.rules mode change 100644 => 100755 raspbian-addons/etc/network/interfaces mode change 100644 => 100755 raspbian-addons/etc/ssh/sshd_config mode change 100644 => 100755 raspbian-addons/etc/sudoers mode change 100644 => 100755 raspbian-addons/etc/wpa_supplicant/wpa_supplicant.conf mode change 100644 => 100755 raspbian-addons/etc/wpa_supplicant/wpa_supplicant.conf.reset diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/coder-base/apps/auth/app.js b/coder-base/apps/auth/app.js old mode 100644 new mode 100755 diff --git a/coder-base/apps/auth/meta.json b/coder-base/apps/auth/meta.json old mode 100644 new mode 100755 diff --git a/coder-base/apps/boilerplate/app.js b/coder-base/apps/boilerplate/app.js old mode 100644 new mode 100755 diff --git a/coder-base/apps/boilerplate/meta.json b/coder-base/apps/boilerplate/meta.json old mode 100644 new mode 100755 diff --git a/coder-base/apps/coder/app.js b/coder-base/apps/coder/app.js old mode 100644 new mode 100755 diff --git a/coder-base/apps/coder/meta.json b/coder-base/apps/coder/meta.json old mode 100644 new mode 100755 diff --git a/coder-base/apps/coderlib/app.js b/coder-base/apps/coderlib/app.js old mode 100644 new mode 100755 diff --git a/coder-base/apps/coderlib/meta.json b/coder-base/apps/coderlib/meta.json old mode 100644 new mode 100755 diff --git a/coder-base/apps/editor/app.js b/coder-base/apps/editor/app.js old mode 100644 new mode 100755 diff --git a/coder-base/apps/editor/meta.json b/coder-base/apps/editor/meta.json old mode 100644 new mode 100755 diff --git a/coder-base/apps/eyeball/app.js b/coder-base/apps/eyeball/app.js old mode 100644 new mode 100755 diff --git a/coder-base/apps/eyeball/meta.json b/coder-base/apps/eyeball/meta.json old mode 100644 new mode 100755 diff --git a/coder-base/apps/game2d/app.js b/coder-base/apps/game2d/app.js old mode 100644 new mode 100755 diff --git a/coder-base/apps/game2d/meta.json b/coder-base/apps/game2d/meta.json old mode 100644 new mode 100755 diff --git a/coder-base/apps/hello_coder/app.js b/coder-base/apps/hello_coder/app.js old mode 100644 new mode 100755 diff --git a/coder-base/apps/hello_coder/meta.json b/coder-base/apps/hello_coder/meta.json old mode 100644 new mode 100755 diff --git a/coder-base/apps/node_js_tests/app.js b/coder-base/apps/node_js_tests/app.js new file mode 100755 index 00000000..5e949e05 --- /dev/null +++ b/coder-base/apps/node_js_tests/app.js @@ -0,0 +1,30 @@ +exports.settings={}; +//These are dynamically updated by the runtime +//settings.appname - the app id (folder) where your app is installed +//settings.viewpath - prefix to where your view html files are located +//settings.staticurl - base url path to static assets /static/apps/appname +//settings.appurl - base url path to this app /app/appname +//settings.device_name - name given to this coder by the user, Ie."Billy's Coder" +//settings.coder_owner - name of the user, Ie. "Suzie Q." +//settings.coder_color - hex css color given to this coder. + +exports.get_routes = [ + { path:'/', handler:'index_handler' }, +]; + +exports.post_routes = [ +]; + + +exports.index_handler = function( req, res ) { + var tmplvars = {}; + tmplvars['static_url'] = exports.settings.staticurl; + tmplvars['app_name'] = exports.settings.appname; + tmplvars['app_url'] = exports.settings.appurl; + tmplvars['device_name'] = exports.settings.device_name; + + res.render( exports.settings.viewpath + '/index', tmplvars ); +}; + +exports.on_destroy = function() { +}; \ No newline at end of file diff --git a/coder-base/apps/node_js_tests/meta.json b/coder-base/apps/node_js_tests/meta.json new file mode 100755 index 00000000..fdcd78c6 --- /dev/null +++ b/coder-base/apps/node_js_tests/meta.json @@ -0,0 +1,8 @@ +{ + "created": "2013-10-03", + "modified": "2013-10-03", + "color": "#f9de2a", + "author": "", + "name": "Node.js tests", + "hidden": false +} \ No newline at end of file diff --git a/coder-base/apps/space_rocks_/app.js b/coder-base/apps/space_rocks_/app.js old mode 100644 new mode 100755 diff --git a/coder-base/apps/space_rocks_/meta.json b/coder-base/apps/space_rocks_/meta.json old mode 100644 new mode 100755 diff --git a/coder-base/apps/wifi/app.js b/coder-base/apps/wifi/app.js old mode 100644 new mode 100755 diff --git a/coder-base/apps/wifi/meta.json b/coder-base/apps/wifi/meta.json old mode 100644 new mode 100755 diff --git a/coder-base/certs/.placeholder b/coder-base/certs/.placeholder old mode 100644 new mode 100755 diff --git a/coder-base/config.js b/coder-base/config.js old mode 100644 new mode 100755 diff --git a/coder-base/device.json b/coder-base/device.json old mode 100644 new mode 100755 index d85d00f9..14bf33ea --- a/coder-base/device.json +++ b/coder-base/device.json @@ -1,7 +1,7 @@ { - "password_hash": "", + "password_hash": "$2a$10$JmznMZfX6yGiZvjVGyl33OeovjmSdY0xk5zdAUxVxvu0VskP8ZJma", "device_name": "Coder", "hostname": "coder", "coder_owner": "", "coder_color": "" -} +} \ No newline at end of file diff --git a/coder-base/device.json.reset b/coder-base/device.json.reset old mode 100644 new mode 100755 diff --git a/coder-base/node_modules_orig/.bin/express b/coder-base/node_modules_orig/.bin/express new file mode 120000 index 00000000..b741d99c --- /dev/null +++ b/coder-base/node_modules_orig/.bin/express @@ -0,0 +1 @@ +../express/bin/express \ No newline at end of file diff --git a/coder-base/node_modules_orig/.bin/nodezip b/coder-base/node_modules_orig/.bin/nodezip new file mode 120000 index 00000000..3543ce80 --- /dev/null +++ b/coder-base/node_modules_orig/.bin/nodezip @@ -0,0 +1 @@ +../node-zip/bin/nodezip \ No newline at end of file diff --git a/coder-base/node_modules_orig/bcrypt/.lock-wscript b/coder-base/node_modules_orig/bcrypt/.lock-wscript new file mode 100755 index 00000000..f412dcc3 --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/.lock-wscript @@ -0,0 +1,9 @@ +argv = ['/usr/bin/node-waf', 'configure', 'build'] +blddir = '/home/pi/cl-project314-coder/coder-base/node_modules/bcrypt/build' +commands = {'dist': 0, 'configure': True, 'distcheck': 0, 'install': 0, 'build': True, 'clean': 0, 'distclean': 0, 'check': 0, 'uninstall': 0} +cwd = '/home/pi/cl-project314-coder/coder-base/node_modules/bcrypt' +environ = {'npm_package_dist_shasum': '105af2782a34278895c338614ddeeb8adce4d23f', 'npm_config_searchopts': '', 'npm_package_contributors_3_name': 'Ben Glow', 'npm_config_group': '1000', 'npm_config_browser': 'google-chrome', 'npm_config_global': '', 'npm_config_color': 'true', 'npm_package_contributors_5_email': 'alfredwesterveld@gmail.com', 'npm_package_contributors_8_email': 'shtylman@gmail.com', 'SHELL': '/bin/bash', 'npm_package_contributors_12_url': 'https://github.com/seanmonstar', 'npm_config_pre': '', 'npm_config_logfd': '2', 'npm_config_tmp': '/tmp', 'npm_package_engines_node': '>= 0.6.0', 'npm_config_argv': '{"remain":[],"cooked":["install"],"original":["install"]}', 'npm_package_contributors_7_email': 'lloyd@hilaiel.com', 'npm_package_contributors_6_email': 'vincentcr@gmail.com', 'npm_package_scripts_preinstall': 'node-waf clean || (exit 0); node-waf configure build', 'npm_package_contributors_13_name': 'Fanie Oosthuysen', 'npm_package_contributors_13_email': 'fanie.oosthuysen@gmail.com', 'npm_package_contributors_7_name': 'Lloyd Hilaiel', 'npm_config_init_version': '0.0.0', 'npm_lifecycle_event': 'preinstall', 'npm_package_contributors_7_url': 'https://github.com/lloyd', 'npm_package_contributors_13_url': 'https://github.com/weareu', 'npm_config_init_author_name': '', 'npm_config_rebuild_bundle': 'true', 'npm_package_contributors_11_url': 'https://github.com/tootallnate', 'npm_config_yes': '', 'npm_config_usage': '', 'npm_package_description': 'A bcrypt library for NodeJS.', 'npm_config_logprefix': 'true', 'MAIL': '/var/mail/pi', 'SSH_CONNECTION': '172.26.29.81 50316 172.26.29.168 22', 'npm_config_ignore': '', 'npm_config_ca': '"-----BEGIN CERTIFICATE-----\\nMIIChzCCAfACCQDauvz/KHp8ejANBgkqhkiG9w0BAQUFADCBhzELMAkGA1UEBhMC\\nVVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMQwwCgYDVQQKEwNucG0x\\nIjAgBgNVBAsTGW5wbSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxDjAMBgNVBAMTBW5w\\nbUNBMRcwFQYJKoZIhvcNAQkBFghpQGl6cy5tZTAeFw0xMTA5MDUwMTQ3MTdaFw0y\\nMTA5MDIwMTQ3MTdaMIGHMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNV\\nBAcTB09ha2xhbmQxDDAKBgNVBAoTA25wbTEiMCAGA1UECxMZbnBtIENlcnRpZmlj\\nYXRlIEF1dGhvcml0eTEOMAwGA1UEAxMFbnBtQ0ExFzAVBgkqhkiG9w0BCQEWCGlA\\naXpzLm1lMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLI4tIqPpRW+ACw9GE\\nOgBlJZwK5f8nnKCLK629Pv5yJpQKs3DENExAyOgDcyaF0HD0zk8zTp+ZsLaNdKOz\\nGn2U181KGprGKAXP6DU6ByOJDWmTlY6+Ad1laYT0m64fERSpHw/hjD3D+iX4aMOl\\ny0HdbT5m1ZGh6SJz3ZqxavhHLQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAC4ySDbC\\nl7W1WpLmtLGEQ/yuMLUf6Jy/vr+CRp4h+UzL+IQpCv8FfxsYE7dhf/bmWTEupBkv\\nyNL18lipt2jSvR3v6oAHAReotvdjqhxddpe5Holns6EQd1/xEZ7sB1YhQKJtvUrl\\nZNufy1Jf1r0ldEGeA+0ISck7s+xSh9rQD2Op\\n-----END CERTIFICATE-----"', 'npm_config_globalconfig': '/etc/npmrc', 'npm_package_contributors_10_url': 'https://github.com/bnoordhuis', 'npm_package_contributors_2_email': 'david@dtrejo.com', 'npm_config_parseable': '', 'npm_package_contributors_1_email': 'the.gol.effect@gmail.com', 'npm_config_userignorefile': '/home/pi/.npmignore', 'USER': 'pi', 'npm_package_author_name': 'Nick Campbell', 'npm_package_contributors_0_url': 'https://github.com/Shadowfiend', 'npm_config_versions': '', 'SHLVL': '1', 'npm_config_init_author_url': '', 'npm_config_cache': '/home/pi/.npm', 'npm_config_proxy': '', 'npm_package_contributors_11_name': 'Nate Rajlich', 'npm_config_depth': 'null', 'npm_config_shell': '/bin/bash', 'npm_config_umask': '022', 'npm_package_contributors_4_name': 'NewITFarmer.com', 'npm_package_contributors_9_name': 'Vadim Graboys', 'npm_config_long': '', 'npm_package_contributors_0_name': 'Antonio Salazar Cardozo', 'npm_config_editor': 'vi', '_': '/usr/bin/npm', 'npm_package_repository_type': 'git', 'npm_package_contributors_1_name': 'Van Nguyen', 'npm_config_npat': '', 'LS_COLORS': 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:', 'npm_package_contributors_11_email': 'nathan@tootallnate.net', 'npm_config_json': '', 'npm_config_searchsort': 'name', 'npm_package_contributors_12_email': 'sean.monstar@gmail.com', 'npm_lifecycle_script': 'node-waf clean || (exit 0); node-waf configure build', 'npm_config_git': 'git', 'npm_package_contributors_1_url': 'https://github.com/thegoleffect', 'npm_package_contributors_6_url': 'https://github.com/vincentcr', 'npm_config_rollback': 'true', 'npm_package_repository_url': 'git://github.com/ncb000gt/node.bcrypt.js.git', 'npm_package_contributors_5_url': 'https://github.com/alfredwesterveld', 'HOME': '/home/pi', 'LANG': 'en_US.UTF-8', 'npm_config_save': '', 'npm_config_registry': 'https://registry.npmjs.org/', 'npm_config_unicode': 'true', 'npm_config_production': '', 'npm_config_message': '%s', 'npm_config_always_auth': '', 'npm_config_prefix': '/usr/local', 'npm_package_devDependencies_nodeunit': '>=0.6.4', 'npm_config_searchexclude': '', 'npm_config_loglevel': 'http', 'npm_package_contributors_8_url': 'https://github.com/shtylman', 'npm_package_scripts_test': 'node-gyp configure build && nodeunit test', 'npm_config_strict_ssl': 'true', 'COMP_WORDBREAKS': ' \t\n"\'><;|&(:', 'npm_package_keywords_2': 'auth', 'npm_package_keywords_3': 'authentication', 'npm_package_keywords_0': 'bcrypt', 'npm_package_keywords_1': 'password', 'npm_package_keywords_6': 'crypto', 'npm_package_keywords_4': 'encryption', 'npm_package_keywords_5': 'crypt', 'npm_package_contributors_2_name': 'David Trejo', 'npm_package_main': './bcrypt', 'npm_config_tag': 'latest', 'npm_package_licenses_0_type': 'MIT', 'npm_package_contributors_3_url': 'https://github.com/pixelglow', 'SSH_TTY': '/dev/pts/0', 'npm_config_globalignorefile': '/etc/npmignore', 'npm_config_version': '', 'npm_package_bugs_url': 'http://github.com/ncb000gt/node.bcrypt.js/issues', 'npm_package_contributors_0_email': 'savedfastcool@gmail.com', 'npm_config_force': '', 'npm_config_username': '', 'npm_config_user': '', 'npm_config_link': '', 'npm_package_contributors_9_url': 'https://github.com/vadimg', 'npm_package_name': 'bcrypt', 'npm_config_userconfig': '/home/pi/.npmrc', 'npm_config_dev': '', 'npm_package_contributors_10_name': 'Ben Noorduis', 'SSH_CLIENT': '172.26.29.81 50316 22', 'npm_config_npaturl': 'http://npat.npmjs.org/', 'LOGNAME': 'pi', 'npm_package_contributors_6_name': 'Vincent C\xc3\xb4t\xc3\xa9-Roy', 'PATH': '/home/pi/cl-project314-coder/coder-base/node_modules/bcrypt/node_modules/.bin:/home/pi/cl-project314-coder/coder-base/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games', 'npm_package_contributors_5_name': 'Alfred Westerveld', 'npm_config_coverage': '', 'TERM': 'xterm-256color', 'XDG_SESSION_COOKIE': '57ae80824714b7b337db9bbc5115ac19-1362422448.671902-492784406', 'npm_config_onload_script': '', 'npm_config_description': 'true', 'npm_package_contributors_8_name': 'Roman Shtylman', 'npm_package_author_url': 'http://github.com/ncb000gt', 'npm_config_bindist': '0.6-ares1.9.1-evundefined-openssl1.0.1c-v83.8.9.20-linux-arm-3.6.11+', 'npm_config___DO_NOT_MODIFY_THIS_FILE___use__etc_npmrc_instead_': 'true', 'npm_package_contributors_12_name': 'Sean McArthur', 'npm_config_viewer': 'man', 'npm_config_showlevel': '2', 'npm_config_unsafe_perm': 'true', 'npm_package_contributors_4_url': 'https://github.com/newitfarmer', 'npm_config_proprietary_attribs': 'true', 'npm_package_version': '0.7.4', 'npm_config_https_proxy': '', 'npm_config_node_version': '0.6.19', 'npm_config_init_author_email': '', 'npm_package_contributors_2_url': 'https://github.com/dtrejo', 'npm_package_dependencies_bindings': '1.0.0', 'npm_package_contributors_3_email': 'glen.low@pixelglow.com', 'OLDPWD': '/home/pi/cl-project314-coder/coder-base/apps/auth', 'npm_config_outfd': '1', 'npm_config_bin_publish': '', 'PWD': '/home/pi/cl-project314-coder/coder-base/node_modules/bcrypt', 'npm_package_contributors_9_email': 'dimva13@gmail.com'} +files = [] +hash = 0 +options = {'compile_targets': None, 'force': False, 'verbose': 0, 'nocache': False, 'progress_bar': 0, 'destdir': '', 'keep': False, 'zones': '', 'blddir': '', 'prefix': '/usr/local/', 'jobs': 1, 'srcdir': '', 'check_cxx_compiler': 'g++ icpc sunc++'} +srcdir = '/home/pi/cl-project314-coder/coder-base/node_modules/bcrypt' diff --git a/coder-base/node_modules_orig/bcrypt/.npmignore b/coder-base/node_modules_orig/bcrypt/.npmignore new file mode 100755 index 00000000..0babfbf8 --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/.npmignore @@ -0,0 +1,5 @@ +.lock* +build +*.node +*.sw[a-z] +node_modules diff --git a/coder-base/node_modules_orig/bcrypt/.travis.yml b/coder-base/node_modules_orig/bcrypt/.travis.yml new file mode 100755 index 00000000..895dbd36 --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 diff --git a/coder-base/node_modules_orig/bcrypt/CHANGELOG b/coder-base/node_modules_orig/bcrypt/CHANGELOG new file mode 100755 index 00000000..05a13c94 --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/CHANGELOG @@ -0,0 +1,46 @@ +v0.5.0 +* Fix for issue around empty string params throwing Errors. +* Method deprecation. +* Upgrade from libeio/ev to libuv. (shtylman) +** --- NOTE --- Breaks 0.4.x compatability +* EV_MULTIPLICITY compile flag. + +v0.4.1 +* Thread safety fix around OpenSSL (GH-32). (bnoordhuis - through node) +* C++ code changes using delete and new instead of malloc and free. (shtylman) +* Compile options for speed, zoom. (shtylman) +* Move much of the type and variable checking to the JS. (shtylman) + +v0.4.0 +* Added getRounds function that will tell you the number of rounds within a hash/salt + +v0.3.2 +* Fix api issue with async salt gen first param + +v0.3.1 +* Compile under node 0.5.x + +v0.3.0 +* Internal Refactoring +* Remove pthread dependencies and locking +* Fix compiler warnings and a memory bug + +v0.2.4 +* Use threadsafe functions instead of pthread mutexes +* salt validation to make sure the salt is of the correct size and format + +v0.2.3 +* cygwin support + +v0.2.2 +* Remove dependency on libbsd, use libssl instead + +v0.2.0 +* Added async functionality +* API changes + * hashpw -> encrypt + * all old sync methods now end with _sync +* Removed libbsd(arc4random) dependency...now uses openssl which is more widely spread + +v0.1.2 +* Security fix. Wasn't reading rounds in properly and was always only using 4 rounds diff --git a/coder-base/node_modules_orig/bcrypt/LICENSE b/coder-base/node_modules_orig/bcrypt/LICENSE new file mode 100755 index 00000000..94e2ba5f --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Nicholas Campbell + +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/coder-base/node_modules_orig/bcrypt/Makefile b/coder-base/node_modules_orig/bcrypt/Makefile new file mode 100755 index 00000000..81735d65 --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/Makefile @@ -0,0 +1,22 @@ +TESTS = test/*.js + +all: test + +build: clean configure compile + +configure: + node-gyp configure + +compile: configure + node-gyp build + npm install . + +test: build + @./node_modules/nodeunit/bin/nodeunit \ + $(TESTS) + +clean: + node-gyp clean + + +.PHONY: clean test build diff --git a/coder-base/node_modules_orig/bcrypt/README.md b/coder-base/node_modules_orig/bcrypt/README.md new file mode 100755 index 00000000..4f09a38c --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/README.md @@ -0,0 +1,243 @@ +node.bcrypt.js +============= + +[![Build Status](https://secure.travis-ci.org/ncb000gt/node.bcrypt.js.png)](http://travis-ci.org/#!/ncb000gt/node.bcrypt.js) + +Lib to help you hash passwords. +[bcrypt on wikipedia][bcryptwiki] + +Catalyst for this module: [How To Safely Store A Password][codahale] + +If You Are Submitting Bugs/Issues +============= + +Because we can't magically know what you are doing to expose an issue, it is best if you provide a snippet of code. This snippet need not include your secret sauce, but it must replicate the issue you are describing. The issues that get closed without resolution tend to be the ones without code examples. Thanks. + + +Version Compatability +============= + + + + + + + + + + + +
Node VerBcrypt Version
<= 0.4.x<= 0.4.x
>= 0.6.x>= 0.5.x
+ +Windows users should make sure to have at least node 0.8.5 installed and version >= 0.7.1 of this module. +`node-gyp` only works with stable/released versions of node. Since the `bcrypt` module uses `node-gyp` to build and install you'll need a stable version of node to use bcrypt. If you do not you'll likely see an error that starts with: + + gyp ERR! stack Error: "pre" versions of node cannot be installed, use the --nodedir flag instead + + + +Security Issues/Concerns +============= + +As should be the case with any security tool, this library should be scrutinized by anyone using it. If you find or suspect an issue with the code- please bring it to my attention and I'll spend some time trying to make sure that this tool is as secure as possible. + +To make it easier for people using this tool to analyze what has been surveyed, here is a list of BCrypt related security issues/concerns as they've come up. + +* An [issue with passwords][jtr] was found with a version of the Blowfish algorithm developed for John the Ripper. This is not present in the OpenBSD version and is thus not a problem for this module. HT [zooko][zooko]. + +Dependencies +============= + +* NodeJS +* OpenSSL (Development Libraries (header files) for compilation) + * For Windows you'll need http://slproweb.com/products/Win32OpenSSL.html installed to the default location of `C:\OpenSSL-Win32` + * Please note that for this to build properly you'll need the Normal version of OpenSSL-Win, not the Light version. The reason for this is that we need to be able to compile the code using the header files that exist in the Normal version. + * For 64 bit use the 64 bit version and install to `C:\OpenSSL-Win64` +* `node-gyp` + * Please check the dependencies for this tool at: https://github.com/TooTallNate/node-gyp/ + * Windows users will need the options for c# and c++ installed with their visual studio instance. + * Python 2.x + +From NPM +============ + + npm install bcrypt + + +From Source +============ + +Assuming you've already built node, you can compile the module with `node-gyp`: + + git clone git://github.com/ncb000gt/node.bcrypt.js.git + cd node.bcrypt.js + node-gyp configure + node-gyp build + + +Note: if you do not have node-gyp installed, install it using: `npm install -g node-gyp` + +Usage - Sync +============ + +To hash a password: + +```javascript +var bcrypt = require('bcrypt'); +var salt = bcrypt.genSaltSync(10); +var hash = bcrypt.hashSync("B4c0/\/", salt); +// Store hash in your password DB. +``` + +To check a password: + +```javascript +// Load hash from your password DB. +bcrypt.compareSync("B4c0/\/", hash); // true +bcrypt.compareSync("not_bacon", hash); // false +``` + +Auto-gen a salt and hash: + +```javascript +var hash = bcrypt.hashSync('bacon', 8); +``` + +Usage - Async +============ + +To hash a password: + +```javascript +var bcrypt = require('bcrypt'); +bcrypt.genSalt(10, function(err, salt) { + bcrypt.hash("B4c0/\/", salt, function(err, hash) { + // Store hash in your password DB. + }); +}); +``` + +To check a password: + +```javascript +// Load hash from your password DB. +bcrypt.compare("B4c0/\/", hash, function(err, res) { + // res == true +}); +bcrypt.compare("not_bacon", hash, function(err, res) { + // res = false +}); +``` + +Auto-gen a salt and hash: + +```javascript +bcrypt.hash('bacon', 8, function(err, hash) { +}); +``` + +API +============ + +`BCrypt.` + + * `genSaltSync(rounds, seed_length)` + * `rounds` - [OPTIONAL] - the number of rounds to process the data for. (default - 10) + * `seed_length` - [OPTIONAL] - RAND_bytes wants a length. to make that a bit flexible, you can specify a seed_length. (default - 20) + * `genSalt(rounds, seed_length, cb)` + * `rounds` - [OPTIONAL] - the number of rounds to process the data for. (default - 10) + * `seed_length` - [OPTIONAL] - RAND_bytes wants a length. to make that a bit flexible, you can specify a seed_length. (default - 20) + * `cb` - [REQUIRED] - a callback to be fired once the salt has been generated. uses eio making it asynchronous. + * `err` - First parameter to the callback detailing any errors. + * `salt` - Second parameter to the callback providing the generated salt. + * `hashSync(data, salt)` + * `data` - [REQUIRED] - the data to be encrypted. + * `salt` - [REQUIRED] - the salt to be used in encryption. + * `hash(data, salt, cb)` + * `data` - [REQUIRED] - the data to be encrypted. + * `salt` - [REQUIRED] - the salt to be used to hash the password. if specified as a number then a salt will be generated and used (see examples). + * `cb` - [REQUIRED] - a callback to be fired once the data has been encrypted. uses eio making it asynchronous. + * `err` - First parameter to the callback detailing any errors. + * `encrypted` - Second parameter to the callback providing the encrypted form. + * `compareSync(data, encrypted)` + * `data` - [REQUIRED] - data to compare. + * `encrypted` - [REQUIRED] - data to be compared to. + * `compare(data, encrypted, cb)` + * `data` - [REQUIRED] - data to compare. + * `encrypted` - [REQUIRED] - data to be compared to. + * `cb` - [REQUIRED] - a callback to be fired once the data has been compared. uses eio making it asynchronous. + * `err` - First parameter to the callback detailing any errors. + * `same` - Second parameter to the callback providing whether the data and encrypted forms match [true | false]. + * `getRounds(encrypted)` - return the number of rounds used to encrypt a given hash + * `encrypted` - [REQUIRED] - hash from which the number of rounds used should be extracted. + + +Hash Info +============ + +The characters that comprise the resultant hash are `./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$`. + +Testing +============ + +If you create a pull request, tests better pass :) + + npm install + npm test + +Credits +============ + +The code for this comes from a few sources: + +* blowfish.cc - OpenBSD +* bcrypt.cc - OpenBSD +* bcrypt::gen_salt - [gen_salt inclusion to bcrypt][bcryptgs] +* bcrypt_node.cc - me + +Contributors +============ + +* [Antonio Salazar Cardozo][shadowfiend] - Early MacOS X support (when we used libbsd) +* [Ben Glow][pixelglow] - Fixes for thread safety with async calls +* [Van Nguyen][thegoleffect] - Found a timing attack in the comparator +* [NewITFarmer][newitfarmer] - Initial Cygwin support +* [David Trejo][dtrejo] - packaging fixes +* [Alfred Westerveld][alfredwesterveld] - packaging fixes +* [Vincent Côté-Roy][vincentr] - Testing around concurrency issues +* [Lloyd Hilaiel][lloyd] - Documentation fixes +* [Roman Shtylman][shtylman] - Code refactoring, general rot reduction, compile options, better memory management with delete and new, and an upgrade to libuv over eio/ev. +* [Vadim Graboys][vadimg] - Code changes to support 0.5.5+ +* [Ben Noordhuis][bnoordhuis] - Fixed a thread safety issue in nodejs that was perfectly mappable to this module. +* [Nate Rajlich][tootallnate] - Bindings and build process. +* [Sean McArthur][seanmonstar] - Windows Support +* [Fanie Oosthuysen][weareu] - Windows Support + +License +============ + +Unless stated elsewhere, file headers or otherwise, the license as stated in the LICENSE file. + + + +[bcryptwiki]: http://en.wikipedia.org/wiki/Bcrypt +[bcryptgs]: http://mail-index.netbsd.org/tech-crypto/2002/05/24/msg000204.html +[codahale]: http://codahale.com/how-to-safely-store-a-password/ +[gh13]: https://github.com/ncb000gt/node.bcrypt.js/issues/13 +[jtr]: http://www.openwall.com/lists/oss-security/2011/06/20/2 + +[shadowfiend]:https://github.com/Shadowfiend +[thegoleffect]:https://github.com/thegoleffect +[pixelglow]:https://github.com/pixelglow +[dtrejo]:https://github.com/dtrejo +[alfredwesterveld]:https://github.com/alfredwesterveld +[newitfarmer]:https://github.com/newitfarmer +[zooko]:https://twitter.com/zooko +[vincentr]:https://twitter.com/vincentcr +[lloyd]:https://github.com/lloyd +[shtylman]:https://github.com/shtylman +[vadimg]:https://github.com/vadimg +[bnoordhuis]:https://github.com/bnoordhuis +[tootallnate]:https://github.com/tootallnate +[seanmonstar]:https://github.com/seanmonstar +[weareu]:https://github.com/weareu diff --git a/coder-base/node_modules_orig/bcrypt/bcrypt.js b/coder-base/node_modules_orig/bcrypt/bcrypt.js new file mode 100755 index 00000000..199bc075 --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/bcrypt.js @@ -0,0 +1,189 @@ +var bindings = require('bindings')('bcrypt_lib'); + +/// generate a salt (sync) +/// @param {Number} [rounds] number of rounds (default 10) +/// @param {Number} [seed_length] number of random bytes (default 20) +/// @return {String} salt +module.exports.gen_salt_sync = function(rounds, seed_length) { + console.log("DEPRECATION WARNING: `gen_salt_sync` has been deprecated. Please use `genSaltSync` instead."); + + return module.exports.genSaltSync(rounds, seed_length); +} + +module.exports.genSaltSync = function(rounds, seed_length) { + // default 10 rounds + if (!rounds) { + rounds = 10; + } else if (typeof rounds !== 'number') { + throw new Error('rounds must be a number'); + } + + // default length 20 + if (!seed_length) { + seed_length = 20; + } else if (typeof seed_length !== 'number') { + throw new Error('seed_length must be a number'); + } + + return bindings.gen_salt_sync(rounds, seed_length); +}; + +/// generate a salt +/// @param {Number} [rounds] number of rounds (default 10) +/// @param {Number} [seed_length] number of random bytes (default 20) +/// @param {Function} cb callback(err, salt) +module.exports.gen_salt = function(rounds, seed_length, cb) { + console.log("DEPRECATION WARNING: `gen_salt` has been deprecated. Please use `genSalt` instead."); + + return module.exports.genSalt(rounds, seed_length, cb); +} + +module.exports.genSalt = function(rounds, seed_length, cb) { + // if callback is first argument, then use defaults for others + if (typeof arguments[0] === 'function') { + // have to set callback first otherwise arguments are overriden + cb = arguments[0]; + rounds = 10; + seed_length = 20; + // callback is second argument + } else if (typeof arguments[1] === 'function') { + // have to set callback first otherwise arguments are overriden + cb = arguments[1]; + seed_length = 20; + } + + // default 10 rounds + if (!rounds) { + rounds = 10; + } else if (typeof rounds !== 'number') { + throw new Error('rounds must be a number'); + } + + // default length 20 + if (!seed_length) { + seed_length = 20; + } else if (typeof seed_length !== 'number') { + throw new Error('seed_length must be a number'); + } + + if (!cb) { + throw new Error('callback required for gen_salt'); + } + + return bindings.gen_salt(rounds, seed_length, cb); +}; + +/// hash data using a salt +/// @param {String} data the data to encrypt +/// @param {String} salt the salt to use when hashing +/// @return {String} hash +module.exports.encrypt_sync = function(data, salt) { + console.log("DEPRECATION WARNING: `encrypt_sync` has been deprecated. Please use `hashSync` instead."); + + return module.exports.hashSync(data, salt); +} + +module.exports.hashSync = function(data, salt) { + if (data == null || data == undefined || salt == null || salt == undefined) { + throw new Error('data and salt arguments required'); + } else if (typeof data !== 'string' && (typeof salt !== 'string' || typeof salt !== 'number')) { + throw new Error('data must be a string and salt must either be a salt string or a number of rounds'); + } + + if (typeof salt === 'number') { + salt = module.exports.genSaltSync(salt); + } + + return bindings.encrypt_sync(data, salt); +}; + +/// hash data using a salt +/// @param {String} data the data to encrypt +/// @param {String} salt the salt to use when hashing +/// @param {Function} cb callback(err, hash) +module.exports.encrypt = function(data, salt, cb) { + console.log("DEPRECATION WARNING: `encrypt` has been deprecated. Please use `hash` instead."); + + return module.exports.hash(data, salt, cb); +} + +module.exports.hash = function(data, salt, cb) { + if (data == null || data == undefined || salt == null || salt == undefined) { + throw new Error('data and salt arguments required'); + } else if (typeof data !== 'string' && (typeof salt !== 'string' || typeof salt !== 'number')) { + throw new Error('data must be a string and salt must either be a salt string or a number of rounds'); + } + + if (!cb) { + throw new Error('callback required for async compare'); + } else if (typeof cb !== 'function') { + throw new Error('callback must be a function'); + } + + if (typeof salt === 'number') { + return module.exports.genSalt(salt, function(err, salt) { + return bindings.encrypt(data, salt, cb); + }); + } + + return bindings.encrypt(data, salt, cb); +}; + +/// compare raw data to hash +/// @param {String} data the data to hash and compare +/// @param {String} hash expected hash +/// @return {bool} true if hashed data matches hash +module.exports.compare_sync = function(data, hash) { + console.log("DEPRECATION WARNING: `compare_sync` has been deprecated. Please use `compareSync` instead."); + + return module.exports.compareSync(data, hash); +} + +module.exports.compareSync = function(data, hash) { + if (data == null || data == undefined || hash == null || hash == undefined) { + throw new Error('data and hash arguments required'); + } else if (typeof data !== 'string' || typeof hash !== 'string') { + throw new Error('data and hash must be strings'); + } + + return bindings.compare_sync(data, hash); +}; + +/// compare raw data to hash +/// @param {String} data the data to hash and compare +/// @param {String} hash expected hash +/// @param {Function} cb callback(err, matched) - matched is true if hashed data matches hash +module.exports.compare = function(data, hash, cb) { + if (data == null || data == undefined || hash == null || hash == undefined) { + throw new Error('data and hash arguments required'); + } else if (typeof data !== 'string' || typeof hash !== 'string') { + throw new Error('data and hash must be strings'); + } + + if (!cb) { + throw new Error('callback required for async compare'); + } else if (typeof cb !== 'function') { + throw new Error('callback must be a function'); + } + + return bindings.compare(data, hash, cb); +}; + +/// @param {String} hash extract rounds from this hash +/// @return {Number} the number of rounds used to encrypt a given hash +module.exports.get_rounds = function(hash) { + console.log("DEPRECATION WARNING: `get_rounds` has been deprecated. Please use `getRounds` instead."); + + return module.exports.getRounds(hash); +} + +module.exports.getRounds = function(hash) { + if (hash == null || hash == undefined) { + throw new Error('hash argument required'); + } else if (typeof hash !== 'string') { + throw new Error('hash must be a string'); + } + + return bindings.get_rounds(hash); +}; + diff --git a/coder-base/node_modules_orig/bcrypt/binding.gyp b/coder-base/node_modules_orig/bcrypt/binding.gyp new file mode 100755 index 00000000..beae424f --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/binding.gyp @@ -0,0 +1,42 @@ +{ + 'targets': [ + { + 'target_name': 'bcrypt_lib', + 'sources': [ + 'src/blowfish.cc', + 'src/bcrypt.cc', + 'src/bcrypt_node.cc' + ], + 'conditions': [ + [ 'OS=="win"', { + 'conditions': [ + # "openssl_root" is the directory on Windows of the OpenSSL files + ['target_arch=="x64"', { + 'variables': { + 'openssl_root%': 'C:/OpenSSL-Win64' + }, + }, { + 'variables': { + 'openssl_root%': 'C:/OpenSSL-Win32' + }, + }], + ], + 'defines': [ + 'uint=unsigned int', + ], + 'libraries': [ + '-l<(openssl_root)/lib/libeay32.lib', + ], + 'include_dirs': [ + '<(openssl_root)/include', + ], + }, { # OS!="win" + 'include_dirs': [ + # use node's bundled openssl headers on Unix platforms + '<(node_root_dir)/deps/openssl/openssl/include' + ], + }], + ], + } + ] +} diff --git a/coder-base/node_modules_orig/bcrypt/build/.conf_check_0/test.cpp b/coder-base/node_modules_orig/bcrypt/build/.conf_check_0/test.cpp new file mode 100755 index 00000000..d10e686d --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/build/.conf_check_0/test.cpp @@ -0,0 +1,5 @@ +#include + +int main() { + return 0; +} diff --git a/coder-base/node_modules_orig/bcrypt/build/.conf_check_0/testbuild/.wafpickle-7 b/coder-base/node_modules_orig/bcrypt/build/.conf_check_0/testbuild/.wafpickle-7 new file mode 100755 index 0000000000000000000000000000000000000000..a0e8b83e1e5a55767582d546ac1045efa41cc2c3 GIT binary patch literal 794 zcmZXSOGp(_7{`6g^*+4X_)JaBN7mf(j*olQvd5w}!2t>3Km<12nS1oy9B1a6Gh+oE zFbFKjKrpg|=mp}+phYbza8;`o7Xqtwt%3*_VJ>PO?%bR|=l?tBeE;v`%$0E{m2i~V znqlS%lxbt0B)r8s09VPHX-p~_CEB#o53N-2VJqt4&?e!SLzv@5oPzdXCI_iN+tJ9p8WLqdHlZUR zogV2x8IQ#MJ7KA=0Ch_q>q03Ghn(GuvSwM(6VSsR>_PIp>UuC9G?gb7gCiUyEUqto zD6W2aur|G1|L~n*{e;v6!-8#^4jiRP9J6y*mEia>4!txr0cl)qTEt*X@3V78UZx=D z7>*V4ivKi&K9t2#RnPl7=%?MgC0SvL!2pLr?_-P;o%r+4aL7t1gT+U;sQq2IW-V^L z`6t|~xd20G1dD&_mdDA<;{6{VmsSQ}Ts{NCE-K+Lf@CayeYS9Z&3*MgesRajp8Nfn zx!zcEY+4EG9OrPt>#ex5S&la@J>U4eTHJoJ^A<)WI*i4$Mk$$lI;q}X`1ZPadvOkn z1>K$1T!)ym#MaGR9!~D9?!YOUlIRc?b9anSe|zt4L2-2XSMtW@-u!zV2Tr@L{2wjm BABzA0 literal 0 HcmV?d00001 diff --git a/coder-base/node_modules_orig/bcrypt/build/.conf_check_0/testbuild/Release/test_1.o b/coder-base/node_modules_orig/bcrypt/build/.conf_check_0/testbuild/Release/test_1.o new file mode 100755 index 0000000000000000000000000000000000000000..bc1b87ca72a7c65b951fddd5c48930f434310eba GIT binary patch literal 2584 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 bQ{{^6IBfD)EOq$~zU$ZQoJIvE9ew&QOa!!1 literal 0 HcmV?d00001 diff --git a/coder-base/node_modules_orig/bcrypt/build/.wafpickle-7 b/coder-base/node_modules_orig/bcrypt/build/.wafpickle-7 new file mode 100755 index 0000000000000000000000000000000000000000..164d517859592e96eef62eef7f1b990dcc379112 GIT binary patch literal 1374 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 literal 0 HcmV?d00001 diff --git a/coder-base/node_modules_orig/bcrypt/build/Release/src/bcrypt_1.o b/coder-base/node_modules_orig/bcrypt/build/Release/src/bcrypt_1.o new file mode 100755 index 0000000000000000000000000000000000000000..654f4eb91c35c7086c861ed65e50b48b5c30fbb1 GIT binary patch literal 13164 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 WiMR1~-pzaX03YOc_ynKkGyER_fNvoH literal 0 HcmV?d00001 diff --git a/coder-base/node_modules_orig/bcrypt/build/Release/src/blowfish_1.o b/coder-base/node_modules_orig/bcrypt/build/Release/src/blowfish_1.o new file mode 100755 index 0000000000000000000000000000000000000000..06002cac431f2ae8bc4478914b85e550d44f473c GIT binary patch literal 24856 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 qrC(E8gn1G4le`Uf!QZqJ+L7i '/usr/bin/g++' + +---------------------------------------- +Checking for program cpp + find program=['cpp'] paths=[] var='CPP' + -> '/usr/bin/cpp' + +---------------------------------------- +Checking for program ar + find program=['ar'] paths=[] var='AR' + -> '/usr/bin/ar' + +---------------------------------------- +Checking for program ranlib + find program=['ranlib'] paths=[] var='RANLIB' + -> '/usr/bin/ranlib' + +---------------------------------------- +Checking for g++ +ok + +---------------------------------------- +Checking for node path +not found + +---------------------------------------- +Checking for node prefix +ok /usr + +---------------------------------------- +Checking for header openssl/rand.h +==> +#include + +int main() { + return 0; +} + +<== +[1/2] cxx: build/.conf_check_0/test.cpp -> build/.conf_check_0/testbuild/Release/test_1.o +['/usr/bin/g++', '-g', '-I/usr/sfw/lib', '-I/opt/local/includes', '-I/usr/local/includes', '-I/usr/includes', '-I/usr/include', '../test.cpp', '-c', '-o', 'Release/test_1.o'] +[2/2] cxx_link: build/.conf_check_0/testbuild/Release/test_1.o -> build/.conf_check_0/testbuild/Release/testprog +['/usr/bin/g++', 'Release/test_1.o', '-o', '/home/pi/cl-project314-coder/coder-base/node_modules/bcrypt/build/.conf_check_0/testbuild/Release/testprog', '-L/lib', '-L/usr/lib', '-L/usr/local/lib', '-L/opt/local/lib', '-L/usr/sfw/lib', '-Wl,-Bdynamic', '-lssl'] +yes diff --git a/coder-base/node_modules_orig/bcrypt/examples/async_compare.js b/coder-base/node_modules_orig/bcrypt/examples/async_compare.js new file mode 100755 index 00000000..e5a8daaf --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/examples/async_compare.js @@ -0,0 +1,21 @@ +var bcrypt = require('../bcrypt'); + +var start = Date.now(); +bcrypt.genSalt(10, function(err, salt) { + console.log('salt: ' + salt); + console.log('salt cb end: ' + (Date.now() - start) + 'ms'); + bcrypt.hash('test', salt, function(err, crypted) { + console.log('crypted: ' + crypted); + console.log('crypted cb end: ' + (Date.now() - start) + 'ms'); + console.log('rounds used from hash:', bcrypt.getRounds(crypted)); + bcrypt.compare('test', crypted, function(err, res) { + console.log('compared true: ' + res); + console.log('compared true cb end: ' + (Date.now() - start) + 'ms'); + }); + bcrypt.compare('bacon', crypted, function(err, res) { + console.log('compared false: ' + res); + console.log('compared false cb end: ' + (Date.now() - start) + 'ms'); + }); + }); +}) +console.log('end: ' + (Date.now() - start) + 'ms'); diff --git a/coder-base/node_modules_orig/bcrypt/examples/forever_gen_salt.js b/coder-base/node_modules_orig/bcrypt/examples/forever_gen_salt.js new file mode 100755 index 00000000..761686a8 --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/examples/forever_gen_salt.js @@ -0,0 +1,8 @@ +var bcrypt = require('../bcrypt'); + +(function printSalt() { + bcrypt.genSalt(10, function(err, salt) { + console.log('salt: ' + salt); + printSalt(); + }); +})() diff --git a/coder-base/node_modules_orig/bcrypt/package.json b/coder-base/node_modules_orig/bcrypt/package.json new file mode 100755 index 00000000..cb38d451 --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/package.json @@ -0,0 +1,124 @@ +{ + "name": "bcrypt", + "description": "A bcrypt library for NodeJS.", + "keywords": [ + "bcrypt", + "password", + "auth", + "authentication", + "encryption", + "crypt", + "crypto" + ], + "main": "./bcrypt", + "version": "0.7.4", + "author": { + "name": "Nick Campbell", + "url": "http://github.com/ncb000gt" + }, + "engines": { + "node": ">= 0.6.0" + }, + "repository": { + "type": "git", + "url": "git://github.com/ncb000gt/node.bcrypt.js.git" + }, + "licenses": [ + { + "type": "MIT" + } + ], + "bugs": { + "url": "http://github.com/ncb000gt/node.bcrypt.js/issues" + }, + "scripts": { + "test": "node-gyp configure build && nodeunit test", + "preinstall": "node-waf clean || (exit 0); node-waf configure build" + }, + "dependencies": { + "bindings": "1.0.0" + }, + "devDependencies": { + "nodeunit": ">=0.6.4" + }, + "contributors": [ + { + "name": "Antonio Salazar Cardozo", + "email": "savedfastcool@gmail.com", + "url": "https://github.com/Shadowfiend" + }, + { + "name": "Van Nguyen", + "email": "the.gol.effect@gmail.com", + "url": "https://github.com/thegoleffect" + }, + { + "name": "David Trejo", + "email": "david@dtrejo.com", + "url": "https://github.com/dtrejo" + }, + { + "name": "Ben Glow", + "email": "glen.low@pixelglow.com", + "url": "https://github.com/pixelglow" + }, + { + "name": "NewITFarmer.com", + "url": "https://github.com/newitfarmer" + }, + { + "name": "Alfred Westerveld", + "email": "alfredwesterveld@gmail.com", + "url": "https://github.com/alfredwesterveld" + }, + { + "name": "Vincent Côté-Roy", + "email": "vincentcr@gmail.com", + "url": "https://github.com/vincentcr" + }, + { + "name": "Lloyd Hilaiel", + "email": "lloyd@hilaiel.com", + "url": "https://github.com/lloyd" + }, + { + "name": "Roman Shtylman", + "email": "shtylman@gmail.com", + "url": "https://github.com/shtylman" + }, + { + "name": "Vadim Graboys", + "email": "dimva13@gmail.com", + "url": "https://github.com/vadimg" + }, + { + "name": "Ben Noorduis", + "url": "https://github.com/bnoordhuis" + }, + { + "name": "Nate Rajlich", + "email": "nathan@tootallnate.net", + "url": "https://github.com/tootallnate" + }, + { + "name": "Sean McArthur", + "email": "sean.monstar@gmail.com", + "url": "https://github.com/seanmonstar" + }, + { + "name": "Fanie Oosthuysen", + "email": "fanie.oosthuysen@gmail.com", + "url": "https://github.com/weareu" + } + ], + "_id": "bcrypt@0.7.4", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.4", + "_nodeVersion": "v0.6.19", + "_defaultsLoaded": true, + "dist": { + "shasum": "105af2782a34278895c338614ddeeb8adce4d23f" + }, + "_from": "bcrypt@*" +} diff --git a/coder-base/node_modules_orig/bcrypt/src/bcrypt.cc b/coder-base/node_modules_orig/bcrypt/src/bcrypt.cc new file mode 100755 index 00000000..b07ccc68 --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/src/bcrypt.cc @@ -0,0 +1,322 @@ +/* $OpenBSD: bcrypt.c,v 1.24 2008/04/02 19:54:05 millert Exp $ */ + +/* + * Copyright 1997 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* This password hashing algorithm was designed by David Mazieres + * and works as follows: + * + * 1. state := InitState () + * 2. state := ExpandKey (state, salt, password) 3. + * REPEAT rounds: + * state := ExpandKey (state, 0, salt) + * state := ExpandKey(state, 0, password) + * 4. ctext := "OrpheanBeholderScryDoubt" + * 5. REPEAT 64: + * ctext := Encrypt_ECB (state, ctext); + * 6. RETURN Concatenate (salt, ctext); + * + */ + +#include +#include +#include +#include +#include "node_blf.h" + +#ifdef _WIN32 +#define snprintf _snprintf +#endif + +//#if !defined(__APPLE__) && !defined(__MACH__) +//#include "bsd/stdlib.h" +//#endif + +/* This implementation is adaptable to current computing power. + * You can have up to 2^31 rounds which should be enough for some + * time to come. + */ + +/*char *bcrypt(const char *, const char *); +void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t); +char * bcrypt_gensalt(u_int8_t log_rounds);*/ + +static void encode_base64(u_int8_t *, u_int8_t *, u_int16_t); +static void decode_base64(u_int8_t *, u_int16_t, u_int8_t *); + +const static char* error = ":"; + +const static u_int8_t Base64Code[] = +"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + +const static u_int8_t index_64[128] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 0, 1, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 255, 255, + 255, 255, 255, 255, 255, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 255, 255, 255, 255, 255, 255, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 255, 255, 255, 255, 255 +}; +#define CHAR64(c) ( (c) > 127 ? 255 : index_64[(c)]) + +static void +decode_base64(u_int8_t *buffer, u_int16_t len, u_int8_t *data) +{ + u_int8_t *bp = buffer; + u_int8_t *p = data; + u_int8_t c1, c2, c3, c4; + while (bp < buffer + len) { + c1 = CHAR64(*p); + c2 = CHAR64(*(p + 1)); + + /* Invalid data */ + if (c1 == 255 || c2 == 255) + break; + + *bp++ = (c1 << 2) | ((c2 & 0x30) >> 4); + if (bp >= buffer + len) + break; + + c3 = CHAR64(*(p + 2)); + if (c3 == 255) + break; + + *bp++ = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2); + if (bp >= buffer + len) + break; + + c4 = CHAR64(*(p + 3)); + if (c4 == 255) + break; + *bp++ = ((c3 & 0x03) << 6) | c4; + + p += 4; + } +} + +void +encode_salt(char *salt, u_int8_t *csalt, u_int16_t clen, u_int8_t logr) +{ + salt[0] = '$'; + salt[1] = BCRYPT_VERSION; + salt[2] = 'a'; + salt[3] = '$'; + + snprintf(salt + 4, 4, "%2.2u$", logr); + + encode_base64((u_int8_t *) salt + 7, csalt, clen); +} + + +/* Generates a salt for this version of crypt. + Since versions may change. Keeping this here + seems sensible. + from: http://mail-index.netbsd.org/tech-crypto/2002/05/24/msg000204.html +*/ +void +bcrypt_gensalt(u_int8_t log_rounds, u_int8_t *seed, char *gsalt) +{ + if (log_rounds < 4) + log_rounds = 4; + else if (log_rounds > 31) + log_rounds = 31; + + encode_salt(gsalt, seed, BCRYPT_MAXSALT, log_rounds); +} + +/* We handle $Vers$log2(NumRounds)$salt+passwd$ + i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */ + +void +bcrypt(const char *key, const char *salt, char *encrypted) +{ + blf_ctx state; + u_int32_t rounds, i, k; + u_int16_t j; + u_int8_t key_len, salt_len, logr, minor; + u_int8_t ciphertext[4 * BCRYPT_BLOCKS+1] = "OrpheanBeholderScryDoubt"; + u_int8_t csalt[BCRYPT_MAXSALT]; + u_int32_t cdata[BCRYPT_BLOCKS]; + int n; + + /* Discard "$" identifier */ + salt++; + + if (*salt > BCRYPT_VERSION) { + /* How do I handle errors ? Return ':' */ + strcpy(encrypted, error); + return; + } + + /* Check for minor versions */ + if (salt[1] != '$') { + switch (salt[1]) { + case 'a': + /* 'ab' should not yield the same as 'abab' */ + minor = salt[1]; + salt++; + break; + default: + strcpy(encrypted, error); + return; + } + } else + minor = 0; + + /* Discard version + "$" identifier */ + salt += 2; + + if (salt[2] != '$') { + /* Out of sync with passwd entry */ + strcpy(encrypted, error); + return; + } + + /* Computer power doesn't increase linear, 2^x should be fine */ + n = atoi(salt); + if (n > 31 || n < 0) { + strcpy(encrypted, error); + return; + } + logr = (u_int8_t)n; + if ((rounds = (u_int32_t) 1 << logr) < BCRYPT_MINROUNDS) { + strcpy(encrypted, error); + return; + } + + /* Discard num rounds + "$" identifier */ + salt += 3; + + if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT) { + strcpy(encrypted, error); + return; + } + + /* We dont want the base64 salt but the raw data */ + decode_base64(csalt, BCRYPT_MAXSALT, (u_int8_t *) salt); + salt_len = BCRYPT_MAXSALT; + key_len = strlen(key) + (minor >= 'a' ? 1 : 0); + + + /* Setting up S-Boxes and Subkeys */ + Blowfish_initstate(&state); + Blowfish_expandstate(&state, csalt, salt_len, + (u_int8_t *) key, key_len); + for (k = 0; k < rounds; k++) { + Blowfish_expand0state(&state, (u_int8_t *) key, key_len); + Blowfish_expand0state(&state, csalt, salt_len); + } + + /* This can be precomputed later */ + j = 0; + for (i = 0; i < BCRYPT_BLOCKS; i++) + cdata[i] = Blowfish_stream2word(ciphertext, 4 * BCRYPT_BLOCKS, &j); + + /* Now do the encryption */ + for (k = 0; k < 64; k++) + blf_enc(&state, cdata, BCRYPT_BLOCKS / 2); + + for (i = 0; i < BCRYPT_BLOCKS; i++) { + ciphertext[4 * i + 3] = cdata[i] & 0xff; + cdata[i] = cdata[i] >> 8; + ciphertext[4 * i + 2] = cdata[i] & 0xff; + cdata[i] = cdata[i] >> 8; + ciphertext[4 * i + 1] = cdata[i] & 0xff; + cdata[i] = cdata[i] >> 8; + ciphertext[4 * i + 0] = cdata[i] & 0xff; + } + + i = 0; + encrypted[i++] = '$'; + encrypted[i++] = BCRYPT_VERSION; + if (minor) + encrypted[i++] = minor; + encrypted[i++] = '$'; + + snprintf(encrypted + i, 4, "%2.2u$", logr); + + encode_base64((u_int8_t *) encrypted + i + 3, csalt, BCRYPT_MAXSALT); + encode_base64((u_int8_t *) encrypted + strlen(encrypted), ciphertext, + 4 * BCRYPT_BLOCKS - 1); + memset(&state, 0, sizeof(state)); + memset(ciphertext, 0, sizeof(ciphertext)); + memset(csalt, 0, sizeof(csalt)); + memset(cdata, 0, sizeof(cdata)); +} + +u_int32_t bcrypt_get_rounds(const char * hash) +{ + /* skip past the leading "$" */ + if (!hash || *(hash++) != '$') return 0; + + /* skip past version */ + if (0 == (*hash++)) return 0; + if (*hash && *hash != '$') hash++; + if (*hash++ != '$') return 0; + + return atoi(hash); +} + +static void +encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len) +{ + u_int8_t *bp = buffer; + u_int8_t *p = data; + u_int8_t c1, c2; + while (p < data + len) { + c1 = *p++; + *bp++ = Base64Code[(c1 >> 2)]; + c1 = (c1 & 0x03) << 4; + if (p >= data + len) { + *bp++ = Base64Code[c1]; + break; + } + c2 = *p++; + c1 |= (c2 >> 4) & 0x0f; + *bp++ = Base64Code[c1]; + c1 = (c2 & 0x0f) << 2; + if (p >= data + len) { + *bp++ = Base64Code[c1]; + break; + } + c2 = *p++; + c1 |= (c2 >> 6) & 0x03; + *bp++ = Base64Code[c1]; + *bp++ = Base64Code[c2 & 0x3f]; + } + *bp = '\0'; +} diff --git a/coder-base/node_modules_orig/bcrypt/src/bcrypt_node.cc b/coder-base/node_modules_orig/bcrypt/src/bcrypt_node.cc new file mode 100755 index 00000000..cb5a7771 --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/src/bcrypt_node.cc @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2010, Nicholas Campbell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include "node_blf.h" + +//pulled from node commit - 97cada0 +#ifdef _WIN32 +# include +#else +# include +#endif + +#define NODE_LESS_THAN (!(NODE_VERSION_AT_LEAST(0, 5, 4))) + +using namespace v8; +using namespace node; + +#ifdef _WIN32 + +static HANDLE* locks; + + +static void crypto_lock_init(void) { + int i, n; + + n = CRYPTO_num_locks(); + locks = new HANDLE[n]; + + for (i = 0; i < n; i++) + if (!(locks[i] = CreateMutex(NULL, FALSE, NULL))) + abort(); +} + +static void crypto_lock_cb(int mode, int n, const char* file, int line) { + if (mode & CRYPTO_LOCK) + WaitForSingleObject(locks[n], INFINITE); + else + ReleaseMutex(locks[n]); +} + +static unsigned long crypto_id_cb(void) { + return (unsigned long) GetCurrentThreadId(); +} + +#else /* !_WIN32 */ + +static pthread_rwlock_t* locks; + +static void crypto_lock_init(void) { + + const int n = CRYPTO_num_locks(); + locks = new pthread_rwlock_t[n]; + + for (int i = 0; i < n; i++) + if (pthread_rwlock_init(locks + i, NULL)) + abort(); +} + +static void crypto_lock_cb(int mode, int n, const char* file, int line) { + if (mode & CRYPTO_LOCK) { + if (mode & CRYPTO_READ) pthread_rwlock_rdlock(locks + n); + if (mode & CRYPTO_WRITE) pthread_rwlock_wrlock(locks + n); + } else { + pthread_rwlock_unlock(locks + n); + } +} + + +static unsigned long crypto_id_cb(void) { + return (unsigned long) pthread_self(); +} + +#endif /* !_WIN32 */ + +namespace { + +struct baton_base { + v8::Persistent callback; + std::string error; + + virtual ~baton_base() { + callback.Dispose(); + } +}; + +struct salt_baton : baton_base { + std::string salt; + int rand_len; + ssize_t rounds; +}; + +struct encrypt_baton : baton_base { + std::string salt; + std::string input; + std::string output; +}; + +struct compare_baton : baton_base { + std::string input; + std::string encrypted; + bool result; +}; + +int GetSeed(uint8_t* seed, int size) { + + // try to get good random bytes first + if (RAND_bytes((unsigned char *)seed, size) > 0) { + return 1; + } + + return RAND_pseudo_bytes(seed, size); +} + +bool ValidateSalt(const char* salt) { + + if (!salt || *salt != '$') { + return false; + } + + // discard $ + salt++; + + if (*salt > BCRYPT_VERSION) { + return false; + } + + if (salt[1] != '$') { + switch (salt[1]) { + case 'a': + salt++; + break; + default: + return false; + } + } + + // discard version + $ + salt += 2; + + if (salt[2] != '$') { + return false; + } + + int n = atoi(salt); + if (n > 31 || n < 0) { + return false; + } + + if (((uint8_t)1 << (uint8_t)n) < BCRYPT_MINROUNDS) { + return false; + } + + salt += 3; + if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT) { + return false; + } + + return true; +} + +/* SALT GENERATION */ +void GenSaltAsync(uv_work_t* req) { + + salt_baton* baton = static_cast(req->data); + + std::vector seed(baton->rand_len); + switch(GetSeed(&seed[0], baton->rand_len)) { + case -1: + baton->error = "Rand operation not supported."; + case 0: + baton->error = "Rand operation did not generate a cryptographically sound seed."; + } + + char salt[_SALT_LEN]; + bcrypt_gensalt(baton->rounds, &seed[0], salt); + baton->salt = std::string(salt); +} + +void GenSaltAsyncAfter(uv_work_t* req) { + HandleScope scope; + + salt_baton* baton = static_cast(req->data); + delete req; + + Handle argv[2]; + + if (!baton->error.empty()) { + argv[0] = Exception::Error(String::New(baton->error.c_str())); + argv[1] = Undefined(); + } + else { + argv[0] = Undefined(); + argv[1] = Encode(baton->salt.c_str(), baton->salt.size(), BINARY); + } + + TryCatch try_catch; // don't quite see the necessity of this + + baton->callback->Call(Context::GetCurrent()->Global(), 2, argv); + + if (try_catch.HasCaught()) + FatalException(try_catch); + + delete baton; +} + +Handle GenerateSalt(const Arguments &args) { + HandleScope scope; + + const ssize_t rounds = args[0]->Int32Value(); + const int rand_len = args[1]->Int32Value(); + Local callback = Local::Cast(args[2]); + + salt_baton* baton = new salt_baton(); + + baton->callback = Persistent::New(callback); + baton->rand_len = rand_len; + baton->rounds = rounds; + + uv_work_t* req = new uv_work_t; + req->data = baton; + uv_queue_work(uv_default_loop(), req, GenSaltAsync, (uv_after_work_cb)GenSaltAsyncAfter); + + return Undefined(); +} + +Handle GenerateSaltSync(const Arguments& args) { + HandleScope scope; + + const ssize_t rounds = args[0]->Int32Value(); + const int size = args[1]->Int32Value(); + + std::vector seed(size); + switch(GetSeed(&seed[0], size)) { + case -1: + return ThrowException(Exception::Error(String::New("Rand operation not supported."))); + case 0: + return ThrowException(Exception::Error(String::New("Rand operation did not generate a cryptographically sound seed."))); + } + + char salt[_SALT_LEN]; + bcrypt_gensalt(rounds, &seed[0], salt); + + return scope.Close(Encode(salt, strlen(salt), BINARY)); +} + +/* ENCRYPT DATA - USED TO BE HASHPW */ +void EncryptAsync(uv_work_t* req) { + encrypt_baton* baton = static_cast(req->data); + + if (!(ValidateSalt(baton->salt.c_str()))) { + baton->error = "Invalid salt. Salt must be in the form of: $Vers$log2(NumRounds)$saltvalue"; + } + + char bcrypted[_PASSWORD_LEN]; + bcrypt(baton->input.c_str(), baton->salt.c_str(), bcrypted); + baton->output = std::string(bcrypted); +} + +void EncryptAsyncAfter(uv_work_t* req) { + HandleScope scope; + + encrypt_baton* baton = static_cast(req->data); + delete req; + + Handle argv[2]; + + if (!baton->error.empty()) { + argv[0] = Exception::Error(String::New(baton->error.c_str())); + argv[1] = Undefined(); + } + else { + argv[0] = Undefined(); + argv[1] = Encode(baton->output.c_str(), baton->output.size(), BINARY); + } + + TryCatch try_catch; // don't quite see the necessity of this + + baton->callback->Call(Context::GetCurrent()->Global(), 2, argv); + + if (try_catch.HasCaught()) + FatalException(try_catch); + + delete baton; +} + +Handle Encrypt(const Arguments& args) { + HandleScope scope; + + String::Utf8Value data(args[0]->ToString()); + String::Utf8Value salt(args[1]->ToString()); + Local callback = Local::Cast(args[2]); + + encrypt_baton* baton = new encrypt_baton(); + baton->callback = Persistent::New(callback); + baton->input = std::string(*data); + baton->salt = std::string(*salt); + + uv_work_t* req = new uv_work_t; + req->data = baton; + uv_queue_work(uv_default_loop(), req, EncryptAsync, (uv_after_work_cb)EncryptAsyncAfter); + + return Undefined(); +} + +Handle EncryptSync(const Arguments& args) { + HandleScope scope; + + String::Utf8Value data(args[0]->ToString()); + String::Utf8Value salt(args[1]->ToString()); + + if (!(ValidateSalt(*salt))) { + return ThrowException(Exception::Error(String::New("Invalid salt. Salt must be in the form of: $Vers$log2(NumRounds)$saltvalue"))); + } + + char bcrypted[_PASSWORD_LEN]; + bcrypt(*data, *salt, bcrypted); + return scope.Close(Encode(bcrypted, strlen(bcrypted), BINARY)); +} + +/* COMPARATOR */ +bool CompareStrings(const char* s1, const char* s2) { + + bool eq = true; + int s1_len = strlen(s1); + int s2_len = strlen(s2); + + if (s1_len != s2_len) { + eq = false; + } + + const int max_len = (s2_len < s1_len) ? s1_len : s2_len; + + // to prevent timing attacks, should check entire string + // don't exit after found to be false + for (int i = 0; i < max_len; ++i) { + if (s1_len >= i && s2_len >= i && s1[i] != s2[i]) { + eq = false; + } + } + + return eq; +} + +void CompareAsync(uv_work_t* req) { + compare_baton* baton = static_cast(req->data); + + char bcrypted[_PASSWORD_LEN]; + bcrypt(baton->input.c_str(), baton->encrypted.c_str(), bcrypted); + baton->result = CompareStrings(bcrypted, baton->encrypted.c_str()); +} + +void CompareAsyncAfter(uv_work_t* req) { + HandleScope scope; + + compare_baton* baton = static_cast(req->data); + delete req; + + Handle argv[2]; + + if (!baton->error.empty()) { + argv[0] = Exception::Error(String::New(baton->error.c_str())); + argv[1] = Undefined(); + } else { + argv[0] = Undefined(); + argv[1] = Boolean::New(baton->result); + } + + TryCatch try_catch; // don't quite see the necessity of this + + baton->callback->Call(Context::GetCurrent()->Global(), 2, argv); + + if (try_catch.HasCaught()) + FatalException(try_catch); + + // done with the baton + // free the memory and callback + delete baton; +} + +Handle Compare(const Arguments& args) { + HandleScope scope; + + String::Utf8Value input(args[0]->ToString()); + String::Utf8Value encrypted(args[1]->ToString()); + Local callback = Local::Cast(args[2]); + + compare_baton* baton = new compare_baton(); + baton->callback = Persistent::New(callback); + baton->input = std::string(*input); + baton->encrypted = std::string(*encrypted); + + uv_work_t* req = new uv_work_t; + req->data = baton; + uv_queue_work(uv_default_loop(), req, CompareAsync, (uv_after_work_cb)CompareAsyncAfter); + + return Undefined(); +} + +Handle CompareSync(const Arguments& args) { + HandleScope scope; + + String::Utf8Value pw(args[0]->ToString()); + String::Utf8Value hash(args[1]->ToString()); + + char bcrypted[_PASSWORD_LEN]; + bcrypt(*pw, *hash, bcrypted); + return Boolean::New(CompareStrings(bcrypted, *hash)); +} + +Handle GetRounds(const Arguments& args) { + HandleScope scope; + + String::Utf8Value hash(args[0]->ToString()); + u_int32_t rounds; + if (!(rounds = bcrypt_get_rounds(*hash))) { + return ThrowException(Exception::Error(String::New("invalid hash provided"))); + } + + return Integer::New(rounds); +} + +} // anonymous namespace + +// bind the bcrypt module +extern "C" void init(Handle target) { + HandleScope scope; + + crypto_lock_init(); + CRYPTO_set_locking_callback(crypto_lock_cb); + CRYPTO_set_id_callback(crypto_id_cb); + + NODE_SET_METHOD(target, "gen_salt_sync", GenerateSaltSync); + NODE_SET_METHOD(target, "encrypt_sync", EncryptSync); + NODE_SET_METHOD(target, "compare_sync", CompareSync); + NODE_SET_METHOD(target, "get_rounds", GetRounds); + NODE_SET_METHOD(target, "gen_salt", GenerateSalt); + NODE_SET_METHOD(target, "encrypt", Encrypt); + NODE_SET_METHOD(target, "compare", Compare); +}; + +NODE_MODULE(bcrypt_lib, init); diff --git a/coder-base/node_modules_orig/bcrypt/src/blowfish.cc b/coder-base/node_modules_orig/bcrypt/src/blowfish.cc new file mode 100755 index 00000000..5a5ca154 --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/src/blowfish.cc @@ -0,0 +1,686 @@ +/* $OpenBSD: blowfish.c,v 1.18 2004/11/02 17:23:26 hshoexer Exp $ */ +/* + * Blowfish block cipher for OpenBSD + * Copyright 1997 Niels Provos + * All rights reserved. + * + * Implementation advice by David Mazieres . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This code is derived from section 14.3 and the given source + * in section V of Applied Cryptography, second edition. + * Blowfish is an unpatented fast block cipher designed by + * Bruce Schneier. + */ + +#if 0 +#include /* used for debugging */ +#include +#endif + +#include + +#include "node_blf.h" + +#undef inline +#ifdef __GNUC__ +#define inline __inline +#else /* !__GNUC__ */ +#define inline +#endif /* !__GNUC__ */ + +/* Function for Feistel Networks */ + +#define F(s, x) ((((s)[ (((x)>>24)&0xFF)] \ + + (s)[0x100 + (((x)>>16)&0xFF)]) \ + ^ (s)[0x200 + (((x)>> 8)&0xFF)]) \ + + (s)[0x300 + ( (x) &0xFF)]) + +#define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n]) + +void +Blowfish_encipher(blf_ctx *c, u_int32_t *xl, u_int32_t *xr) +{ + u_int32_t Xl; + u_int32_t Xr; + u_int32_t *s = c->S[0]; + u_int32_t *p = c->P; + + Xl = *xl; + Xr = *xr; + + Xl ^= p[0]; + BLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2); + BLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4); + BLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6); + BLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8); + BLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10); + BLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12); + BLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14); + BLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16); + + *xl = Xr ^ p[17]; + *xr = Xl; +} + +void +Blowfish_decipher(blf_ctx *c, u_int32_t *xl, u_int32_t *xr) +{ + u_int32_t Xl; + u_int32_t Xr; + u_int32_t *s = c->S[0]; + u_int32_t *p = c->P; + + Xl = *xl; + Xr = *xr; + + Xl ^= p[17]; + BLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15); + BLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13); + BLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11); + BLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9); + BLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7); + BLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5); + BLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3); + BLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1); + + *xl = Xr ^ p[0]; + *xr = Xl; +} + +void +Blowfish_initstate(blf_ctx *c) +{ + /* P-box and S-box tables initialized with digits of Pi */ + + static const blf_ctx initstate = + { { + { + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a}, + { + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7}, + { + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0}, + { + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6} + }, + { + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b + } }; + + *c = initstate; +} + +u_int32_t +Blowfish_stream2word(const u_int8_t *data, u_int16_t databytes, + u_int16_t *current) +{ + u_int8_t i; + u_int16_t j; + u_int32_t temp; + + temp = 0x00000000; + j = *current; + + for (i = 0; i < 4; i++, j++) { + if (j >= databytes) + j = 0; + temp = (temp << 8) | data[j]; + } + + *current = j; + return temp; +} + +void +Blowfish_expand0state(blf_ctx *c, const u_int8_t *key, u_int16_t keybytes) +{ + u_int16_t i; + u_int16_t j; + u_int16_t k; + u_int32_t temp; + u_int32_t datal; + u_int32_t datar; + + j = 0; + for (i = 0; i < BLF_N + 2; i++) { + /* Extract 4 int8 to 1 int32 from keystream */ + temp = Blowfish_stream2word(key, keybytes, &j); + c->P[i] = c->P[i] ^ temp; + } + + j = 0; + datal = 0x00000000; + datar = 0x00000000; + for (i = 0; i < BLF_N + 2; i += 2) { + Blowfish_encipher(c, &datal, &datar); + + c->P[i] = datal; + c->P[i + 1] = datar; + } + + for (i = 0; i < 4; i++) { + for (k = 0; k < 256; k += 2) { + Blowfish_encipher(c, &datal, &datar); + + c->S[i][k] = datal; + c->S[i][k + 1] = datar; + } + } +} + + +void +Blowfish_expandstate(blf_ctx *c, const u_int8_t *data, u_int16_t databytes, + const u_int8_t *key, u_int16_t keybytes) +{ + u_int16_t i; + u_int16_t j; + u_int16_t k; + u_int32_t temp; + u_int32_t datal; + u_int32_t datar; + + j = 0; + for (i = 0; i < BLF_N + 2; i++) { + /* Extract 4 int8 to 1 int32 from keystream */ + temp = Blowfish_stream2word(key, keybytes, &j); + c->P[i] = c->P[i] ^ temp; + } + + j = 0; + datal = 0x00000000; + datar = 0x00000000; + for (i = 0; i < BLF_N + 2; i += 2) { + datal ^= Blowfish_stream2word(data, databytes, &j); + datar ^= Blowfish_stream2word(data, databytes, &j); + Blowfish_encipher(c, &datal, &datar); + + c->P[i] = datal; + c->P[i + 1] = datar; + } + + for (i = 0; i < 4; i++) { + for (k = 0; k < 256; k += 2) { + datal ^= Blowfish_stream2word(data, databytes, &j); + datar ^= Blowfish_stream2word(data, databytes, &j); + Blowfish_encipher(c, &datal, &datar); + + c->S[i][k] = datal; + c->S[i][k + 1] = datar; + } + } + +} + +void +blf_key(blf_ctx *c, const u_int8_t *k, u_int16_t len) +{ + /* Initialize S-boxes and subkeys with Pi */ + Blowfish_initstate(c); + + /* Transform S-boxes and subkeys with key */ + Blowfish_expand0state(c, k, len); +} + +void +blf_enc(blf_ctx *c, u_int32_t *data, u_int16_t blocks) +{ + u_int32_t *d; + u_int16_t i; + + d = data; + for (i = 0; i < blocks; i++) { + Blowfish_encipher(c, d, d + 1); + d += 2; + } +} + +void +blf_dec(blf_ctx *c, u_int32_t *data, u_int16_t blocks) +{ + u_int32_t *d; + u_int16_t i; + + d = data; + for (i = 0; i < blocks; i++) { + Blowfish_decipher(c, d, d + 1); + d += 2; + } +} + +void +blf_ecb_encrypt(blf_ctx *c, u_int8_t *data, u_int32_t len) +{ + u_int32_t l, r; + u_int32_t i; + + for (i = 0; i < len; i += 8) { + l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; + r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; + Blowfish_encipher(c, &l, &r); + data[0] = l >> 24 & 0xff; + data[1] = l >> 16 & 0xff; + data[2] = l >> 8 & 0xff; + data[3] = l & 0xff; + data[4] = r >> 24 & 0xff; + data[5] = r >> 16 & 0xff; + data[6] = r >> 8 & 0xff; + data[7] = r & 0xff; + data += 8; + } +} + +void +blf_ecb_decrypt(blf_ctx *c, u_int8_t *data, u_int32_t len) +{ + u_int32_t l, r; + u_int32_t i; + + for (i = 0; i < len; i += 8) { + l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; + r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; + Blowfish_decipher(c, &l, &r); + data[0] = l >> 24 & 0xff; + data[1] = l >> 16 & 0xff; + data[2] = l >> 8 & 0xff; + data[3] = l & 0xff; + data[4] = r >> 24 & 0xff; + data[5] = r >> 16 & 0xff; + data[6] = r >> 8 & 0xff; + data[7] = r & 0xff; + data += 8; + } +} + +void +blf_cbc_encrypt(blf_ctx *c, u_int8_t *iv, u_int8_t *data, u_int32_t len) +{ + u_int32_t l, r; + u_int32_t i, j; + + for (i = 0; i < len; i += 8) { + for (j = 0; j < 8; j++) + data[j] ^= iv[j]; + l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; + r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; + Blowfish_encipher(c, &l, &r); + data[0] = l >> 24 & 0xff; + data[1] = l >> 16 & 0xff; + data[2] = l >> 8 & 0xff; + data[3] = l & 0xff; + data[4] = r >> 24 & 0xff; + data[5] = r >> 16 & 0xff; + data[6] = r >> 8 & 0xff; + data[7] = r & 0xff; + iv = data; + data += 8; + } +} + +void +blf_cbc_decrypt(blf_ctx *c, u_int8_t *iva, u_int8_t *data, u_int32_t len) +{ + u_int32_t l, r; + u_int8_t *iv; + u_int32_t i, j; + + iv = data + len - 16; + data = data + len - 8; + for (i = len - 8; i >= 8; i -= 8) { + l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; + r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; + Blowfish_decipher(c, &l, &r); + data[0] = l >> 24 & 0xff; + data[1] = l >> 16 & 0xff; + data[2] = l >> 8 & 0xff; + data[3] = l & 0xff; + data[4] = r >> 24 & 0xff; + data[5] = r >> 16 & 0xff; + data[6] = r >> 8 & 0xff; + data[7] = r & 0xff; + for (j = 0; j < 8; j++) + data[j] ^= iv[j]; + iv -= 8; + data -= 8; + } + l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; + r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; + Blowfish_decipher(c, &l, &r); + data[0] = l >> 24 & 0xff; + data[1] = l >> 16 & 0xff; + data[2] = l >> 8 & 0xff; + data[3] = l & 0xff; + data[4] = r >> 24 & 0xff; + data[5] = r >> 16 & 0xff; + data[6] = r >> 8 & 0xff; + data[7] = r & 0xff; + for (j = 0; j < 8; j++) + data[j] ^= iva[j]; +} + +#if 0 +void +report(u_int32_t data[], u_int16_t len) +{ + u_int16_t i; + for (i = 0; i < len; i += 2) + printf("Block %0hd: %08lx %08lx.\n", + i / 2, data[i], data[i + 1]); +} +void +main(void) +{ + + blf_ctx c; + char key[] = "AAAAA"; + char key2[] = "abcdefghijklmnopqrstuvwxyz"; + + u_int32_t data[10]; + u_int32_t data2[] = + {0x424c4f57l, 0x46495348l}; + + u_int16_t i; + + /* First test */ + for (i = 0; i < 10; i++) + data[i] = i; + + blf_key(&c, (u_int8_t *) key, 5); + blf_enc(&c, data, 5); + blf_dec(&c, data, 1); + blf_dec(&c, data + 2, 4); + printf("Should read as 0 - 9.\n"); + report(data, 10); + + /* Second test */ + blf_key(&c, (u_int8_t *) key2, strlen(key2)); + blf_enc(&c, data2, 1); + printf("\nShould read as: 0x324ed0fe 0xf413a203.\n"); + report(data2, 2); + blf_dec(&c, data2, 1); + report(data2, 2); +} +#endif diff --git a/coder-base/node_modules_orig/bcrypt/src/node_blf.h b/coder-base/node_modules_orig/bcrypt/src/node_blf.h new file mode 100755 index 00000000..ad674f0d --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/src/node_blf.h @@ -0,0 +1,111 @@ +/* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */ +/* + * Blowfish - a fast block cipher designed by Bruce Schneier + * + * Copyright 1997 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NODE_BLF_H_ +#define _NODE_BLF_H_ + +/* Solaris compatibility */ +#ifdef __sun +#define u_int8_t uint8_t +#define u_int16_t uint16_t +#define u_int32_t uint32_t +#define u_int64_t uint64_t +#endif + +#ifdef _WIN32 +#define u_int8_t unsigned __int8 +#define u_int16_t unsigned __int16 +#define u_int32_t unsigned __int32 +#define u_int64_t unsigned __int64 +#endif + +#define BCRYPT_VERSION '2' +#define BCRYPT_MAXSALT 16 /* Precomputation is just so nice */ +#define BCRYPT_BLOCKS 6 /* Ciphertext blocks */ +#define BCRYPT_MINROUNDS 16 /* we have log2(rounds) in salt */ + +/* Schneier specifies a maximum key length of 56 bytes. + * This ensures that every key bit affects every cipher + * bit. However, the subkeys can hold up to 72 bytes. + * Warning: For normal blowfish encryption only 56 bytes + * of the key affect all cipherbits. + */ + +#define BLF_N 16 /* Number of Subkeys */ +#define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */ +#define BLF_MAXUTILIZED ((BLF_N+2)*4) /* 576 bits */ + +#define _PASSWORD_LEN 128 /* max length, not counting NUL */ +#define _SALT_LEN 32 /* max length */ + +/* Blowfish context */ +typedef struct BlowfishContext { + u_int32_t S[4][256]; /* S-Boxes */ + u_int32_t P[BLF_N + 2]; /* Subkeys */ +} blf_ctx; + +/* Raw access to customized Blowfish + * blf_key is just: + * Blowfish_initstate( state ) + * Blowfish_expand0state( state, key, keylen ) + */ + +void Blowfish_encipher(blf_ctx *, u_int32_t *, u_int32_t *); +void Blowfish_decipher(blf_ctx *, u_int32_t *, u_int32_t *); +void Blowfish_initstate(blf_ctx *); +void Blowfish_expand0state(blf_ctx *, const u_int8_t *, u_int16_t); +void Blowfish_expandstate +(blf_ctx *, const u_int8_t *, u_int16_t, const u_int8_t *, u_int16_t); + +/* Standard Blowfish */ + +void blf_key(blf_ctx *, const u_int8_t *, u_int16_t); +void blf_enc(blf_ctx *, u_int32_t *, u_int16_t); +void blf_dec(blf_ctx *, u_int32_t *, u_int16_t); + +void blf_ecb_encrypt(blf_ctx *, u_int8_t *, u_int32_t); +void blf_ecb_decrypt(blf_ctx *, u_int8_t *, u_int32_t); + +void blf_cbc_encrypt(blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t); +void blf_cbc_decrypt(blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t); + +/* Converts u_int8_t to u_int32_t */ +u_int32_t Blowfish_stream2word(const u_int8_t *, u_int16_t , u_int16_t *); + +/* bcrypt functions*/ +void bcrypt_gensalt(u_int8_t, u_int8_t*, char *); +void bcrypt(const char *, const char *, char *); +void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t); +u_int32_t bcrypt_get_rounds(const char *); + +#endif diff --git a/coder-base/node_modules_orig/bcrypt/test/async.js b/coder-base/node_modules_orig/bcrypt/test/async.js new file mode 100755 index 00000000..ff3e115a --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/test/async.js @@ -0,0 +1,137 @@ +var bcrypt = require('../bcrypt'); + +module.exports = { + test_salt_length: function(assert) { + assert.expect(1); + bcrypt.genSalt(10, function(err, salt) { + assert.equals(29, salt.length, "Salt isn't the correct length."); + assert.done(); + }); + }, + test_salt_no_params: function(assert) { + assert.throws(function() {bcrypt.genSalt();}, "Should throw an Error. genSalt requires a callback."); + assert.done(); + }, + test_salt_only_cb: function(assert) { + assert.doesNotThrow(function() {bcrypt.genSalt(function(err, salt) {});}, "Should not throw an Error. Rounds and seed length are optional."); + assert.done(); + }, + test_salt_rounds_is_string_number: function(assert) { + assert.throws(function() {bcrypt.genSalt('10');}, "Should throw an Error. No params."); + assert.done(); + }, + test_salt_rounds_is_NaN: function(assert) { + assert.throws(function() {bcrypt.genSalt('b');}, "Should throw an Error. genSalt requires rounds to be a number."); + assert.done(); + }, + test_hash: function(assert) { + assert.expect(1); + bcrypt.genSalt(10, function(err, salt) { + bcrypt.hash('password', salt, function(err, res) { + assert.ok(res, "Res should be defined."); + assert.done(); + }); + }); + }, + test_hash_rounds: function(assert) { + assert.expect(1); + bcrypt.hash('bacon', 8, function(err, hash) { + assert.equals(bcrypt.getRounds(hash), 8, "Number of rounds should be that specified in the function call."); + assert.done(); + }); + }, + test_hash_empty_strings: function(assert) { + assert.expect(2); + bcrypt.genSalt(10, function(err, salt) { + bcrypt.hash('', salt, function(err, res) { + assert.ok(res, "Res should be defined even with an empty pw."); + bcrypt.hash('', '', function(err, res) { + if (err) { + assert.ok(err); + } else { + assert.fail(); + } + + assert.done(); + }); + }); + }); + }, + test_hash_no_params: function(assert) { + assert.throws(function() {bcrypt.hash();}, "Should throw an Error. No Params."); + assert.done(); + }, + test_hash_one_param: function(assert) { + assert.throws(function() {bcrypt.hash('password');}, "Should throw an Error. No salt."); + assert.done(); + }, + test_hash_not_hash_str: function(assert) { + assert.throws(function() {bcrypt.hash('password', 1);}, "Should throw an Error. hash should be a string."); + assert.done(); + }, + test_hash_salt_validity: function(assert) { + assert.expect(3); + bcrypt.hash('password', '$2a$10$somesaltyvaluertsetrse', function(err, enc) { + assert.equal(err, undefined); + bcrypt.hash('password', 'some$value', function(err, enc) { + assert.notEqual(err, undefined); + assert.equal(err.message, "Invalid salt. Salt must be in the form of: $Vers$log2(NumRounds)$saltvalue"); + assert.done(); + }); + }); + }, + test_verify_salt: function(assert) { + assert.expect(2); + bcrypt.genSalt(10, function(err, salt) { + var split_salt = salt.split('$'); + assert.ok(split_salt[1], '2a'); + assert.ok(split_salt[2], '10'); + assert.done(); + }); + }, + test_verify_salt_min_rounds: function(assert) { + assert.expect(2); + bcrypt.genSalt(1, function(err, salt) { + var split_salt = salt.split('$'); + assert.ok(split_salt[1], '2a'); + assert.ok(split_salt[2], '4'); + assert.done(); + }); + }, + test_verify_salt_max_rounds: function(assert) { + assert.expect(2); + bcrypt.genSalt(100, function(err, salt) { + var split_salt = salt.split('$'); + assert.ok(split_salt[1], '2a'); + assert.ok(split_salt[2], '31'); + assert.done(); + }); + }, + test_hash_compare: function(assert) { + assert.expect(3); + bcrypt.genSalt(10, function(err, salt) { + assert.equals(29, salt.length, "Salt isn't the correct length."); + bcrypt.hash("test", salt, function(err, hash) { + bcrypt.compare("test", hash, function(err, res) { + assert.equal(res, true, "These hashes should be equal."); + bcrypt.compare("blah", hash, function(err, res) { + assert.equal(res, false, "These hashes should not be equal."); + assert.done(); + }); + }); + }); + }); + }, + test_hash_compare_empty_strings: function(assert) { + assert.expect(2); + var hash = bcrypt.hashSync("test", bcrypt.genSaltSync(10)); + + bcrypt.compare("", hash, function(err, res) { + assert.equal(res, false, "These hashes should be equal."); + bcrypt.compare("", "", function(err, res) { + assert.equal(res, false, "These hashes should be equal."); + assert.done(); + }); + }); + } +}; diff --git a/coder-base/node_modules_orig/bcrypt/test/deprecated.js b/coder-base/node_modules_orig/bcrypt/test/deprecated.js new file mode 100755 index 00000000..0802bd98 --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/test/deprecated.js @@ -0,0 +1,34 @@ +var bcrypt = require('../bcrypt'); + +module.exports = { + test_encrypt: function(assert) { + assert.expect(1); + bcrypt.gen_salt(10, function(err, salt) { + bcrypt.encrypt('password', salt, function(err, res) { + assert.ok(res, "Res should be defined."); + assert.done(); + }); + }); + }, + test_gen_salt_sync: function(assert) { + var salt = bcrypt.gen_salt_sync(10); + assert.equals(29, salt.length, "Salt isn't the correct length."); + var split_salt = salt.split('$'); + assert.ok(split_salt[1], '2a'); + assert.ok(split_salt[2], '10'); + assert.done(); + }, + test_encrypt_compare_sync: function(assert) { + var salt = bcrypt.gen_salt_sync(10); + assert.equals(29, salt.length, "Salt isn't the correct length."); + var hash = bcrypt.encrypt_sync("test", salt); + assert.ok(bcrypt.compare_sync("test", hash), "These hashes should be equal."); + assert.ok(!(bcrypt.compare_sync("blah", hash)), "These hashes should not be equal."); + assert.done(); + }, + test_get_rounds_sync: function(assert) { + var hash = bcrypt.encrypt_sync("test", bcrypt.gen_salt_sync(9)); + assert.equals(9, bcrypt.get_rounds(hash), "get_rounds can't extract rounds"); + assert.done(); + } +} diff --git a/coder-base/node_modules_orig/bcrypt/test/repetitions.js b/coder-base/node_modules_orig/bcrypt/test/repetitions.js new file mode 100755 index 00000000..f05b7168 --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/test/repetitions.js @@ -0,0 +1,118 @@ +var bcrypt = require('../bcrypt'); + +var EXPECTED = 2500; //number of times to iterate these tests... + +module.exports = { + test_salt_length: function(assert) { + assert.expect(EXPECTED); + var n = 0; + for (var i = 0; i < EXPECTED; i++) { + bcrypt.genSalt(10, function(err, salt) { + assert.equals(29, salt.length, "Salt ("+salt+") isn't the correct length. It is: " + salt.length); + n++; + }); + } + + function checkVal() { + if (n == EXPECTED) { + assert.done(); + } else { + setTimeout(checkVal, 100); + } + } + setTimeout(checkVal, 100); + }, + test_hash_length: function(assert) { + assert.expect(EXPECTED); + var SALT = '$2a$04$TnjywYklQbbZjdjBgBoA4e'; + var n = 0; + for (var i = 0; i < EXPECTED; i++) { + bcrypt.hash('test', SALT, function(err, crypted) { + assert.equals(60, crypted.length, "Encrypted ("+crypted+") isn't the correct length. It is: " + crypted.length); + n++; + }); + } + + function checkVal() { + if (n == EXPECTED) { + assert.done(); + } else { + setTimeout(checkVal, 100); + } + } + setTimeout(checkVal, 100); + }, + test_compare: function(assert) { + assert.expect(EXPECTED); + var HASH = '$2a$04$TnjywYklQbbZjdjBgBoA4e9G7RJt9blgMgsCvUvus4Iv4TENB5nHy'; + var n = 0; + for (var i = 0; i < EXPECTED; i++) { + bcrypt.compare('test', HASH, function(err, match) { + assert.equal(true, match, "No match."); + n++; + }); + } + + function checkVal() { + if (n == EXPECTED) { + assert.done(); + } else { + setTimeout(checkVal, 100); + } + } + setTimeout(checkVal, 100); + }, + test_hash_and_compare: function(assert) { + assert.expect((EXPECTED-1)*3); + var salt = bcrypt.genSaltSync(4), + idx = 0, + good_done = false, + bad_done = false; + + function next() { + return test('secret' + Math.random()); + } + + function test(password) { + idx += 1; + return bcrypt.hash(password, salt, function(err, hash) { + if (err) throw err; + //console.log('\nbcrypt iter ' + idx); + + assert.ok(hash); + + bcrypt.compare(password, hash, function(err, res) { + //if (err) throw err; + assert.ok(res); + if (idx >= (EXPECTED-1)) { + good_done = true; + } + }); + + bcrypt.compare('bad' + password, hash, function(err, res) { + //if (err) throw err; + assert.ok(!res); + if (idx >= (EXPECTED-1)) { + bad_done = true; + } + }); + + if (idx < ((EXPECTED)-1)) { + next(); + } else { + function checkDone() { + if (idx >= (EXPECTED-1) && good_done && bad_done) { + assert.done(); + } else { + setTimeout(checkDone, 100); + } + } + + setTimeout(checkDone, 100); + } + }); + } + + next(); + } +}; diff --git a/coder-base/node_modules_orig/bcrypt/test/sync.js b/coder-base/node_modules_orig/bcrypt/test/sync.js new file mode 100755 index 00000000..60cd5768 --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/test/sync.js @@ -0,0 +1,109 @@ +var bcrypt = require('../bcrypt'); + +module.exports = { + test_salt_length: function(assert) { + var salt = bcrypt.genSaltSync(10); + assert.equals(29, salt.length, "Salt isn't the correct length."); + var split_salt = salt.split('$'); + assert.ok(split_salt[1], '2a'); + assert.ok(split_salt[2], '10'); + assert.done(); + }, + test_salt_no_params: function(assert) { + // same as test_verify_salt except using default rounds of 10 + var salt = bcrypt.genSaltSync(); + var split_salt = salt.split('$'); + assert.ok(split_salt[1], '2a'); + assert.ok(split_salt[2], '10'); + assert.done(); + }, + test_salt_rounds_is_string_number: function(assert) { + assert.throws(function() {bcrypt.genSaltSync('10');}, "Should throw an Error. No params."); + assert.done(); + }, + test_salt_rounds_is_NaN: function(assert) { + assert.throws(function() {bcrypt.genSaltSync('b');}, "Should throw an Error. gen_salt requires rounds to be a number."); + assert.done(); + }, + test_hash: function(assert) { + assert.ok(bcrypt.hashSync('password', bcrypt.genSaltSync(10)), "Shouldn't throw an Error."); + assert.done(); + }, + test_hash_rounds: function(assert) { + var hash = bcrypt.hashSync('password', 8); + assert.equals(bcrypt.getRounds(hash), 8, "Number of rounds should equal 8."); + assert.done(); + }, + test_hash_empty_string: function(assert) { + assert.ok(bcrypt.hashSync('', bcrypt.genSaltSync(10)), "Shouldn't throw an Error."); + assert.throws(function() {bcrypt.hashSync('password', '')}, "Should have thrown an Error related to the salt."); + assert.throws(function() {bcrypt.hashSync('', '')}, "Should have thrown an Error related to the salt."); + assert.done(); + }, + test_hash_pw_no_params: function(assert) { + assert.throws(function() {bcrypt.hashSync();}, "Should throw an Error. No Params."); + assert.done(); + }, + test_hash_pw_one_param: function(assert) { + assert.throws(function() {bcrypt.hashSync('password');}, "Should throw an Error. No salt."); + assert.done(); + }, + test_hash_pw_not_hash_str: function(assert) { + assert.throws(function() {bcrypt.hashSync('password', {});}, "Should throw an Error. hash should be a string or number."); + assert.done(); + }, + test_hash_salt_validity: function(assert) { + assert.expect(2); + assert.ok(bcrypt.hashSync('password', '$2a$10$somesaltyvaluertsetrse')); + assert.throws(function() { + bcrypt.hashSync('password', 'some$value'); + }); + assert.done(); + }, + test_verify_salt: function(assert) { + var salt = bcrypt.genSaltSync(10); + var split_salt = salt.split('$'); + assert.ok(split_salt[1], '2a'); + assert.ok(split_salt[2], '10'); + assert.done(); + }, + test_verify_salt_min_rounds: function(assert) { + var salt = bcrypt.genSaltSync(1); + var split_salt = salt.split('$'); + assert.ok(split_salt[1], '2a'); + assert.ok(split_salt[2], '4'); + assert.done(); + }, + test_verify_salt_max_rounds: function(assert) { + var salt = bcrypt.genSaltSync(100); + var split_salt = salt.split('$'); + assert.ok(split_salt[1], '2a'); + assert.ok(split_salt[2], '31'); + assert.done(); + }, + test_hash_compare: function(assert) { + var salt = bcrypt.genSaltSync(10); + assert.equals(29, salt.length, "Salt isn't the correct length."); + var hash = bcrypt.hashSync("test", salt); + assert.ok(bcrypt.compareSync("test", hash), "These hashes should be equal."); + assert.ok(!(bcrypt.compareSync("blah", hash)), "These hashes should not be equal."); + assert.done(); + }, + test_hash_compare_empty_strings: function(assert) { + assert.ok(!(bcrypt.compareSync("", "password")), "These hashes should not be equal."); + assert.ok(!(bcrypt.compareSync("", "")), "These hashes should not be equal."); + assert.ok(!(bcrypt.compareSync("password", "")), "These hashes should not be equal."); + assert.done(); + }, + test_getRounds: function(assert) { + var hash = bcrypt.hashSync("test", bcrypt.genSaltSync(9)); + assert.equals(9, bcrypt.getRounds(hash), "getRounds can't extract rounds"); + assert.done(); + }, + test_getRounds: function(assert) { + var hash = bcrypt.hashSync("test", bcrypt.genSaltSync(9)); + assert.equals(9, bcrypt.getRounds(hash), "getRounds can't extract rounds"); + assert.throws(function() {bcrypt.getRounds(''); }, "Must pass a valid hash to getRounds"); + assert.done(); + } +}; diff --git a/coder-base/node_modules_orig/bcrypt/wscript b/coder-base/node_modules_orig/bcrypt/wscript new file mode 100755 index 00000000..7da36fdb --- /dev/null +++ b/coder-base/node_modules_orig/bcrypt/wscript @@ -0,0 +1,60 @@ +# -*- mode: python -*- + +import Options, Utils, sys, re, os + +srcdir = "." +blddir = "build" +VERSION = "0.0.1" +node_version = os.popen("node --version").read() + +def set_options(opt): + opt.tool_options("compiler_cxx") + +def configure(conf): + conf.check_tool("compiler_cxx") + conf.check_tool("node_addon") + o = Options.options + + nodepath = 'NODE_PATH' in os.environ and os.environ['NODE_PATH'] or None + + libpath = ['/lib', '/usr/lib', '/usr/local/lib', '/opt/local/lib', '/usr/sfw/lib'] + if nodepath: + libpath.append(nodepath) + includes = ['/usr/include', '/usr/includes', '/usr/local/includes', '/opt/local/includes', '/usr/sfw/lib']; + + libssl = conf.check(lib="ssl", + header_name='openssl/rand.h', + includes=includes, + libpath=libpath, + mandatory=True, + uselib_store='OPENSSL') + + if sys.platform == "cygwin": + libcrypto = conf.check(lib="crypto", + includes=includes, + libpath=libpath, + uselib_store='CRYPTO') + libz = conf.check(lib="z", + includes=includes, + libpath=libpath, + uselib_store='Z') + +def build(bld): + bcryptnode = bld.new_task_gen("cxx", "shlib", "node_addon") + cxxflags = [ "-O3" ] + if not node_version.startswith("v0.4"): + cxxflags.append("-DEV_MULTIPLICITY=1") + bcryptnode.cxxflags = cxxflags + bcryptnode.target = "bcrypt_lib" + bcryptnode.source = """ + src/blowfish.cc + src/bcrypt.cc + src/bcrypt_node.cc + """ + uselib = "OPENSSL" + if sys.platform == "cygwin": + uselib += " CRYPTO Z" + bcryptnode.uselib = uselib + +def test(t): + Utils.exec_command('make test') diff --git a/coder-base/node_modules_orig/consolidate/.npmignore b/coder-base/node_modules_orig/consolidate/.npmignore new file mode 100755 index 00000000..f1250e58 --- /dev/null +++ b/coder-base/node_modules_orig/consolidate/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/coder-base/node_modules_orig/consolidate/History.md b/coder-base/node_modules_orig/consolidate/History.md new file mode 100755 index 00000000..4e7da969 --- /dev/null +++ b/coder-base/node_modules_orig/consolidate/History.md @@ -0,0 +1,66 @@ + +0.8.0 / 2013-01-23 +================== + + * add templayed support + * add `then-jade` as an alternative to `jade` + +0.7.0 / 2012-12-28 +================== + + * add atpl support + +0.6.0 2012-12-22 +================== + + * add partials support + * add support for toffee templates + * remove dot it still leaks and the author has not fixed it + +0.5.0 / 2012-10-29 +================== + + * add `mote` support + * add support to `dust` partials + * add support for `ECT` + * add support for rendering without file + * add support for `JUST` + * improve Haml-Coffee caching. + +0.4.0 / 2012-07-30 +================== + + * add doT support [sannis] + * add mustache support [ForbesLindesay] + * add walrus support [kagd] + +0.3.1 / 2012-06-28 +================== + + * add QEJS support + * add underscore support + * change whiskers to use pre-defined `.__express` + * remove engines. Closes #37 + * remove kernel, cannot comply with our caching + +0.3.0 / 2012-04-18 +================== + + * Added partials loading for whiskers [gsf] + * Added dustjs-linkedin support + +0.2.0 / 2012-04-04 +================== + + * Added support for dust [fatjonny] + * Added handlebars support [jstewmon] + +0.1.0 / 2012-01-03 +================== + + * Added support for several more engines + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/coder-base/node_modules_orig/consolidate/Makefile b/coder-base/node_modules_orig/consolidate/Makefile new file mode 100755 index 00000000..2bc56b4c --- /dev/null +++ b/coder-base/node_modules_orig/consolidate/Makefile @@ -0,0 +1,9 @@ + +REPORTER = spec + +test: + @./node_modules/.bin/mocha \ + --slow 30 \ + --reporter $(REPORTER) + +.PHONY: test \ No newline at end of file diff --git a/coder-base/node_modules_orig/consolidate/Readme.md b/coder-base/node_modules_orig/consolidate/Readme.md new file mode 100755 index 00000000..d00de1ef --- /dev/null +++ b/coder-base/node_modules_orig/consolidate/Readme.md @@ -0,0 +1,153 @@ +# Consolidate.js + + Template engine consolidation library. + +## Installation + + $ npm install consolidate + +## Supported template engines + + - [atpl](https://github.com/soywiz/atpl.js) + - [dust](https://github.com/akdubya/dustjs) [(website)](http://akdubya.github.com/dustjs/) + - [eco](https://github.com/sstephenson/eco) + - [ect](https://github.com/baryshev/ect) [(website)](http://ectjs.com/) + - [ejs](https://github.com/visionmedia/ejs) + - [haml](https://github.com/visionmedia/haml.js) [(website)](http://haml-lang.com/) + - [haml-coffee](https://github.com/9elements/haml-coffee) [(website)](http://haml-lang.com/) + - [handlebars](https://github.com/wycats/handlebars.js/) [(website)](http://handlebarsjs.com/) + - [hogan](https://github.com/twitter/hogan.js) [(website)](http://twitter.github.com/hogan.js/) + - [jade](https://github.com/visionmedia/jade) [(website)](http://jade-lang.com/) + - [jazz](https://github.com/shinetech/jazz) + - [jqtpl](https://github.com/kof/node-jqtpl) [(website)](http://api.jquery.com/category/plugins/templates/) + - [JUST](https://github.com/baryshev/just) + - [liquor](https://github.com/chjj/liquor) + - [mustache](https://github.com/janl/mustache.js) + - [QEJS](https://github.com/jepso/QEJS) + - [swig](https://github.com/paularmstrong/swig) [(website)](http://paularmstrong.github.com/swig/) + - [templayed](http://archan937.github.com/templayed.js/) + - [toffee](https://github.com/malgorithms/toffee) + - [underscore](https://github.com/documentcloud/underscore) [(website)](http://documentcloud.github.com/underscore/) + - [walrus](https://github.com/jeremyruppel/walrus) [(website)](http://documentup.com/jeremyruppel/walrus/) + - [whiskers](https://github.com/gsf/whiskers.js/tree/) + +__NOTE__: you must still install the engines you wish to use, add them to your package.json dependencies. + +## API + + All templates supported by this library may be rendered using the signature `(path[, locals], callback)` as shown below, which happens to be the signature that Express 3.x supports so any of these engines may be used within Express. + +__NOTE__: All this example code uses cons.swig for the swig template engine. Replace swig with whatever templating you are using. For exmaple, use cons.hogan for hogan.js, cons.jade for jade, etc. `console.log(cons)` for the full list of identifiers. + +```js +var cons = require('consolidate'); +cons.swig('views/page.html', { user: 'tobi' }, function(err, html){ + if (err) throw err; + console.log(html); +}); +``` + + Or without options / local variables: + +```js +var cons = require('consolidate'); +cons.swig('views/page.html', function(err, html){ + if (err) throw err; + console.log(html); +}); +``` + + To dynamically pass the engine, simply use the subscript operator and a variable: + +```js +var cons = require('consolidate') + , name = 'swig'; + +cons[name]('views/page.html', { user: 'tobi' }, function(err, html){ + if (err) throw err; + console.log(html); +}); +``` + +## Caching + + To enable caching simply pass `{ cache: true }`. Engines _may_ use this option to cache things reading the file contents, compiled `Function`s etc. Engines which do _not_ support this may simply ignore it. All engines that consolidate.js implements I/O for will cache the file contents, ideal for production environments. + +```js +var cons = require('consolidate'); +cons.swig('views/page.html', { user: 'tobi' }, function(err, html){ + if (err) throw err; + console.log(html); +}); +``` + +## Express 3.x example + +```js +var express = require('express') + , cons = require('consolidate') + , app = express(); + +// assign the swig engine to .html files +app.engine('html', cons.swig); + +// set .html as the default extension +app.set('view engine', 'html'); +app.set('views', __dirname + '/views'); + +var users = []; +users.push({ name: 'tobi' }); +users.push({ name: 'loki' }); +users.push({ name: 'jane' }); + +app.get('/', function(req, res){ + res.render('index', { + title: 'Consolidate.js' + }); +}); + +app.get('/users', function(req, res){ + res.render('users', { + title: 'Users', + users: users + }); +}); + +app.listen(3000); +console.log('Express server listening on port 3000'); +``` + +## Running tests + + Install dev deps: + + $ npm install -d + + Run the tests: + + $ make test + +## 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. diff --git a/coder-base/node_modules_orig/consolidate/index.js b/coder-base/node_modules_orig/consolidate/index.js new file mode 100755 index 00000000..4a0df174 --- /dev/null +++ b/coder-base/node_modules_orig/consolidate/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/consolidate'); \ No newline at end of file diff --git a/coder-base/node_modules_orig/consolidate/lib/consolidate.js b/coder-base/node_modules_orig/consolidate/lib/consolidate.js new file mode 100755 index 00000000..4ab7d676 --- /dev/null +++ b/coder-base/node_modules_orig/consolidate/lib/consolidate.js @@ -0,0 +1,676 @@ +/*! + * consolidate + * Copyright(c) 2012 TJ Holowaychuk + * MIT Licensed + * + * Engines which do not support caching of their file contents + * should use the `read()` function defined in consolidate.js + * On top of this, when an engine compiles to a `Function`, + * these functions should either be cached within consolidate.js + * or the engine itself via `options.cache`. This will allow + * users and frameworks to pass `options.cache = true` for + * `NODE_ENV=production`, however edit the file(s) without + * re-loading the application in development. + */ + +/** + * Module dependencies. + */ + +var fs = require('fs') + , path = require('path') + , join = path.join + , extname = path.extname + , dirname = path.dirname; + +var readCache = {}; + +/** + * Require cache. + */ + +var cacheStore = {}; + +/** + * Require cache. + */ + +var requires = {}; + +/** + * Clear the cache. + * + * @api public + */ + +exports.clearCache = function(){ + cacheStore = {}; +}; + +/** + * Conditionally cache `compiled` template based + * on the `options` filename and `.cache` boolean. + * + * @param {Object} options + * @param {Function} compiled + * @return {Function} + * @api private + */ + +function cache(options, compiled) { + // cachable + if (compiled && options.filename && options.cache) { + delete readCache[options.filename]; + cacheStore[options.filename] = compiled; + return compiled; + } + + // check cache + if (options.filename && options.cache) { + return cacheStore[options.filename]; + } + + return compiled; +} + +/** + * Read `path` with `options` with + * callback `(err, str)`. When `options.cache` + * is true the template string will be cached. + * + * @param {String} options + * @param {Function} fn + * @api private + */ + +function read(path, options, fn) { + var str = readCache[path]; + var cached = options.cache && str && 'string' == typeof str; + + // cached (only if cached is a string and not a compiled template function) + if (cached) return fn(null, str); + + // read + fs.readFile(path, 'utf8', function(err, str){ + if (err) return fn(err); + if (options.cache) readCache[path] = str; + fn(null, str); + }); +} + +/** + * Read `path` with `options` with + * callback `(err, str)`. When `options.cache` + * is true the partial string will be cached. + * + * @param {String} options + * @param {Function} fn + * @api private + */ + +function readPartials(path, options, fn) { + if (!options.partials) return fn(); + var partials = options.partials; + var keys = Object.keys(partials); + + function next(index) { + if (index == keys.length) return fn(null); + var key = keys[index]; + var file = join(dirname(path), partials[key] + extname(path)); + read(file, options, function(err, str){ + if (err) return fn(err); + options.partials[key] = str; + next(++index); + }); + } + + next(0); +} + +/** + * fromStringRenderer + */ + +function fromStringRenderer(name) { + return function(path, options, fn){ + options.filename = path; + readPartials(path, options, function (err) { + if (err) return fn(err); + if (cache(options)) { + exports[name].render('', options, fn); + } else { + read(path, options, function(err, str){ + if (err) return fn(err); + exports[name].render(str, options, fn); + }); + } + }); + }; +} + +/** + * Jade support. + */ + +exports.jade = function(path, options, fn){ + var engine = requires.jade; + if (!engine) { + try { + engine = requires.jade = require('jade'); + } catch (err) { + engine = requires.jade = require('then-jade'); + } + } + engine.renderFile(path, options, fn); +}; + +/** + * Jade string support. + */ + +exports.jade.render = function(str, options, fn){ + var engine = requires.jade; + if (!engine) { + try { + engine = requires.jade = require('jade'); + } catch (err) { + engine = requires.jade = require('then-jade'); + } + } + engine.render(str, options, fn); +}; + +/** + * Dust support. + */ + +exports.dust = fromStringRenderer('dust'); + +/** + * Dust string support. + */ + +exports.dust.render = function(str, options, fn){ + var engine = requires.dust; + if (!engine) { + try { + engine = requires.dust = require('dust'); + } catch (err) { + engine = requires.dust = require('dustjs-linkedin'); + } + } + + var ext = 'dust' + , views = '.'; + + if (options) { + if (options.ext) ext = options.ext; + if (options.views) views = options.views; + if (options.settings && options.settings.views) views = options.settings.views; + } + + engine.onLoad = function(path, callback){ + if ('' == extname(path)) path += '.' + ext; + if ('/' !== path[0]) path = views + '/' + path; + read(path, options, callback); + }; + + try { + var tmpl = cache(options) || cache(options, engine.compileFn(str)); + tmpl(options, fn); + } catch (err) { + fn(err); + } +}; + +/** + * Swig support. + */ + +exports.swig = fromStringRenderer('swig'); + +/** + * Swig string support. + */ + +exports.swig.render = function(str, options, fn){ + var engine = requires.swig || (requires.swig = require('swig')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } +}; + +/** + * Atpl support. + */ + +exports.atpl = fromStringRenderer('atpl'); + +/** + * Atpl string support. + */ + +exports.atpl.render = function(str, options, fn){ + var engine = requires.atpl || (requires.atpl = require('atpl')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } +}; + +/** + * Liquor support, + */ + +exports.liquor = fromStringRenderer('liquor'); + +/** + * Liquor string support. + */ + +exports.liquor.render = function(str, options, fn){ + var engine = requires.liquor || (requires.liquor = require('liquor')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } +}; + +/** + * EJS support. + */ + +exports.ejs = fromStringRenderer('ejs'); + +/** + * EJS string support. + */ + +exports.ejs.render = function(str, options, fn){ + var engine = requires.ejs || (requires.ejs = require('ejs')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } +}; + + +/** + * Eco support. + */ + +exports.eco = fromStringRenderer('eco'); + +/** + * Eco string support. + */ + +exports.eco.render = function(str, options, fn){ + var engine = requires.eco || (requires.eco = require('eco')); + try { + fn(null, engine.render(str, options)); + } catch (err) { + fn(err); + } +}; + +/** + * Jazz support. + */ + +exports.jazz = fromStringRenderer('jazz'); + +/** + * Jazz string support. + */ + +exports.jazz.render = function(str, options, fn){ + var engine = requires.jazz || (requires.jazz = require('jazz')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + tmpl.eval(options, function(str){ + fn(null, str); + }); + } catch (err) { + fn(err); + } +}; + +/** + * JQTPL support. + */ + +exports.jqtpl = fromStringRenderer('jqtpl'); + +/** + * JQTPL string support. + */ + +exports.jqtpl.render = function(str, options, fn){ + var engine = requires.jqtpl || (requires.jqtpl = require('jqtpl')); + try { + engine.template(str, str); + fn(null, engine.tmpl(str, options)); + } catch (err) { + fn(err); + } +}; + +/** + * Haml support. + */ + +exports.haml = fromStringRenderer('haml'); + +/** + * Haml string support. + */ + +exports.haml.render = function(str, options, fn){ + var engine = requires.hamljs || (requires.hamljs = require('hamljs')); + try { + options.locals = options; + fn(null, engine.render(str, options).trimLeft()); + } catch (err) { + fn(err); + } +}; + +/** + * Whiskers support. + */ + +exports.whiskers = function(path, options, fn){ + var engine = requires.whiskers || (requires.whiskers = require('whiskers')); + engine.__express(path, options, fn); +}; + +/** + * Whiskers string support. + */ + +exports.whiskers.render = function(str, options, fn){ + var engine = requires.whiskers || (requires.whiskers = require('whiskers')); + try { + fn(null, engine.render(str, options)); + } catch (err) { + fn(err); + } +}; + +/** + * Coffee-HAML support. + */ + +exports['haml-coffee'] = fromStringRenderer('haml-coffee'); + +/** + * Coffee-HAML string support. + */ + +exports['haml-coffee'].render = function(str, options, fn){ + var engine = requires.HAMLCoffee || (requires.HAMLCoffee = require('haml-coffee')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } +}; + +/** + * Hogan support. + */ + +exports.hogan = fromStringRenderer('hogan'); + +/** + * Hogan string support. + */ + +exports.hogan.render = function(str, options, fn){ + var engine = requires.hogan || (requires.hogan = require('hogan.js')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl.render(options, options.partials)); + } catch (err) { + fn(err); + } +}; + +/** + * templayed.js support. + */ + +exports.templayed = fromStringRenderer('templayed'); + +/** + * templayed.js string support. + */ + +exports.templayed.render = function(str, options, fn){ + var engine = requires.templayed || (requires.templayed = require('templayed')); + try { + var tmpl = cache(options) || cache(options, engine(str)(options)); + fn(null, tmpl); + } catch (err) { + fn(err); + } +}; + +/** + * Handlebars support. + */ + +exports.handlebars = fromStringRenderer('handlebars'); + +/** + * Handlebars string support. + */ + +exports.handlebars.render = function(str, options, fn) { + var engine = requires.handlebars || (requires.handlebars = require('handlebars')); + try { + for (var partial in options.partials) { + engine.registerPartial(partial, options.partials[partial]); + } + var tmpl = cache(options) || cache(options, engine.compile(str, options)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } +} + +/** + * Underscore support. + */ + +exports.underscore = fromStringRenderer('underscore'); + +/** + * Underscore string support. + */ + +exports.underscore.render = function(str, options, fn) { + var engine = requires.underscore || (requires.underscore = require('underscore')); + try { + var tmpl = cache(options) || cache(options, engine.template(str, null, options)); + fn(null, tmpl(options).replace(/\n$/, '')); + } catch (err) { + fn(err); + } +}; + + +/** + * QEJS support. + */ + +exports.qejs = function (path, options, fn) { + try { + var engine = requires.qejs || (requires.qejs = require('qejs')); + engine.renderFile(path, options).then(function (result) { + fn(null, result); + }, function (err) { + fn(err); + }).end(); + } catch (err) { + fn(err); + } +}; + +/** + * QEJS string support. + */ + +exports.qejs.render = function (str, options, fn) { + try { + var engine = requires.qejs || (requires.qejs = require('qejs')); + engine.render(str, options).then(function (result) { + fn(null, result); + }, function (err) { + fn(err); + }).end(); + } catch (err) { + fn(err); + } +}; + + +/** + * Walrus support. + */ + +exports.walrus = fromStringRenderer('walrus'); + +/** + * Walrus string support. + */ + +exports.walrus.render = function (str, options, fn) { + var engine = requires.walrus || (requires.walrus = require('walrus')); + try { + var tmpl = cache(options) || cache(options, engine.parse(str)); + fn(null, tmpl.compile(options)); + } catch (err) { + fn(err); + } +}; + +/** + * Mustache support. + */ + +exports.mustache = fromStringRenderer('mustache'); + +/** + * Mustache string support. + */ + +exports.mustache.render = function(str, options, fn) { + var engine = requires.mustache || (requires.mustache = require('mustache')); + try { + fn(null, engine.to_html(str, options, options.partials)); + } catch (err) { + fn(err); + } +}; + +/** + * Just support. + */ + +exports.just = function(path, options, fn){ + var engine = requires.just; + if (!engine) { + var JUST = require('just'); + engine = requires.just = new JUST(); + } + engine.configure({ useCache: options.cache }); + engine.render(path, options, fn); +}; + +/** + * Just string support. + */ + +exports.just.render = function(str, options, fn){ + var JUST = require('just'); + var engine = new JUST({ root: { page: str }}); + engine.render('page', options, fn); +}; + +/** + * ECT support. + */ + +exports.ect = function(path, options, fn){ + var engine = requires.ect; + if (!engine) { + var ECT = require('ect'); + engine = requires.ect = new ECT(); + } + engine.configure({ cache: options.cache }); + engine.render(path, options, fn); +}; + +/** + * ECT string support. + */ + +exports.ect.render = function(str, options, fn){ + var ECT = require('ect'); + var engine = new ECT({ root: { page: str }}); + engine.render('page', options, fn); +}; + +/** + * mote support. + */ + +exports.mote = fromStringRenderer('mote'); + +/** + * mote string support. + */ + +exports.mote.render = function(str, options, fn){ + var engine = requires.mote || (requires.mote = require('mote')); + try { + var tmpl = cache(options) || cache(options, engine.compile(str)); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } +}; + +/** + * Toffee support. + */ + +exports.toffee = function(path, options, fn){ + var toffee = requires.toffee || (requires.toffee = require('toffee')); + toffee.__consolidate_engine_render(path, options, fn); +}; + +/** + * Toffee string support. + */ + +exports.toffee.render = function(str, options, fn) { + var engine = requires.toffee || (requires.toffee = require('toffee')); + try { + engine.str_render(str, options,fn); + } catch (err) { + fn(err); + } +} diff --git a/coder-base/node_modules_orig/consolidate/package.json b/coder-base/node_modules_orig/consolidate/package.json new file mode 100755 index 00000000..eac19adf --- /dev/null +++ b/coder-base/node_modules_orig/consolidate/package.json @@ -0,0 +1,60 @@ +{ + "name": "consolidate", + "version": "0.8.0", + "description": "Template engine consolidation library", + "keywords": [ + "template", + "engine", + "view" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "devDependencies": { + "mocha": "*", + "should": "*", + "jade": "0.26.0", + "ejs": "0.7.1", + "eco": "1.1.0-rc-3", + "swig": "0.12.0", + "jazz": "0.0.18", + "jqtpl": "1.1.0", + "liquor": "0.0.4", + "hamljs": "0.6.1", + "whiskers": "0.2.2", + "haml-coffee": "1.4.0", + "hogan.js": "2.0.0", + "dust": "0.3.0", + "dustjs-linkedin": "0.4.0", + "handlebars": "1.0.7", + "underscore": "1.3.3", + "qejs": "0.0.1", + "walrus": "0.9.0", + "mustache": "0.4.0", + "just": "0.1.8", + "ect": "0.2.10", + "mote": "0.2.0", + "toffee": "0.0.52", + "atpl": ">=0.5.5", + "templayed": ">=0.2.3" + }, + "main": "index", + "scripts": { + "test": "mocha" + }, + "_id": "consolidate@0.8.0", + "dependencies": {}, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "_engineSupported": true, + "_npmVersion": "1.1.4", + "_nodeVersion": "v0.6.19", + "_defaultsLoaded": true, + "dist": { + "shasum": "d5c8d2c8638eceb6ff5e2b8959b0b21f43483691" + }, + "_from": "consolidate@*" +} diff --git a/coder-base/node_modules_orig/express-params/.npmignore b/coder-base/node_modules_orig/express-params/.npmignore new file mode 100755 index 00000000..f1250e58 --- /dev/null +++ b/coder-base/node_modules_orig/express-params/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/coder-base/node_modules_orig/express-params/History.md b/coder-base/node_modules_orig/express-params/History.md new file mode 100755 index 00000000..ddf346b0 --- /dev/null +++ b/coder-base/node_modules_orig/express-params/History.md @@ -0,0 +1,16 @@ + +0.0.3 / 2012-06-26 +================== + + * remove engines field. Closes #2 + * update to work with express 3x + +0.0.2 / 2011-12-16 +================== + + * Added support for node 0.6.x + +0.0.1 / 2011-05-23 +================== + + * Initial release diff --git a/coder-base/node_modules_orig/express-params/Makefile b/coder-base/node_modules_orig/express-params/Makefile new file mode 100755 index 00000000..91bbc1f8 --- /dev/null +++ b/coder-base/node_modules_orig/express-params/Makefile @@ -0,0 +1,6 @@ + +test: + @NODE_ENV=test ./node_modules/expresso/bin/expresso \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/coder-base/node_modules_orig/express-params/Readme.md b/coder-base/node_modules_orig/express-params/Readme.md new file mode 100755 index 00000000..8989f1bf --- /dev/null +++ b/coder-base/node_modules_orig/express-params/Readme.md @@ -0,0 +1,115 @@ + +# express-params + + Express param pre-condition functions. + +## Installation + + Works with Express 2.5.x + + $ npm install express-params + +## Usage + + Simply invoke the `extend()` method on an express `HTTPServer` to add this functionality. + +```javascript +var express = require('express') + , params = require('express-params') + , app = express.createServer(); + +params.extend(app); +``` + +## RegExp + + Regular expressions can be used to extract data from pathname + segments as shown below. When matched `req.params.range` contains + the capture groups of the `regexp.exec()` call. + +```javascript +app.param('range', /^(\w+)\.\.(\w+)?$/); + +app.get('/range/:range', function(req, res, next){ + var range = req.params.range; + res.send('from ' + range[1] + ' to ' + range[2]); +}); +``` + + Another use-case for regular expression parameters is to validate input, + for example here we may want to route via numeric id, followed by a route + which will accept other values. + +```javascript +app.param('uid', /^[0-9]+$/); + +app.get('/user/:uid', function(req, res, next){ + var uid = req.params.uid; + res.send('user ' + uid); +}); + +app.get('/user/:name', function(req, res, next){ + var name = req.params.name; + res.send('user ' + name); +}); +``` + +## Return Value + + Functions with arity < 3 (less than three parameters) are not + considered to be middleware-style, and are useful for type coercion. + For example below we pass `Number`, a function which accepts a string coercing to a number, alternatively we could use `parseInt` here. The result of `req.params.id` will then be a number, however if we were to issue `GET /user/tj` the result would be `NaN`, which is considered invalid by `exports.invalidParamReturnValue(val)` so `next('route')` is called, ignoring the route. + +```javascript +app.param('id', Number); + +app.get('/user/:id', function(req, res, next){ + var id = req.params.id; + res.send('typeof ' + typeof id + ' ' + id); +}); +``` + + The following default logic is applied to test if a return value is invalid: + +```javascript +return null == val + || false === val + || ('number' == typeof val && isNaN(val)); +``` + + It's safe to throw in these functions, as connect's router wraps them in a try/catch block, and they are not asynchronous. + +## Running Tests + + First install dependencies: + + $ npm install -g + + Then run the tests: + + $ make test + +## 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/coder-base/node_modules_orig/express-params/index.js b/coder-base/node_modules_orig/express-params/index.js new file mode 100755 index 00000000..230bea5c --- /dev/null +++ b/coder-base/node_modules_orig/express-params/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/express-params'); \ No newline at end of file diff --git a/coder-base/node_modules_orig/express-params/lib/express-params.js b/coder-base/node_modules_orig/express-params/lib/express-params.js new file mode 100755 index 00000000..d58872d8 --- /dev/null +++ b/coder-base/node_modules_orig/express-params/lib/express-params.js @@ -0,0 +1,89 @@ + +/*! + * express-params + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Library version. + */ + +exports.version = '0.0.3'; + +/** + * Add all param functions to `app`. + * + * @param {express.HTTPServer} app + * @api public + */ + +exports.extend = function(app){ + exports.extend.returnValue(app); + exports.extend.regexp(app); +}; + +/** + * Adds `RegExp` support. + * + * @param {express.HTTPServer} app + * @api public + */ + +exports.extend.regexp = function(app){ + app.param(function(name, fn){ + if (fn instanceof RegExp) { + return function(req, res, next, val){ + var captures; + if (captures = fn.exec(String(val))) { + req.params[name] = captures; + next(); + } else { + next('route'); + } + } + } + }); +}; + +/** + * Treat functions with arity < 3 to + * return a value, replacing the raw + * param string. + * + * @param {express.HTTPServer} app + * @api public + */ + +exports.extend.returnValue = function(app){ + app.param(function(name, fn){ + if (fn.length < 3) { + return function(req, res, next, val){ + val = req.params[name] = fn(val); + if (exports.invalidParamReturnValue(val)) { + next('route'); + } else { + next(); + } + }; + } + }); +}; + +/** + * Check if `val` is an invalid return value, aka: + * + * - is `null` or `undefined` + * - is `false` + * - is `NaN` + * + * @param {Mixed} val + * @return {Boolean} + * @api private + */ + +exports.invalidParamReturnValue = function(val){ + return null == val + || false === val + || ('number' == typeof val && isNaN(val)); +}; \ No newline at end of file diff --git a/coder-base/node_modules_orig/express-params/package.json b/coder-base/node_modules_orig/express-params/package.json new file mode 100755 index 00000000..2b50e94c --- /dev/null +++ b/coder-base/node_modules_orig/express-params/package.json @@ -0,0 +1,32 @@ +{ + "name": "express-params", + "version": "0.0.3", + "description": "Express param functions", + "keywords": [ + "express" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": {}, + "devDependencies": { + "express": "2.5.x", + "should": "0.3.x", + "expresso": "0.9.x" + }, + "main": "index", + "_id": "express-params@0.0.3", + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "_engineSupported": true, + "_npmVersion": "1.1.4", + "_nodeVersion": "v0.6.19", + "_defaultsLoaded": true, + "dist": { + "shasum": "aa26254a0863b832426827c5d96c9827561700a4" + }, + "_from": "express-params@*" +} diff --git a/coder-base/node_modules_orig/express/.npmignore b/coder-base/node_modules_orig/express/.npmignore new file mode 100755 index 00000000..caf574de --- /dev/null +++ b/coder-base/node_modules_orig/express/.npmignore @@ -0,0 +1,9 @@ +.git* +docs/ +examples/ +support/ +test/ +testing.js +.DS_Store +coverage.html +lib-cov diff --git a/coder-base/node_modules_orig/express/.travis.yml b/coder-base/node_modules_orig/express/.travis.yml new file mode 100755 index 00000000..895dbd36 --- /dev/null +++ b/coder-base/node_modules_orig/express/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 diff --git a/coder-base/node_modules_orig/express/History.md b/coder-base/node_modules_orig/express/History.md new file mode 100755 index 00000000..1a2b1710 --- /dev/null +++ b/coder-base/node_modules_orig/express/History.md @@ -0,0 +1,1091 @@ + +3.1.0 / 2013-01-25 +================== + + * add support for leading "." in "view engine" setting + * add array support to `res.set()` + * add node 0.8.x to travis.yml + * add "subdomain offset" setting for tweaking `req.subdomains` + * add `res.location(url)` implementing `res.redirect()`-like setting of Location + * use app.get() for x-powered-by setting for inheritance + * fix colons in passwords for `req.auth` + +3.0.6 / 2013-01-04 +================== + + * add http verb methods to Router + * update connect + * fix mangling of the `res.cookie()` options object + * fix jsonp whitespace escape. Closes #1132 + +3.0.5 / 2012-12-19 +================== + + * add throwing when a non-function is passed to a route + * fix: explicitly remove Transfer-Encoding header from 204 and 304 responses + * revert "add 'etag' option" + +3.0.4 / 2012-12-05 +================== + + * add 'etag' option to disable `res.send()` Etags + * add escaping of urls in text/plain in `res.redirect()` + for old browsers interpreting as html + * change crc32 module for a more liberal license + * update connect + +3.0.3 / 2012-11-13 +================== + + * update connect + * update cookie module + * fix cookie max-age + +3.0.2 / 2012-11-08 +================== + + * add OPTIONS to cors example. Closes #1398 + * fix route chaining regression. Closes #1397 + +3.0.1 / 2012-11-01 +================== + + * update connect + +3.0.0 / 2012-10-23 +================== + + * add `make clean` + * add "Basic" check to req.auth + * add `req.auth` test coverage + * add cb && cb(payload) to `res.jsonp()`. Closes #1374 + * add backwards compat for `res.redirect()` status. Closes #1336 + * add support for `res.json()` to retain previously defined Content-Types. Closes #1349 + * update connect + * change `res.redirect()` to utilize a pathname-relative Location again. Closes #1382 + * remove non-primitive string support for `res.send()` + * fix view-locals example. Closes #1370 + * fix route-separation example + +3.0.0rc5 / 2012-09-18 +================== + + * update connect + * add redis search example + * add static-files example + * add "x-powered-by" setting (`app.disable('x-powered-by')`) + * add "application/octet-stream" redirect Accept test case. Closes #1317 + +3.0.0rc4 / 2012-08-30 +================== + + * add `res.jsonp()`. Closes #1307 + * add "verbose errors" option to error-pages example + * add another route example to express(1) so people are not so confused + * add redis online user activity tracking example + * update connect dep + * fix etag quoting. Closes #1310 + * fix error-pages 404 status + * fix jsonp callback char restrictions + * remove old OPTIONS default response + +3.0.0rc3 / 2012-08-13 +================== + + * update connect dep + * fix signed cookies to work with `connect.cookieParser()` ("s:" prefix was missing) [tnydwrds] + * fix `res.render()` clobbering of "locals" + +3.0.0rc2 / 2012-08-03 +================== + + * add CORS example + * update connect dep + * deprecate `.createServer()` & remove old stale examples + * fix: escape `res.redirect()` link + * fix vhost example + +3.0.0rc1 / 2012-07-24 +================== + + * add more examples to view-locals + * add scheme-relative redirects (`res.redirect("//foo.com")`) support + * update cookie dep + * update connect dep + * update send dep + * fix `express(1)` -h flag, use -H for hogan. Closes #1245 + * fix `res.sendfile()` socket error handling regression + +3.0.0beta7 / 2012-07-16 +================== + + * update connect dep for `send()` root normalization regression + +3.0.0beta6 / 2012-07-13 +================== + + * add `err.view` property for view errors. Closes #1226 + * add "jsonp callback name" setting + * add support for "/foo/:bar*" non-greedy matches + * change `res.sendfile()` to use `send()` module + * change `res.send` to use "response-send" module + * remove `app.locals.use` and `res.locals.use`, use regular middleware + +3.0.0beta5 / 2012-07-03 +================== + + * add "make check" support + * add route-map example + * add `res.json(obj, status)` support back for BC + * add "methods" dep, remove internal methods module + * update connect dep + * update auth example to utilize cores pbkdf2 + * updated tests to use "supertest" + +3.0.0beta4 / 2012-06-25 +================== + + * Added `req.auth` + * Added `req.range(size)` + * Added `res.links(obj)` + * Added `res.send(body, status)` support back for backwards compat + * Added `.default()` support to `res.format()` + * Added 2xx / 304 check to `req.fresh` + * Revert "Added + support to the router" + * Fixed `res.send()` freshness check, respect res.statusCode + +3.0.0beta3 / 2012-06-15 +================== + + * Added hogan `--hjs` to express(1) [nullfirm] + * Added another example to content-negotiation + * Added `fresh` dep + * Changed: `res.send()` always checks freshness + * Fixed: expose connects mime module. Cloases #1165 + +3.0.0beta2 / 2012-06-06 +================== + + * Added `+` support to the router + * Added `req.host` + * Changed `req.param()` to check route first + * Update connect dep + +3.0.0beta1 / 2012-06-01 +================== + + * Added `res.format()` callback to override default 406 behaviour + * Fixed `res.redirect()` 406. Closes #1154 + +3.0.0alpha5 / 2012-05-30 +================== + + * Added `req.ip` + * Added `{ signed: true }` option to `res.cookie()` + * Removed `res.signedCookie()` + * Changed: dont reverse `req.ips` + * Fixed "trust proxy" setting check for `req.ips` + +3.0.0alpha4 / 2012-05-09 +================== + + * Added: allow `[]` in jsonp callback. Closes #1128 + * Added `PORT` env var support in generated template. Closes #1118 [benatkin] + * Updated: connect 2.2.2 + +3.0.0alpha3 / 2012-05-04 +================== + + * Added public `app.routes`. Closes #887 + * Added _view-locals_ example + * Added _mvc_ example + * Added `res.locals.use()`. Closes #1120 + * Added conditional-GET support to `res.send()` + * Added: coerce `res.set()` values to strings + * Changed: moved `static()` in generated apps below router + * Changed: `res.send()` only set ETag when not previously set + * Changed connect 2.2.1 dep + * Changed: `make test` now runs unit / acceptance tests + * Fixed req/res proto inheritance + +3.0.0alpha2 / 2012-04-26 +================== + + * Added `make benchmark` back + * Added `res.send()` support for `String` objects + * Added client-side data exposing example + * Added `res.header()` and `req.header()` aliases for BC + * Added `express.createServer()` for BC + * Perf: memoize parsed urls + * Perf: connect 2.2.0 dep + * Changed: make `expressInit()` middleware self-aware + * Fixed: use app.get() for all core settings + * Fixed redis session example + * Fixed session example. Closes #1105 + * Fixed generated express dep. Closes #1078 + +3.0.0alpha1 / 2012-04-15 +================== + + * Added `app.locals.use(callback)` + * Added `app.locals` object + * Added `app.locals(obj)` + * Added `res.locals` object + * Added `res.locals(obj)` + * Added `res.format()` for content-negotiation + * Added `app.engine()` + * Added `res.cookie()` JSON cookie support + * Added "trust proxy" setting + * Added `req.subdomains` + * Added `req.protocol` + * Added `req.secure` + * Added `req.path` + * Added `req.ips` + * Added `req.fresh` + * Added `req.stale` + * Added comma-delmited / array support for `req.accepts()` + * Added debug instrumentation + * Added `res.set(obj)` + * Added `res.set(field, value)` + * Added `res.get(field)` + * Added `app.get(setting)`. Closes #842 + * Added `req.acceptsLanguage()` + * Added `req.acceptsCharset()` + * Added `req.accepted` + * Added `req.acceptedLanguages` + * Added `req.acceptedCharsets` + * Added "json replacer" setting + * Added "json spaces" setting + * Added X-Forwarded-Proto support to `res.redirect()`. Closes #92 + * Added `--less` support to express(1) + * Added `express.response` prototype + * Added `express.request` prototype + * Added `express.application` prototype + * Added `app.path()` + * Added `app.render()` + * Added `res.type()` to replace `res.contentType()` + * Changed: `res.redirect()` to add relative support + * Changed: enable "jsonp callback" by default + * Changed: renamed "case sensitive routes" to "case sensitive routing" + * Rewrite of all tests with mocha + * Removed "root" setting + * Removed `res.redirect('home')` support + * Removed `req.notify()` + * Removed `app.register()` + * Removed `app.redirect()` + * Removed `app.is()` + * Removed `app.helpers()` + * Removed `app.dynamicHelpers()` + * Fixed `res.sendfile()` with non-GET. Closes #723 + * Fixed express(1) public dir for windows. Closes #866 + +2.5.9/ 2012-04-02 +================== + + * Added support for PURGE request method [pbuyle] + * Fixed `express(1)` generated app `app.address()` before `listening` [mmalecki] + +2.5.8 / 2012-02-08 +================== + + * Update mkdirp dep. Closes #991 + +2.5.7 / 2012-02-06 +================== + + * Fixed `app.all` duplicate DELETE requests [mscdex] + +2.5.6 / 2012-01-13 +================== + + * Updated hamljs dev dep. Closes #953 + +2.5.5 / 2012-01-08 +================== + + * Fixed: set `filename` on cached templates [matthewleon] + +2.5.4 / 2012-01-02 +================== + + * Fixed `express(1)` eol on 0.4.x. Closes #947 + +2.5.3 / 2011-12-30 +================== + + * Fixed `req.is()` when a charset is present + +2.5.2 / 2011-12-10 +================== + + * Fixed: express(1) LF -> CRLF for windows + +2.5.1 / 2011-11-17 +================== + + * Changed: updated connect to 1.8.x + * Removed sass.js support from express(1) + +2.5.0 / 2011-10-24 +================== + + * Added ./routes dir for generated app by default + * Added npm install reminder to express(1) app gen + * Added 0.5.x support + * Removed `make test-cov` since it wont work with node 0.5.x + * Fixed express(1) public dir for windows. Closes #866 + +2.4.7 / 2011-10-05 +================== + + * Added mkdirp to express(1). Closes #795 + * Added simple _json-config_ example + * Added shorthand for the parsed request's pathname via `req.path` + * Changed connect dep to 1.7.x to fix npm issue... + * Fixed `res.redirect()` __HEAD__ support. [reported by xerox] + * Fixed `req.flash()`, only escape args + * Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie] + +2.4.6 / 2011-08-22 +================== + + * Fixed multiple param callback regression. Closes #824 [reported by TroyGoode] + +2.4.5 / 2011-08-19 +================== + + * Added support for routes to handle errors. Closes #809 + * Added `app.routes.all()`. Closes #803 + * Added "basepath" setting to work in conjunction with reverse proxies etc. + * Refactored `Route` to use a single array of callbacks + * Added support for multiple callbacks for `app.param()`. Closes #801 +Closes #805 + * Changed: removed .call(self) for route callbacks + * Dependency: `qs >= 0.3.1` + * Fixed `res.redirect()` on windows due to `join()` usage. Closes #808 + +2.4.4 / 2011-08-05 +================== + + * Fixed `res.header()` intention of a set, even when `undefined` + * Fixed `*`, value no longer required + * Fixed `res.send(204)` support. Closes #771 + +2.4.3 / 2011-07-14 +================== + + * Added docs for `status` option special-case. Closes #739 + * Fixed `options.filename`, exposing the view path to template engines + +2.4.2. / 2011-07-06 +================== + + * Revert "removed jsonp stripping" for XSS + +2.4.1 / 2011-07-06 +================== + + * Added `res.json()` JSONP support. Closes #737 + * Added _extending-templates_ example. Closes #730 + * Added "strict routing" setting for trailing slashes + * Added support for multiple envs in `app.configure()` calls. Closes #735 + * Changed: `res.send()` using `res.json()` + * Changed: when cookie `path === null` don't default it + * Changed; default cookie path to "home" setting. Closes #731 + * Removed _pids/logs_ creation from express(1) + +2.4.0 / 2011-06-28 +================== + + * Added chainable `res.status(code)` + * Added `res.json()`, an explicit version of `res.send(obj)` + * Added simple web-service example + +2.3.12 / 2011-06-22 +================== + + * \#express is now on freenode! come join! + * Added `req.get(field, param)` + * Added links to Japanese documentation, thanks @hideyukisaito! + * Added; the `express(1)` generated app outputs the env + * Added `content-negotiation` example + * Dependency: connect >= 1.5.1 < 2.0.0 + * Fixed view layout bug. Closes #720 + * Fixed; ignore body on 304. Closes #701 + +2.3.11 / 2011-06-04 +================== + + * Added `npm test` + * Removed generation of dummy test file from `express(1)` + * Fixed; `express(1)` adds express as a dep + * Fixed; prune on `prepublish` + +2.3.10 / 2011-05-27 +================== + + * Added `req.route`, exposing the current route + * Added _package.json_ generation support to `express(1)` + * Fixed call to `app.param()` function for optional params. Closes #682 + +2.3.9 / 2011-05-25 +================== + + * Fixed bug-ish with `../' in `res.partial()` calls + +2.3.8 / 2011-05-24 +================== + + * Fixed `app.options()` + +2.3.7 / 2011-05-23 +================== + + * Added route `Collection`, ex: `app.get('/user/:id').remove();` + * Added support for `app.param(fn)` to define param logic + * Removed `app.param()` support for callback with return value + * Removed module.parent check from express(1) generated app. Closes #670 + * Refactored router. Closes #639 + +2.3.6 / 2011-05-20 +================== + + * Changed; using devDependencies instead of git submodules + * Fixed redis session example + * Fixed markdown example + * Fixed view caching, should not be enabled in development + +2.3.5 / 2011-05-20 +================== + + * Added export `.view` as alias for `.View` + +2.3.4 / 2011-05-08 +================== + + * Added `./examples/say` + * Fixed `res.sendfile()` bug preventing the transfer of files with spaces + +2.3.3 / 2011-05-03 +================== + + * Added "case sensitive routes" option. + * Changed; split methods supported per rfc [slaskis] + * Fixed route-specific middleware when using the same callback function several times + +2.3.2 / 2011-04-27 +================== + + * Fixed view hints + +2.3.1 / 2011-04-26 +================== + + * Added `app.match()` as `app.match.all()` + * Added `app.lookup()` as `app.lookup.all()` + * Added `app.remove()` for `app.remove.all()` + * Added `app.remove.VERB()` + * Fixed template caching collision issue. Closes #644 + * Moved router over from connect and started refactor + +2.3.0 / 2011-04-25 +================== + + * Added options support to `res.clearCookie()` + * Added `res.helpers()` as alias of `res.locals()` + * Added; json defaults to UTF-8 with `res.send()`. Closes #632. [Daniel * Dependency `connect >= 1.4.0` + * Changed; auto set Content-Type in res.attachement [Aaron Heckmann] + * Renamed "cache views" to "view cache". Closes #628 + * Fixed caching of views when using several apps. Closes #637 + * Fixed gotcha invoking `app.param()` callbacks once per route middleware. +Closes #638 + * Fixed partial lookup precedence. Closes #631 +Shaw] + +2.2.2 / 2011-04-12 +================== + + * Added second callback support for `res.download()` connection errors + * Fixed `filename` option passing to template engine + +2.2.1 / 2011-04-04 +================== + + * Added `layout(path)` helper to change the layout within a view. Closes #610 + * Fixed `partial()` collection object support. + Previously only anything with `.length` would work. + When `.length` is present one must still be aware of holes, + however now `{ collection: {foo: 'bar'}}` is valid, exposes + `keyInCollection` and `keysInCollection`. + + * Performance improved with better view caching + * Removed `request` and `response` locals + * Changed; errorHandler page title is now `Express` instead of `Connect` + +2.2.0 / 2011-03-30 +================== + + * Added `app.lookup.VERB()`, ex `app.lookup.put('/user/:id')`. Closes #606 + * Added `app.match.VERB()`, ex `app.match.put('/user/12')`. Closes #606 + * Added `app.VERB(path)` as alias of `app.lookup.VERB()`. + * Dependency `connect >= 1.2.0` + +2.1.1 / 2011-03-29 +================== + + * Added; expose `err.view` object when failing to locate a view + * Fixed `res.partial()` call `next(err)` when no callback is given [reported by aheckmann] + * Fixed; `res.send(undefined)` responds with 204 [aheckmann] + +2.1.0 / 2011-03-24 +================== + + * Added `/_?` partial lookup support. Closes #447 + * Added `request`, `response`, and `app` local variables + * Added `settings` local variable, containing the app's settings + * Added `req.flash()` exception if `req.session` is not available + * Added `res.send(bool)` support (json response) + * Fixed stylus example for latest version + * Fixed; wrap try/catch around `res.render()` + +2.0.0 / 2011-03-17 +================== + + * Fixed up index view path alternative. + * Changed; `res.locals()` without object returns the locals + +2.0.0rc3 / 2011-03-17 +================== + + * Added `res.locals(obj)` to compliment `res.local(key, val)` + * Added `res.partial()` callback support + * Fixed recursive error reporting issue in `res.render()` + +2.0.0rc2 / 2011-03-17 +================== + + * Changed; `partial()` "locals" are now optional + * Fixed `SlowBuffer` support. Closes #584 [reported by tyrda01] + * Fixed .filename view engine option [reported by drudge] + * Fixed blog example + * Fixed `{req,res}.app` reference when mounting [Ben Weaver] + +2.0.0rc / 2011-03-14 +================== + + * Fixed; expose `HTTPSServer` constructor + * Fixed express(1) default test charset. Closes #579 [reported by secoif] + * Fixed; default charset to utf-8 instead of utf8 for lame IE [reported by NickP] + +2.0.0beta3 / 2011-03-09 +================== + + * Added support for `res.contentType()` literal + The original `res.contentType('.json')`, + `res.contentType('application/json')`, and `res.contentType('json')` + will work now. + * Added `res.render()` status option support back + * Added charset option for `res.render()` + * Added `.charset` support (via connect 1.0.4) + * Added view resolution hints when in development and a lookup fails + * Added layout lookup support relative to the page view. + For example while rendering `./views/user/index.jade` if you create + `./views/user/layout.jade` it will be used in favour of the root layout. + * Fixed `res.redirect()`. RFC states absolute url [reported by unlink] + * Fixed; default `res.send()` string charset to utf8 + * Removed `Partial` constructor (not currently used) + +2.0.0beta2 / 2011-03-07 +================== + + * Added res.render() `.locals` support back to aid in migration process + * Fixed flash example + +2.0.0beta / 2011-03-03 +================== + + * Added HTTPS support + * Added `res.cookie()` maxAge support + * Added `req.header()` _Referrer_ / _Referer_ special-case, either works + * Added mount support for `res.redirect()`, now respects the mount-point + * Added `union()` util, taking place of `merge(clone())` combo + * Added stylus support to express(1) generated app + * Added secret to session middleware used in examples and generated app + * Added `res.local(name, val)` for progressive view locals + * Added default param support to `req.param(name, default)` + * Added `app.disabled()` and `app.enabled()` + * Added `app.register()` support for omitting leading ".", either works + * Added `res.partial()`, using the same interface as `partial()` within a view. Closes #539 + * Added `app.param()` to map route params to async/sync logic + * Added; aliased `app.helpers()` as `app.locals()`. Closes #481 + * Added extname with no leading "." support to `res.contentType()` + * Added `cache views` setting, defaulting to enabled in "production" env + * Added index file partial resolution, eg: partial('user') may try _views/user/index.jade_. + * Added `req.accepts()` support for extensions + * Changed; `res.download()` and `res.sendfile()` now utilize Connect's + static file server `connect.static.send()`. + * Changed; replaced `connect.utils.mime()` with npm _mime_ module + * Changed; allow `req.query` to be pre-defined (via middleware or other parent + * Changed view partial resolution, now relative to parent view + * Changed view engine signature. no longer `engine.render(str, options, callback)`, now `engine.compile(str, options) -> Function`, the returned function accepts `fn(locals)`. + * Fixed `req.param()` bug returning Array.prototype methods. Closes #552 + * Fixed; using `Stream#pipe()` instead of `sys.pump()` in `res.sendfile()` + * Fixed; using _qs_ module instead of _querystring_ + * Fixed; strip unsafe chars from jsonp callbacks + * Removed "stream threshold" setting + +1.0.8 / 2011-03-01 +================== + + * Allow `req.query` to be pre-defined (via middleware or other parent app) + * "connect": ">= 0.5.0 < 1.0.0". Closes #547 + * Removed the long deprecated __EXPRESS_ENV__ support + +1.0.7 / 2011-02-07 +================== + + * Fixed `render()` setting inheritance. + Mounted apps would not inherit "view engine" + +1.0.6 / 2011-02-07 +================== + + * Fixed `view engine` setting bug when period is in dirname + +1.0.5 / 2011-02-05 +================== + + * Added secret to generated app `session()` call + +1.0.4 / 2011-02-05 +================== + + * Added `qs` dependency to _package.json_ + * Fixed namespaced `require()`s for latest connect support + +1.0.3 / 2011-01-13 +================== + + * Remove unsafe characters from JSONP callback names [Ryan Grove] + +1.0.2 / 2011-01-10 +================== + + * Removed nested require, using `connect.router` + +1.0.1 / 2010-12-29 +================== + + * Fixed for middleware stacked via `createServer()` + previously the `foo` middleware passed to `createServer(foo)` + would not have access to Express methods such as `res.send()` + or props like `req.query` etc. + +1.0.0 / 2010-11-16 +================== + + * Added; deduce partial object names from the last segment. + For example by default `partial('forum/post', postObject)` will + give you the _post_ object, providing a meaningful default. + * Added http status code string representation to `res.redirect()` body + * Added; `res.redirect()` supporting _text/plain_ and _text/html_ via __Accept__. + * Added `req.is()` to aid in content negotiation + * Added partial local inheritance [suggested by masylum]. Closes #102 + providing access to parent template locals. + * Added _-s, --session[s]_ flag to express(1) to add session related middleware + * Added _--template_ flag to express(1) to specify the + template engine to use. + * Added _--css_ flag to express(1) to specify the + stylesheet engine to use (or just plain css by default). + * Added `app.all()` support [thanks aheckmann] + * Added partial direct object support. + You may now `partial('user', user)` providing the "user" local, + vs previously `partial('user', { object: user })`. + * Added _route-separation_ example since many people question ways + to do this with CommonJS modules. Also view the _blog_ example for + an alternative. + * Performance; caching view path derived partial object names + * Fixed partial local inheritance precedence. [reported by Nick Poulden] Closes #454 + * Fixed jsonp support; _text/javascript_ as per mailinglist discussion + +1.0.0rc4 / 2010-10-14 +================== + + * Added _NODE_ENV_ support, _EXPRESS_ENV_ is deprecated and will be removed in 1.0.0 + * Added route-middleware support (very helpful, see the [docs](http://expressjs.com/guide.html#Route-Middleware)) + * Added _jsonp callback_ setting to enable/disable jsonp autowrapping [Dav Glass] + * Added callback query check on response.send to autowrap JSON objects for simple webservice implementations [Dav Glass] + * Added `partial()` support for array-like collections. Closes #434 + * Added support for swappable querystring parsers + * Added session usage docs. Closes #443 + * Added dynamic helper caching. Closes #439 [suggested by maritz] + * Added authentication example + * Added basic Range support to `res.sendfile()` (and `res.download()` etc) + * Changed; `express(1)` generated app using 2 spaces instead of 4 + * Default env to "development" again [aheckmann] + * Removed _context_ option is no more, use "scope" + * Fixed; exposing _./support_ libs to examples so they can run without installs + * Fixed mvc example + +1.0.0rc3 / 2010-09-20 +================== + + * Added confirmation for `express(1)` app generation. Closes #391 + * Added extending of flash formatters via `app.flashFormatters` + * Added flash formatter support. Closes #411 + * Added streaming support to `res.sendfile()` using `sys.pump()` when >= "stream threshold" + * Added _stream threshold_ setting for `res.sendfile()` + * Added `res.send()` __HEAD__ support + * Added `res.clearCookie()` + * Added `res.cookie()` + * Added `res.render()` headers option + * Added `res.redirect()` response bodies + * Added `res.render()` status option support. Closes #425 [thanks aheckmann] + * Fixed `res.sendfile()` responding with 403 on malicious path + * Fixed `res.download()` bug; when an error occurs remove _Content-Disposition_ + * Fixed; mounted apps settings now inherit from parent app [aheckmann] + * Fixed; stripping Content-Length / Content-Type when 204 + * Fixed `res.send()` 204. Closes #419 + * Fixed multiple _Set-Cookie_ headers via `res.header()`. Closes #402 + * Fixed bug messing with error handlers when `listenFD()` is called instead of `listen()`. [thanks guillermo] + + +1.0.0rc2 / 2010-08-17 +================== + + * Added `app.register()` for template engine mapping. Closes #390 + * Added `res.render()` callback support as second argument (no options) + * Added callback support to `res.download()` + * Added callback support for `res.sendfile()` + * Added support for middleware access via `express.middlewareName()` vs `connect.middlewareName()` + * Added "partials" setting to docs + * Added default expresso tests to `express(1)` generated app. Closes #384 + * Fixed `res.sendfile()` error handling, defer via `next()` + * Fixed `res.render()` callback when a layout is used [thanks guillermo] + * Fixed; `make install` creating ~/.node_libraries when not present + * Fixed issue preventing error handlers from being defined anywhere. Closes #387 + +1.0.0rc / 2010-07-28 +================== + + * Added mounted hook. Closes #369 + * Added connect dependency to _package.json_ + + * Removed "reload views" setting and support code + development env never caches, production always caches. + + * Removed _param_ in route callbacks, signature is now + simply (req, res, next), previously (req, res, params, next). + Use _req.params_ for path captures, _req.query_ for GET params. + + * Fixed "home" setting + * Fixed middleware/router precedence issue. Closes #366 + * Fixed; _configure()_ callbacks called immediately. Closes #368 + +1.0.0beta2 / 2010-07-23 +================== + + * Added more examples + * Added; exporting `Server` constructor + * Added `Server#helpers()` for view locals + * Added `Server#dynamicHelpers()` for dynamic view locals. Closes #349 + * Added support for absolute view paths + * Added; _home_ setting defaults to `Server#route` for mounted apps. Closes #363 + * Added Guillermo Rauch to the contributor list + * Added support for "as" for non-collection partials. Closes #341 + * Fixed _install.sh_, ensuring _~/.node_libraries_ exists. Closes #362 [thanks jf] + * Fixed `res.render()` exceptions, now passed to `next()` when no callback is given [thanks guillermo] + * Fixed instanceof `Array` checks, now `Array.isArray()` + * Fixed express(1) expansion of public dirs. Closes #348 + * Fixed middleware precedence. Closes #345 + * Fixed view watcher, now async [thanks aheckmann] + +1.0.0beta / 2010-07-15 +================== + + * Re-write + - much faster + - much lighter + - Check [ExpressJS.com](http://expressjs.com) for migration guide and updated docs + +0.14.0 / 2010-06-15 +================== + + * Utilize relative requires + * Added Static bufferSize option [aheckmann] + * Fixed caching of view and partial subdirectories [aheckmann] + * Fixed mime.type() comments now that ".ext" is not supported + * Updated haml submodule + * Updated class submodule + * Removed bin/express + +0.13.0 / 2010-06-01 +================== + + * Added node v0.1.97 compatibility + * Added support for deleting cookies via Request#cookie('key', null) + * Updated haml submodule + * Fixed not-found page, now using using charset utf-8 + * Fixed show-exceptions page, now using using charset utf-8 + * Fixed view support due to fs.readFile Buffers + * Changed; mime.type() no longer accepts ".type" due to node extname() changes + +0.12.0 / 2010-05-22 +================== + + * Added node v0.1.96 compatibility + * Added view `helpers` export which act as additional local variables + * Updated haml submodule + * Changed ETag; removed inode, modified time only + * Fixed LF to CRLF for setting multiple cookies + * Fixed cookie complation; values are now urlencoded + * Fixed cookies parsing; accepts quoted values and url escaped cookies + +0.11.0 / 2010-05-06 +================== + + * Added support for layouts using different engines + - this.render('page.html.haml', { layout: 'super-cool-layout.html.ejs' }) + - this.render('page.html.haml', { layout: 'foo' }) // assumes 'foo.html.haml' + - this.render('page.html.haml', { layout: false }) // no layout + * Updated ext submodule + * Updated haml submodule + * Fixed EJS partial support by passing along the context. Issue #307 + +0.10.1 / 2010-05-03 +================== + + * Fixed binary uploads. + +0.10.0 / 2010-04-30 +================== + + * Added charset support via Request#charset (automatically assigned to 'UTF-8' when respond()'s + encoding is set to 'utf8' or 'utf-8'. + * Added "encoding" option to Request#render(). Closes #299 + * Added "dump exceptions" setting, which is enabled by default. + * Added simple ejs template engine support + * Added error reponse support for text/plain, application/json. Closes #297 + * Added callback function param to Request#error() + * Added Request#sendHead() + * Added Request#stream() + * Added support for Request#respond(304, null) for empty response bodies + * Added ETag support to Request#sendfile() + * Added options to Request#sendfile(), passed to fs.createReadStream() + * Added filename arg to Request#download() + * Performance enhanced due to pre-reversing plugins so that plugins.reverse() is not called on each request + * Performance enhanced by preventing several calls to toLowerCase() in Router#match() + * Changed; Request#sendfile() now streams + * Changed; Renamed Request#halt() to Request#respond(). Closes #289 + * Changed; Using sys.inspect() instead of JSON.encode() for error output + * Changed; run() returns the http.Server instance. Closes #298 + * Changed; Defaulting Server#host to null (INADDR_ANY) + * Changed; Logger "common" format scale of 0.4f + * Removed Logger "request" format + * Fixed; Catching ENOENT in view caching, preventing error when "views/partials" is not found + * Fixed several issues with http client + * Fixed Logger Content-Length output + * Fixed bug preventing Opera from retaining the generated session id. Closes #292 + +0.9.0 / 2010-04-14 +================== + + * Added DSL level error() route support + * Added DSL level notFound() route support + * Added Request#error() + * Added Request#notFound() + * Added Request#render() callback function. Closes #258 + * Added "max upload size" setting + * Added "magic" variables to collection partials (\_\_index\_\_, \_\_length\_\_, \_\_isFirst\_\_, \_\_isLast\_\_). Closes #254 + * Added [haml.js](http://github.com/visionmedia/haml.js) submodule; removed haml-js + * Added callback function support to Request#halt() as 3rd/4th arg + * Added preprocessing of route param wildcards using param(). Closes #251 + * Added view partial support (with collections etc) + * Fixed bug preventing falsey params (such as ?page=0). Closes #286 + * Fixed setting of multiple cookies. Closes #199 + * Changed; view naming convention is now NAME.TYPE.ENGINE (for example page.html.haml) + * Changed; session cookie is now httpOnly + * Changed; Request is no longer global + * Changed; Event is no longer global + * Changed; "sys" module is no longer global + * Changed; moved Request#download to Static plugin where it belongs + * Changed; Request instance created before body parsing. Closes #262 + * Changed; Pre-caching views in memory when "cache view contents" is enabled. Closes #253 + * Changed; Pre-caching view partials in memory when "cache view partials" is enabled + * Updated support to node --version 0.1.90 + * Updated dependencies + * Removed set("session cookie") in favour of use(Session, { cookie: { ... }}) + * Removed utils.mixin(); use Object#mergeDeep() + +0.8.0 / 2010-03-19 +================== + + * Added coffeescript example app. Closes #242 + * Changed; cache api now async friendly. Closes #240 + * Removed deprecated 'express/static' support. Use 'express/plugins/static' + +0.7.6 / 2010-03-19 +================== + + * Added Request#isXHR. Closes #229 + * Added `make install` (for the executable) + * Added `express` executable for setting up simple app templates + * Added "GET /public/*" to Static plugin, defaulting to /public + * Added Static plugin + * Fixed; Request#render() only calls cache.get() once + * Fixed; Namespacing View caches with "view:" + * Fixed; Namespacing Static caches with "static:" + * Fixed; Both example apps now use the Static plugin + * Fixed set("views"). Closes #239 + * Fixed missing space for combined log format + * Deprecated Request#sendfile() and 'express/static' + * Removed Server#running + +0.7.5 / 2010-03-16 +================== + + * Added Request#flash() support without args, now returns all flashes + * Updated ext submodule + +0.7.4 / 2010-03-16 +================== + + * Fixed session reaper + * Changed; class.js replacing js-oo Class implementation (quite a bit faster, no browser cruft) + +0.7.3 / 2010-03-16 +================== + + * Added package.json + * Fixed requiring of haml / sass due to kiwi removal + +0.7.2 / 2010-03-16 +================== + + * Fixed GIT submodules (HAH!) + +0.7.1 / 2010-03-16 +================== + + * Changed; Express now using submodules again until a PM is adopted + * Changed; chat example using millisecond conversions from ext + +0.7.0 / 2010-03-15 +================== + + * Added Request#pass() support (finds the next matching route, or the given path) + * Added Logger plugin (default "common" format replaces CommonLogger) + * Removed Profiler plugin + * Removed CommonLogger plugin + +0.6.0 / 2010-03-11 +================== + + * Added seed.yml for kiwi package management support + * Added HTTP client query string support when method is GET. Closes #205 + + * Added support for arbitrary view engines. + For example "foo.engine.html" will now require('engine'), + the exports from this module are cached after the first require(). + + * Added async plugin support + + * Removed usage of RESTful route funcs as http client + get() etc, use http.get() and friends + + * Removed custom exceptions + +0.5.0 / 2010-03-10 +================== + + * Added ext dependency (library of js extensions) + * Removed extname() / basename() utils. Use path module + * Removed toArray() util. Use arguments.values + * Removed escapeRegexp() util. Use RegExp.escape() + * Removed process.mixin() dependency. Use utils.mixin() + * Removed Collection + * Removed ElementCollection + * Shameless self promotion of ebook "Advanced JavaScript" (http://dev-mag.com) ;) + +0.4.0 / 2010-02-11 +================== + + * Added flash() example to sample upload app + * Added high level restful http client module (express/http) + * Changed; RESTful route functions double as HTTP clients. Closes #69 + * Changed; throwing error when routes are added at runtime + * Changed; defaulting render() context to the current Request. Closes #197 + * Updated haml submodule + +0.3.0 / 2010-02-11 +================== + + * Updated haml / sass submodules. Closes #200 + * Added flash message support. Closes #64 + * Added accepts() now allows multiple args. fixes #117 + * Added support for plugins to halt. Closes #189 + * Added alternate layout support. Closes #119 + * Removed Route#run(). Closes #188 + * Fixed broken specs due to use(Cookie) missing + +0.2.1 / 2010-02-05 +================== + + * Added "plot" format option for Profiler (for gnuplot processing) + * Added request number to Profiler plugin + * Fixed binary encoding for multi-part file uploads, was previously defaulting to UTF8 + * Fixed issue with routes not firing when not files are present. Closes #184 + * Fixed process.Promise -> events.Promise + +0.2.0 / 2010-02-03 +================== + + * Added parseParam() support for name[] etc. (allows for file inputs with "multiple" attr) Closes #180 + * Added Both Cache and Session option "reapInterval" may be "reapEvery". Closes #174 + * Added expiration support to cache api with reaper. Closes #133 + * Added cache Store.Memory#reap() + * Added Cache; cache api now uses first class Cache instances + * Added abstract session Store. Closes #172 + * Changed; cache Memory.Store#get() utilizing Collection + * Renamed MemoryStore -> Store.Memory + * Fixed use() of the same plugin several time will always use latest options. Closes #176 + +0.1.0 / 2010-02-03 +================== + + * Changed; Hooks (before / after) pass request as arg as well as evaluated in their context + * Updated node support to 0.1.27 Closes #169 + * Updated dirname(__filename) -> __dirname + * Updated libxmljs support to v0.2.0 + * Added session support with memory store / reaping + * Added quick uid() helper + * Added multi-part upload support + * Added Sass.js support / submodule + * Added production env caching view contents and static files + * Added static file caching. Closes #136 + * Added cache plugin with memory stores + * Added support to StaticFile so that it works with non-textual files. + * Removed dirname() helper + * Removed several globals (now their modules must be required) + +0.0.2 / 2010-01-10 +================== + + * Added view benchmarks; currently haml vs ejs + * Added Request#attachment() specs. Closes #116 + * Added use of node's parseQuery() util. Closes #123 + * Added `make init` for submodules + * Updated Haml + * Updated sample chat app to show messages on load + * Updated libxmljs parseString -> parseHtmlString + * Fixed `make init` to work with older versions of git + * Fixed specs can now run independant specs for those who cant build deps. Closes #127 + * Fixed issues introduced by the node url module changes. Closes 126. + * Fixed two assertions failing due to Collection#keys() returning strings + * Fixed faulty Collection#toArray() spec due to keys() returning strings + * Fixed `make test` now builds libxmljs.node before testing + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/coder-base/node_modules_orig/express/LICENSE b/coder-base/node_modules_orig/express/LICENSE new file mode 100755 index 00000000..36075a3b --- /dev/null +++ b/coder-base/node_modules_orig/express/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2009-2011 TJ Holowaychuk + +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/coder-base/node_modules_orig/express/Makefile b/coder-base/node_modules_orig/express/Makefile new file mode 100755 index 00000000..e820e31c --- /dev/null +++ b/coder-base/node_modules_orig/express/Makefile @@ -0,0 +1,33 @@ + +MOCHA_OPTS= +REPORTER = dot + +check: test + +test: test-unit test-acceptance + +test-unit: + @NODE_ENV=test ./node_modules/.bin/mocha \ + --reporter $(REPORTER) \ + $(MOCHA_OPTS) + +test-acceptance: + @NODE_ENV=test ./node_modules/.bin/mocha \ + --reporter $(REPORTER) \ + --bail \ + test/acceptance/*.js + +test-cov: lib-cov + @EXPRESS_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html + +lib-cov: + @jscoverage lib lib-cov + +benchmark: + @./support/bench + +clean: + rm -f coverage.html + rm -fr lib-cov + +.PHONY: test test-unit test-acceptance benchmark clean diff --git a/coder-base/node_modules_orig/express/Readme.md b/coder-base/node_modules_orig/express/Readme.md new file mode 100755 index 00000000..6bb8b95e --- /dev/null +++ b/coder-base/node_modules_orig/express/Readme.md @@ -0,0 +1,179 @@ +![express logo](http://f.cl.ly/items/0V2S1n0K1i3y1c122g04/Screen%20Shot%202012-04-11%20at%209.59.42%20AM.png) + + 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) + +```js +var express = require('express'); +var app = express(); + +app.get('/', function(req, res){ + res.send('Hello World'); +}); + +app.listen(3000); +``` + +## Installation + + $ npm install -g express + +## Quick Start + + The quickest way to get started with express is to utilize the executable `express(1)` to generate an application as shown below: + + Create the app: + + $ npm install -g express + $ express /tmp/foo && cd /tmp/foo + + Install dependencies: + + $ npm install + + Start the server: + + $ node app + +## Features + + * Built on [Connect](http://github.com/senchalabs/connect) + * Robust routing + * HTTP helpers (redirection, caching, etc) + * View system supporting 14+ template engines + * Content negotiation + * Focus on high performance + * Environment based configuration + * Executable for generating applications quickly + * High test coverage + +## Philosophy + + The Express philosophy is to provide small, robust tooling for HTTP servers. Making + it a great solution for single page applications, web sites, hybrids, or public + HTTP APIs. + + Built on Connect you can use _only_ what you need, and nothing more, applications + can be as big or as small as you like, even a single file. Express does + not force you to use any specific ORM or template engine. With support for over + 14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js) + you can quickly craft your perfect framework. + +## More Information + + * Join #express on freenode + * [Google Group](http://groups.google.com/group/express-js) for discussion + * Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates + * Visit the [Wiki](http://github.com/visionmedia/express/wiki) + * [日本語ドキュメンテーション](http://hideyukisaito.com/doc/expressjs/) by [hideyukisaito](https://github.com/hideyukisaito) + * [Русскоязычная документация](http://express-js.ru/) + +## Viewing Examples + +Clone the Express repo, then install the dev dependencies to install all the example / test suite deps: + + $ git clone git://github.com/visionmedia/express.git --depth 1 + $ cd express + $ npm install + +then run whichever tests you want: + + $ node examples/content-negotiation + +## Running Tests + +To run the test suite first invoke the following command within the repo, installing the development dependencies: + + $ npm install + +then run the tests: + + $ make test + +## Contributors + +``` +project: express +commits: 3559 +active : 468 days +files : 237 +authors: + 1891 Tj Holowaychuk 53.1% + 1285 visionmedia 36.1% + 182 TJ Holowaychuk 5.1% + 54 Aaron Heckmann 1.5% + 34 csausdev 1.0% + 26 ciaranj 0.7% + 21 Robert Sköld 0.6% + 6 Guillermo Rauch 0.2% + 3 Dav Glass 0.1% + 3 Nick Poulden 0.1% + 2 Randy Merrill 0.1% + 2 Benny Wong 0.1% + 2 Hunter Loftis 0.1% + 2 Jake Gordon 0.1% + 2 Brian McKinney 0.1% + 2 Roman Shtylman 0.1% + 2 Ben Weaver 0.1% + 2 Dave Hoover 0.1% + 2 Eivind Fjeldstad 0.1% + 2 Daniel Shaw 0.1% + 1 Matt Colyer 0.0% + 1 Pau Ramon 0.0% + 1 Pero Pejovic 0.0% + 1 Peter Rekdal Sunde 0.0% + 1 Raynos 0.0% + 1 Teng Siong Ong 0.0% + 1 Viktor Kelemen 0.0% + 1 ctide 0.0% + 1 8bitDesigner 0.0% + 1 isaacs 0.0% + 1 mgutz 0.0% + 1 pikeas 0.0% + 1 shuwatto 0.0% + 1 tstrimple 0.0% + 1 ewoudj 0.0% + 1 Adam Sanderson 0.0% + 1 Andrii Kostenko 0.0% + 1 Andy Hiew 0.0% + 1 Arpad Borsos 0.0% + 1 Ashwin Purohit 0.0% + 1 Benjen 0.0% + 1 Darren Torpey 0.0% + 1 Greg Ritter 0.0% + 1 Gregory Ritter 0.0% + 1 James Herdman 0.0% + 1 Jim Snodgrass 0.0% + 1 Joe McCann 0.0% + 1 Jonathan Dumaine 0.0% + 1 Jonathan Palardy 0.0% + 1 Jonathan Zacsh 0.0% + 1 Justin Lilly 0.0% + 1 Ken Sato 0.0% + 1 Maciej Małecki 0.0% + 1 Masahiro Hayashi 0.0% +``` + +## License + +(The MIT License) + +Copyright (c) 2009-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/coder-base/node_modules_orig/express/bin/express b/coder-base/node_modules_orig/express/bin/express new file mode 100755 index 00000000..3c0090c6 --- /dev/null +++ b/coder-base/node_modules_orig/express/bin/express @@ -0,0 +1,422 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var exec = require('child_process').exec + , program = require('commander') + , mkdirp = require('mkdirp') + , pkg = require('../package.json') + , version = pkg.version + , os = require('os') + , fs = require('fs'); + +// CLI + +program + .version(version) + .option('-s, --sessions', 'add session support') + .option('-e, --ejs', 'add ejs engine support (defaults to jade)') + .option('-J, --jshtml', 'add jshtml engine support (defaults to jade)') + .option('-H, --hogan', 'add hogan.js engine support') + .option('-c, --css ', 'add stylesheet support (less|stylus) (defaults to plain css)') + .option('-f, --force', 'force on non-empty directory') + .parse(process.argv); + +// Path + +var path = program.args.shift() || '.'; + +// end-of-line code + +var eol = 'win32' == os.platform() ? '\r\n' : '\n' + +// Template engine + +program.template = 'jade'; +if (program.ejs) program.template = 'ejs'; +if (program.jshtml) program.template = 'jshtml'; +if (program.hogan) program.template = 'hjs'; + +/** + * Routes index template. + */ + +var index = [ + '' + , '/*' + , ' * GET home page.' + , ' */' + , '' + , 'exports.index = function(req, res){' + , ' res.render(\'index\', { title: \'Express\' });' + , '};' +].join(eol); + +/** + * Routes users template. + */ + +var users = [ + '' + , '/*' + , ' * GET users listing.' + , ' */' + , '' + , 'exports.list = function(req, res){' + , ' res.send("respond with a resource");' + , '};' +].join(eol); + +/** + * Jade layout template. + */ + +var jadeLayout = [ + 'doctype 5' + , 'html' + , ' head' + , ' title= title' + , ' link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')' + , ' body' + , ' block content' +].join(eol); + +/** + * Jade index template. + */ + +var jadeIndex = [ + 'extends layout' + , '' + , 'block content' + , ' h1= title' + , ' p Welcome to #{title}' +].join(eol); + +/** + * EJS index template. + */ + +var ejsIndex = [ + '' + , '' + , ' ' + , ' <%= title %>' + , ' ' + , ' ' + , ' ' + , '

<%= title %>

' + , '

Welcome to <%= title %>

' + , ' ' + , '' +].join(eol); + +/** + * JSHTML layout template. + */ + +var jshtmlLayout = [ + '' + , '' + , ' ' + , ' @write(title) ' + , ' ' + , ' ' + , ' ' + , ' @write(body)' + , ' ' + , '' +].join(eol); + +/** + * JSHTML index template. + */ + +var jshtmlIndex = [ + '

@write(title)

' + , '

Welcome to @write(title)

' +].join(eol); + +/** + * Hogan.js index template. + */ +var hoganIndex = [ + '' + , '' + , ' ' + , ' {{ title }}' + , ' ' + , ' ' + , ' ' + , '

{{ title }}

' + , '

Welcome to {{ title }}

' + , ' ' + , '' +].join(eol); + +/** + * Default css template. + */ + +var css = [ + 'body {' + , ' padding: 50px;' + , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;' + , '}' + , '' + , 'a {' + , ' color: #00B7FF;' + , '}' +].join(eol); + +/** + * Default less template. + */ + +var less = [ + 'body {' + , ' padding: 50px;' + , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;' + , '}' + , '' + , 'a {' + , ' color: #00B7FF;' + , '}' +].join(eol); + +/** + * Default stylus template. + */ + +var stylus = [ + 'body' + , ' padding: 50px' + , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif' + , 'a' + , ' color: #00B7FF' +].join(eol); + +/** + * App template. + */ + +var app = [ + '' + , '/**' + , ' * Module dependencies.' + , ' */' + , '' + , 'var express = require(\'express\')' + , ' , routes = require(\'./routes\')' + , ' , user = require(\'./routes/user\')' + , ' , http = require(\'http\')' + , ' , path = require(\'path\');' + , '' + , 'var app = express();' + , '' + , 'app.configure(function(){' + , ' app.set(\'port\', process.env.PORT || 3000);' + , ' app.set(\'views\', __dirname + \'/views\');' + , ' app.set(\'view engine\', \':TEMPLATE\');' + , ' app.use(express.favicon());' + , ' app.use(express.logger(\'dev\'));' + , ' app.use(express.bodyParser());' + , ' app.use(express.methodOverride());{sess}' + , ' app.use(app.router);{css}' + , ' app.use(express.static(path.join(__dirname, \'public\')));' + , '});' + , '' + , 'app.configure(\'development\', function(){' + , ' app.use(express.errorHandler());' + , '});' + , '' + , 'app.get(\'/\', routes.index);' + , 'app.get(\'/users\', user.list);' + , '' + , 'http.createServer(app).listen(app.get(\'port\'), function(){' + , ' console.log("Express server listening on port " + app.get(\'port\'));' + , '});' + , '' +].join(eol); + +// Generate application + +(function createApplication(path) { + emptyDirectory(path, function(empty){ + if (empty || program.force) { + createApplicationAt(path); + } else { + program.confirm('destination is not empty, continue? ', function(ok){ + if (ok) { + process.stdin.destroy(); + createApplicationAt(path); + } else { + abort('aborting'); + } + }); + } + }); +})(path); + +/** + * Create application at the given directory `path`. + * + * @param {String} path + */ + +function createApplicationAt(path) { + console.log(); + process.on('exit', function(){ + console.log(); + console.log(' install dependencies:'); + console.log(' $ cd %s && npm install', path); + console.log(); + console.log(' run the app:'); + console.log(' $ node app'); + console.log(); + }); + + mkdir(path, function(){ + mkdir(path + '/public'); + mkdir(path + '/public/javascripts'); + mkdir(path + '/public/images'); + mkdir(path + '/public/stylesheets', function(){ + switch (program.css) { + case 'less': + write(path + '/public/stylesheets/style.less', less); + break; + case 'stylus': + write(path + '/public/stylesheets/style.styl', stylus); + break; + default: + write(path + '/public/stylesheets/style.css', css); + } + }); + + mkdir(path + '/routes', function(){ + write(path + '/routes/index.js', index); + write(path + '/routes/user.js', users); + }); + + mkdir(path + '/views', function(){ + switch (program.template) { + case 'ejs': + write(path + '/views/index.ejs', ejsIndex); + break; + case 'jade': + write(path + '/views/layout.jade', jadeLayout); + write(path + '/views/index.jade', jadeIndex); + break; + case 'jshtml': + write(path + '/views/layout.jshtml', jshtmlLayout); + write(path + '/views/index.jshtml', jshtmlIndex); + break; + case 'hjs': + write(path + '/views/index.hjs', hoganIndex); + break; + + } + }); + + // CSS Engine support + switch (program.css) { + case 'less': + app = app.replace('{css}', eol + ' app.use(require(\'less-middleware\')({ src: __dirname + \'/public\' }));'); + break; + case 'stylus': + app = app.replace('{css}', eol + ' app.use(require(\'stylus\').middleware(__dirname + \'/public\'));'); + break; + default: + app = app.replace('{css}', ''); + } + + // Session support + app = app.replace('{sess}', program.sessions + ? eol + ' app.use(express.cookieParser(\'your secret here\'));' + eol + ' app.use(express.session());' + : ''); + + // Template support + app = app.replace(':TEMPLATE', program.template); + + // package.json + var pkg = { + name: 'application-name' + , version: '0.0.1' + , private: true + , scripts: { start: 'node app' } + , dependencies: { + express: version + } + } + + if (program.template) pkg.dependencies[program.template] = '*'; + + // CSS Engine support + switch (program.css) { + case 'less': + pkg.dependencies['less-middleware'] = '*'; + break; + default: + if (program.css) { + pkg.dependencies[program.css] = '*'; + } + } + + write(path + '/package.json', JSON.stringify(pkg, null, 2)); + write(path + '/app.js', app); + }); +} + +/** + * Check if the given directory `path` is empty. + * + * @param {String} path + * @param {Function} fn + */ + +function emptyDirectory(path, fn) { + fs.readdir(path, function(err, files){ + if (err && 'ENOENT' != err.code) throw err; + fn(!files || !files.length); + }); +} + +/** + * echo str > path. + * + * @param {String} path + * @param {String} str + */ + +function write(path, str) { + fs.writeFile(path, str); + console.log(' \x1b[36mcreate\x1b[0m : ' + path); +} + +/** + * Mkdir -p. + * + * @param {String} path + * @param {Function} fn + */ + +function mkdir(path, fn) { + mkdirp(path, 0755, function(err){ + if (err) throw err; + console.log(' \033[36mcreate\033[0m : ' + path); + fn && fn(); + }); +} + +/** + * Exit with the given `str`. + * + * @param {String} str + */ + +function abort(str) { + console.error(str); + process.exit(1); +} diff --git a/coder-base/node_modules_orig/express/client.js b/coder-base/node_modules_orig/express/client.js new file mode 100755 index 00000000..8984c44d --- /dev/null +++ b/coder-base/node_modules_orig/express/client.js @@ -0,0 +1,25 @@ + +var http = require('http'); + +var times = 50; + +while (times--) { + var req = http.request({ + port: 3000 + , method: 'POST' + , headers: { 'Content-Type': 'application/x-www-form-urlencoded' } + }); + + req.on('response', function(res){ + console.log(res.statusCode); + }); + + var n = 500000; + while (n--) { + req.write('foo=bar&bar=baz&'); + } + + req.write('foo=bar&bar=baz'); + + req.end(); +} \ No newline at end of file diff --git a/coder-base/node_modules_orig/express/index.js b/coder-base/node_modules_orig/express/index.js new file mode 100755 index 00000000..bfe99345 --- /dev/null +++ b/coder-base/node_modules_orig/express/index.js @@ -0,0 +1,4 @@ + +module.exports = process.env.EXPRESS_COV + ? require('./lib-cov/express') + : require('./lib/express'); \ No newline at end of file diff --git a/coder-base/node_modules_orig/express/lib/application.js b/coder-base/node_modules_orig/express/lib/application.js new file mode 100755 index 00000000..7ebc6f66 --- /dev/null +++ b/coder-base/node_modules_orig/express/lib/application.js @@ -0,0 +1,534 @@ +/** + * Module dependencies. + */ + +var connect = require('connect') + , Router = require('./router') + , methods = require('methods') + , middleware = require('./middleware') + , debug = require('debug')('express:application') + , locals = require('./utils').locals + , View = require('./view') + , utils = connect.utils + , path = require('path') + , http = require('http') + , join = path.join; + +/** + * Application prototype. + */ + +var app = exports = module.exports = {}; + +/** + * Initialize the server. + * + * - setup default configuration + * - setup default middleware + * - setup route reflection methods + * + * @api private + */ + +app.init = function(){ + this.cache = {}; + this.settings = {}; + this.engines = {}; + this.viewCallbacks = []; + this.defaultConfiguration(); +}; + +/** + * Initialize application configuration. + * + * @api private + */ + +app.defaultConfiguration = function(){ + // default settings + this.enable('x-powered-by'); + this.set('env', process.env.NODE_ENV || 'development'); + this.set('subdomain offset', 2); + debug('booting in %s mode', this.get('env')); + + // implicit middleware + this.use(connect.query()); + this.use(middleware.init(this)); + + // inherit protos + this.on('mount', function(parent){ + this.request.__proto__ = parent.request; + this.response.__proto__ = parent.response; + this.engines.__proto__ = parent.engines; + }); + + // router + this._router = new Router(this); + this.routes = this._router.map; + this.__defineGetter__('router', function(){ + this._usedRouter = true; + this._router.caseSensitive = this.enabled('case sensitive routing'); + this._router.strict = this.enabled('strict routing'); + return this._router.middleware; + }); + + // setup locals + this.locals = locals(this); + + // default locals + this.locals.settings = this.settings; + + // default configuration + this.set('views', process.cwd() + '/views'); + this.set('jsonp callback name', 'callback'); + + this.configure('development', function(){ + this.set('json spaces', 2); + }); + + this.configure('production', function(){ + this.enable('view cache'); + }); +}; + +/** + * Proxy `connect#use()` to apply settings to + * mounted applications. + * + * @param {String|Function|Server} route + * @param {Function|Server} fn + * @return {app} for chaining + * @api public + */ + +app.use = function(route, fn){ + var app; + + // default route to '/' + if ('string' != typeof route) fn = route, route = '/'; + + // express app + if (fn.handle && fn.set) app = fn; + + // restore .app property on req and res + if (app) { + app.route = route; + fn = function(req, res, next) { + var orig = req.app; + app.handle(req, res, function(err){ + req.app = res.app = orig; + req.__proto__ = orig.request; + res.__proto__ = orig.response; + next(err); + }); + }; + } + + connect.proto.use.call(this, route, fn); + + // mounted an app + if (app) { + app.parent = this; + app.emit('mount', this); + } + + return this; +}; + +/** + * Register the given template engine callback `fn` + * as `ext`. + * + * By default will `require()` the engine based on the + * file extension. For example if you try to render + * a "foo.jade" file Express will invoke the following internally: + * + * app.engine('jade', require('jade').__express); + * + * For engines that do not provide `.__express` out of the box, + * or if you wish to "map" a different extension to the template engine + * you may use this method. For example mapping the EJS template engine to + * ".html" files: + * + * app.engine('html', require('ejs').renderFile); + * + * In this case EJS provides a `.renderFile()` method with + * the same signature that Express expects: `(path, options, callback)`, + * though note that it aliases this method as `ejs.__express` internally + * so if you're using ".ejs" extensions you dont need to do anything. + * + * Some template engines do not follow this convention, the + * [Consolidate.js](https://github.com/visionmedia/consolidate.js) + * library was created to map all of node's popular template + * engines to follow this convention, thus allowing them to + * work seeessly within Express. + * + * @param {String} ext + * @param {Function} fn + * @return {app} for chaining + * @api public + */ + +app.engine = function(ext, fn){ + if ('function' != typeof fn) throw new Error('callback function required'); + if ('.' != ext[0]) ext = '.' + ext; + this.engines[ext] = fn; + return this; +}; + +/** + * Map the given param placeholder `name`(s) to the given callback(s). + * + * Parameter mapping is used to provide pre-conditions to routes + * which use normalized placeholders. For example a _:user_id_ parameter + * could automatically load a user's information from the database without + * any additional code, + * + * The callback uses the samesignature as middleware, the only differencing + * being that the value of the placeholder is passed, in this case the _id_ + * of the user. Once the `next()` function is invoked, just like middleware + * it will continue on to execute the route, or subsequent parameter functions. + * + * app.param('user_id', function(req, res, next, id){ + * User.find(id, function(err, user){ + * if (err) { + * next(err); + * } else if (user) { + * req.user = user; + * next(); + * } else { + * next(new Error('failed to load user')); + * } + * }); + * }); + * + * @param {String|Array} name + * @param {Function} fn + * @return {app} for chaining + * @api public + */ + +app.param = function(name, fn){ + var self = this + , fns = [].slice.call(arguments, 1); + + // array + if (Array.isArray(name)) { + name.forEach(function(name){ + fns.forEach(function(fn){ + self.param(name, fn); + }); + }); + // param logic + } else if ('function' == typeof name) { + this._router.param(name); + // single + } else { + if (':' == name[0]) name = name.substr(1); + fns.forEach(function(fn){ + self._router.param(name, fn); + }); + } + + return this; +}; + +/** + * Assign `setting` to `val`, or return `setting`'s value. + * + * app.set('foo', 'bar'); + * app.get('foo'); + * // => "bar" + * + * Mounted servers inherit their parent server's settings. + * + * @param {String} setting + * @param {String} val + * @return {Server} for chaining + * @api public + */ + +app.set = function(setting, val){ + if (1 == arguments.length) { + if (this.settings.hasOwnProperty(setting)) { + return this.settings[setting]; + } else if (this.parent) { + return this.parent.set(setting); + } + } else { + this.settings[setting] = val; + return this; + } +}; + +/** + * Return the app's absolute pathname + * based on the parent(s) that have + * mounted it. + * + * For example if the application was + * mounted as "/admin", which itself + * was mounted as "/blog" then the + * return value would be "/blog/admin". + * + * @return {String} + * @api private + */ + +app.path = function(){ + return this.parent + ? this.parent.path() + this.route + : ''; +}; + +/** + * Check if `setting` is enabled (truthy). + * + * app.enabled('foo') + * // => false + * + * app.enable('foo') + * app.enabled('foo') + * // => true + * + * @param {String} setting + * @return {Boolean} + * @api public + */ + +app.enabled = function(setting){ + return !!this.set(setting); +}; + +/** + * Check if `setting` is disabled. + * + * app.disabled('foo') + * // => true + * + * app.enable('foo') + * app.disabled('foo') + * // => false + * + * @param {String} setting + * @return {Boolean} + * @api public + */ + +app.disabled = function(setting){ + return !this.set(setting); +}; + +/** + * Enable `setting`. + * + * @param {String} setting + * @return {app} for chaining + * @api public + */ + +app.enable = function(setting){ + return this.set(setting, true); +}; + +/** + * Disable `setting`. + * + * @param {String} setting + * @return {app} for chaining + * @api public + */ + +app.disable = function(setting){ + return this.set(setting, false); +}; + +/** + * Configure callback for zero or more envs, + * when no `env` is specified that callback will + * be invoked for all environments. Any combination + * can be used multiple times, in any order desired. + * + * Examples: + * + * app.configure(function(){ + * // executed for all envs + * }); + * + * app.configure('stage', function(){ + * // executed staging env + * }); + * + * app.configure('stage', 'production', function(){ + * // executed for stage and production + * }); + * + * Note: + * + * These callbacks are invoked immediately, and + * are effectively sugar for the following: + * + * var env = process.env.NODE_ENV || 'development'; + * + * switch (env) { + * case 'development': + * ... + * break; + * case 'stage': + * ... + * break; + * case 'production': + * ... + * break; + * } + * + * @param {String} env... + * @param {Function} fn + * @return {app} for chaining + * @api public + */ + +app.configure = function(env, fn){ + var envs = 'all' + , args = [].slice.call(arguments); + fn = args.pop(); + if (args.length) envs = args; + if ('all' == envs || ~envs.indexOf(this.settings.env)) fn.call(this); + return this; +}; + +/** + * Delegate `.VERB(...)` calls to `router.VERB(...)`. + */ + +methods.forEach(function(method){ + app[method] = function(path){ + if ('get' == method && 1 == arguments.length) return this.set(path); + + // if no router attacked yet, attach the router + if (!this._usedRouter) this.use(this.router); + + // setup route + this._router[method].apply(this._router, arguments); + return this; + }; +}); + +/** + * Special-cased "all" method, applying the given route `path`, + * middleware, and callback to _every_ HTTP method. + * + * @param {String} path + * @param {Function} ... + * @return {app} for chaining + * @api public + */ + +app.all = function(path){ + var args = arguments; + methods.forEach(function(method){ + app[method].apply(this, args); + }, this); + return this; +}; + +// del -> delete alias + +app.del = app.delete; + +/** + * Render the given view `name` name with `options` + * and a callback accepting an error and the + * rendered template string. + * + * Example: + * + * app.render('email', { name: 'Tobi' }, function(err, html){ + * // ... + * }) + * + * @param {String} name + * @param {String|Function} options or fn + * @param {Function} fn + * @api public + */ + +app.render = function(name, options, fn){ + var opts = {} + , cache = this.cache + , engines = this.engines + , view; + + // support callback function as second arg + if ('function' == typeof options) { + fn = options, options = {}; + } + + // merge app.locals + utils.merge(opts, this.locals); + + // merge options._locals + if (options._locals) utils.merge(opts, options._locals); + + // merge options + utils.merge(opts, options); + + // set .cache unless explicitly provided + opts.cache = null == opts.cache + ? this.enabled('view cache') + : opts.cache; + + // primed cache + if (opts.cache) view = cache[name]; + + // view + if (!view) { + view = new View(name, { + defaultEngine: this.get('view engine'), + root: this.get('views'), + engines: engines + }); + + if (!view.path) { + var err = new Error('Failed to lookup view "' + name + '"'); + err.view = view; + return fn(err); + } + + // prime the cache + if (opts.cache) cache[name] = view; + } + + // render + try { + view.render(opts, fn); + } catch (err) { + fn(err); + } +}; + +/** + * Listen for connections. + * + * A node `http.Server` is returned, with this + * application (which is a `Function`) as its + * callback. If you wish to create both an HTTP + * and HTTPS server you may do so with the "http" + * and "https" modules as shown here: + * + * var http = require('http') + * , https = require('https') + * , express = require('express') + * , app = express(); + * + * http.createServer(app).listen(80); + * https.createServer({ ... }, app).listen(443); + * + * @return {http.Server} + * @api public + */ + +app.listen = function(){ + var server = http.createServer(this); + return server.listen.apply(server, arguments); +}; diff --git a/coder-base/node_modules_orig/express/lib/express.js b/coder-base/node_modules_orig/express/lib/express.js new file mode 100755 index 00000000..2a704b21 --- /dev/null +++ b/coder-base/node_modules_orig/express/lib/express.js @@ -0,0 +1,92 @@ +/** + * Module dependencies. + */ + +var connect = require('connect') + , proto = require('./application') + , Route = require('./router/route') + , Router = require('./router') + , req = require('./request') + , res = require('./response') + , utils = connect.utils; + +/** + * Expose `createApplication()`. + */ + +exports = module.exports = createApplication; + +/** + * Framework version. + */ + +exports.version = '3.1.0'; + +/** + * Expose mime. + */ + +exports.mime = connect.mime; + +/** + * Create an express application. + * + * @return {Function} + * @api public + */ + +function createApplication() { + var app = connect(); + utils.merge(app, proto); + app.request = { __proto__: req }; + app.response = { __proto__: res }; + app.init(); + return app; +} + +/** + * Expose connect.middleware as express.* + * for example `express.logger` etc. + */ + +for (var key in connect.middleware) { + Object.defineProperty( + exports + , key + , Object.getOwnPropertyDescriptor(connect.middleware, key)); +} + +/** + * Error on createServer(). + */ + +exports.createServer = function(){ + console.warn('Warning: express.createServer() is deprecated, express'); + console.warn('applications no longer inherit from http.Server,'); + console.warn('please use:'); + console.warn(''); + console.warn(' var express = require("express");'); + console.warn(' var app = express();'); + console.warn(''); + return createApplication(); +}; + +/** + * Expose the prototypes. + */ + +exports.application = proto; +exports.request = req; +exports.response = res; + +/** + * Expose constructors. + */ + +exports.Route = Route; +exports.Router = Router; + +// Error handler title + +exports.errorHandler.title = 'Express'; + diff --git a/coder-base/node_modules_orig/express/lib/middleware.js b/coder-base/node_modules_orig/express/lib/middleware.js new file mode 100755 index 00000000..308c5bb6 --- /dev/null +++ b/coder-base/node_modules_orig/express/lib/middleware.js @@ -0,0 +1,33 @@ + +/** + * Module dependencies. + */ + +var utils = require('./utils'); + +/** + * Initialization middleware, exposing the + * request and response to eachother, as well + * as defaulting the X-Powered-By header field. + * + * @param {Function} app + * @return {Function} + * @api private + */ + +exports.init = function(app){ + return function expressInit(req, res, next){ + req.app = res.app = app; + if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express'); + req.res = res; + res.req = req; + req.next = next; + + req.__proto__ = app.request; + res.__proto__ = app.response; + + res.locals = res.locals || utils.locals(res); + + next(); + } +}; diff --git a/coder-base/node_modules_orig/express/lib/request.js b/coder-base/node_modules_orig/express/lib/request.js new file mode 100755 index 00000000..1c6048d9 --- /dev/null +++ b/coder-base/node_modules_orig/express/lib/request.js @@ -0,0 +1,493 @@ + +/** + * Module dependencies. + */ + +var http = require('http') + , utils = require('./utils') + , connect = require('connect') + , fresh = require('fresh') + , parseRange = require('range-parser') + , parse = connect.utils.parseUrl + , mime = connect.mime; + +/** + * Request prototype. + */ + +var req = exports = module.exports = { + __proto__: http.IncomingMessage.prototype +}; + +/** + * Return request header. + * + * The `Referrer` header field is special-cased, + * both `Referrer` and `Referer` are interchangeable. + * + * Examples: + * + * req.get('Content-Type'); + * // => "text/plain" + * + * req.get('content-type'); + * // => "text/plain" + * + * req.get('Something'); + * // => undefined + * + * Aliased as `req.header()`. + * + * @param {String} name + * @return {String} + * @api public + */ + +req.get = +req.header = function(name){ + switch (name = name.toLowerCase()) { + case 'referer': + case 'referrer': + return this.headers.referrer + || this.headers.referer; + default: + return this.headers[name]; + } +}; + +/** + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single mime type string + * such as "application/json", the extension name + * such as "json", a comma-delimted list such as "json, html, text/plain", + * or an array `["json", "html", "text/plain"]`. When a list + * or array is given the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * req.accepts('html'); + * // => "html" + * + * // Accept: text/*, application/json + * req.accepts('html'); + * // => "html" + * req.accepts('text/html'); + * // => "text/html" + * req.accepts('json, text'); + * // => "json" + * req.accepts('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * req.accepts('image/png'); + * req.accepts('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * req.accepts(['html', 'json']); + * req.accepts('html, json'); + * // => "json" + * + * @param {String|Array} type(s) + * @return {String} + * @api public + */ + +req.accepts = function(type){ + return utils.accepts(type, this.get('Accept')); +}; + +/** + * Check if the given `charset` is acceptable, + * otherwise you should respond with 406 "Not Acceptable". + * + * @param {String} charset + * @return {Boolean} + * @api public + */ + +req.acceptsCharset = function(charset){ + var accepted = this.acceptedCharsets; + return accepted.length + ? ~accepted.indexOf(charset) + : true; +}; + +/** + * Check if the given `lang` is acceptable, + * otherwise you should respond with 406 "Not Acceptable". + * + * @param {String} lang + * @return {Boolean} + * @api public + */ + +req.acceptsLanguage = function(lang){ + var accepted = this.acceptedLanguages; + return accepted.length + ? ~accepted.indexOf(lang) + : true; +}; + +/** + * Parse Range header field, + * capping to the given `size`. + * + * Unspecified ranges such as "0-" require + * knowledge of your resource length. In + * the case of a byte range this is of course + * the total number of bytes. If the Range + * header field is not given `null` is returned, + * `-1` when unsatisfiable, `-2` when syntactically invalid. + * + * NOTE: remember that ranges are inclusive, so + * for example "Range: users=0-3" should respond + * with 4 users when available, not 3. + * + * @param {Number} size + * @return {Array} + * @api public + */ + +req.range = function(size){ + var range = this.get('Range'); + if (!range) return; + return parseRange(size, range); +}; + +/** + * Return an array of Accepted media types + * ordered from highest quality to lowest. + * + * Examples: + * + * [ { value: 'application/json', + * quality: 1, + * type: 'application', + * subtype: 'json' }, + * { value: 'text/html', + * quality: 0.5, + * type: 'text', + * subtype: 'html' } ] + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('accepted', function(){ + var accept = this.get('Accept'); + return accept + ? utils.parseAccept(accept) + : []; +}); + +/** + * Return an array of Accepted languages + * ordered from highest quality to lowest. + * + * Examples: + * + * Accept-Language: en;q=.5, en-us + * ['en-us', 'en'] + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('acceptedLanguages', function(){ + var accept = this.get('Accept-Language'); + return accept + ? utils + .parseQuality(accept) + .map(function(obj){ + return obj.value; + }) + : []; +}); + +/** + * Return an array of Accepted charsets + * ordered from highest quality to lowest. + * + * Examples: + * + * Accept-Charset: iso-8859-5;q=.2, unicode-1-1;q=0.8 + * ['unicode-1-1', 'iso-8859-5'] + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('acceptedCharsets', function(){ + var accept = this.get('Accept-Charset'); + return accept + ? utils + .parseQuality(accept) + .map(function(obj){ + return obj.value; + }) + : []; +}); + +/** + * Return the value of param `name` when present or `defaultValue`. + * + * - Checks route placeholders, ex: _/user/:id_ + * - Checks body params, ex: id=12, {"id":12} + * - Checks query string params, ex: ?id=12 + * + * To utilize request bodies, `req.body` + * should be an object. This can be done by using + * the `connect.bodyParser()` middleware. + * + * @param {String} name + * @param {Mixed} defaultValue + * @return {String} + * @api public + */ + +req.param = function(name, defaultValue){ + var params = this.params || {}; + var body = this.body || {}; + var query = this.query || {}; + if (null != params[name] && params.hasOwnProperty(name)) return params[name]; + if (null != body[name]) return body[name]; + if (null != query[name]) return query[name]; + return defaultValue; +}; + +/** + * Check if the incoming request contains the "Content-Type" + * header field, and it contains the give mime `type`. + * + * Examples: + * + * // With Content-Type: text/html; charset=utf-8 + * req.is('html'); + * req.is('text/html'); + * req.is('text/*'); + * // => true + * + * // When Content-Type is application/json + * req.is('json'); + * req.is('application/json'); + * req.is('application/*'); + * // => true + * + * req.is('html'); + * // => false + * + * @param {String} type + * @return {Boolean} + * @api public + */ + +req.is = function(type){ + var ct = this.get('Content-Type'); + if (!ct) return false; + ct = ct.split(';')[0]; + if (!~type.indexOf('/')) type = mime.lookup(type); + if (~type.indexOf('*')) { + type = type.split('/'); + ct = ct.split('/'); + if ('*' == type[0] && type[1] == ct[1]) return true; + if ('*' == type[1] && type[0] == ct[0]) return true; + return false; + } + return !! ~ct.indexOf(type); +}; + +/** + * Return the protocol string "http" or "https" + * when requested with TLS. When the "trust proxy" + * setting is enabled the "X-Forwarded-Proto" header + * field will be trusted. If you're running behind + * a reverse proxy that supplies https for you this + * may be enabled. + * + * @return {String} + * @api public + */ + +req.__defineGetter__('protocol', function(){ + var trustProxy = this.app.get('trust proxy'); + return this.connection.encrypted + ? 'https' + : trustProxy + ? (this.get('X-Forwarded-Proto') || 'http') + : 'http'; +}); + +/** + * Short-hand for: + * + * req.protocol == 'https' + * + * @return {Boolean} + * @api public + */ + +req.__defineGetter__('secure', function(){ + return 'https' == this.protocol; +}); + +/** + * Return the remote address, or when + * "trust proxy" is `true` return + * the upstream addr. + * + * @return {String} + * @api public + */ + +req.__defineGetter__('ip', function(){ + return this.ips[0] || this.connection.remoteAddress; +}); + +/** + * When "trust proxy" is `true`, parse + * the "X-Forwarded-For" ip address list. + * + * For example if the value were "client, proxy1, proxy2" + * you would receive the array `["client", "proxy1", "proxy2"]` + * where "proxy2" is the furthest down-stream. + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('ips', function(){ + var trustProxy = this.app.get('trust proxy'); + var val = this.get('X-Forwarded-For'); + return trustProxy && val + ? val.split(/ *, */) + : []; +}); + +/** + * Return basic auth credentials. + * + * Examples: + * + * // http://tobi:hello@example.com + * req.auth + * // => { username: 'tobi', password: 'hello' } + * + * @return {Object} or undefined + * @api public + */ + +req.__defineGetter__('auth', function(){ + // missing + var auth = this.get('Authorization'); + if (!auth) return; + + // malformed + var parts = auth.split(' '); + if ('basic' != parts[0].toLowerCase()) return; + if (!parts[1]) return; + auth = parts[1]; + + // credentials + auth = new Buffer(auth, 'base64').toString().match(/^([^:]*):(.*)$/); + if (!auth) return; + return { username: auth[1], password: auth[2] }; +}); + +/** + * Return subdomains as an array. + * + * Subdomains are the dot-separated parts of the host before the main domain of + * the app. By default, the domain of the app is assumed to be the last two + * parts of the host. This can be changed by setting "subdomain offset". + * + * For example, if the domain is "tobi.ferrets.example.com": + * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`. + * If "subdomain offset" is 3, req.subdomains is `["tobi"]`. + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('subdomains', function(){ + var offset = this.app.get('subdomain offset'); + return this.get('Host') + .split('.') + .reverse() + .slice(offset); +}); + +/** + * Short-hand for `url.parse(req.url).pathname`. + * + * @return {String} + * @api public + */ + +req.__defineGetter__('path', function(){ + return parse(this).pathname; +}); + +/** + * Parse the "Host" header field hostname. + * + * @return {String} + * @api public + */ + +req.__defineGetter__('host', function(){ + return this.get('Host').split(':')[0]; +}); + +/** + * Check if the request is fresh, aka + * Last-Modified and/or the ETag + * still match. + * + * @return {Boolean} + * @api public + */ + +req.__defineGetter__('fresh', function(){ + var method = this.method; + var s = this.res.statusCode; + + // GET or HEAD for weak freshness validation only + if ('GET' != method && 'HEAD' != method) return false; + + // 2xx or 304 as per rfc2616 14.26 + if ((s >= 200 && s < 300) || 304 == s) { + return fresh(this.headers, this.res._headers); + } + + return false; +}); + +/** + * Check if the request is stale, aka + * "Last-Modified" and / or the "ETag" for the + * resource has changed. + * + * @return {Boolean} + * @api public + */ + +req.__defineGetter__('stale', function(){ + return !this.fresh; +}); + +/** + * Check if the request was an _XMLHttpRequest_. + * + * @return {Boolean} + * @api public + */ + +req.__defineGetter__('xhr', function(){ + var val = this.get('X-Requested-With') || ''; + return 'xmlhttprequest' == val.toLowerCase(); +}); diff --git a/coder-base/node_modules_orig/express/lib/response.js b/coder-base/node_modules_orig/express/lib/response.js new file mode 100755 index 00000000..2b66c88e --- /dev/null +++ b/coder-base/node_modules_orig/express/lib/response.js @@ -0,0 +1,754 @@ +/** + * Module dependencies. + */ + +var http = require('http') + , path = require('path') + , connect = require('connect') + , utils = connect.utils + , sign = require('cookie-signature').sign + , normalizeType = require('./utils').normalizeType + , normalizeTypes = require('./utils').normalizeTypes + , etag = require('./utils').etag + , statusCodes = http.STATUS_CODES + , cookie = require('cookie') + , send = require('send') + , mime = connect.mime + , basename = path.basename + , extname = path.extname + , join = path.join; + +/** + * Response prototype. + */ + +var res = module.exports = { + __proto__: http.ServerResponse.prototype +}; + +/** + * Set status `code`. + * + * @param {Number} code + * @return {ServerResponse} + * @api public + */ + +res.status = function(code){ + this.statusCode = code; + return this; +}; + +/** + * Set Link header field with the given `links`. + * + * Examples: + * + * res.links({ + * next: 'http://api.example.com/users?page=2', + * last: 'http://api.example.com/users?page=5' + * }); + * + * @param {Object} links + * @return {ServerResponse} + * @api public + */ + +res.links = function(links){ + return this.set('Link', Object.keys(links).map(function(rel){ + return '<' + links[rel] + '>; rel="' + rel + '"'; + }).join(', ')); +}; + +/** + * Send a response. + * + * Examples: + * + * res.send(new Buffer('wahoo')); + * res.send({ some: 'json' }); + * res.send('

some html

'); + * res.send(404, 'Sorry, cant find that'); + * res.send(404); + * + * @param {Mixed} body or status + * @param {Mixed} body + * @return {ServerResponse} + * @api public + */ + +res.send = function(body){ + var req = this.req + , head = 'HEAD' == req.method + , len; + + // allow status / body + if (2 == arguments.length) { + // res.send(body, status) backwards compat + if ('number' != typeof body && 'number' == typeof arguments[1]) { + this.statusCode = arguments[1]; + } else { + this.statusCode = body; + body = arguments[1]; + } + } + + switch (typeof body) { + // response status + case 'number': + this.get('Content-Type') || this.type('txt'); + this.statusCode = body; + body = http.STATUS_CODES[body]; + break; + // string defaulting to html + case 'string': + if (!this.get('Content-Type')) { + this.charset = this.charset || 'utf-8'; + this.type('html'); + } + break; + case 'boolean': + case 'object': + if (null == body) { + body = ''; + } else if (Buffer.isBuffer(body)) { + this.get('Content-Type') || this.type('bin'); + } else { + return this.json(body); + } + break; + } + + // populate Content-Length + if (undefined !== body && !this.get('Content-Length')) { + this.set('Content-Length', len = Buffer.isBuffer(body) + ? body.length + : Buffer.byteLength(body)); + } + + // ETag support + // TODO: W/ support + if (len > 1024) { + if (!this.get('ETag')) { + this.set('ETag', etag(body)); + } + } + + // freshness + if (req.fresh) this.statusCode = 304; + + // strip irrelevant headers + if (204 == this.statusCode || 304 == this.statusCode) { + this.removeHeader('Content-Type'); + this.removeHeader('Content-Length'); + this.removeHeader('Transfer-Encoding'); + body = ''; + } + + // respond + this.end(head ? null : body); + return this; +}; + +/** + * Send JSON response. + * + * Examples: + * + * res.json(null); + * res.json({ user: 'tj' }); + * res.json(500, 'oh noes!'); + * res.json(404, 'I dont have that'); + * + * @param {Mixed} obj or status + * @param {Mixed} obj + * @return {ServerResponse} + * @api public + */ + +res.json = function(obj){ + // allow status / body + if (2 == arguments.length) { + // res.json(body, status) backwards compat + if ('number' == typeof arguments[1]) { + this.statusCode = arguments[1]; + } else { + this.statusCode = obj; + obj = arguments[1]; + } + } + + // settings + var app = this.app; + var replacer = app.get('json replacer'); + var spaces = app.get('json spaces'); + var body = JSON.stringify(obj, replacer, spaces); + + // content-type + this.charset = this.charset || 'utf-8'; + this.get('Content-Type') || this.set('Content-Type', 'application/json'); + + return this.send(body); +}; + +/** + * Send JSON response with JSONP callback support. + * + * Examples: + * + * res.jsonp(null); + * res.jsonp({ user: 'tj' }); + * res.jsonp(500, 'oh noes!'); + * res.jsonp(404, 'I dont have that'); + * + * @param {Mixed} obj or status + * @param {Mixed} obj + * @return {ServerResponse} + * @api public + */ + +res.jsonp = function(obj){ + // allow status / body + if (2 == arguments.length) { + // res.json(body, status) backwards compat + if ('number' == typeof arguments[1]) { + this.statusCode = arguments[1]; + } else { + this.statusCode = obj; + obj = arguments[1]; + } + } + + // settings + var app = this.app; + var replacer = app.get('json replacer'); + var spaces = app.get('json spaces'); + var body = JSON.stringify(obj, replacer, spaces) + .replace(/\u2028/g, '\\u2028') + .replace(/\u2029/g, '\\u2029'); + var callback = this.req.query[app.get('jsonp callback name')]; + + // content-type + this.charset = this.charset || 'utf-8'; + this.set('Content-Type', 'application/json'); + + // jsonp + if (callback) { + this.set('Content-Type', 'text/javascript'); + var cb = callback.replace(/[^\[\]\w$.]/g, ''); + body = cb + ' && ' + cb + '(' + body + ');'; + } + + return this.send(body); +}; + +/** + * Transfer the file at the given `path`. + * + * Automatically sets the _Content-Type_ response header field. + * The callback `fn(err)` is invoked when the transfer is complete + * or when an error occurs. Be sure to check `res.sentHeader` + * if you wish to attempt responding, as the header and some data + * may have already been transferred. + * + * Options: + * + * - `maxAge` defaulting to 0 + * - `root` root directory for relative filenames + * + * Examples: + * + * The following example illustrates how `res.sendfile()` may + * be used as an alternative for the `static()` middleware for + * dynamic situations. The code backing `res.sendfile()` is actually + * the same code, so HTTP cache support etc is identical. + * + * app.get('/user/:uid/photos/:file', function(req, res){ + * var uid = req.params.uid + * , file = req.params.file; + * + * req.user.mayViewFilesFrom(uid, function(yes){ + * if (yes) { + * res.sendfile('/uploads/' + uid + '/' + file); + * } else { + * res.send(403, 'Sorry! you cant see that.'); + * } + * }); + * }); + * + * @param {String} path + * @param {Object|Function} options or fn + * @param {Function} fn + * @api public + */ + +res.sendfile = function(path, options, fn){ + var self = this + , req = self.req + , next = this.req.next + , options = options || {} + , done; + + // support function as second arg + if ('function' == typeof options) { + fn = options; + options = {}; + } + + // socket errors + req.socket.on('error', error); + + // errors + function error(err) { + if (done) return; + done = true; + + // clean up + cleanup(); + if (!self.headerSent) self.removeHeader('Content-Disposition'); + + // callback available + if (fn) return fn(err); + + // list in limbo if there's no callback + if (self.headerSent) return; + + // delegate + next(err); + } + + // streaming + function stream() { + if (done) return; + cleanup(); + if (fn) self.on('finish', fn); + } + + // cleanup + function cleanup() { + req.socket.removeListener('error', error); + } + + // transfer + var file = send(req, path); + if (options.root) file.root(options.root); + file.maxage(options.maxAge || 0); + file.on('error', error); + file.on('directory', next); + file.on('stream', stream); + file.pipe(this); + this.on('finish', cleanup); +}; + +/** + * Transfer the file at the given `path` as an attachment. + * + * Optionally providing an alternate attachment `filename`, + * and optional callback `fn(err)`. The callback is invoked + * when the data transfer is complete, or when an error has + * ocurred. Be sure to check `res.headerSent` if you plan to respond. + * + * This method uses `res.sendfile()`. + * + * @param {String} path + * @param {String|Function} filename or fn + * @param {Function} fn + * @api public + */ + +res.download = function(path, filename, fn){ + // support function as second arg + if ('function' == typeof filename) { + fn = filename; + filename = null; + } + + filename = filename || path; + this.set('Content-Disposition', 'attachment; filename="' + basename(filename) + '"'); + return this.sendfile(path, fn); +}; + +/** + * Set _Content-Type_ response header with `type` through `mime.lookup()` + * when it does not contain "/", or set the Content-Type to `type` otherwise. + * + * Examples: + * + * res.type('.html'); + * res.type('html'); + * res.type('json'); + * res.type('application/json'); + * res.type('png'); + * + * @param {String} type + * @return {ServerResponse} for chaining + * @api public + */ + +res.contentType = +res.type = function(type){ + return this.set('Content-Type', ~type.indexOf('/') + ? type + : mime.lookup(type)); +}; + +/** + * Respond to the Acceptable formats using an `obj` + * of mime-type callbacks. + * + * This method uses `req.accepted`, an array of + * acceptable types ordered by their quality values. + * When "Accept" is not present the _first_ callback + * is invoked, otherwise the first match is used. When + * no match is performed the server responds with + * 406 "Not Acceptable". + * + * Content-Type is set for you, however if you choose + * you may alter this within the callback using `res.type()` + * or `res.set('Content-Type', ...)`. + * + * res.format({ + * 'text/plain': function(){ + * res.send('hey'); + * }, + * + * 'text/html': function(){ + * res.send('

hey

'); + * }, + * + * 'appliation/json': function(){ + * res.send({ message: 'hey' }); + * } + * }); + * + * In addition to canonicalized MIME types you may + * also use extnames mapped to these types: + * + * res.format({ + * text: function(){ + * res.send('hey'); + * }, + * + * html: function(){ + * res.send('

hey

'); + * }, + * + * json: function(){ + * res.send({ message: 'hey' }); + * } + * }); + * + * By default Express passes an `Error` + * with a `.status` of 406 to `next(err)` + * if a match is not made. If you provide + * a `.default` callback it will be invoked + * instead. + * + * @param {Object} obj + * @return {ServerResponse} for chaining + * @api public + */ + +res.format = function(obj){ + var req = this.req + , next = req.next; + + var fn = obj.default; + if (fn) delete obj.default; + var keys = Object.keys(obj); + + var key = req.accepts(keys); + + this.set('Vary', 'Accept'); + + if (key) { + this.set('Content-Type', normalizeType(key)); + obj[key](req, this, next); + } else if (fn) { + fn(); + } else { + var err = new Error('Not Acceptable'); + err.status = 406; + err.types = normalizeTypes(keys); + next(err); + } + + return this; +}; + +/** + * Set _Content-Disposition_ header to _attachment_ with optional `filename`. + * + * @param {String} filename + * @return {ServerResponse} + * @api public + */ + +res.attachment = function(filename){ + if (filename) this.type(extname(filename)); + this.set('Content-Disposition', filename + ? 'attachment; filename="' + basename(filename) + '"' + : 'attachment'); + return this; +}; + +/** + * Set header `field` to `val`, or pass + * an object of header fields. + * + * Examples: + * + * res.set('Foo', ['bar', 'baz']); + * res.set('Accept', 'application/json'); + * res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' }); + * + * Aliased as `res.header()`. + * + * @param {String|Object|Array} field + * @param {String} val + * @return {ServerResponse} for chaining + * @api public + */ + +res.set = +res.header = function(field, val){ + if (2 == arguments.length) { + if (Array.isArray(val)) val = val.map(String); + else val = String(val); + this.setHeader(field, val); + } else { + for (var key in field) { + this.set(key, field[key]); + } + } + return this; +}; + +/** + * Get value for header `field`. + * + * @param {String} field + * @return {String} + * @api public + */ + +res.get = function(field){ + return this.getHeader(field); +}; + +/** + * Clear cookie `name`. + * + * @param {String} name + * @param {Object} options + * @param {ServerResponse} for chaining + * @api public + */ + +res.clearCookie = function(name, options){ + var opts = { expires: new Date(1), path: '/' }; + return this.cookie(name, '', options + ? utils.merge(opts, options) + : opts); +}; + +/** + * Set cookie `name` to `val`, with the given `options`. + * + * Options: + * + * - `maxAge` max-age in milliseconds, converted to `expires` + * - `signed` sign the cookie + * - `path` defaults to "/" + * + * Examples: + * + * // "Remember Me" for 15 minutes + * res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true }); + * + * // save as above + * res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true }) + * + * @param {String} name + * @param {String|Object} val + * @param {Options} options + * @api public + */ + +res.cookie = function(name, val, options){ + options = utils.merge({}, options); + var secret = this.req.secret; + var signed = options.signed; + if (signed && !secret) throw new Error('connect.cookieParser("secret") required for signed cookies'); + if ('object' == typeof val) val = 'j:' + JSON.stringify(val); + if (signed) val = 's:' + sign(val, secret); + if ('maxAge' in options) { + options.expires = new Date(Date.now() + options.maxAge); + options.maxAge /= 1000; + } + if (null == options.path) options.path = '/'; + this.set('Set-Cookie', cookie.serialize(name, String(val), options)); + return this; +}; + + +/** + * Set the location header to `url`. + * + * The given `url` can also be the name of a mapped url, for + * example by default express supports "back" which redirects + * to the _Referrer_ or _Referer_ headers or "/". + * + * Examples: + * + * res.location('/foo/bar').; + * res.location('http://example.com/'); + * res.location('../login'); // /blog/post/1 -> /blog/login + * + * Mounting: + * + * When an application is mounted and `res.location()` + * is given a path that does _not_ lead with "/" it becomes + * relative to the mount-point. For example if the application + * is mounted at "/blog", the following would become "/blog/login". + * + * res.location('login'); + * + * While the leading slash would result in a location of "/login": + * + * res.location('/login'); + * + * @param {String} url + * @api public + */ + +res.location = function(url){ + var app = this.app + , req = this.req; + + // setup redirect map + var map = { back: req.get('Referrer') || '/' }; + + // perform redirect + url = map[url] || url; + + // relative + if (!~url.indexOf('://') && 0 != url.indexOf('//')) { + var path = app.path(); + + // relative to path + if ('.' == url[0]) { + url = req.path + '/' + url; + // relative to mount-point + } else if ('/' != url[0]) { + url = path + '/' + url; + } + } + + // Respond + this.set('Location', url); + return this; +}; + +/** + * Redirect to the given `url` with optional response `status` + * defaulting to 302. + * + * The resulting `url` is determined by `res.location()`, so + * it will play nicely with mounted apps, relative paths, + * `"back"` etc. + * + * Examples: + * + * res.redirect('/foo/bar'); + * res.redirect('http://example.com/'); + * res.redirect(301, 'http://example.com/'); + * res.redirect('http://example.com/', 301); + * res.redirect('../login'); // /blog/post/1 -> /blog/login + * + * @param {String} url + * @param {Number} code + * @api public + */ + +res.redirect = function(url){ + var app = this.app + , head = 'HEAD' == this.req.method + , status = 302 + , body; + + // allow status / url + if (2 == arguments.length) { + if ('number' == typeof url) { + status = url; + url = arguments[1]; + } else { + status = arguments[1]; + } + } + + // Set location header + this.location(url); + url = this.get('Location'); + + // Support text/{plain,html} by default + this.format({ + text: function(){ + body = statusCodes[status] + '. Redirecting to ' + encodeURI(url); + }, + + html: function(){ + var u = utils.escape(url); + body = '

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

'; + }, + + default: function(){ + body = ''; + } + }); + + // Respond + this.statusCode = status; + this.set('Content-Length', Buffer.byteLength(body)); + this.end(head ? null : body); +}; + +/** + * Render `view` with the given `options` and optional callback `fn`. + * When a callback function is given a response will _not_ be made + * automatically, otherwise a response of _200_ and _text/html_ is given. + * + * Options: + * + * - `cache` boolean hinting to the engine it should cache + * - `filename` filename of the view being rendered + * + * @param {String} view + * @param {Object|Function} options or callback function + * @param {Function} fn + * @api public + */ + +res.render = function(view, options, fn){ + var self = this + , options = options || {} + , req = this.req + , app = req.app; + + // support callback function as second arg + if ('function' == typeof options) { + fn = options, options = {}; + } + + // merge res.locals + options._locals = self.locals; + + // default callback to respond + fn = fn || function(err, str){ + if (err) return req.next(err); + self.send(str); + }; + + // render + app.render(view, options, fn); +}; diff --git a/coder-base/node_modules_orig/express/lib/router/index.js b/coder-base/node_modules_orig/express/lib/router/index.js new file mode 100755 index 00000000..662dc29b --- /dev/null +++ b/coder-base/node_modules_orig/express/lib/router/index.js @@ -0,0 +1,273 @@ +/** + * Module dependencies. + */ + +var Route = require('./route') + , utils = require('../utils') + , methods = require('methods') + , debug = require('debug')('express:router') + , parse = require('connect').utils.parseUrl; + +/** + * Expose `Router` constructor. + */ + +exports = module.exports = Router; + +/** + * Initialize a new `Router` with the given `options`. + * + * @param {Object} options + * @api private + */ + +function Router(options) { + options = options || {}; + var self = this; + this.map = {}; + this.params = {}; + this._params = []; + this.caseSensitive = options.caseSensitive; + this.strict = options.strict; + this.middleware = function router(req, res, next){ + self._dispatch(req, res, next); + }; +} + +/** + * Register a param callback `fn` for the given `name`. + * + * @param {String|Function} name + * @param {Function} fn + * @return {Router} for chaining + * @api public + */ + +Router.prototype.param = function(name, fn){ + // param logic + if ('function' == typeof name) { + this._params.push(name); + return; + } + + // apply param functions + var params = this._params + , len = params.length + , ret; + + for (var i = 0; i < len; ++i) { + if (ret = params[i](name, fn)) { + fn = ret; + } + } + + // ensure we end up with a + // middleware function + if ('function' != typeof fn) { + throw new Error('invalid param() call for ' + name + ', got ' + fn); + } + + (this.params[name] = this.params[name] || []).push(fn); + return this; +}; + +/** + * Route dispatcher aka the route "middleware". + * + * @param {IncomingMessage} req + * @param {ServerResponse} res + * @param {Function} next + * @api private + */ + +Router.prototype._dispatch = function(req, res, next){ + var params = this.params + , self = this; + + debug('dispatching %s %s (%s)', req.method, req.url, req.originalUrl); + + // route dispatch + (function pass(i, err){ + var paramCallbacks + , paramIndex = 0 + , paramVal + , route + , keys + , key; + + // match next route + function nextRoute(err) { + pass(req._route_index + 1, err); + } + + // match route + req.route = route = self.matchRequest(req, i); + + // no route + if (!route) return next(err); + debug('matched %s %s', route.method, route.path); + + // we have a route + // start at param 0 + req.params = route.params; + keys = route.keys; + i = 0; + + // param callbacks + function param(err) { + paramIndex = 0; + key = keys[i++]; + paramVal = key && req.params[key.name]; + paramCallbacks = key && params[key.name]; + + try { + if ('route' == err) { + nextRoute(); + } else if (err) { + i = 0; + callbacks(err); + } else if (paramCallbacks && undefined !== paramVal) { + paramCallback(); + } else if (key) { + param(); + } else { + i = 0; + callbacks(); + } + } catch (err) { + param(err); + } + }; + + param(err); + + // single param callbacks + function paramCallback(err) { + var fn = paramCallbacks[paramIndex++]; + if (err || !fn) return param(err); + fn(req, res, paramCallback, paramVal, key.name); + } + + // invoke route callbacks + function callbacks(err) { + var fn = route.callbacks[i++]; + try { + if ('route' == err) { + nextRoute(); + } else if (err && fn) { + if (fn.length < 4) return callbacks(err); + fn(err, req, res, callbacks); + } else if (fn) { + if (fn.length < 4) return fn(req, res, callbacks); + callbacks(); + } else { + nextRoute(err); + } + } catch (err) { + callbacks(err); + } + } + })(0); +}; + +/** + * Attempt to match a route for `req` + * with optional starting index of `i` + * defaulting to 0. + * + * @param {IncomingMessage} req + * @param {Number} i + * @return {Route} + * @api private + */ + +Router.prototype.matchRequest = function(req, i, head){ + var method = req.method.toLowerCase() + , url = parse(req) + , path = url.pathname + , routes = this.map + , i = i || 0 + , route; + + // HEAD support + if (!head && 'head' == method) { + route = this.matchRequest(req, i, true); + if (route) return route; + method = 'get'; + } + + // routes for this method + if (routes = routes[method]) { + + // matching routes + for (var len = routes.length; i < len; ++i) { + route = routes[i]; + if (route.match(path)) { + req._route_index = i; + return route; + } + } + } +}; + +/** + * Attempt to match a route for `method` + * and `url` with optional starting + * index of `i` defaulting to 0. + * + * @param {String} method + * @param {String} url + * @param {Number} i + * @return {Route} + * @api private + */ + +Router.prototype.match = function(method, url, i, head){ + var req = { method: method, url: url }; + return this.matchRequest(req, i, head); +}; + +/** + * Route `method`, `path`, and one or more callbacks. + * + * @param {String} method + * @param {String} path + * @param {Function} callback... + * @return {Router} for chaining + * @api private + */ + +Router.prototype.route = function(method, path, callbacks){ + var method = method.toLowerCase() + , callbacks = utils.flatten([].slice.call(arguments, 2)); + + // ensure path was given + if (!path) throw new Error('Router#' + method + '() requires a path'); + + // ensure all callbacks are functions + callbacks.forEach(function(fn, i){ + if ('function' == typeof fn) return; + var type = {}.toString.call(fn); + var msg = '.' + method + '() requires callback functions but got a ' + type; + throw new Error(msg); + }); + + // create the route + debug('defined %s %s', method, path); + var route = new Route(method, path, callbacks, { + sensitive: this.caseSensitive, + strict: this.strict + }); + + // add it + (this.map[method] = this.map[method] || []).push(route); + return this; +}; + +methods.forEach(function(method){ + Router.prototype[method] = function(path){ + var args = [method].concat([].slice.call(arguments)); + this.route.apply(this, args); + return this; + }; +}); diff --git a/coder-base/node_modules_orig/express/lib/router/route.js b/coder-base/node_modules_orig/express/lib/router/route.js new file mode 100755 index 00000000..c1a0b5ea --- /dev/null +++ b/coder-base/node_modules_orig/express/lib/router/route.js @@ -0,0 +1,72 @@ + +/** + * Module dependencies. + */ + +var utils = require('../utils'); + +/** + * Expose `Route`. + */ + +module.exports = Route; + +/** + * Initialize `Route` with the given HTTP `method`, `path`, + * and an array of `callbacks` and `options`. + * + * Options: + * + * - `sensitive` enable case-sensitive routes + * - `strict` enable strict matching for trailing slashes + * + * @param {String} method + * @param {String} path + * @param {Array} callbacks + * @param {Object} options. + * @api private + */ + +function Route(method, path, callbacks, options) { + options = options || {}; + this.path = path; + this.method = method; + this.callbacks = callbacks; + this.regexp = utils.pathRegexp(path + , this.keys = [] + , options.sensitive + , options.strict); +} + +/** + * Check if this route matches `path`, if so + * populate `.params`. + * + * @param {String} path + * @return {Boolean} + * @api private + */ + +Route.prototype.match = function(path){ + var keys = this.keys + , params = this.params = [] + , m = this.regexp.exec(path); + + if (!m) return false; + + for (var i = 1, len = m.length; i < len; ++i) { + var key = keys[i - 1]; + + var val = 'string' == typeof m[i] + ? decodeURIComponent(m[i]) + : m[i]; + + if (key) { + params[key.name] = val; + } else { + params.push(val); + } + } + + return true; +}; diff --git a/coder-base/node_modules_orig/express/lib/utils.js b/coder-base/node_modules_orig/express/lib/utils.js new file mode 100755 index 00000000..8b1da1ac --- /dev/null +++ b/coder-base/node_modules_orig/express/lib/utils.js @@ -0,0 +1,282 @@ + +/** + * Module dependencies. + */ + +var mime = require('connect').mime + , crc32 = require('buffer-crc32'); + +/** + * Return ETag for `body`. + * + * @param {String|Buffer} body + * @return {String} + * @api private + */ + +exports.etag = function(body){ + return '"' + crc32.signed(body) + '"'; +}; + +/** + * Make `locals()` bound to the given `obj`. + * + * This is used for `app.locals` and `res.locals`. + * + * @param {Object} obj + * @return {Function} + * @api private + */ + +exports.locals = function(obj){ + obj.viewCallbacks = obj.viewCallbacks || []; + + function locals(obj){ + for (var key in obj) locals[key] = obj[key]; + return obj; + }; + + return locals; +}; + +/** + * Check if `path` looks absolute. + * + * @param {String} path + * @return {Boolean} + * @api private + */ + +exports.isAbsolute = function(path){ + if ('/' == path[0]) return true; + if (':' == path[1] && '\\' == path[2]) return true; +}; + +/** + * Flatten the given `arr`. + * + * @param {Array} arr + * @return {Array} + * @api private + */ + +exports.flatten = function(arr, ret){ + var ret = ret || [] + , len = arr.length; + for (var i = 0; i < len; ++i) { + if (Array.isArray(arr[i])) { + exports.flatten(arr[i], ret); + } else { + ret.push(arr[i]); + } + } + return ret; +}; + +/** + * Normalize the given `type`, for example "html" becomes "text/html". + * + * @param {String} type + * @return {String} + * @api private + */ + +exports.normalizeType = function(type){ + return ~type.indexOf('/') ? type : mime.lookup(type); +}; + +/** + * Normalize `types`, for example "html" becomes "text/html". + * + * @param {Array} types + * @return {Array} + * @api private + */ + +exports.normalizeTypes = function(types){ + var ret = []; + + for (var i = 0; i < types.length; ++i) { + ret.push(~types[i].indexOf('/') + ? types[i] + : mime.lookup(types[i])); + } + + return ret; +}; + +/** + * Return the acceptable type in `types`, if any. + * + * @param {Array} types + * @param {String} str + * @return {String} + * @api private + */ + +exports.acceptsArray = function(types, str){ + // accept anything when Accept is not present + if (!str) return types[0]; + + // parse + var accepted = exports.parseAccept(str) + , normalized = exports.normalizeTypes(types) + , len = accepted.length; + + for (var i = 0; i < len; ++i) { + for (var j = 0, jlen = types.length; j < jlen; ++j) { + if (exports.accept(normalized[j].split('/'), accepted[i])) { + return types[j]; + } + } + } +}; + +/** + * Check if `type(s)` are acceptable based on + * the given `str`. + * + * @param {String|Array} type(s) + * @param {String} str + * @return {Boolean|String} + * @api private + */ + +exports.accepts = function(type, str){ + if ('string' == typeof type) type = type.split(/ *, */); + return exports.acceptsArray(type, str); +}; + +/** + * Check if `type` array is acceptable for `other`. + * + * @param {Array} type + * @param {Object} other + * @return {Boolean} + * @api private + */ + +exports.accept = function(type, other){ + return (type[0] == other.type || '*' == other.type) + && (type[1] == other.subtype || '*' == other.subtype); +}; + +/** + * Parse accept `str`, returning + * an array objects containing + * `.type` and `.subtype` along + * with the values provided by + * `parseQuality()`. + * + * @param {Type} name + * @return {Type} + * @api private + */ + +exports.parseAccept = function(str){ + return exports + .parseQuality(str) + .map(function(obj){ + var parts = obj.value.split('/'); + obj.type = parts[0]; + obj.subtype = parts[1]; + return obj; + }); +}; + +/** + * Parse quality `str`, returning an + * array of objects with `.value` and + * `.quality`. + * + * @param {Type} name + * @return {Type} + * @api private + */ + +exports.parseQuality = function(str){ + return str + .split(/ *, */) + .map(quality) + .filter(function(obj){ + return obj.quality; + }) + .sort(function(a, b){ + return b.quality - a.quality; + }); +}; + +/** + * Parse quality `str` returning an + * object with `.value` and `.quality`. + * + * @param {String} str + * @return {Object} + * @api private + */ + +function quality(str) { + var parts = str.split(/ *; */) + , val = parts[0]; + + var q = parts[1] + ? parseFloat(parts[1].split(/ *= */)[1]) + : 1; + + return { value: val, quality: q }; +} + +/** + * Escape special characters in the given string of html. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html) { + return String(html) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(//g, '>'); +}; + +/** + * Normalize the given path string, + * returning a regular expression. + * + * An empty array should be passed, + * which will contain the placeholder + * key names. For example "/user/:id" will + * then contain ["id"]. + * + * @param {String|RegExp|Array} path + * @param {Array} keys + * @param {Boolean} sensitive + * @param {Boolean} strict + * @return {RegExp} + * @api private + */ + +exports.pathRegexp = function(path, keys, sensitive, strict) { + if (path instanceof RegExp) return path; + if (Array.isArray(path)) path = '(' + path.join('|') + ')'; + path = path + .concat(strict ? '' : '/?') + .replace(/\/\(/g, '(?:/') + .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g, function(_, slash, format, key, capture, optional, star){ + keys.push({ name: key, optional: !! optional }); + slash = slash || ''; + return '' + + (optional ? '' : slash) + + '(?:' + + (optional ? slash : '') + + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')' + + (optional || '') + + (star ? '(/*)?' : ''); + }) + .replace(/([\/.])/g, '\\$1') + .replace(/\*/g, '(.*)'); + return new RegExp('^' + path + '$', sensitive ? '' : 'i'); +} \ No newline at end of file diff --git a/coder-base/node_modules_orig/express/lib/view.js b/coder-base/node_modules_orig/express/lib/view.js new file mode 100755 index 00000000..c7399a44 --- /dev/null +++ b/coder-base/node_modules_orig/express/lib/view.js @@ -0,0 +1,76 @@ +/** + * Module dependencies. + */ + +var path = require('path') + , fs = require('fs') + , utils = require('./utils') + , dirname = path.dirname + , basename = path.basename + , extname = path.extname + , exists = fs.existsSync || path.existsSync + , join = path.join; + +/** + * Expose `View`. + */ + +module.exports = View; + +/** + * Initialize a new `View` with the given `name`. + * + * Options: + * + * - `defaultEngine` the default template engine name + * - `engines` template engine require() cache + * - `root` root path for view lookup + * + * @param {String} name + * @param {Object} options + * @api private + */ + +function View(name, options) { + options = options || {}; + this.name = name; + this.root = options.root; + var engines = options.engines; + this.defaultEngine = options.defaultEngine; + var ext = this.ext = extname(name); + if (!ext) name += (ext = this.ext = ('.' != this.defaultEngine[0] ? '.' : '') + this.defaultEngine); + this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express); + this.path = this.lookup(name); +} + +/** + * Lookup view by the given `path` + * + * @param {String} path + * @return {String} + * @api private + */ + +View.prototype.lookup = function(path){ + var ext = this.ext; + + // . + if (!utils.isAbsolute(path)) path = join(this.root, path); + if (exists(path)) return path; + + // /index. + path = join(dirname(path), basename(path, ext), 'index' + ext); + if (exists(path)) return path; +}; + +/** + * Render with the given `options` and callback `fn(err, str)`. + * + * @param {Object} options + * @param {Function} fn + * @api private + */ + +View.prototype.render = function(options, fn){ + this.engine(this.path, options, fn); +}; diff --git a/coder-base/node_modules_orig/express/package.json b/coder-base/node_modules_orig/express/package.json new file mode 100755 index 00000000..3334230f --- /dev/null +++ b/coder-base/node_modules_orig/express/package.json @@ -0,0 +1,87 @@ +{ + "name": "express", + "description": "Sinatra inspired web development framework", + "version": "3.1.0", + "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.7.2", + "commander": "0.6.1", + "range-parser": "0.0.4", + "mkdirp": "0.3.3", + "cookie": "0.0.5", + "buffer-crc32": "0.1.1", + "fresh": "0.1.0", + "methods": "0.0.1", + "send": "0.1.0", + "cookie-signature": "0.0.1", + "debug": "*" + }, + "devDependencies": { + "ejs": "*", + "mocha": "*", + "jade": "*", + "hjs": "*", + "stylus": "*", + "should": "*", + "connect-redis": "*", + "github-flavored-markdown": "*", + "supertest": "0.0.1" + }, + "keywords": [ + "express", + "framework", + "sinatra", + "web", + "rest", + "restful", + "router", + "app", + "api" + ], + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/express.git" + }, + "main": "index", + "bin": { + "express": "./bin/express" + }, + "scripts": { + "prepublish": "npm prune", + "test": "make test" + }, + "engines": { + "node": "*" + }, + "_id": "express@3.1.0", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.4", + "_nodeVersion": "v0.6.19", + "_defaultsLoaded": true, + "dist": { + "shasum": "216e9ecdbf094df6b641dfd28039c48986bcf324" + }, + "_from": "express@3.x" +} diff --git a/coder-base/node_modules_orig/express/test.js b/coder-base/node_modules_orig/express/test.js new file mode 100755 index 00000000..112ee0ad --- /dev/null +++ b/coder-base/node_modules_orig/express/test.js @@ -0,0 +1,14 @@ + +/** + * Module dependencies. + */ + +var express = require('./') + , app = express() + +app.get('/', function(req, res){ + console.log(req.query); +}); + +app.listen(3000); +console.log('listening on 3000'); diff --git a/coder-base/node_modules_orig/mustache/.jshintrc b/coder-base/node_modules_orig/mustache/.jshintrc new file mode 100755 index 00000000..28dff710 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/.jshintrc @@ -0,0 +1,5 @@ +{ + "eqnull": true, + "evil": true +} + diff --git a/coder-base/node_modules_orig/mustache/.npmignore b/coder-base/node_modules_orig/mustache/.npmignore new file mode 100755 index 00000000..90007769 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/.npmignore @@ -0,0 +1,10 @@ +.DS_Store +.rvmrc +node_modules +runner.js +jquery.mustache.js +qooxdoo.mustache.js +dojox +yui3 +requirejs.mustache.js + diff --git a/coder-base/node_modules_orig/mustache/.travis.yml b/coder-base/node_modules_orig/mustache/.travis.yml new file mode 100755 index 00000000..3d839b0e --- /dev/null +++ b/coder-base/node_modules_orig/mustache/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + diff --git a/coder-base/node_modules_orig/mustache/CHANGES b/coder-base/node_modules_orig/mustache/CHANGES new file mode 100755 index 00000000..b5b04f44 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/CHANGES @@ -0,0 +1,34 @@ += 0.7.2 / 27 Dec 2012 + + * Fixed a rendering bug (#274) when using nested higher-order sections. + * Converted tests to use mocha instead of vows. + += 0.7.1 / 6 Dec 2012 + + * Handle empty templates gracefully. Fixes #265, #267, and #270. + * Cache partials by template, not by name. Fixes #257. + * Added Mustache.compileTokens to compile the output of Mustache.parse. Fixes + #258. + += 0.7.0 / 10 Sep 2012 + + * Rename Renderer => Writer. + * Allow partials to be loaded dynamically using a callback (thanks + @TiddoLangerak for the suggestion). + * Fixed a bug with higher-order sections that prevented them from being + passed the raw text of the section from the original template. + * More concise token format. Tokens also include start/end indices in the + original template. + * High-level API is consistent with the Writer API. + * Allow partials to be passed to the pre-compiled function (thanks + @fallenice). + * Don't use eval (thanks @cweider). + += 0.6.0 / 31 Aug 2012 + + * Use JavaScript's definition of falsy when determining whether to render an + inverted section or not. Issue #186. + * Use Mustache.escape to escape values inside {{}}. This function may be + reassigned to alter the default escaping behavior. Issue #244. + * Fixed a bug that clashed with QUnit (thanks @kannix). + * Added volo support (thanks @guybedford). diff --git a/coder-base/node_modules_orig/mustache/LICENSE b/coder-base/node_modules_orig/mustache/LICENSE new file mode 100755 index 00000000..6626848b --- /dev/null +++ b/coder-base/node_modules_orig/mustache/LICENSE @@ -0,0 +1,10 @@ +The MIT License + +Copyright (c) 2009 Chris Wanstrath (Ruby) +Copyright (c) 2010 Jan Lehnardt (JavaScript) + +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/coder-base/node_modules_orig/mustache/README.md b/coder-base/node_modules_orig/mustache/README.md new file mode 100755 index 00000000..d4b6ad08 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/README.md @@ -0,0 +1,400 @@ +# mustache.js - Logic-less {{mustache}} templates with JavaScript + +> What could be more logical awesome than no logic at all? + +[mustache.js](http://github.com/janl/mustache.js) is an implementation of the [mustache](http://mustache.github.com/) template system in JavaScript. + +[Mustache](http://mustache.github.com/) is a logic-less template syntax. It can be used for HTML, config files, source code - anything. It works by expanding tags in a template using values provided in a hash or object. + +We call it "logic-less" because there are no if statements, else clauses, or for loops. Instead there are only tags. Some tags are replaced with a value, some nothing, and others a series of values. + +For a language-agnostic overview of mustache's template syntax, see the `mustache(5)` [manpage](http://mustache.github.com/mustache.5.html). + +## Where to use mustache.js? + +You can use mustache.js to render mustache templates anywhere you can use JavaScript. This includes web browsers, server-side environments such as [node](http://nodejs.org/), and [CouchDB](http://couchdb.apache.org/) views. + +mustache.js ships with support for both the [CommonJS](http://www.commonjs.org/) module API and the [Asynchronous Module Definition](https://github.com/amdjs/amdjs-api/wiki/AMD) API, or AMD. + +## Who uses mustache.js? + +An updated list of mustache.js users is kept [on the Github wiki](http://wiki.github.com/janl/mustache.js/beard-competition). Add yourself or your company if you use mustache.js! + +## Usage + +Below is quick example how to use mustache.js: + + var view = { + title: "Joe", + calc: function () { + return 2 + 4; + } + }; + + var output = Mustache.render("{{title}} spends {{calc}}", view); + +In this example, the `Mustache.render` function takes two parameters: 1) the [mustache](http://mustache.github.com/) template and 2) a `view` object that contains the data and code needed to render the template. + +## Templates + +A [mustache](http://mustache.github.com/) template is a string that contains any number of mustache tags. Tags are indicated by the double mustaches that surround them. `{{person}}` is a tag, as is `{{#person}}`. In both examples we refer to `person` as the tag's key. + +There are several types of tags available in mustache.js. + +### Variables + +The most basic tag type is a simple variable. A `{{name}}` tag renders the value of the `name` key in the current context. If there is no such key, nothing is rendered. + +All variables are HTML-escaped by default. If you want to render unescaped HTML, use the triple mustache: `{{{name}}}`. You can also use `&` to unescape a variable. + +View: + + { + "name": "Chris", + "company": "GitHub" + } + +Template: + + * {{name}} + * {{age}} + * {{company}} + * {{{company}}} + * {{&company}} + +Output: + + * Chris + * + * <b>GitHub</b> + * GitHub + * GitHub + +JavaScript's dot notation may be used to access keys that are properties of objects in a view. + +View: + + { + "name": { + "first": "Michael", + "last": "Jackson" + }, + "age": "RIP" + } + +Template: + + * {{name.first}} {{name.last}} + * {{age}} + +Output: + + * Michael Jackson + * RIP + +### Sections + +Sections render blocks of text one or more times, depending on the value of the key in the current context. + +A section begins with a pound and ends with a slash. That is, `{{#person}}` begins a `person` section, while `{{/person}}` ends it. The text between the two tags is referred to as that section's "block". + +The behavior of the section is determined by the value of the key. + +#### False Values or Empty Lists + +If the `person` key does not exist, or exists and has a value of `null`, `undefined`, or `false`, or is an empty list, the block will not be rendered. + +View: + + { + "person": false + } + +Template: + + Shown. + {{#person}} + Never shown! + {{/person}} + +Output: + + Shown. + +#### Non-Empty Lists + +If the `person` key exists and is not `null`, `undefined`, or `false`, and is not an empty list the block will be rendered one or more times. + +When the value is a list, the block is rendered once for each item in the list. The context of the block is set to the current item in the list for each iteration. In this way we can loop over collections. + +View: + + { + "stooges": [ + { "name": "Moe" }, + { "name": "Larry" }, + { "name": "Curly" } + ] + } + +Template: + + {{#stooges}} + {{name}} + {{/stooges}} + +Output: + + Moe + Larry + Curly + +When looping over an array of strings, a `.` can be used to refer to the current item in the list. + +View: + + { + "musketeers": ["Athos", "Aramis", "Porthos", "D'Artagnan"] + } + +Template: + + {{#musketeers}} + * {{.}} + {{/musketeers}} + +Output: + + * Athos + * Aramis + * Porthos + * D'Artagnan + +If the value of a section variable is a function, it will be called in the context of the current item in the list on each iteration. + +View: + + { + "beatles": [ + { "firstName": "John", "lastName": "Lennon" }, + { "firstName": "Paul", "lastName": "McCartney" }, + { "firstName": "George", "lastName": "Harrison" }, + { "firstName": "Ringo", "lastName": "Starr" } + ], + "name": function () { + return this.firstName + " " + this.lastName; + } + } + +Template: + + {{#beatles}} + * {{name}} + {{/beatles}} + +Output: + + * John Lennon + * Paul McCartney + * George Harrison + * Ringo Starr + +#### Functions + +If the value of a section key is a function, it is called with the section's literal block of text, un-rendered, as its first argument. The second argument is a special rendering function that uses the current view as its view argument. It is called in the context of the current view object. + +View: + + { + "name": "Tater", + "bold": function () { + return function (text, render) { + return "" + render(text) + ""; + } + } + } + +Template: + + {{#bold}}Hi {{name}}.{{/bold}} + +Output: + + Hi Tater. + +### Inverted Sections + +An inverted section opens with `{{^section}}` instead of `{{#section}}`. The block of an inverted section is rendered only if the value of that section's tag is `null`, `undefined`, `false`, or an empty list. + +View: + + { + "repos": [] + } + +Template: + + {{#repos}}{{name}}{{/repos}} + {{^repos}}No repos :({{/repos}} + +Output: + + No repos :( + +### Comments + +Comments begin with a bang and are ignored. The following template: + +

Today{{! ignore me }}.

+ +Will render as follows: + +

Today.

+ +Comments may contain newlines. + +### Partials + +Partials begin with a greater than sign, like {{> box}}. + +Partials are rendered at runtime (as opposed to compile time), so recursive partials are possible. Just avoid infinite loops. + +They also inherit the calling context. Whereas in ERB you may have this: + + <%= partial :next_more, :start => start, :size => size %> + +Mustache requires only this: + + {{> next_more}} + +Why? Because the `next_more.mustache` file will inherit the `size` and `start` variables from the calling context. In this way you may want to think of partials as includes, or template expansion, even though it's not literally true. + +For example, this template and partial: + + base.mustache: +

Names

+ {{#names}} + {{> user}} + {{/names}} + + user.mustache: + {{name}} + +Can be thought of as a single, expanded template: + +

Names

+ {{#names}} + {{name}} + {{/names}} + +In mustache.js an object of partials may be passed as the third argument to `Mustache.render`. The object should be keyed by the name of the partial, and its value should be the partial text. + +### Set Delimiter + +Set Delimiter tags start with an equals sign and change the tag delimiters from `{{` and `}}` to custom strings. + +Consider the following contrived example: + + * {{ default_tags }} + {{=<% %>=}} + * <% erb_style_tags %> + <%={{ }}=%> + * {{ default_tags_again }} + +Here we have a list with three items. The first item uses the default tag style, the second uses ERB style as defined by the Set Delimiter tag, and the third returns to the default style after yet another Set Delimiter declaration. + +According to [ctemplates](http://google-ctemplate.googlecode.com/svn/trunk/doc/howto.html), this "is useful for languages like TeX, where double-braces may occur in the text and are awkward to use for markup." + +Custom delimiters may not contain whitespace or the equals sign. + +### Compiled Templates + +Mustache templates can be compiled into JavaScript functions using `Mustache.compile` for improved rendering performance. + +If you have template views that are rendered multiple times, compiling your template into a JavaScript function will minimise the amount of work required for each re-render. + +Pre-compiled templates can also be generated server-side, for delivery to the browser as ready to use JavaScript functions, further reducing the amount of client side processing required for initialising templates. + +**Mustache.compile** + +Use `Mustache.compile` to compile standard Mustache string templates into reusable Mustache template functions. + + var compiledTemplate = Mustache.compile(stringTemplate); + +The function returned from `Mustache.compile` can then be called directly, passing in the template data as an argument (with an object of partials as an optional second parameter), to generate the final output. + + var templateOutput = compiledTemplate(templateData); + +**Mustache.compilePartial** + +Template partials can also be compiled using the `Mustache.compilePartial` function. The first parameter of this function, is the name of the partial as it appears within parent templates. + + Mustache.compilePartial('partial-name', stringTemplate); + +Compiled partials are then available to both `Mustache.render` and `Mustache.compile`. + +## Plugins for JavaScript Libraries + +mustache.js may be built specifically for several different client libraries, including the following: + + - [jQuery](http://jquery.com/) + - [MooTools](http://mootools.net/) + - [Dojo](http://www.dojotoolkit.org/) + - [YUI](http://developer.yahoo.com/yui/) + - [qooxdoo](http://qooxdoo.org/) + +These may be built using [Rake](http://rake.rubyforge.org/) and one of the following commands: + + $ rake jquery + $ rake mootools + $ rake dojo + $ rake yui + $ rake qooxdoo + +## Testing + +The mustache.js test suite uses the [vows](http://vowsjs.org/) testing framework. In order to run the tests you'll need to install [node](http://nodejs.org/). Once that's done you can install vows using [npm](http://npmjs.org/). + + $ npm install -g vows + +Then run the tests. + + $ vows --spec + +The test suite consists of both unit and integration tests. If a template isn't rendering correctly for you, you can make a test for it by doing the following: + + 1. Create a template file named `mytest.mustache` in the `test/_files` + directory. Replace `mytest` with the name of your test. + 2. Create a corresponding view file named `mytest.js` in the same directory. + This file should contain a JavaScript object literal enclosed in + parentheses. See any of the other view files for an example. + 3. Create a file with the expected output in `mytest.txt` in the same + directory. + +Then, you can run the test with: + + $ TEST=mytest vows test/render_test.js + +## Thanks + +mustache.js wouldn't kick ass if it weren't for these fine souls: + + * Chris Wanstrath / defunkt + * Alexander Lang / langalex + * Sebastian Cohnen / tisba + * J Chris Anderson / jchris + * Tom Robinson / tlrobinson + * Aaron Quint / quirkey + * Douglas Crockford + * Nikita Vasilyev / NV + * Elise Wood / glytch + * Damien Mathieu / dmathieu + * Jakub Kuźma / qoobaa + * Will Leinweber / will + * dpree + * Jason Smith / jhs + * Aaron Gibralter / agibralter + * Ross Boucher / boucher + * Matt Sanford / mzsanford + * Ben Cherry / bcherry + * Michael Jackson / mjijackson diff --git a/coder-base/node_modules_orig/mustache/Rakefile b/coder-base/node_modules_orig/mustache/Rakefile new file mode 100755 index 00000000..bc321758 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/Rakefile @@ -0,0 +1,68 @@ +require 'rake' +require 'rake/clean' + +task :default => :test + +ROOT = File.expand_path('..', __FILE__) +MUSTACHE_JS = File.read(File.join(ROOT, 'mustache.js')) + +def mustache_version + match = MUSTACHE_JS.match(/exports\.version = "([^"]+)";/) + match[1] +end + +def minified_file + ENV['FILE'] || 'mustache.min.js' +end + +desc "Run all tests, requires vows (see http://vowsjs.org)" +task :test do + sh "vows --spec" +end + +desc "Minify to #{minified_file}, requires UglifyJS (see http://marijnhaverbeke.nl/uglifyjs)" +task :minify do + sh "uglifyjs mustache.js > #{minified_file}" +end + +desc "Run JSHint, requires jshint (see http://www.jshint.com)" +task :lint do + sh "jshint mustache.js" +end + +# Creates a task that uses the various template wrappers to make a wrapped +# output file. There is some extra complexity because Dojo and YUI use +# different final locations. +def templated_build(name, opts={}) + short = name.downcase + source = File.join("wrappers", short) + dependencies = ["mustache.js"] + Dir.glob("#{source}/*.tpl.*") + target_js = opts[:location] ? "mustache.js" : "#{short}.mustache.js" + + CLEAN.include(opts[:location] ? opts[:location] : target_js) + + desc "Package for #{name}" + task short.to_sym => dependencies do + puts "Packaging for #{name}" + + mkdir_p opts[:location] if opts[:location] + + files = [ + "#{source}/mustache.js.pre", + 'mustache.js', + "#{source}/mustache.js.post" + ] + + open("#{opts[:location] || '.'}/#{target_js}", 'w') do |f| + files.each {|file| f << File.read(file) } + end + + puts "Done, see #{opts[:location] || '.'}/#{target_js}" + end +end + +templated_build "jQuery" +templated_build "MooTools" +templated_build "Dojo", :location => "dojox/string" +templated_build "YUI3", :location => "yui3/mustache" +templated_build "qooxdoo" diff --git a/coder-base/node_modules_orig/mustache/mustache.js b/coder-base/node_modules_orig/mustache/mustache.js new file mode 100755 index 00000000..932052b4 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/mustache.js @@ -0,0 +1,610 @@ +/*! + * mustache.js - Logic-less {{mustache}} templates with JavaScript + * http://github.com/janl/mustache.js + */ + +/*global define: false*/ + +(function (root, factory) { + if (typeof exports === "object" && exports) { + module.exports = factory; // CommonJS + } else if (typeof define === "function" && define.amd) { + define(factory); // AMD + } else { + root.Mustache = factory; // diff --git a/coder-base/node_modules_orig/mustache/test/_files/backslashes.txt b/coder-base/node_modules_orig/mustache/test/_files/backslashes.txt new file mode 100755 index 00000000..038dd37e --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/backslashes.txt @@ -0,0 +1,7 @@ +* \abc +* \abc +* \abc + diff --git a/coder-base/node_modules_orig/mustache/test/_files/bug_11_eating_whitespace.js b/coder-base/node_modules_orig/mustache/test/_files/bug_11_eating_whitespace.js new file mode 100755 index 00000000..e41ccd15 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/bug_11_eating_whitespace.js @@ -0,0 +1,3 @@ +({ + tag: "yo" +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/bug_11_eating_whitespace.mustache b/coder-base/node_modules_orig/mustache/test/_files/bug_11_eating_whitespace.mustache new file mode 100755 index 00000000..8d5cd921 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/bug_11_eating_whitespace.mustache @@ -0,0 +1 @@ +{{tag}} foo diff --git a/coder-base/node_modules_orig/mustache/test/_files/bug_11_eating_whitespace.txt b/coder-base/node_modules_orig/mustache/test/_files/bug_11_eating_whitespace.txt new file mode 100755 index 00000000..f5bbc85c --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/bug_11_eating_whitespace.txt @@ -0,0 +1 @@ +yo foo diff --git a/coder-base/node_modules_orig/mustache/test/_files/changing_delimiters.js b/coder-base/node_modules_orig/mustache/test/_files/changing_delimiters.js new file mode 100755 index 00000000..b808f4c8 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/changing_delimiters.js @@ -0,0 +1,4 @@ +({ + "foo": "foooooooooooooo", + "bar": "bar!" +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/changing_delimiters.mustache b/coder-base/node_modules_orig/mustache/test/_files/changing_delimiters.mustache new file mode 100755 index 00000000..0cd044c9 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/changing_delimiters.mustache @@ -0,0 +1 @@ +{{=<% %>=}}<% foo %> {{foo}} <%{bar}%> {{{bar}}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/changing_delimiters.txt b/coder-base/node_modules_orig/mustache/test/_files/changing_delimiters.txt new file mode 100755 index 00000000..1b1510da --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/changing_delimiters.txt @@ -0,0 +1 @@ +foooooooooooooo {{foo}} bar! {{{bar}}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/check_falsy.js b/coder-base/node_modules_orig/mustache/test/_files/check_falsy.js new file mode 100755 index 00000000..5a599cab --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/check_falsy.js @@ -0,0 +1,7 @@ +({ + number: function(text, render) { + return function(text, render) { + return +render(text); + } + } +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/check_falsy.mustache b/coder-base/node_modules_orig/mustache/test/_files/check_falsy.mustache new file mode 100755 index 00000000..30e2547f --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/check_falsy.mustache @@ -0,0 +1 @@ +

{{#number}}0{{/number}}

diff --git a/coder-base/node_modules_orig/mustache/test/_files/check_falsy.txt b/coder-base/node_modules_orig/mustache/test/_files/check_falsy.txt new file mode 100755 index 00000000..3bb2f51f --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/check_falsy.txt @@ -0,0 +1 @@ +

0

diff --git a/coder-base/node_modules_orig/mustache/test/_files/comments.js b/coder-base/node_modules_orig/mustache/test/_files/comments.js new file mode 100755 index 00000000..f20b8b11 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/comments.js @@ -0,0 +1,5 @@ +({ + title: function () { + return "A Comedy of Errors"; + } +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/comments.mustache b/coder-base/node_modules_orig/mustache/test/_files/comments.mustache new file mode 100755 index 00000000..50368018 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/comments.mustache @@ -0,0 +1 @@ +

{{title}}{{! just something interesting... or not... }}

diff --git a/coder-base/node_modules_orig/mustache/test/_files/comments.txt b/coder-base/node_modules_orig/mustache/test/_files/comments.txt new file mode 100755 index 00000000..0133517b --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/comments.txt @@ -0,0 +1 @@ +

A Comedy of Errors

diff --git a/coder-base/node_modules_orig/mustache/test/_files/complex.js b/coder-base/node_modules_orig/mustache/test/_files/complex.js new file mode 100755 index 00000000..68a48093 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/complex.js @@ -0,0 +1,19 @@ +({ + header: function () { + return "Colors"; + }, + item: [ + {name: "red", current: true, url: "#Red"}, + {name: "green", current: false, url: "#Green"}, + {name: "blue", current: false, url: "#Blue"} + ], + link: function () { + return this["current"] !== true; + }, + list: function () { + return this.item.length !== 0; + }, + empty: function () { + return this.item.length === 0; + } +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/complex.mustache b/coder-base/node_modules_orig/mustache/test/_files/complex.mustache new file mode 100755 index 00000000..869a4f06 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/complex.mustache @@ -0,0 +1,16 @@ +

{{header}}

+{{#list}} +
    + {{#item}} + {{#current}} +
  • {{name}}
  • + {{/current}} + {{#link}} +
  • {{name}}
  • + {{/link}} + {{/item}} +
+{{/list}} +{{#empty}} +

The list is empty.

+{{/empty}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/complex.txt b/coder-base/node_modules_orig/mustache/test/_files/complex.txt new file mode 100755 index 00000000..596d3f69 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/complex.txt @@ -0,0 +1,6 @@ +

Colors

+ diff --git a/coder-base/node_modules_orig/mustache/test/_files/context_lookup.js b/coder-base/node_modules_orig/mustache/test/_files/context_lookup.js new file mode 100755 index 00000000..8ce62999 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/context_lookup.js @@ -0,0 +1,8 @@ +({ + "outer": { + "id": 1, + "second": { + "nothing": 2 + } + } +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/context_lookup.mustache b/coder-base/node_modules_orig/mustache/test/_files/context_lookup.mustache new file mode 100755 index 00000000..3c7b7677 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/context_lookup.mustache @@ -0,0 +1 @@ +{{#outer}}{{#second}}{{id}}{{/second}}{{/outer}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/context_lookup.txt b/coder-base/node_modules_orig/mustache/test/_files/context_lookup.txt new file mode 100755 index 00000000..d00491fd --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/context_lookup.txt @@ -0,0 +1 @@ +1 diff --git a/coder-base/node_modules_orig/mustache/test/_files/delimiters.js b/coder-base/node_modules_orig/mustache/test/_files/delimiters.js new file mode 100755 index 00000000..365d01e8 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/delimiters.js @@ -0,0 +1,6 @@ +({ + first: "It worked the first time.", + second: "And it worked the second time.", + third: "Then, surprisingly, it worked the third time.", + fourth: "Fourth time also fine!." +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/delimiters.mustache b/coder-base/node_modules_orig/mustache/test/_files/delimiters.mustache new file mode 100755 index 00000000..7fac8469 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/delimiters.mustache @@ -0,0 +1,7 @@ +{{=<% %>=}}* +<% first %> +* <% second %> +<%=| |=%> +* | third | +|={{ }}=| +* {{ fourth }} diff --git a/coder-base/node_modules_orig/mustache/test/_files/delimiters.txt b/coder-base/node_modules_orig/mustache/test/_files/delimiters.txt new file mode 100755 index 00000000..698a6bbd --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/delimiters.txt @@ -0,0 +1,5 @@ +* +It worked the first time. +* And it worked the second time. +* Then, surprisingly, it worked the third time. +* Fourth time also fine!. diff --git a/coder-base/node_modules_orig/mustache/test/_files/disappearing_whitespace.js b/coder-base/node_modules_orig/mustache/test/_files/disappearing_whitespace.js new file mode 100755 index 00000000..973dd1c9 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/disappearing_whitespace.js @@ -0,0 +1,4 @@ +({ + bedrooms: true, + total: 1 +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/disappearing_whitespace.mustache b/coder-base/node_modules_orig/mustache/test/_files/disappearing_whitespace.mustache new file mode 100755 index 00000000..16c16e05 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/disappearing_whitespace.mustache @@ -0,0 +1 @@ +{{#bedrooms}}{{total}}{{/bedrooms}} BED diff --git a/coder-base/node_modules_orig/mustache/test/_files/disappearing_whitespace.txt b/coder-base/node_modules_orig/mustache/test/_files/disappearing_whitespace.txt new file mode 100755 index 00000000..66e98ef4 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/disappearing_whitespace.txt @@ -0,0 +1 @@ +1 BED diff --git a/coder-base/node_modules_orig/mustache/test/_files/dot_notation.js b/coder-base/node_modules_orig/mustache/test/_files/dot_notation.js new file mode 100755 index 00000000..de06a03a --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/dot_notation.js @@ -0,0 +1,23 @@ +({ + name: "A Book", + authors: ["John Power", "Jamie Walsh"], + price: { + value: 200, + vat: function () { + return this.value * 0.2; + }, + currency: { + symbol: '$', + name: 'USD' + } + }, + availability: { + status: true, + text: "In Stock" + }, + // And now, some truthy false values + truthy: { + zero: 0, + notTrue: false + } +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/dot_notation.mustache b/coder-base/node_modules_orig/mustache/test/_files/dot_notation.mustache new file mode 100755 index 00000000..f89d70ba --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/dot_notation.mustache @@ -0,0 +1,9 @@ + +

{{name}}

+

Authors:

    {{#authors}}
  • {{.}}
  • {{/authors}}

+

Price: {{{price.currency.symbol}}}{{price.value}} {{#price.currency}}{{name}} {{availability.text}}{{/price.currency}}

+

VAT: {{{price.currency.symbol}}}{{#price}}{{vat}}{{/price}}

+ +

Test truthy false values:

+

Zero: {{truthy.zero}}

+

False: {{truthy.notTrue}}

diff --git a/coder-base/node_modules_orig/mustache/test/_files/dot_notation.txt b/coder-base/node_modules_orig/mustache/test/_files/dot_notation.txt new file mode 100755 index 00000000..08afa052 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/dot_notation.txt @@ -0,0 +1,9 @@ + +

A Book

+

Authors:

  • John Power
  • Jamie Walsh

+

Price: $200 USD In Stock

+

VAT: $40

+ +

Test truthy false values:

+

Zero: 0

+

False: false

diff --git a/coder-base/node_modules_orig/mustache/test/_files/double_render.js b/coder-base/node_modules_orig/mustache/test/_files/double_render.js new file mode 100755 index 00000000..28acb2c1 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/double_render.js @@ -0,0 +1,5 @@ +({ + foo: true, + bar: "{{win}}", + win: "FAIL" +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/double_render.mustache b/coder-base/node_modules_orig/mustache/test/_files/double_render.mustache new file mode 100755 index 00000000..4500fd76 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/double_render.mustache @@ -0,0 +1 @@ +{{#foo}}{{bar}}{{/foo}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/double_render.txt b/coder-base/node_modules_orig/mustache/test/_files/double_render.txt new file mode 100755 index 00000000..b6e652d0 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/double_render.txt @@ -0,0 +1 @@ +{{win}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/empty_list.js b/coder-base/node_modules_orig/mustache/test/_files/empty_list.js new file mode 100755 index 00000000..c0e11594 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/empty_list.js @@ -0,0 +1,3 @@ +({ + jobs: [] +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/empty_list.mustache b/coder-base/node_modules_orig/mustache/test/_files/empty_list.mustache new file mode 100755 index 00000000..4fdf13d0 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/empty_list.mustache @@ -0,0 +1,4 @@ +These are the jobs: +{{#jobs}} +{{.}} +{{/jobs}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/empty_list.txt b/coder-base/node_modules_orig/mustache/test/_files/empty_list.txt new file mode 100755 index 00000000..d9b4a672 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/empty_list.txt @@ -0,0 +1 @@ +These are the jobs: diff --git a/coder-base/node_modules_orig/mustache/test/_files/empty_sections.js b/coder-base/node_modules_orig/mustache/test/_files/empty_sections.js new file mode 100755 index 00000000..b4100a59 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/empty_sections.js @@ -0,0 +1 @@ +({}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/empty_sections.mustache b/coder-base/node_modules_orig/mustache/test/_files/empty_sections.mustache new file mode 100755 index 00000000..b6065dbb --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/empty_sections.mustache @@ -0,0 +1 @@ +{{#foo}}{{/foo}}foo{{#bar}}{{/bar}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/empty_sections.txt b/coder-base/node_modules_orig/mustache/test/_files/empty_sections.txt new file mode 100755 index 00000000..257cc564 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/empty_sections.txt @@ -0,0 +1 @@ +foo diff --git a/coder-base/node_modules_orig/mustache/test/_files/empty_string.js b/coder-base/node_modules_orig/mustache/test/_files/empty_string.js new file mode 100755 index 00000000..be6e0587 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/empty_string.js @@ -0,0 +1,6 @@ +({ + description: "That is all!", + child: { + description: "" + } +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/empty_string.mustache b/coder-base/node_modules_orig/mustache/test/_files/empty_string.mustache new file mode 100755 index 00000000..f568441c --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/empty_string.mustache @@ -0,0 +1 @@ +{{description}}{{#child}}{{description}}{{/child}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/empty_string.txt b/coder-base/node_modules_orig/mustache/test/_files/empty_string.txt new file mode 100755 index 00000000..22e2a6e5 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/empty_string.txt @@ -0,0 +1 @@ +That is all! diff --git a/coder-base/node_modules_orig/mustache/test/_files/empty_template.js b/coder-base/node_modules_orig/mustache/test/_files/empty_template.js new file mode 100755 index 00000000..b4100a59 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/empty_template.js @@ -0,0 +1 @@ +({}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/empty_template.mustache b/coder-base/node_modules_orig/mustache/test/_files/empty_template.mustache new file mode 100755 index 00000000..bb2367a2 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/empty_template.mustache @@ -0,0 +1 @@ +

Test

\ No newline at end of file diff --git a/coder-base/node_modules_orig/mustache/test/_files/empty_template.txt b/coder-base/node_modules_orig/mustache/test/_files/empty_template.txt new file mode 100755 index 00000000..bb2367a2 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/empty_template.txt @@ -0,0 +1 @@ +

Test

\ No newline at end of file diff --git a/coder-base/node_modules_orig/mustache/test/_files/error_not_found.js b/coder-base/node_modules_orig/mustache/test/_files/error_not_found.js new file mode 100755 index 00000000..10e47091 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/error_not_found.js @@ -0,0 +1,3 @@ +({ + bar: 2 +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/error_not_found.mustache b/coder-base/node_modules_orig/mustache/test/_files/error_not_found.mustache new file mode 100755 index 00000000..24369f73 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/error_not_found.mustache @@ -0,0 +1 @@ +{{foo}} \ No newline at end of file diff --git a/coder-base/node_modules_orig/mustache/test/_files/error_not_found.txt b/coder-base/node_modules_orig/mustache/test/_files/error_not_found.txt new file mode 100755 index 00000000..e69de29b diff --git a/coder-base/node_modules_orig/mustache/test/_files/escaped.js b/coder-base/node_modules_orig/mustache/test/_files/escaped.js new file mode 100755 index 00000000..cd77c1f4 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/escaped.js @@ -0,0 +1,6 @@ +({ + title: function () { + return "Bear > Shark"; + }, + entities: "" \"'<>/" +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/escaped.mustache b/coder-base/node_modules_orig/mustache/test/_files/escaped.mustache new file mode 100755 index 00000000..93e800b3 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/escaped.mustache @@ -0,0 +1,2 @@ +

{{title}}

+And even {{entities}}, but not {{{entities}}}. diff --git a/coder-base/node_modules_orig/mustache/test/_files/escaped.txt b/coder-base/node_modules_orig/mustache/test/_files/escaped.txt new file mode 100755 index 00000000..c1527d51 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/escaped.txt @@ -0,0 +1,2 @@ +

Bear > Shark

+And even &quot; "'<>/, but not " "'<>/. diff --git a/coder-base/node_modules_orig/mustache/test/_files/falsy.js b/coder-base/node_modules_orig/mustache/test/_files/falsy.js new file mode 100755 index 00000000..ae9b9bf2 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/falsy.js @@ -0,0 +1,8 @@ +({ + "emptyString": "", + "emptyArray": [], + "zero": 0, + "null": null, + "undefined": undefined, + "NaN": 0/0 +}) \ No newline at end of file diff --git a/coder-base/node_modules_orig/mustache/test/_files/falsy.mustache b/coder-base/node_modules_orig/mustache/test/_files/falsy.mustache new file mode 100755 index 00000000..f3698da6 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/falsy.mustache @@ -0,0 +1,12 @@ +{{#emptyString}}empty string{{/emptyString}} +{{^emptyString}}inverted empty string{{/emptyString}} +{{#emptyArray}}empty array{{/emptyArray}} +{{^emptyArray}}inverted empty array{{/emptyArray}} +{{#zero}}zero{{/zero}} +{{^zero}}inverted zero{{/zero}} +{{#null}}null{{/null}} +{{^null}}inverted null{{/null}} +{{#undefined}}undefined{{/undefined}} +{{^undefined}}inverted undefined{{/undefined}} +{{#NaN}}NaN{{/NaN}} +{{^NaN}}inverted NaN{{/NaN}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/falsy.txt b/coder-base/node_modules_orig/mustache/test/_files/falsy.txt new file mode 100755 index 00000000..9b7cde39 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/falsy.txt @@ -0,0 +1,12 @@ + +inverted empty string + +inverted empty array + +inverted zero + +inverted null + +inverted undefined + +inverted NaN diff --git a/coder-base/node_modules_orig/mustache/test/_files/grandparent_context.js b/coder-base/node_modules_orig/mustache/test/_files/grandparent_context.js new file mode 100755 index 00000000..97dbfd39 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/grandparent_context.js @@ -0,0 +1,19 @@ +({ + grand_parent_id: 'grand_parent1', + parent_contexts: [ + { + parent_id: 'parent1', + child_contexts: [ + { child_id: 'parent1-child1' }, + { child_id: 'parent1-child2' } + ] + }, + { + parent_id: 'parent2', + child_contexts: [ + { child_id: 'parent2-child1' }, + { child_id: 'parent2-child2' } + ] + } + ] +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/grandparent_context.mustache b/coder-base/node_modules_orig/mustache/test/_files/grandparent_context.mustache new file mode 100755 index 00000000..e6c07a22 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/grandparent_context.mustache @@ -0,0 +1,10 @@ +{{grand_parent_id}} +{{#parent_contexts}} +{{grand_parent_id}} +{{parent_id}} +{{#child_contexts}} +{{grand_parent_id}} +{{parent_id}} +{{child_id}} +{{/child_contexts}} +{{/parent_contexts}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/grandparent_context.txt b/coder-base/node_modules_orig/mustache/test/_files/grandparent_context.txt new file mode 100755 index 00000000..64996ad4 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/grandparent_context.txt @@ -0,0 +1,17 @@ +grand_parent1 +grand_parent1 +parent1 +grand_parent1 +parent1 +parent1-child1 +grand_parent1 +parent1 +parent1-child2 +grand_parent1 +parent2 +grand_parent1 +parent2 +parent2-child1 +grand_parent1 +parent2 +parent2-child2 diff --git a/coder-base/node_modules_orig/mustache/test/_files/higher_order_sections.js b/coder-base/node_modules_orig/mustache/test/_files/higher_order_sections.js new file mode 100755 index 00000000..bacb0a44 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/higher_order_sections.js @@ -0,0 +1,9 @@ +({ + name: "Tater", + helper: "To tinker?", + bolder: function () { + return function (text, render) { + return text + ' => ' + render(text) + ' ' + this.helper; + } + } +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/higher_order_sections.mustache b/coder-base/node_modules_orig/mustache/test/_files/higher_order_sections.mustache new file mode 100755 index 00000000..04f5318d --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/higher_order_sections.mustache @@ -0,0 +1 @@ +{{#bolder}}Hi {{name}}.{{/bolder}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/higher_order_sections.txt b/coder-base/node_modules_orig/mustache/test/_files/higher_order_sections.txt new file mode 100755 index 00000000..be50ad76 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/higher_order_sections.txt @@ -0,0 +1 @@ +Hi {{name}}. => Hi Tater. To tinker? diff --git a/coder-base/node_modules_orig/mustache/test/_files/included_tag.js b/coder-base/node_modules_orig/mustache/test/_files/included_tag.js new file mode 100755 index 00000000..eb032a42 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/included_tag.js @@ -0,0 +1,3 @@ +({ + html: "I like {{mustache}}" +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/included_tag.mustache b/coder-base/node_modules_orig/mustache/test/_files/included_tag.mustache new file mode 100755 index 00000000..70631c25 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/included_tag.mustache @@ -0,0 +1 @@ +You said "{{{html}}}" today diff --git a/coder-base/node_modules_orig/mustache/test/_files/included_tag.txt b/coder-base/node_modules_orig/mustache/test/_files/included_tag.txt new file mode 100755 index 00000000..1af45567 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/included_tag.txt @@ -0,0 +1 @@ +You said "I like {{mustache}}" today diff --git a/coder-base/node_modules_orig/mustache/test/_files/inverted_section.js b/coder-base/node_modules_orig/mustache/test/_files/inverted_section.js new file mode 100755 index 00000000..f8f08fd2 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/inverted_section.js @@ -0,0 +1,3 @@ +({ + "repos": [] +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/inverted_section.mustache b/coder-base/node_modules_orig/mustache/test/_files/inverted_section.mustache new file mode 100755 index 00000000..b0a183b1 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/inverted_section.mustache @@ -0,0 +1,3 @@ +{{#repos}}{{name}}{{/repos}} +{{^repos}}No repos :({{/repos}} +{{^nothin}}Hello!{{/nothin}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/inverted_section.txt b/coder-base/node_modules_orig/mustache/test/_files/inverted_section.txt new file mode 100755 index 00000000..b421582e --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/inverted_section.txt @@ -0,0 +1,3 @@ + +No repos :( +Hello! diff --git a/coder-base/node_modules_orig/mustache/test/_files/keys_with_questionmarks.js b/coder-base/node_modules_orig/mustache/test/_files/keys_with_questionmarks.js new file mode 100755 index 00000000..becd6310 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/keys_with_questionmarks.js @@ -0,0 +1,5 @@ +({ + "person?": { + name: "Jon" + } +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/keys_with_questionmarks.mustache b/coder-base/node_modules_orig/mustache/test/_files/keys_with_questionmarks.mustache new file mode 100755 index 00000000..417f17f3 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/keys_with_questionmarks.mustache @@ -0,0 +1,3 @@ +{{#person?}} + Hi {{name}}! +{{/person?}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/keys_with_questionmarks.txt b/coder-base/node_modules_orig/mustache/test/_files/keys_with_questionmarks.txt new file mode 100755 index 00000000..0f69b943 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/keys_with_questionmarks.txt @@ -0,0 +1 @@ + Hi Jon! diff --git a/coder-base/node_modules_orig/mustache/test/_files/malicious_template.js b/coder-base/node_modules_orig/mustache/test/_files/malicious_template.js new file mode 100755 index 00000000..b4100a59 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/malicious_template.js @@ -0,0 +1 @@ +({}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/malicious_template.mustache b/coder-base/node_modules_orig/mustache/test/_files/malicious_template.mustache new file mode 100755 index 00000000..b956867e --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/malicious_template.mustache @@ -0,0 +1,5 @@ +{{"+(function () {throw "evil"})()+"}} +{{{"+(function () {throw "evil"})()+"}}} +{{> "+(function () {throw "evil"})()+"}} +{{# "+(function () {throw "evil"})()+"}} +{{/ "+(function () {throw "evil"})()+"}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/malicious_template.txt b/coder-base/node_modules_orig/mustache/test/_files/malicious_template.txt new file mode 100755 index 00000000..139597f9 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/malicious_template.txt @@ -0,0 +1,2 @@ + + diff --git a/coder-base/node_modules_orig/mustache/test/_files/multiline_comment.js b/coder-base/node_modules_orig/mustache/test/_files/multiline_comment.js new file mode 100755 index 00000000..b4100a59 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/multiline_comment.js @@ -0,0 +1 @@ +({}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/multiline_comment.mustache b/coder-base/node_modules_orig/mustache/test/_files/multiline_comment.mustache new file mode 100755 index 00000000..dff0893d --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/multiline_comment.mustache @@ -0,0 +1,6 @@ +{{! + +This is a multi-line comment. + +}} +Hello world! diff --git a/coder-base/node_modules_orig/mustache/test/_files/multiline_comment.txt b/coder-base/node_modules_orig/mustache/test/_files/multiline_comment.txt new file mode 100755 index 00000000..cd087558 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/multiline_comment.txt @@ -0,0 +1 @@ +Hello world! diff --git a/coder-base/node_modules_orig/mustache/test/_files/nested_higher_order_sections.js b/coder-base/node_modules_orig/mustache/test/_files/nested_higher_order_sections.js new file mode 100755 index 00000000..3ccf4d37 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/nested_higher_order_sections.js @@ -0,0 +1,8 @@ +({ + bold: function () { + return function (text, render) { + return '' + render(text) + ''; + }; + }, + person: { name: 'Jonas' } +}); diff --git a/coder-base/node_modules_orig/mustache/test/_files/nested_higher_order_sections.mustache b/coder-base/node_modules_orig/mustache/test/_files/nested_higher_order_sections.mustache new file mode 100755 index 00000000..e312fe79 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/nested_higher_order_sections.mustache @@ -0,0 +1 @@ +{{#bold}}{{#person}}My name is {{name}}!{{/person}}{{/bold}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/nested_higher_order_sections.txt b/coder-base/node_modules_orig/mustache/test/_files/nested_higher_order_sections.txt new file mode 100755 index 00000000..0ee6a406 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/nested_higher_order_sections.txt @@ -0,0 +1 @@ +My name is Jonas! diff --git a/coder-base/node_modules_orig/mustache/test/_files/nested_iterating.js b/coder-base/node_modules_orig/mustache/test/_files/nested_iterating.js new file mode 100755 index 00000000..2708b2db --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/nested_iterating.js @@ -0,0 +1,8 @@ +({ + inner: [{ + foo: 'foo', + inner: [{ + bar: 'bar' + }] + }] +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/nested_iterating.mustache b/coder-base/node_modules_orig/mustache/test/_files/nested_iterating.mustache new file mode 100755 index 00000000..1a3bb1a2 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/nested_iterating.mustache @@ -0,0 +1 @@ +{{#inner}}{{foo}}{{#inner}}{{bar}}{{/inner}}{{/inner}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/nested_iterating.txt b/coder-base/node_modules_orig/mustache/test/_files/nested_iterating.txt new file mode 100755 index 00000000..323fae03 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/nested_iterating.txt @@ -0,0 +1 @@ +foobar diff --git a/coder-base/node_modules_orig/mustache/test/_files/nesting.js b/coder-base/node_modules_orig/mustache/test/_files/nesting.js new file mode 100755 index 00000000..264cc2f7 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/nesting.js @@ -0,0 +1,7 @@ +({ + foo: [ + {a: {b: 1}}, + {a: {b: 2}}, + {a: {b: 3}} + ] +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/nesting.mustache b/coder-base/node_modules_orig/mustache/test/_files/nesting.mustache new file mode 100755 index 00000000..551366de --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/nesting.mustache @@ -0,0 +1,5 @@ +{{#foo}} + {{#a}} + {{b}} + {{/a}} +{{/foo}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/nesting.txt b/coder-base/node_modules_orig/mustache/test/_files/nesting.txt new file mode 100755 index 00000000..7db34b17 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/nesting.txt @@ -0,0 +1,3 @@ + 1 + 2 + 3 diff --git a/coder-base/node_modules_orig/mustache/test/_files/nesting_same_name.js b/coder-base/node_modules_orig/mustache/test/_files/nesting_same_name.js new file mode 100755 index 00000000..10a0c140 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/nesting_same_name.js @@ -0,0 +1,8 @@ +({ + items: [ + { + name: 'name', + items: [1, 2, 3, 4] + } + ] +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/nesting_same_name.mustache b/coder-base/node_modules_orig/mustache/test/_files/nesting_same_name.mustache new file mode 100755 index 00000000..777dbd68 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/nesting_same_name.mustache @@ -0,0 +1 @@ +{{#items}}{{name}}{{#items}}{{.}}{{/items}}{{/items}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/nesting_same_name.txt b/coder-base/node_modules_orig/mustache/test/_files/nesting_same_name.txt new file mode 100755 index 00000000..34fcfd3e --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/nesting_same_name.txt @@ -0,0 +1 @@ +name1234 diff --git a/coder-base/node_modules_orig/mustache/test/_files/null_string.js b/coder-base/node_modules_orig/mustache/test/_files/null_string.js new file mode 100755 index 00000000..984ee516 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/null_string.js @@ -0,0 +1,10 @@ +({ + name: "Elise", + glytch: true, + binary: false, + value: null, + undef: undefined, + numeric: function() { + return NaN; + } +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/null_string.mustache b/coder-base/node_modules_orig/mustache/test/_files/null_string.mustache new file mode 100755 index 00000000..a6f33009 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/null_string.mustache @@ -0,0 +1,6 @@ +Hello {{name}} +glytch {{glytch}} +binary {{binary}} +value {{value}} +undef {{undef}} +numeric {{numeric}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/null_string.txt b/coder-base/node_modules_orig/mustache/test/_files/null_string.txt new file mode 100755 index 00000000..bcabe0a5 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/null_string.txt @@ -0,0 +1,6 @@ +Hello Elise +glytch true +binary false +value +undef +numeric NaN diff --git a/coder-base/node_modules_orig/mustache/test/_files/null_view.js b/coder-base/node_modules_orig/mustache/test/_files/null_view.js new file mode 100755 index 00000000..dbdae728 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/null_view.js @@ -0,0 +1,4 @@ +({ + name: 'Joe', + friends: null +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/null_view.mustache b/coder-base/node_modules_orig/mustache/test/_files/null_view.mustache new file mode 100755 index 00000000..115b376b --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/null_view.mustache @@ -0,0 +1 @@ +{{name}}'s friends: {{#friends}}{{name}}, {{/friends}} \ No newline at end of file diff --git a/coder-base/node_modules_orig/mustache/test/_files/null_view.txt b/coder-base/node_modules_orig/mustache/test/_files/null_view.txt new file mode 100755 index 00000000..15ed2abe --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/null_view.txt @@ -0,0 +1 @@ +Joe's friends: \ No newline at end of file diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_array.js b/coder-base/node_modules_orig/mustache/test/_files/partial_array.js new file mode 100755 index 00000000..2a6ddf1c --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_array.js @@ -0,0 +1,3 @@ +({ + array: ['1', '2', '3', '4'] +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_array.mustache b/coder-base/node_modules_orig/mustache/test/_files/partial_array.mustache new file mode 100755 index 00000000..7a336fee --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_array.mustache @@ -0,0 +1 @@ +{{>partial}} \ No newline at end of file diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_array.partial b/coder-base/node_modules_orig/mustache/test/_files/partial_array.partial new file mode 100755 index 00000000..0ba652c1 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_array.partial @@ -0,0 +1,4 @@ +Here's a non-sense array of values +{{#array}} + {{.}} +{{/array}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_array.txt b/coder-base/node_modules_orig/mustache/test/_files/partial_array.txt new file mode 100755 index 00000000..892837cb --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_array.txt @@ -0,0 +1,5 @@ +Here's a non-sense array of values + 1 + 2 + 3 + 4 diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.js b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.js new file mode 100755 index 00000000..03f13c94 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.js @@ -0,0 +1,8 @@ +({ + numbers: [ + {i: '1'}, + {i: '2'}, + {i: '3'}, + {i: '4'} + ] +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.mustache b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.mustache new file mode 100755 index 00000000..1af6d68c --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.mustache @@ -0,0 +1,4 @@ +Here is some stuff! +{{#numbers}} +{{>partial}} +{{/numbers}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.partial b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.partial new file mode 100755 index 00000000..bdde77da --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.partial @@ -0,0 +1 @@ +{{i}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.txt b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.txt new file mode 100755 index 00000000..f622375c --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials.txt @@ -0,0 +1,5 @@ +Here is some stuff! +1 +2 +3 +4 diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.js b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.js new file mode 100755 index 00000000..9ec0c00f --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.js @@ -0,0 +1,3 @@ +({ + numbers: ['1', '2', '3', '4'] +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.mustache b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.mustache new file mode 100755 index 00000000..1af6d68c --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.mustache @@ -0,0 +1,4 @@ +Here is some stuff! +{{#numbers}} +{{>partial}} +{{/numbers}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.partial b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.partial new file mode 100755 index 00000000..12f71598 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.partial @@ -0,0 +1 @@ +{{.}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.txt b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.txt new file mode 100755 index 00000000..f622375c --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_array_of_partials_implicit.txt @@ -0,0 +1,5 @@ +Here is some stuff! +1 +2 +3 +4 diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_empty.js b/coder-base/node_modules_orig/mustache/test/_files/partial_empty.js new file mode 100755 index 00000000..82b8c224 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_empty.js @@ -0,0 +1,3 @@ +({ + foo: 1 +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_empty.mustache b/coder-base/node_modules_orig/mustache/test/_files/partial_empty.mustache new file mode 100755 index 00000000..a7100470 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_empty.mustache @@ -0,0 +1,2 @@ +hey {{foo}} +{{>partial}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_empty.partial b/coder-base/node_modules_orig/mustache/test/_files/partial_empty.partial new file mode 100755 index 00000000..e69de29b diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_empty.txt b/coder-base/node_modules_orig/mustache/test/_files/partial_empty.txt new file mode 100755 index 00000000..1a679077 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_empty.txt @@ -0,0 +1 @@ +hey 1 diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_template.js b/coder-base/node_modules_orig/mustache/test/_files/partial_template.js new file mode 100755 index 00000000..a913f878 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_template.js @@ -0,0 +1,6 @@ +({ + title: function () { + return "Welcome"; + }, + again: "Goodbye" +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_template.mustache b/coder-base/node_modules_orig/mustache/test/_files/partial_template.mustache new file mode 100755 index 00000000..6a7492e0 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_template.mustache @@ -0,0 +1,2 @@ +

{{title}}

+{{>partial}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_template.partial b/coder-base/node_modules_orig/mustache/test/_files/partial_template.partial new file mode 100755 index 00000000..a4045292 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_template.partial @@ -0,0 +1 @@ +Again, {{again}}! diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_template.txt b/coder-base/node_modules_orig/mustache/test/_files/partial_template.txt new file mode 100755 index 00000000..692698f0 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_template.txt @@ -0,0 +1,2 @@ +

Welcome

+Again, Goodbye! diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_view.js b/coder-base/node_modules_orig/mustache/test/_files/partial_view.js new file mode 100755 index 00000000..3ad70d35 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_view.js @@ -0,0 +1,14 @@ +({ + greeting: function () { + return "Welcome"; + }, + farewell: function () { + return "Fair enough, right?"; + }, + name: "Chris", + value: 10000, + taxed_value: function () { + return this.value - (this.value * 0.4); + }, + in_ca: true +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_view.mustache b/coder-base/node_modules_orig/mustache/test/_files/partial_view.mustache new file mode 100755 index 00000000..f8f6a5b7 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_view.mustache @@ -0,0 +1,3 @@ +

{{greeting}}

+{{>partial}} +

{{farewell}}

diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_view.partial b/coder-base/node_modules_orig/mustache/test/_files/partial_view.partial new file mode 100755 index 00000000..03df2068 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_view.partial @@ -0,0 +1,5 @@ +Hello {{name}} +You have just won ${{value}}! +{{#in_ca}} +Well, ${{ taxed_value }}, after taxes. +{{/in_ca}} \ No newline at end of file diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_view.txt b/coder-base/node_modules_orig/mustache/test/_files/partial_view.txt new file mode 100755 index 00000000..c09147c7 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_view.txt @@ -0,0 +1,5 @@ +

Welcome

+Hello Chris +You have just won $10000! +Well, $6000, after taxes. +

Fair enough, right?

diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.js b/coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.js new file mode 100755 index 00000000..3ad70d35 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.js @@ -0,0 +1,14 @@ +({ + greeting: function () { + return "Welcome"; + }, + farewell: function () { + return "Fair enough, right?"; + }, + name: "Chris", + value: 10000, + taxed_value: function () { + return this.value - (this.value * 0.4); + }, + in_ca: true +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.mustache b/coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.mustache new file mode 100755 index 00000000..48bd1ff8 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.mustache @@ -0,0 +1,3 @@ +

{{ greeting }}

+{{> partial }} +

{{ farewell }}

diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.partial b/coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.partial new file mode 100755 index 00000000..30de8f6c --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.partial @@ -0,0 +1,5 @@ +Hello {{ name}} +You have just won ${{value }}! +{{# in_ca }} +Well, ${{ taxed_value }}, after taxes. +{{/ in_ca }} \ No newline at end of file diff --git a/coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.txt b/coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.txt new file mode 100755 index 00000000..c09147c7 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/partial_whitespace.txt @@ -0,0 +1,5 @@ +

Welcome

+Hello Chris +You have just won $10000! +Well, $6000, after taxes. +

Fair enough, right?

diff --git a/coder-base/node_modules_orig/mustache/test/_files/recursion_with_same_names.js b/coder-base/node_modules_orig/mustache/test/_files/recursion_with_same_names.js new file mode 100755 index 00000000..ce265029 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/recursion_with_same_names.js @@ -0,0 +1,8 @@ +({ + name: 'name', + description: 'desc', + terms: [ + {name: 't1', index: 0}, + {name: 't2', index: 1} + ] +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/recursion_with_same_names.mustache b/coder-base/node_modules_orig/mustache/test/_files/recursion_with_same_names.mustache new file mode 100755 index 00000000..c331d045 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/recursion_with_same_names.mustache @@ -0,0 +1,7 @@ +{{ name }} +{{ description }} + +{{#terms}} + {{name}} + {{index}} +{{/terms}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/recursion_with_same_names.txt b/coder-base/node_modules_orig/mustache/test/_files/recursion_with_same_names.txt new file mode 100755 index 00000000..cb15d750 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/recursion_with_same_names.txt @@ -0,0 +1,7 @@ +name +desc + + t1 + 0 + t2 + 1 diff --git a/coder-base/node_modules_orig/mustache/test/_files/reuse_of_enumerables.js b/coder-base/node_modules_orig/mustache/test/_files/reuse_of_enumerables.js new file mode 100755 index 00000000..4368b574 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/reuse_of_enumerables.js @@ -0,0 +1,6 @@ +({ + terms: [ + {name: 't1', index: 0}, + {name: 't2', index: 1} + ] +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/reuse_of_enumerables.mustache b/coder-base/node_modules_orig/mustache/test/_files/reuse_of_enumerables.mustache new file mode 100755 index 00000000..cc0cb7a4 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/reuse_of_enumerables.mustache @@ -0,0 +1,8 @@ +{{#terms}} + {{name}} + {{index}} +{{/terms}} +{{#terms}} + {{name}} + {{index}} +{{/terms}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/reuse_of_enumerables.txt b/coder-base/node_modules_orig/mustache/test/_files/reuse_of_enumerables.txt new file mode 100755 index 00000000..6d05d964 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/reuse_of_enumerables.txt @@ -0,0 +1,8 @@ + t1 + 0 + t2 + 1 + t1 + 0 + t2 + 1 diff --git a/coder-base/node_modules_orig/mustache/test/_files/section_as_context.js b/coder-base/node_modules_orig/mustache/test/_files/section_as_context.js new file mode 100755 index 00000000..425b29cb --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/section_as_context.js @@ -0,0 +1,10 @@ +({ + a_object: { + title: 'this is an object', + description: 'one of its attributes is a list', + a_list: [ + {label: 'listitem1'}, + {label: 'listitem2'} + ] + } +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/section_as_context.mustache b/coder-base/node_modules_orig/mustache/test/_files/section_as_context.mustache new file mode 100755 index 00000000..59990f65 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/section_as_context.mustache @@ -0,0 +1,9 @@ +{{#a_object}} +

{{title}}

+

{{description}}

+
    + {{#a_list}} +
  • {{label}}
  • + {{/a_list}} +
+{{/a_object}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/section_as_context.txt b/coder-base/node_modules_orig/mustache/test/_files/section_as_context.txt new file mode 100755 index 00000000..d834e804 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/section_as_context.txt @@ -0,0 +1,6 @@ +

this is an object

+

one of its attributes is a list

+
    +
  • listitem1
  • +
  • listitem2
  • +
diff --git a/coder-base/node_modules_orig/mustache/test/_files/simple.js b/coder-base/node_modules_orig/mustache/test/_files/simple.js new file mode 100755 index 00000000..1d8d6f42 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/simple.js @@ -0,0 +1,8 @@ +({ + name: "Chris", + value: 10000, + taxed_value: function () { + return this.value - (this.value * 0.4); + }, + in_ca: true +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/simple.mustache b/coder-base/node_modules_orig/mustache/test/_files/simple.mustache new file mode 100755 index 00000000..2fea6327 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/simple.mustache @@ -0,0 +1,5 @@ +Hello {{name}} +You have just won ${{value}}! +{{#in_ca}} +Well, ${{ taxed_value }}, after taxes. +{{/in_ca}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/simple.txt b/coder-base/node_modules_orig/mustache/test/_files/simple.txt new file mode 100755 index 00000000..5d75d656 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/simple.txt @@ -0,0 +1,3 @@ +Hello Chris +You have just won $10000! +Well, $6000, after taxes. diff --git a/coder-base/node_modules_orig/mustache/test/_files/string_as_context.js b/coder-base/node_modules_orig/mustache/test/_files/string_as_context.js new file mode 100755 index 00000000..e8bb4da0 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/string_as_context.js @@ -0,0 +1,4 @@ +({ + a_string: 'aa', + a_list: ['a','b','c'] +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/string_as_context.mustache b/coder-base/node_modules_orig/mustache/test/_files/string_as_context.mustache new file mode 100755 index 00000000..c6aa11a4 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/string_as_context.mustache @@ -0,0 +1,5 @@ +
    +{{#a_list}} +
  • {{.}}
  • +{{/a_list}} +
\ No newline at end of file diff --git a/coder-base/node_modules_orig/mustache/test/_files/string_as_context.txt b/coder-base/node_modules_orig/mustache/test/_files/string_as_context.txt new file mode 100755 index 00000000..35e63067 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/string_as_context.txt @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/coder-base/node_modules_orig/mustache/test/_files/two_in_a_row.js b/coder-base/node_modules_orig/mustache/test/_files/two_in_a_row.js new file mode 100755 index 00000000..9c17c117 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/two_in_a_row.js @@ -0,0 +1,4 @@ +({ + name: "Joe", + greeting: "Welcome" +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/two_in_a_row.mustache b/coder-base/node_modules_orig/mustache/test/_files/two_in_a_row.mustache new file mode 100755 index 00000000..b23f29e8 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/two_in_a_row.mustache @@ -0,0 +1 @@ +{{greeting}}, {{name}}! diff --git a/coder-base/node_modules_orig/mustache/test/_files/two_in_a_row.txt b/coder-base/node_modules_orig/mustache/test/_files/two_in_a_row.txt new file mode 100755 index 00000000..c6d6a9b4 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/two_in_a_row.txt @@ -0,0 +1 @@ +Welcome, Joe! diff --git a/coder-base/node_modules_orig/mustache/test/_files/two_sections.js b/coder-base/node_modules_orig/mustache/test/_files/two_sections.js new file mode 100755 index 00000000..b4100a59 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/two_sections.js @@ -0,0 +1 @@ +({}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/two_sections.mustache b/coder-base/node_modules_orig/mustache/test/_files/two_sections.mustache new file mode 100755 index 00000000..a4b9f2a7 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/two_sections.mustache @@ -0,0 +1,4 @@ +{{#foo}} +{{/foo}} +{{#bar}} +{{/bar}} diff --git a/coder-base/node_modules_orig/mustache/test/_files/two_sections.txt b/coder-base/node_modules_orig/mustache/test/_files/two_sections.txt new file mode 100755 index 00000000..e69de29b diff --git a/coder-base/node_modules_orig/mustache/test/_files/unescaped.js b/coder-base/node_modules_orig/mustache/test/_files/unescaped.js new file mode 100755 index 00000000..b6d064f1 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/unescaped.js @@ -0,0 +1,5 @@ +({ + title: function () { + return "Bear > Shark"; + } +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/unescaped.mustache b/coder-base/node_modules_orig/mustache/test/_files/unescaped.mustache new file mode 100755 index 00000000..6b07d7b7 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/unescaped.mustache @@ -0,0 +1 @@ +

{{{title}}}

diff --git a/coder-base/node_modules_orig/mustache/test/_files/unescaped.txt b/coder-base/node_modules_orig/mustache/test/_files/unescaped.txt new file mode 100755 index 00000000..089ad796 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/unescaped.txt @@ -0,0 +1 @@ +

Bear > Shark

diff --git a/coder-base/node_modules_orig/mustache/test/_files/whitespace.js b/coder-base/node_modules_orig/mustache/test/_files/whitespace.js new file mode 100755 index 00000000..f41cb564 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/whitespace.js @@ -0,0 +1,4 @@ +({ + tag1: "Hello", + tag2: "World" +}) diff --git a/coder-base/node_modules_orig/mustache/test/_files/whitespace.mustache b/coder-base/node_modules_orig/mustache/test/_files/whitespace.mustache new file mode 100755 index 00000000..aa76e08e --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/whitespace.mustache @@ -0,0 +1,4 @@ +{{tag1}} + + +{{tag2}}. diff --git a/coder-base/node_modules_orig/mustache/test/_files/whitespace.txt b/coder-base/node_modules_orig/mustache/test/_files/whitespace.txt new file mode 100755 index 00000000..851fa744 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/_files/whitespace.txt @@ -0,0 +1,4 @@ +Hello + + +World. diff --git a/coder-base/node_modules_orig/mustache/test/context-test.js b/coder-base/node_modules_orig/mustache/test/context-test.js new file mode 100755 index 00000000..752f74bc --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/context-test.js @@ -0,0 +1,51 @@ +require('./helper'); +var Context = Mustache.Context; + +describe('A new Mustache.Context', function () { + var context; + beforeEach(function () { + context = new Context({ name: 'parent', message: 'hi', a: { b: 'b' } }); + }); + + it('is able to lookup properties of its own view', function () { + assert.equal(context.lookup('name'), 'parent'); + }); + + it('is able to lookup nested properties of its own view', function () { + assert.equal(context.lookup('a.b'), 'b'); + }); + + describe('when pushed', function () { + beforeEach(function () { + context = context.push({ name: 'child', c: { d: 'd' } }); + }); + + it('returns the child context', function () { + assert.equal(context.view.name, 'child'); + assert.equal(context.parent.view.name, 'parent'); + }); + + it('is able to lookup properties of its own view', function () { + assert.equal(context.lookup('name'), 'child'); + }); + + it("is able to lookup properties of the parent context's view", function () { + assert.equal(context.lookup('message'), 'hi'); + }); + + it('is able to lookup nested properties of its own view', function () { + assert.equal(context.lookup('c.d'), 'd'); + }); + + it('is able to lookup nested properties of its parent view', function () { + assert.equal(context.lookup('a.b'), 'b'); + }); + }); +}); + +describe('Mustache.Context.make', function () { + it('returns the same object when given a Context', function () { + var context = new Context; + assert.strictEqual(Context.make(context), context); + }); +}); diff --git a/coder-base/node_modules_orig/mustache/test/helper.js b/coder-base/node_modules_orig/mustache/test/helper.js new file mode 100755 index 00000000..a91fe499 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/helper.js @@ -0,0 +1,2 @@ +assert = require('assert'); +Mustache = require('../mustache'); diff --git a/coder-base/node_modules_orig/mustache/test/parse-test.js b/coder-base/node_modules_orig/mustache/test/parse-test.js new file mode 100755 index 00000000..40d23a43 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/parse-test.js @@ -0,0 +1,106 @@ +require('./helper'); + +// A map of templates to their expected token output. Tokens are in the format: +// [type, value, startIndex, endIndex, subTokens]. +var expectations = { + '' : [], + '{{hi}}' : [ [ 'name', 'hi', 0, 6 ] ], + '{{hi.world}}' : [ [ 'name', 'hi.world', 0, 12 ] ], + '{{hi . world}}' : [ [ 'name', 'hi . world', 0, 14 ] ], + '{{ hi}}' : [ [ 'name', 'hi', 0, 7 ] ], + '{{hi }}' : [ [ 'name', 'hi', 0, 7 ] ], + '{{ hi }}' : [ [ 'name', 'hi', 0, 8 ] ], + '{{{hi}}}' : [ [ '&', 'hi', 0, 8 ] ], + '{{!hi}}' : [ [ '!', 'hi', 0, 7 ] ], + '{{! hi}}' : [ [ '!', 'hi', 0, 8 ] ], + '{{! hi }}' : [ [ '!', 'hi', 0, 9 ] ], + '{{ !hi}}' : [ [ '!', 'hi', 0, 8 ] ], + '{{ ! hi}}' : [ [ '!', 'hi', 0, 9 ] ], + '{{ ! hi }}' : [ [ '!', 'hi', 0, 10 ] ], + 'a\n b' : [ [ 'text', 'a\n b', 0, 4 ] ], + 'a{{hi}}' : [ [ 'text', 'a', 0, 1 ], [ 'name', 'hi', 1, 7 ] ], + 'a {{hi}}' : [ [ 'text', 'a ', 0, 2 ], [ 'name', 'hi', 2, 8 ] ], + ' a{{hi}}' : [ [ 'text', ' a', 0, 2 ], [ 'name', 'hi', 2, 8 ] ], + ' a {{hi}}' : [ [ 'text', ' a ', 0, 3 ], [ 'name', 'hi', 3, 9 ] ], + 'a{{hi}}b' : [ [ 'text', 'a', 0, 1 ], [ 'name', 'hi', 1, 7 ], [ 'text', 'b', 7, 8 ] ], + 'a{{hi}} b' : [ [ 'text', 'a', 0, 1 ], [ 'name', 'hi', 1, 7 ], [ 'text', ' b', 7, 9 ] ], + 'a{{hi}}b ' : [ [ 'text', 'a', 0, 1 ], [ 'name', 'hi', 1, 7 ], [ 'text', 'b ', 7, 9 ] ], + 'a\n{{hi}} b \n' : [ [ 'text', 'a\n', 0, 2 ], [ 'name', 'hi', 2, 8 ], [ 'text', ' b \n', 8, 12 ] ], + 'a\n {{hi}} \nb' : [ [ 'text', 'a\n ', 0, 3 ], [ 'name', 'hi', 3, 9 ], [ 'text', ' \nb', 9, 12 ] ], + 'a\n {{!hi}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '!', 'hi', 3, 10 ], [ 'text', 'b', 12, 13 ] ], + 'a\n{{#a}}{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 2, 8, [], 8 ], [ 'text', 'b', 15, 16 ] ], + 'a\n {{#a}}{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [], 9 ], [ 'text', 'b', 16, 17 ] ], + 'a\n {{#a}}{{/a}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [], 9 ], [ 'text', 'b', 17, 18 ] ], + 'a\n{{#a}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 2, 8, [], 9 ], [ 'text', 'b', 16, 17 ] ], + 'a\n {{#a}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [], 10 ], [ 'text', 'b', 17, 18 ] ], + 'a\n {{#a}}\n{{/a}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [], 10 ], [ 'text', 'b', 18, 19 ] ], + 'a\n{{#a}}\n{{/a}}\n{{#b}}\n{{/b}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 2, 8, [], 9 ], [ '#', 'b', 16, 22, [], 23 ], [ 'text', 'b', 30, 31 ] ], + 'a\n {{#a}}\n{{/a}}\n{{#b}}\n{{/b}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [], 10 ], [ '#', 'b', 17, 23, [], 24 ], [ 'text', 'b', 31, 32 ] ], + 'a\n {{#a}}\n{{/a}}\n{{#b}}\n{{/b}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [], 10 ], [ '#', 'b', 17, 23, [], 24 ], [ 'text', 'b', 32, 33 ] ], + 'a\n{{#a}}\n{{#b}}\n{{/b}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 2, 8, [ [ '#', 'b', 9, 15, [], 16 ] ], 23 ], [ 'text', 'b', 30, 31 ] ], + 'a\n {{#a}}\n{{#b}}\n{{/b}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [ [ '#', 'b', 10, 16, [], 17 ] ], 24 ], [ 'text', 'b', 31, 32 ] ], + 'a\n {{#a}}\n{{#b}}\n{{/b}}\n{{/a}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [ [ '#', 'b', 10, 16, [], 17 ] ], 24 ], [ 'text', 'b', 32, 33 ] ], + '{{>abc}}' : [ [ '>', 'abc', 0, 8 ] ], + '{{> abc }}' : [ [ '>', 'abc', 0, 10 ] ], + '{{ > abc }}' : [ [ '>', 'abc', 0, 11 ] ], + '{{=<% %>=}}' : [ [ '=', '<% %>', 0, 11 ] ], + '{{= <% %> =}}' : [ [ '=', '<% %>', 0, 13 ] ], + '{{=<% %>=}}<%={{ }}=%>' : [ [ '=', '<% %>', 0, 11 ], [ '=', '{{ }}', 11, 22 ] ], + '{{=<% %>=}}<%hi%>' : [ [ '=', '<% %>', 0, 11 ], [ 'name', 'hi', 11, 17 ] ], + '{{#a}}{{/a}}hi{{#b}}{{/b}}\n' : [ [ '#', 'a', 0, 6, [], 6 ], [ 'text', 'hi', 12, 14 ], [ '#', 'b', 14, 20, [], 20 ], [ 'text', '\n', 26, 27 ] ], + '{{a}}\n{{b}}\n\n{{#c}}\n{{/c}}\n' : [ [ 'name', 'a', 0, 5 ], [ 'text', '\n', 5, 6 ], [ 'name', 'b', 6, 11 ], [ 'text', '\n\n', 11, 13 ], [ '#', 'c', 13, 19, [], 20 ] ], + '{{#foo}}\n {{#a}}\n {{b}}\n {{/a}}\n{{/foo}}\n' + : [ [ '#', 'foo', 0, 8, [ [ '#', 'a', 11, 17, [ [ 'text', ' ', 18, 22 ], [ 'name', 'b', 22, 27 ], [ 'text', '\n', 27, 28 ] ], 30 ] ], 37 ] ] +}; + +describe('Mustache.parse', function () { + + for (var template in expectations) { + (function (template, tokens) { + it('knows how to parse ' + JSON.stringify(template), function () { + assert.deepEqual(Mustache.parse(template), tokens); + }); + })(template, expectations[template]); + } + + describe('when there is an unclosed tag', function () { + it('throws an error', function () { + assert.throws(function () { + Mustache.parse('My name is {{name'); + }, /unclosed tag at 17/i); + }); + }); + + describe('when there is an unclosed section', function () { + it('throws an error', function () { + assert.throws(function () { + Mustache.parse('A list: {{#people}}{{name}}'); + }, /unclosed section "people" at 27/i); + }); + }); + + describe('when there is an unopened section', function () { + it('throws an error', function () { + assert.throws(function () { + Mustache.parse('The end of the list! {{/people}}'); + }, /unopened section "people" at 21/i); + }); + }); + + describe('when invalid tags are given as an argument', function () { + it('throws an error', function () { + assert.throws(function () { + Mustache.parse('A template <% name %>', [ '<%' ]); + }, /invalid tags/i); + }); + }); + + describe('when the template contains invalid tags', function () { + it('throws an error', function () { + assert.throws(function () { + Mustache.parse('A template {{=<%=}}'); + }, /invalid tags at 11/i); + }); + }); + +}); diff --git a/coder-base/node_modules_orig/mustache/test/render-test.js b/coder-base/node_modules_orig/mustache/test/render-test.js new file mode 100755 index 00000000..acec47ff --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/render-test.js @@ -0,0 +1,68 @@ +require('./helper'); + +var fs = require('fs'); +var path = require('path'); +var _files = path.join(__dirname, '_files'); + +function getContents(testName, ext) { + return fs.readFileSync(path.join(_files, testName + '.' + ext), 'utf8'); +} + +function getView(testName) { + var view = getContents(testName, 'js'); + if (!view) throw new Error('Cannot find view for test "' + testName + '"'); + return eval(view); +} + +function getPartial(testName) { + try { + return getContents(testName, 'partial'); + } catch (e) { + // No big deal. Not all tests need to test partial support. + } +} + +function getTest(testName) { + var test = {}; + test.view = getView(testName); + test.template = getContents(testName, 'mustache'); + test.partial = getPartial(testName); + test.expect = getContents(testName, 'txt'); + return test; +} + +// You can put the name of a specific test to run in the TEST environment +// variable (e.g. TEST=backslashes vows test/render-test.js) +var testToRun = process.env.TEST; + +var testNames; +if (testToRun) { + testNames = [testToRun]; +} else { + testNames = fs.readdirSync(_files).filter(function (file) { + return (/\.js$/).test(file); + }).map(function (file) { + return path.basename(file).replace(/\.js$/, ''); + }); +} + +describe('Mustache.render', function () { + beforeEach(function () { + Mustache.clearCache(); + }); + + testNames.forEach(function (testName) { + var test = getTest(testName); + + it('knows how to render ' + testName, function () { + var output; + if (test.partial) { + output = Mustache.render(test.template, test.view, { partial: test.partial }); + } else { + output = Mustache.render(test.template, test.view); + } + + assert.equal(output, test.expect); + }); + }); +}); diff --git a/coder-base/node_modules_orig/mustache/test/scanner-test.js b/coder-base/node_modules_orig/mustache/test/scanner-test.js new file mode 100755 index 00000000..9c976642 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/scanner-test.js @@ -0,0 +1,78 @@ +require('./helper'); +var Scanner = Mustache.Scanner; + +describe('A new Mustache.Scanner', function () { + describe('for an empty string', function () { + it('is at the end', function () { + var scanner = new Scanner(''); + assert(scanner.eos()); + }); + }); + + describe('for a non-empty string', function () { + var scanner; + beforeEach(function () { + scanner = new Scanner('a b c'); + }); + + describe('scan', function () { + describe('when the RegExp matches the entire string', function () { + it('returns the entire string', function () { + var match = scanner.scan(/a b c/); + assert.equal(match, scanner.string); + assert(scanner.eos()); + }); + }); + + describe('when the RegExp matches at index 0', function () { + it('returns the portion of the string that matched', function () { + var match = scanner.scan(/a/); + assert.equal(match, 'a'); + assert.equal(scanner.pos, 1); + }); + }); + + describe('when the RegExp matches at some index other than 0', function () { + it('returns the empty string', function () { + var match = scanner.scan(/b/); + assert.equal(match, ''); + assert.equal(scanner.pos, 0); + }); + }); + + describe('when the RegExp does not match', function () { + it('returns the empty string', function () { + var match = scanner.scan(/z/); + assert.equal(match, ''); + assert.equal(scanner.pos, 0); + }); + }); + }); // scan + + describe('scanUntil', function () { + describe('when the RegExp matches at index 0', function () { + it('returns the empty string', function () { + var match = scanner.scanUntil(/a/); + assert.equal(match, ''); + assert.equal(scanner.pos, 0); + }); + }); + + describe('when the RegExp matches at some index other than 0', function () { + it('returns the string up to that index', function () { + var match = scanner.scanUntil(/b/); + assert.equal(match, 'a '); + assert.equal(scanner.pos, 2); + }); + }); + + describe('when the RegExp does not match', function () { + it('returns the entire string', function () { + var match = scanner.scanUntil(/z/); + assert.equal(match, scanner.string); + assert(scanner.eos()); + }); + }); + }); // scanUntil + }); // for a non-empty string +}); diff --git a/coder-base/node_modules_orig/mustache/test/writer-test.js b/coder-base/node_modules_orig/mustache/test/writer-test.js new file mode 100755 index 00000000..db2813a5 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/test/writer-test.js @@ -0,0 +1,43 @@ +require('./helper'); +var Writer = Mustache.Writer; + +describe('A new Mustache.Writer', function () { + var writer; + beforeEach(function () { + writer = new Writer; + }); + + it('loads partials correctly', function () { + var partial = 'The content of the partial.'; + var result = writer.render('{{>partial}}', {}, function (name) { + assert.equal(name, 'partial'); + return partial; + }); + + assert.equal(result, partial); + }); + + it('caches partials by content, not name', function () { + var result = writer.render('{{>partial}}', {}, { + partial: 'partial one' + }); + + assert.equal(result, 'partial one'); + + result = writer.render('{{>partial}}', {}, { + partial: 'partial two' + }); + + assert.equal(result, 'partial two'); + }); + + it('can compile an array of tokens', function () { + var template = 'Hello {{name}}!'; + var tokens = Mustache.parse(template); + var render = writer.compileTokens(tokens, template); + + var result = render({ name: 'Michael' }); + + assert.equal(result, 'Hello Michael!'); + }); +}); diff --git a/coder-base/node_modules_orig/mustache/wrappers/dojo/mustache.js.post b/coder-base/node_modules_orig/mustache/wrappers/dojo/mustache.js.post new file mode 100755 index 00000000..eeeb4b7f --- /dev/null +++ b/coder-base/node_modules_orig/mustache/wrappers/dojo/mustache.js.post @@ -0,0 +1,4 @@ + + dojox.mustache = dojo.hitch(Mustache, "render"); + +})(); \ No newline at end of file diff --git a/coder-base/node_modules_orig/mustache/wrappers/dojo/mustache.js.pre b/coder-base/node_modules_orig/mustache/wrappers/dojo/mustache.js.pre new file mode 100755 index 00000000..f87f3cd7 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/wrappers/dojo/mustache.js.pre @@ -0,0 +1,9 @@ +/* +Shameless port of a shameless port +@defunkt => @janl => @aq => @voodootikigod + +See http://github.com/defunkt/mustache for more info. +*/ + +dojo.provide("dojox.mustache._base"); +(function(){ diff --git a/coder-base/node_modules_orig/mustache/wrappers/jquery/mustache.js.post b/coder-base/node_modules_orig/mustache/wrappers/jquery/mustache.js.post new file mode 100755 index 00000000..d27d7301 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/wrappers/jquery/mustache.js.post @@ -0,0 +1,14 @@ + + $.mustache = function (template, view, partials) { + return Mustache.render(template, view, partials); + }; + + $.fn.mustache = function (view, partials) { + return $(this).map(function (i, elm) { + var template = $(elm).html().trim(); + var output = $.mustache(template, view, partials); + return $(output).get(); + }); + }; + +})(jQuery); diff --git a/coder-base/node_modules_orig/mustache/wrappers/jquery/mustache.js.pre b/coder-base/node_modules_orig/mustache/wrappers/jquery/mustache.js.pre new file mode 100755 index 00000000..b4d8af5e --- /dev/null +++ b/coder-base/node_modules_orig/mustache/wrappers/jquery/mustache.js.pre @@ -0,0 +1,9 @@ +/* +Shameless port of a shameless port +@defunkt => @janl => @aq + +See http://github.com/defunkt/mustache for more info. +*/ + +;(function($) { + diff --git a/coder-base/node_modules_orig/mustache/wrappers/mootools/mustache.js.post b/coder-base/node_modules_orig/mustache/wrappers/mootools/mustache.js.post new file mode 100755 index 00000000..aa9b8fab --- /dev/null +++ b/coder-base/node_modules_orig/mustache/wrappers/mootools/mustache.js.post @@ -0,0 +1,5 @@ + + Object.implement('mustache', function(view, partials){ + return Mustache.render(view, this, partials); + }); +})(); diff --git a/coder-base/node_modules_orig/mustache/wrappers/mootools/mustache.js.pre b/coder-base/node_modules_orig/mustache/wrappers/mootools/mustache.js.pre new file mode 100755 index 00000000..9839f993 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/wrappers/mootools/mustache.js.pre @@ -0,0 +1,2 @@ +(function(){ + diff --git a/coder-base/node_modules_orig/mustache/wrappers/qooxdoo/mustache.js.post b/coder-base/node_modules_orig/mustache/wrappers/qooxdoo/mustache.js.post new file mode 100755 index 00000000..aba7af6a --- /dev/null +++ b/coder-base/node_modules_orig/mustache/wrappers/qooxdoo/mustache.js.post @@ -0,0 +1,9 @@ +/** + * Above is the original mustache code. + */ + +// EXPOSE qooxdoo variant +qx.bom.Template.version = Mustache.version; +qx.bom.Template.render = Mustache.render; + +})(); diff --git a/coder-base/node_modules_orig/mustache/wrappers/qooxdoo/mustache.js.pre b/coder-base/node_modules_orig/mustache/wrappers/qooxdoo/mustache.js.pre new file mode 100755 index 00000000..b51ccf99 --- /dev/null +++ b/coder-base/node_modules_orig/mustache/wrappers/qooxdoo/mustache.js.pre @@ -0,0 +1,134 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2012 1&1 Internet AG, Germany, http://www.1und1.de + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Martin Wittemann (martinwittemann) + + ====================================================================== + + This class contains code based on the following work: + + * Mustache.js version 0.5.1-dev + + Code: + https://github.com/janl/mustache.js + + Copyright: + (c) 2009 Chris Wanstrath (Ruby) + (c) 2010 Jan Lehnardt (JavaScript) + + License: + MIT: http://www.opensource.org/licenses/mit-license.php + + ---------------------------------------------------------------------- + + Copyright (c) 2009 Chris Wanstrath (Ruby) + Copyright (c) 2010 Jan Lehnardt (JavaScript) + + 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. + +************************************************************************ */ + +/** + * The is a template class which can be used for HTML templating. In fact, + * this is a wrapper for mustache.js which is a "framework-agnostic way to + * render logic-free views". + * + * Here is a basic example how to use it: + * Template: + *
+ * var template = "Hi, my name is {{name}}!";
+ * var view = {name: "qooxdoo"};
+ * qx.bom.Template.toHtml(template, view);
+ * // return "Hi, my name is qooxdoo!"
+ * 
+ * + * For further details, please visit the mustache.js documentation here: + * https://github.com/janl/mustache.js/blob/master/README.md + */ +qx.Bootstrap.define("qx.bom.Template", { + statics : { + /** Contains the mustache.js version. */ + version: null, + + /** + * Original and only template method of mustache.js. For further + * documentation, please visit https://github.com/janl/mustache.js + * + * @signature function(template, view, partials) + * @param template {String} The String containing the template. + * @param view {Object} The object holding the data to render. + * @param partials {Object} Object holding parts of a template. + * @return {String} The parsed template. + */ + render: null, + + + /** + * Helper method which provides you with a direct access to templates + * stored as HTML in the DOM. The DOM node with the given ID will be used + * as a template, parsed and a new DOM node will be returned containing the + * parsed data. Keep in mind to have only one root DOM element in the the + * template. + * + * @param id {String} The id of the HTML template in the DOM. + * @param view {Object} The object holding the data to render. + * @param partials {Object} Object holding parts of a template. + * @return {DomNode} A DOM element holding the parsed template data. + */ + get : function(id, view, partials) { + // get the content stored in the DOM + var template = document.getElementById(id); + var inner = template.innerHTML; + + // apply the view + inner = this.toHtml(inner, view, partials); + + // special case for text only conversion + if (inner.search(/<|>/) === -1) { + return inner; + } + + // create a helper to convert the string into DOM nodes + var helper = qx.bom.Element.create("div"); + helper.innerHTML = inner; + + return helper.children[0]; + } + } +}); + +(function() { + +/** + * Below is the original mustache.js code. Snapshot date is mentioned in + * the head of this file. + */ diff --git a/coder-base/node_modules_orig/redis/.npmignore b/coder-base/node_modules_orig/redis/.npmignore new file mode 100755 index 00000000..3c3629e6 --- /dev/null +++ b/coder-base/node_modules_orig/redis/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/coder-base/node_modules_orig/redis/README.md b/coder-base/node_modules_orig/redis/README.md new file mode 100755 index 00000000..46e7018c --- /dev/null +++ b/coder-base/node_modules_orig/redis/README.md @@ -0,0 +1,691 @@ +redis - a node.js redis client +=========================== + +This is a complete Redis client for node.js. It supports all Redis commands, including many recently added commands like EVAL from +experimental Redis server branches. + + +Install with: + + npm install redis + +Pieter Noordhuis has provided a binding to the official `hiredis` C library, which is non-blocking and fast. To use `hiredis`, do: + + npm install hiredis redis + +If `hiredis` is installed, `node_redis` will use it by default. Otherwise, a pure JavaScript parser will be used. + +If you use `hiredis`, be sure to rebuild it whenever you upgrade your version of node. There are mysterious failures that can +happen between node and native code modules after a node upgrade. + + +## Usage + +Simple example, included as `examples/simple.js`: + +```js + var redis = require("redis"), + client = redis.createClient(); + + // if you'd like to select database 3, instead of 0 (default), call + // client.select(3, function() { /* ... */ }); + + client.on("error", function (err) { + console.log("Error " + err); + }); + + client.set("string key", "string val", redis.print); + client.hset("hash key", "hashtest 1", "some value", redis.print); + client.hset(["hash key", "hashtest 2", "some other value"], redis.print); + client.hkeys("hash key", function (err, replies) { + console.log(replies.length + " replies:"); + replies.forEach(function (reply, i) { + console.log(" " + i + ": " + reply); + }); + client.quit(); + }); +``` + +This will display: + + mjr:~/work/node_redis (master)$ node example.js + Reply: OK + Reply: 0 + Reply: 0 + 2 replies: + 0: hashtest 1 + 1: hashtest 2 + mjr:~/work/node_redis (master)$ + + +## Performance + +Here are typical results of `multi_bench.js` which is similar to `redis-benchmark` from the Redis distribution. +It uses 50 concurrent connections with no pipelining. + +JavaScript parser: + + PING: 20000 ops 42283.30 ops/sec 0/5/1.182 + SET: 20000 ops 32948.93 ops/sec 1/7/1.515 + GET: 20000 ops 28694.40 ops/sec 0/9/1.740 + INCR: 20000 ops 39370.08 ops/sec 0/8/1.269 + LPUSH: 20000 ops 36429.87 ops/sec 0/8/1.370 + LRANGE (10 elements): 20000 ops 9891.20 ops/sec 1/9/5.048 + LRANGE (100 elements): 20000 ops 1384.56 ops/sec 10/91/36.072 + +hiredis parser: + + PING: 20000 ops 46189.38 ops/sec 1/4/1.082 + SET: 20000 ops 41237.11 ops/sec 0/6/1.210 + GET: 20000 ops 39682.54 ops/sec 1/7/1.257 + INCR: 20000 ops 40080.16 ops/sec 0/8/1.242 + LPUSH: 20000 ops 41152.26 ops/sec 0/3/1.212 + LRANGE (10 elements): 20000 ops 36563.07 ops/sec 1/8/1.363 + LRANGE (100 elements): 20000 ops 21834.06 ops/sec 0/9/2.287 + +The performance of `node_redis` improves dramatically with pipelining, which happens automatically in most normal programs. + + +### Sending Commands + +Each Redis command is exposed as a function on the `client` object. +All functions take either an `args` Array plus optional `callback` Function or +a variable number of individual arguments followed by an optional callback. +Here is an example of passing an array of arguments and a callback: + + client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {}); + +Here is that same call in the second style: + + client.mset("test keys 1", "test val 1", "test keys 2", "test val 2", function (err, res) {}); + +Note that in either form the `callback` is optional: + + client.set("some key", "some val"); + client.set(["some other key", "some val"]); + +If the key is missing, reply will be null (probably): + + client.get("missingkey", function(err, reply) { + // reply is null when the key is missing + console.log(reply); + }); + +For a list of Redis commands, see [Redis Command Reference](http://redis.io/commands) + +The commands can be specified in uppercase or lowercase for convenience. `client.get()` is the same as `client.GET()`. + +Minimal parsing is done on the replies. Commands that return a single line reply return JavaScript Strings, +integer replies return JavaScript Numbers, "bulk" replies return node Buffers, and "multi bulk" replies return a +JavaScript Array of node Buffers. `HGETALL` returns an Object with Buffers keyed by the hash keys. + +# API + +## Connection Events + +`client` will emit some events about the state of the connection to the Redis server. + +### "ready" + +`client` will emit `ready` a connection is established to the Redis server and the server reports +that it is ready to receive commands. Commands issued before the `ready` event are queued, +then replayed just before this event is emitted. + +### "connect" + +`client` will emit `connect` at the same time as it emits `ready` unless `client.options.no_ready_check` +is set. If this options is set, `connect` will be emitted when the stream is connected, and then +you are free to try to send commands. + +### "error" + +`client` will emit `error` when encountering an error connecting to the Redis server. + +Note that "error" is a special event type in node. If there are no listeners for an +"error" event, node will exit. This is usually what you want, but it can lead to some +cryptic error messages like this: + + mjr:~/work/node_redis (master)$ node example.js + + node.js:50 + throw e; + ^ + Error: ECONNREFUSED, Connection refused + at IOWatcher.callback (net:870:22) + at node.js:607:9 + +Not very useful in diagnosing the problem, but if your program isn't ready to handle this, +it is probably the right thing to just exit. + +`client` will also emit `error` if an exception is thrown inside of `node_redis` for whatever reason. +It would be nice to distinguish these two cases. + +### "end" + +`client` will emit `end` when an established Redis server connection has closed. + +### "drain" + +`client` will emit `drain` when the TCP connection to the Redis server has been buffering, but is now +writable. This event can be used to stream commands in to Redis and adapt to backpressure. Right now, +you need to check `client.command_queue.length` to decide when to reduce your send rate. Then you can +resume sending when you get `drain`. + +### "idle" + +`client` will emit `idle` when there are no outstanding commands that are awaiting a response. + +## redis.createClient(port, host, options) + +Create a new client connection. `port` defaults to `6379` and `host` defaults +to `127.0.0.1`. If you have `redis-server` running on the same computer as node, then the defaults for +port and host are probably fine. `options` in an object with the following possible properties: + +* `parser`: which Redis protocol reply parser to use. Defaults to `hiredis` if that module is installed. +This may also be set to `javascript`. +* `return_buffers`: defaults to `false`. If set to `true`, then all replies will be sent to callbacks as node Buffer +objects instead of JavaScript Strings. +* `detect_buffers`: default to `false`. If set to `true`, then replies will be sent to callbacks as node Buffer objects +if any of the input arguments to the original command were Buffer objects. +This option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to +every command on a client. +* `socket_nodelay`: defaults to `true`. Whether to call setNoDelay() on the TCP stream, which disables the +Nagle algorithm on the underlying socket. Setting this option to `false` can result in additional throughput at the +cost of more latency. Most applications will want this set to `true`. +* `no_ready_check`: defaults to `false`. When a connection is established to the Redis server, the server might still +be loading the database from disk. While loading, the server not respond to any commands. To work around this, +`node_redis` has a "ready check" which sends the `INFO` command to the server. The response from the `INFO` command +indicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event. +Setting `no_ready_check` to `true` will inhibit this check. +* `enable_offline_queue`: defaults to `true`. By default, if there is no active +connection to the redis server, commands are added to a queue and are executed +once the connection has been established. Setting `enable_offline_queue` to +`false` will disable this feature and the callback will be execute immediately +with an error, or an error will be thrown if no callback is specified. + +```js + var redis = require("redis"), + client = redis.createClient(null, null, {detect_buffers: true}); + + client.set("foo_rand000000000000", "OK"); + + // This will return a JavaScript String + client.get("foo_rand000000000000", function (err, reply) { + console.log(reply.toString()); // Will print `OK` + }); + + // This will return a Buffer since original key is specified as a Buffer + client.get(new Buffer("foo_rand000000000000"), function (err, reply) { + console.log(reply.toString()); // Will print `` + }); + client.end(); +``` + +`createClient()` returns a `RedisClient` object that is named `client` in all of the examples here. + +## client.auth(password, callback) + +When connecting to Redis servers that require authentication, the `AUTH` command must be sent as the +first command after connecting. This can be tricky to coordinate with reconnections, the ready check, +etc. To make this easier, `client.auth()` stashes `password` and will send it after each connection, +including reconnections. `callback` is invoked only once, after the response to the very first +`AUTH` command sent. +NOTE: Your call to `client.auth()` should not be inside the ready handler. If +you are doing this wrong, `client` will emit an error that looks +something like this `Error: Ready check failed: ERR operation not permitted`. + +## client.end() + +Forcibly close the connection to the Redis server. Note that this does not wait until all replies have been parsed. +If you want to exit cleanly, call `client.quit()` to send the `QUIT` command after you have handled all replies. + +This example closes the connection to the Redis server before the replies have been read. You probably don't +want to do this: + +```js + var redis = require("redis"), + client = redis.createClient(); + + client.set("foo_rand000000000000", "some fantastic value"); + client.get("foo_rand000000000000", function (err, reply) { + console.log(reply.toString()); + }); + client.end(); +``` + +`client.end()` is useful for timeout cases where something is stuck or taking too long and you want +to start over. + +## Friendlier hash commands + +Most Redis commands take a single String or an Array of Strings as arguments, and replies are sent back as a single String or an Array of Strings. +When dealing with hash values, there are a couple of useful exceptions to this. + +### client.hgetall(hash) + +The reply from an HGETALL command will be converted into a JavaScript Object by `node_redis`. That way you can interact +with the responses using JavaScript syntax. + +Example: + + client.hmset("hosts", "mjr", "1", "another", "23", "home", "1234"); + client.hgetall("hosts", function (err, obj) { + console.dir(obj); + }); + +Output: + + { mjr: '1', another: '23', home: '1234' } + +### client.hmset(hash, obj, [callback]) + +Multiple values in a hash can be set by supplying an object: + + client.HMSET(key2, { + "0123456789": "abcdefghij", // NOTE: the key and value must both be strings + "some manner of key": "a type of value" + }); + +The properties and values of this Object will be set as keys and values in the Redis hash. + +### client.hmset(hash, key1, val1, ... keyn, valn, [callback]) + +Multiple values may also be set by supplying a list: + + client.HMSET(key1, "0123456789", "abcdefghij", "some manner of key", "a type of value"); + + +## Publish / Subscribe + +Here is a simple example of the API for publish / subscribe. This program opens two +client connections, subscribes to a channel on one of them, and publishes to that +channel on the other: + +```js + var redis = require("redis"), + client1 = redis.createClient(), client2 = redis.createClient(), + msg_count = 0; + + client1.on("subscribe", function (channel, count) { + client2.publish("a nice channel", "I am sending a message."); + client2.publish("a nice channel", "I am sending a second message."); + client2.publish("a nice channel", "I am sending my last message."); + }); + + client1.on("message", function (channel, message) { + console.log("client1 channel " + channel + ": " + message); + msg_count += 1; + if (msg_count === 3) { + client1.unsubscribe(); + client1.end(); + client2.end(); + } + }); + + client1.incr("did a thing"); + client1.subscribe("a nice channel"); +``` + +When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into "pub/sub" mode. +At that point, only commands that modify the subscription set are valid. When the subscription +set is empty, the connection is put back into regular mode. + +If you need to send regular commands to Redis while in pub/sub mode, just open another connection. + +## Pub / Sub Events + +If a client has subscriptions active, it may emit these events: + +### "message" (channel, message) + +Client will emit `message` for every message received that matches an active subscription. +Listeners are passed the channel name as `channel` and the message Buffer as `message`. + +### "pmessage" (pattern, channel, message) + +Client will emit `pmessage` for every message received that matches an active subscription pattern. +Listeners are passed the original pattern used with `PSUBSCRIBE` as `pattern`, the sending channel +name as `channel`, and the message Buffer as `message`. + +### "subscribe" (channel, count) + +Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are passed the +channel name as `channel` and the new count of subscriptions for this client as `count`. + +### "psubscribe" (pattern, count) + +Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners are passed the +original pattern as `pattern`, and the new count of subscriptions for this client as `count`. + +### "unsubscribe" (channel, count) + +Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners are passed the +channel name as `channel` and the new count of subscriptions for this client as `count`. When +`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted. + +### "punsubscribe" (pattern, count) + +Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command. Listeners are passed the +channel name as `channel` and the new count of subscriptions for this client as `count`. When +`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted. + +## client.multi([commands]) + +`MULTI` commands are queued up until an `EXEC` is issued, and then all commands are run atomically by +Redis. The interface in `node_redis` is to return an individual `Multi` object by calling `client.multi()`. + +```js + var redis = require("./index"), + client = redis.createClient(), set_size = 20; + + client.sadd("bigset", "a member"); + client.sadd("bigset", "another member"); + + while (set_size > 0) { + client.sadd("bigset", "member " + set_size); + set_size -= 1; + } + + // multi chain with an individual callback + client.multi() + .scard("bigset") + .smembers("bigset") + .keys("*", function (err, replies) { + // NOTE: code in this callback is NOT atomic + // this only happens after the the .exec call finishes. + client.mget(replies, redis.print); + }) + .dbsize() + .exec(function (err, replies) { + console.log("MULTI got " + replies.length + " replies"); + replies.forEach(function (reply, index) { + console.log("Reply " + index + ": " + reply.toString()); + }); + }); +``` + +`client.multi()` is a constructor that returns a `Multi` object. `Multi` objects share all of the +same command methods as `client` objects do. Commands are queued up inside the `Multi` object +until `Multi.exec()` is invoked. + +You can either chain together `MULTI` commands as in the above example, or you can queue individual +commands while still sending regular client command as in this example: + +```js + var redis = require("redis"), + client = redis.createClient(), multi; + + // start a separate multi command queue + multi = client.multi(); + multi.incr("incr thing", redis.print); + multi.incr("incr other thing", redis.print); + + // runs immediately + client.mset("incr thing", 100, "incr other thing", 1, redis.print); + + // drains multi queue and runs atomically + multi.exec(function (err, replies) { + console.log(replies); // 101, 2 + }); + + // you can re-run the same transaction if you like + multi.exec(function (err, replies) { + console.log(replies); // 102, 3 + client.quit(); + }); +``` + +In addition to adding commands to the `MULTI` queue individually, you can also pass an array +of commands and arguments to the constructor: + +```js + var redis = require("redis"), + client = redis.createClient(), multi; + + client.multi([ + ["mget", "multifoo", "multibar", redis.print], + ["incr", "multifoo"], + ["incr", "multibar"] + ]).exec(function (err, replies) { + console.log(replies); + }); +``` + + +## Monitor mode + +Redis supports the `MONITOR` command, which lets you see all commands received by the Redis server +across all client connections, including from other client libraries and other computers. + +After you send the `MONITOR` command, no other commands are valid on that connection. `node_redis` +will emit a `monitor` event for every new monitor message that comes across. The callback for the +`monitor` event takes a timestamp from the Redis server and an array of command arguments. + +Here is a simple example: + +```js + var client = require("redis").createClient(), + util = require("util"); + + client.monitor(function (err, res) { + console.log("Entering monitoring mode."); + }); + + client.on("monitor", function (time, args) { + console.log(time + ": " + util.inspect(args)); + }); +``` + +# Extras + +Some other things you might like to know about. + +## client.server_info + +After the ready probe completes, the results from the INFO command are saved in the `client.server_info` +object. + +The `versions` key contains an array of the elements of the version string for easy comparison. + + > client.server_info.redis_version + '2.3.0' + > client.server_info.versions + [ 2, 3, 0 ] + +## redis.print() + +A handy callback function for displaying return values when testing. Example: + +```js + var redis = require("redis"), + client = redis.createClient(); + + client.on("connect", function () { + client.set("foo_rand000000000000", "some fantastic value", redis.print); + client.get("foo_rand000000000000", redis.print); + }); +``` + +This will print: + + Reply: OK + Reply: some fantastic value + +Note that this program will not exit cleanly because the client is still connected. + +## redis.debug_mode + +Boolean to enable debug mode and protocol tracing. + +```js + var redis = require("redis"), + client = redis.createClient(); + + redis.debug_mode = true; + + client.on("connect", function () { + client.set("foo_rand000000000000", "some fantastic value"); + }); +``` + +This will display: + + mjr:~/work/node_redis (master)$ node ~/example.js + send command: *3 + $3 + SET + $20 + foo_rand000000000000 + $20 + some fantastic value + + on_data: +OK + +`send command` is data sent into Redis and `on_data` is data received from Redis. + +## client.send_command(command_name, args, callback) + +Used internally to send commands to Redis. For convenience, nearly all commands that are published on the Redis +Wiki have been added to the `client` object. However, if I missed any, or if new commands are introduced before +this library is updated, you can use `send_command()` to send arbitrary commands to Redis. + +All commands are sent as multi-bulk commands. `args` can either be an Array of arguments, or omitted. + +## client.connected + +Boolean tracking the state of the connection to the Redis server. + +## client.command_queue.length + +The number of commands that have been sent to the Redis server but not yet replied to. You can use this to +enforce some kind of maximum queue depth for commands while connected. + +Don't mess with `client.command_queue` though unless you really know what you are doing. + +## client.offline_queue.length + +The number of commands that have been queued up for a future connection. You can use this to enforce +some kind of maximum queue depth for pre-connection commands. + +## client.retry_delay + +Current delay in milliseconds before a connection retry will be attempted. This starts at `250`. + +## client.retry_backoff + +Multiplier for future retry timeouts. This should be larger than 1 to add more time between retries. +Defaults to 1.7. The default initial connection retry is 250, so the second retry will be 425, followed by 723.5, etc. + +### Commands with Optional and Keyword arguments + +This applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset count]` in the [redis.io/commands](http://redis.io/commands) documentation. + +Example: +```js +var args = [ 'myzset', 1, 'one', 2, 'two', 3, 'three', 99, 'ninety-nine' ]; +client.zadd(args, function (err, response) { + if (err) throw err; + console.log('added '+response+' items.'); + + // -Infinity and +Infinity also work + var args1 = [ 'myzset', '+inf', '-inf' ]; + client.zrevrangebyscore(args1, function (err, response) { + if (err) throw err; + console.log('example1', response); + // write your code here + }); + + var max = 3, min = 1, offset = 1, count = 2; + var args2 = [ 'myzset', max, min, 'WITHSCORES', 'LIMIT', offset, count ]; + client.zrevrangebyscore(args2, function (err, response) { + if (err) throw err; + console.log('example2', response); + // write your code here + }); +}); +``` + +## TODO + +Better tests for auth, disconnect/reconnect, and all combinations thereof. + +Stream large set/get values into and out of Redis. Otherwise the entire value must be in node's memory. + +Performance can be better for very large values. + +I think there are more performance improvements left in there for smaller values, especially for large lists of small values. + +## How to Contribute +- open a pull request and then wait for feedback (if + [DTrejo](http://github.com/dtrejo) does not get back to you within 2 days, + comment again with indignation!) + +## Contributors +Some people have have added features and fixed bugs in `node_redis` other than me. + +Ordered by date of first contribution. +[Auto-generated](http://github.com/dtrejo/node-authors) on Wed Jul 25 2012 19:14:59 GMT-0700 (PDT). + +- [Matt Ranney aka `mranney`](https://github.com/mranney) +- [Tim-Smart aka `tim-smart`](https://github.com/tim-smart) +- [Tj Holowaychuk aka `visionmedia`](https://github.com/visionmedia) +- [rick aka `technoweenie`](https://github.com/technoweenie) +- [Orion Henry aka `orionz`](https://github.com/orionz) +- [Aivo Paas aka `aivopaas`](https://github.com/aivopaas) +- [Hank Sims aka `hanksims`](https://github.com/hanksims) +- [Paul Carey aka `paulcarey`](https://github.com/paulcarey) +- [Pieter Noordhuis aka `pietern`](https://github.com/pietern) +- [nithesh aka `nithesh`](https://github.com/nithesh) +- [Andy Ray aka `andy2ray`](https://github.com/andy2ray) +- [unknown aka `unknowdna`](https://github.com/unknowdna) +- [Dave Hoover aka `redsquirrel`](https://github.com/redsquirrel) +- [Vladimir Dronnikov aka `dvv`](https://github.com/dvv) +- [Umair Siddique aka `umairsiddique`](https://github.com/umairsiddique) +- [Louis-Philippe Perron aka `lp`](https://github.com/lp) +- [Mark Dawson aka `markdaws`](https://github.com/markdaws) +- [Ian Babrou aka `bobrik`](https://github.com/bobrik) +- [Felix Geisendörfer aka `felixge`](https://github.com/felixge) +- [Jean-Hugues Pinson aka `undefined`](https://github.com/undefined) +- [Maksim Lin aka `maks`](https://github.com/maks) +- [Owen Smith aka `orls`](https://github.com/orls) +- [Zachary Scott aka `zzak`](https://github.com/zzak) +- [TEHEK Firefox aka `TEHEK`](https://github.com/TEHEK) +- [Isaac Z. Schlueter aka `isaacs`](https://github.com/isaacs) +- [David Trejo aka `DTrejo`](https://github.com/DTrejo) +- [Brian Noguchi aka `bnoguchi`](https://github.com/bnoguchi) +- [Philip Tellis aka `bluesmoon`](https://github.com/bluesmoon) +- [Marcus Westin aka `marcuswestin2`](https://github.com/marcuswestin2) +- [Jed Schmidt aka `jed`](https://github.com/jed) +- [Dave Peticolas aka `jdavisp3`](https://github.com/jdavisp3) +- [Trae Robrock aka `trobrock`](https://github.com/trobrock) +- [Shankar Karuppiah aka `shankar0306`](https://github.com/shankar0306) +- [Ignacio Burgueño aka `ignacio`](https://github.com/ignacio) + +Thanks. + +## LICENSE - "MIT License" + +Copyright (c) 2010 Matthew Ranney, http://ranney.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. + +![spacer](http://ranney.com/1px.gif) diff --git a/coder-base/node_modules_orig/redis/benches/buffer_bench.js b/coder-base/node_modules_orig/redis/benches/buffer_bench.js new file mode 100755 index 00000000..a504fbc0 --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/buffer_bench.js @@ -0,0 +1,89 @@ +var source = new Buffer(100), + dest = new Buffer(100), i, j, k, tmp, count = 1000000, bytes = 100; + +for (i = 99 ; i >= 0 ; i--) { + source[i] = 120; +} + +var str = "This is a nice String.", + buf = new Buffer("This is a lovely Buffer."); + +var start = new Date(); +for (i = count * 100; i > 0 ; i--) { + if (Buffer.isBuffer(str)) {} +} +var end = new Date(); +console.log("Buffer.isBuffer(str) " + (end - start) + " ms"); + +var start = new Date(); +for (i = count * 100; i > 0 ; i--) { + if (Buffer.isBuffer(buf)) {} +} +var end = new Date(); +console.log("Buffer.isBuffer(buf) " + (end - start) + " ms"); + +var start = new Date(); +for (i = count * 100; i > 0 ; i--) { + if (str instanceof Buffer) {} +} +var end = new Date(); +console.log("str instanceof Buffer " + (end - start) + " ms"); + +var start = new Date(); +for (i = count * 100; i > 0 ; i--) { + if (buf instanceof Buffer) {} +} +var end = new Date(); +console.log("buf instanceof Buffer " + (end - start) + " ms"); + +for (i = bytes ; i > 0 ; i --) { + var start = new Date(); + for (j = count ; j > 0; j--) { + tmp = source.toString("ascii", 0, bytes); + } + var end = new Date(); + console.log("toString() " + i + " bytes " + (end - start) + " ms"); +} + +for (i = bytes ; i > 0 ; i --) { + var start = new Date(); + for (j = count ; j > 0; j--) { + tmp = ""; + for (k = 0; k <= i ; k++) { + tmp += String.fromCharCode(source[k]); + } + } + var end = new Date(); + console.log("manual string " + i + " bytes " + (end - start) + " ms"); +} + +for (i = bytes ; i > 0 ; i--) { + var start = new Date(); + for (j = count ; j > 0 ; j--) { + for (k = i ; k > 0 ; k--) { + dest[k] = source[k]; + } + } + var end = new Date(); + console.log("Manual copy " + i + " bytes " + (end - start) + " ms"); +} + +for (i = bytes ; i > 0 ; i--) { + var start = new Date(); + for (j = count ; j > 0 ; j--) { + for (k = i ; k > 0 ; k--) { + dest[k] = 120; + } + } + var end = new Date(); + console.log("Direct assignment " + i + " bytes " + (end - start) + " ms"); +} + +for (i = bytes ; i > 0 ; i--) { + var start = new Date(); + for (j = count ; j > 0 ; j--) { + source.copy(dest, 0, 0, i); + } + var end = new Date(); + console.log("Buffer.copy() " + i + " bytes " + (end - start) + " ms"); +} diff --git a/coder-base/node_modules_orig/redis/benches/hiredis_parser.js b/coder-base/node_modules_orig/redis/benches/hiredis_parser.js new file mode 100755 index 00000000..f1515b11 --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/hiredis_parser.js @@ -0,0 +1,38 @@ +var Parser = require('../lib/parser/hiredis').Parser; +var assert = require('assert'); + +/* +This test makes sure that exceptions thrown inside of "reply" event handlers +are not trapped and mistakenly emitted as parse errors. +*/ +(function testExecuteDoesNotCatchReplyCallbackExceptions() { + var parser = new Parser(); + var replies = [{}]; + + parser.reader = { + feed: function() {}, + get: function() { + return replies.shift(); + } + }; + + var emittedError = false; + var caughtException = false; + + parser + .on('error', function() { + emittedError = true; + }) + .on('reply', function() { + throw new Error('bad'); + }); + + try { + parser.execute(); + } catch (err) { + caughtException = true; + } + + assert.equal(caughtException, true); + assert.equal(emittedError, false); +})(); diff --git a/coder-base/node_modules_orig/redis/benches/re_sub_test.js b/coder-base/node_modules_orig/redis/benches/re_sub_test.js new file mode 100755 index 00000000..64b8f312 --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/re_sub_test.js @@ -0,0 +1,14 @@ +var client = require('../index').createClient() + , client2 = require('../index').createClient() + , assert = require('assert'); + +client.once('subscribe', function (channel, count) { + client.unsubscribe('x'); + client.subscribe('x', function () { + client.quit(); + client2.quit(); + }); + client2.publish('x', 'hi'); +}); + +client.subscribe('x'); diff --git a/coder-base/node_modules_orig/redis/benches/reconnect_test.js b/coder-base/node_modules_orig/redis/benches/reconnect_test.js new file mode 100755 index 00000000..7abdd516 --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/reconnect_test.js @@ -0,0 +1,29 @@ +var redis = require("../index").createClient(null, null, { +// max_attempts: 4 +}); + +redis.on("error", function (err) { + console.log("Redis says: " + err); +}); + +redis.on("ready", function () { + console.log("Redis ready."); +}); + +redis.on("reconnecting", function (arg) { + console.log("Redis reconnecting: " + JSON.stringify(arg)); +}); +redis.on("connect", function () { + console.log("Redis connected."); +}); + +setInterval(function () { + var now = Date.now(); + redis.set("now", now, function (err, res) { + if (err) { + console.log(now + " Redis reply error: " + err); + } else { + console.log(now + " Redis reply: " + res); + } + }); +}, 100); diff --git a/coder-base/node_modules_orig/redis/benches/stress/codec.js b/coder-base/node_modules_orig/redis/benches/stress/codec.js new file mode 100755 index 00000000..7d764f60 --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/stress/codec.js @@ -0,0 +1,16 @@ +var json = { + encode: JSON.stringify, + decode: JSON.parse +}; + +var MsgPack = require('node-msgpack'); +msgpack = { + encode: MsgPack.pack, + decode: function(str) { return MsgPack.unpack(new Buffer(str)); } +}; + +bison = require('bison'); + +module.exports = json; +//module.exports = msgpack; +//module.exports = bison; diff --git a/coder-base/node_modules_orig/redis/benches/stress/pubsub/pub.js b/coder-base/node_modules_orig/redis/benches/stress/pubsub/pub.js new file mode 100755 index 00000000..0acde7a6 --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/stress/pubsub/pub.js @@ -0,0 +1,38 @@ +'use strict'; + +var freemem = require('os').freemem; +var profiler = require('v8-profiler'); +var codec = require('../codec'); + +var sent = 0; + +var pub = require('redis').createClient(null, null, { + //command_queue_high_water: 5, + //command_queue_low_water: 1 +}) +.on('ready', function() { + this.emit('drain'); +}) +.on('drain', function() { + process.nextTick(exec); +}); + +var payload = '1'; for (var i = 0; i < 12; ++i) payload += payload; +console.log('Message payload length', payload.length); + +function exec() { + pub.publish('timeline', codec.encode({ foo: payload })); + ++sent; + if (!pub.should_buffer) { + process.nextTick(exec); + } +} + +profiler.takeSnapshot('s_0'); + +exec(); + +setInterval(function() { + profiler.takeSnapshot('s_' + sent); + console.error('sent', sent, 'free', freemem(), 'cmdqlen', pub.command_queue.length, 'offqlen', pub.offline_queue.length); +}, 2000); diff --git a/coder-base/node_modules_orig/redis/benches/stress/pubsub/run b/coder-base/node_modules_orig/redis/benches/stress/pubsub/run new file mode 100755 index 00000000..bd9ac392 --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/stress/pubsub/run @@ -0,0 +1,10 @@ +#!/bin/sh +node server.js & +node server.js & +node server.js & +node server.js & +node server.js & +node server.js & +node server.js & +node server.js & +node --debug pub.js diff --git a/coder-base/node_modules_orig/redis/benches/stress/pubsub/server.js b/coder-base/node_modules_orig/redis/benches/stress/pubsub/server.js new file mode 100755 index 00000000..035e6b74 --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/stress/pubsub/server.js @@ -0,0 +1,23 @@ +'use strict'; + +var freemem = require('os').freemem; +var codec = require('../codec'); + +var id = Math.random(); +var recv = 0; + +var sub = require('redis').createClient() + .on('ready', function() { + this.subscribe('timeline'); + }) + .on('message', function(channel, message) { + var self = this; + if (message) { + message = codec.decode(message); + ++recv; + } + }); + +setInterval(function() { + console.error('id', id, 'received', recv, 'free', freemem()); +}, 2000); diff --git a/coder-base/node_modules_orig/redis/benches/stress/rpushblpop/pub.js b/coder-base/node_modules_orig/redis/benches/stress/rpushblpop/pub.js new file mode 100755 index 00000000..9caf1d0b --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/stress/rpushblpop/pub.js @@ -0,0 +1,49 @@ +'use strict'; + +var freemem = require('os').freemem; +//var profiler = require('v8-profiler'); +var codec = require('../codec'); + +var sent = 0; + +var pub = require('redis').createClient(null, null, { + //command_queue_high_water: 5, + //command_queue_low_water: 1 +}) +.on('ready', function() { + this.del('timeline'); + this.emit('drain'); +}) +.on('drain', function() { + process.nextTick(exec); +}); + +var payload = '1'; for (var i = 0; i < 12; ++i) payload += payload; +console.log('Message payload length', payload.length); + +function exec() { + pub.rpush('timeline', codec.encode({ foo: payload })); + ++sent; + if (!pub.should_buffer) { + process.nextTick(exec); + } +} + +//profiler.takeSnapshot('s_0'); + +exec(); + +setInterval(function() { + //var ss = profiler.takeSnapshot('s_' + sent); + //console.error(ss.stringify()); + pub.llen('timeline', function(err, result) { + console.error('sent', sent, 'free', freemem(), + 'cmdqlen', pub.command_queue.length, 'offqlen', pub.offline_queue.length, + 'llen', result + ); + }); +}, 2000); + +/*setTimeout(function() { + process.exit(); +}, 30000);*/ diff --git a/coder-base/node_modules_orig/redis/benches/stress/rpushblpop/run b/coder-base/node_modules_orig/redis/benches/stress/rpushblpop/run new file mode 100755 index 00000000..8045ae80 --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/stress/rpushblpop/run @@ -0,0 +1,6 @@ +#!/bin/sh +node server.js & +#node server.js & +#node server.js & +#node server.js & +node --debug pub.js diff --git a/coder-base/node_modules_orig/redis/benches/stress/rpushblpop/server.js b/coder-base/node_modules_orig/redis/benches/stress/rpushblpop/server.js new file mode 100755 index 00000000..9cbcdd9e --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/stress/rpushblpop/server.js @@ -0,0 +1,30 @@ +'use strict'; + +var freemem = require('os').freemem; +var codec = require('../codec'); + +var id = Math.random(); +var recv = 0; + +var cmd = require('redis').createClient(); +var sub = require('redis').createClient() + .on('ready', function() { + this.emit('timeline'); + }) + .on('timeline', function() { + var self = this; + this.blpop('timeline', 0, function(err, result) { + var message = result[1]; + if (message) { + message = codec.decode(message); + ++recv; + } + self.emit('timeline'); + }); + }); + +setInterval(function() { + cmd.llen('timeline', function(err, result) { + console.error('id', id, 'received', recv, 'free', freemem(), 'llen', result); + }); +}, 2000); diff --git a/coder-base/node_modules_orig/redis/benches/stress/speed/00 b/coder-base/node_modules_orig/redis/benches/stress/speed/00 new file mode 100755 index 00000000..29d7bf7c --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/stress/speed/00 @@ -0,0 +1,13 @@ +# size JSON msgpack bison +26602 2151.0170848180414 +25542 ? 2842.589272665782 +24835 ? ? 7280.4538397469805 +6104 6985.234528557929 +5045 ? 7217.461392841478 +4341 ? ? 14261.406335354604 +4180 15864.633685636572 +4143 ? 12954.806235781925 +4141 ? ? 44650.70733912719 +75 114227.07313350472 +40 ? 30162.440062810834 +39 ? ? 119815.66013519121 diff --git a/coder-base/node_modules_orig/redis/benches/stress/speed/plot b/coder-base/node_modules_orig/redis/benches/stress/speed/plot new file mode 100755 index 00000000..2563797c --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/stress/speed/plot @@ -0,0 +1,13 @@ +#!/bin/sh + +gnuplot >size-rate.jpg << _EOF_ + +set terminal png nocrop enhanced font verdana 12 size 640,480 +set logscale x +set logscale y +set grid +set xlabel 'Serialized object size, octets' +set ylabel 'decode(encode(obj)) rate, 1/sec' +plot '00' using 1:2 title 'json' smooth bezier, '00' using 1:3 title 'msgpack' smooth bezier, '00' using 1:4 title 'bison' smooth bezier + +_EOF_ diff --git a/coder-base/node_modules_orig/redis/benches/stress/speed/size-rate.png b/coder-base/node_modules_orig/redis/benches/stress/speed/size-rate.png new file mode 100755 index 0000000000000000000000000000000000000000..c9c2bee6b076040ccf7e6bc337c307732c400463 GIT binary patch literal 6672 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 H#^C-7XAtZ( literal 0 HcmV?d00001 diff --git a/coder-base/node_modules_orig/redis/benches/stress/speed/speed.js b/coder-base/node_modules_orig/redis/benches/stress/speed/speed.js new file mode 100755 index 00000000..8e43cbc0 --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/stress/speed/speed.js @@ -0,0 +1,84 @@ +var msgpack = require('node-msgpack'); +var bison = require('bison'); +var codec = { + JSON: { + encode: JSON.stringify, + decode: JSON.parse + }, + msgpack: { + encode: msgpack.pack, + decode: msgpack.unpack + }, + bison: bison +}; + +var obj, l; + +var s = '0'; +for (var i = 0; i < 12; ++i) s += s; + +obj = { + foo: s, + arrrrrr: [{a:1,b:false,c:null,d:1.0}, 1111, 2222, 33333333], + rand: [], + a: s, + ccc: s, + b: s + s + s +}; +for (i = 0; i < 100; ++i) obj.rand.push(Math.random()); +forObj(obj); + +obj = { + foo: s, + arrrrrr: [{a:1,b:false,c:null,d:1.0}, 1111, 2222, 33333333], + rand: [] +}; +for (i = 0; i < 100; ++i) obj.rand.push(Math.random()); +forObj(obj); + +obj = { + foo: s, + arrrrrr: [{a:1,b:false,c:null,d:1.0}, 1111, 2222, 33333333], + rand: [] +}; +forObj(obj); + +obj = { + arrrrrr: [{a:1,b:false,c:null,d:1.0}, 1111, 2222, 33333333], + rand: [] +}; +forObj(obj); + +function run(obj, codec) { + var t1 = Date.now(); + var n = 10000; + for (var i = 0; i < n; ++i) { + codec.decode(l = codec.encode(obj)); + } + var t2 = Date.now(); + //console.log('DONE', n*1000/(t2-t1), 'codecs/sec, length=', l.length); + return [n*1000/(t2-t1), l.length]; +} + +function series(obj, cname, n) { + var rate = 0; + var len = 0; + for (var i = 0; i < n; ++i) { + var r = run(obj, codec[cname]); + rate += r[0]; + len += r[1]; + } + rate /= n; + len /= n; + console.log(cname + ' ' + rate + ' ' + len); + return [rate, len]; +} + +function forObj(obj) { + var r = { + JSON: series(obj, 'JSON', 20), + msgpack: series(obj, 'msgpack', 20), + bison: series(obj, 'bison', 20) + }; + return r; +} diff --git a/coder-base/node_modules_orig/redis/benches/sub_quit_test.js b/coder-base/node_modules_orig/redis/benches/sub_quit_test.js new file mode 100755 index 00000000..ad1f4132 --- /dev/null +++ b/coder-base/node_modules_orig/redis/benches/sub_quit_test.js @@ -0,0 +1,18 @@ +var client = require("redis").createClient(), + client2 = require("redis").createClient(); + +client.subscribe("something"); +client.on("subscribe", function (channel, count) { + console.log("Got sub: " + channel); + client.unsubscribe("something"); +}); + +client.on("unsubscribe", function (channel, count) { + console.log("Got unsub: " + channel + ", quitting"); + client.quit(); +}); + +// exercise unsub before sub +client2.unsubscribe("something"); +client2.subscribe("another thing"); +client2.quit(); diff --git a/coder-base/node_modules_orig/redis/changelog.md b/coder-base/node_modules_orig/redis/changelog.md new file mode 100755 index 00000000..e4e3277b --- /dev/null +++ b/coder-base/node_modules_orig/redis/changelog.md @@ -0,0 +1,240 @@ +Changelog +========= + +## v0.8.2 - November 11, 2012 + +Another version bump because 0.8.1 didn't get applied properly for some mysterious reason. +Sorry about that. + +Changed name of "faster" parser to "javascript". + +## v0.8.1 - September 11, 2012 + +Important bug fix for null responses (Jerry Sievert) + +## v0.8.0 - September 10, 2012 + +Many contributed features and fixes, including: + +* Pure JavaScript reply parser that is usually faster than hiredis (Jerry Sievert) +* Remove hiredis as optionalDependency from package.json. It still works if you want it. +* Restore client state on reconnect, including select, subscribe, and monitor. (Ignacio Burgueño) +* Fix idle event (Trae Robrock) +* Many documentation improvements and bug fixes (David Trejo) + +## v0.7.2 - April 29, 2012 + +Many contributed fixes. Thank you, contributors. + +* [GH-190] - pub/sub mode fix (Brian Noguchi) +* [GH-165] - parser selection fix (TEHEK) +* numerous documentation and examples updates +* auth errors emit Errors instead of Strings (David Trejo) + +## v0.7.1 - November 15, 2011 + +Fix regression in reconnect logic. + +Very much need automated tests for reconnection and queue logic. + +## v0.7.0 - November 14, 2011 + +Many contributed fixes. Thanks everybody. + +* [GH-127] - properly re-initialize parser on reconnect +* [GH-136] - handle passing undefined as callback (Ian Babrou) +* [GH-139] - properly handle exceptions thrown in pub/sub event handlers (Felix Geisendörfer) +* [GH-141] - detect closing state on stream error (Felix Geisendörfer) +* [GH-142] - re-select database on reconnection (Jean-Hugues Pinson) +* [GH-146] - add sort example (Maksim Lin) + +Some more goodies: + +* Fix bugs with node 0.6 +* Performance improvements +* New version of `multi_bench.js` that tests more realistic scenarios +* [GH-140] - support optional callback for subscribe commands +* Properly flush and error out command queue when connection fails +* Initial work on reconnection thresholds + +## v0.6.7 - July 30, 2011 + +(accidentally skipped v0.6.6) + +Fix and test for [GH-123] + +Passing an Array as as the last argument should expand as users +expect. The old behavior was to coerce the arguments into Strings, +which did surprising things with Arrays. + +## v0.6.5 - July 6, 2011 + +Contributed changes: + +* Support SlowBuffers (Umair Siddique) +* Add Multi to exports (Louis-Philippe Perron) +* Fix for drain event calculation (Vladimir Dronnikov) + +Thanks! + +## v0.6.4 - June 30, 2011 + +Fix bug with optional callbacks for hmset. + +## v0.6.2 - June 30, 2011 + +Bugs fixed: + +* authentication retry while server is loading db (danmaz74) [GH-101] +* command arguments processing issue with arrays + +New features: + +* Auto update of new commands from redis.io (Dave Hoover) +* Performance improvements and backpressure controls. +* Commands now return the true/false value from the underlying socket write(s). +* Implement command_queue high water and low water for more better control of queueing. + +See `examples/backpressure_drain.js` for more information. + +## v0.6.1 - June 29, 2011 + +Add support and tests for Redis scripting through EXEC command. + +Bug fix for monitor mode. (forddg) + +Auto update of new commands from redis.io (Dave Hoover) + +## v0.6.0 - April 21, 2011 + +Lots of bugs fixed. + +* connection error did not properly trigger reconnection logic [GH-85] +* client.hmget(key, [val1, val2]) was not expanding properly [GH-66] +* client.quit() while in pub/sub mode would throw an error [GH-87] +* client.multi(['hmset', 'key', {foo: 'bar'}]) fails [GH-92] +* unsubscribe before subscribe would make things very confused [GH-88] +* Add BRPOPLPUSH [GH-79] + +## v0.5.11 - April 7, 2011 + +Added DISCARD + +I originally didn't think DISCARD would do anything here because of the clever MULTI interface, but somebody +pointed out to me that DISCARD can be used to flush the WATCH set. + +## v0.5.10 - April 6, 2011 + +Added HVALS + +## v0.5.9 - March 14, 2011 + +Fix bug with empty Array arguments - Andy Ray + +## v0.5.8 - March 14, 2011 + +Add `MONITOR` command and special monitor command reply parsing. + +## v0.5.7 - February 27, 2011 + +Add magical auth command. + +Authentication is now remembered by the client and will be automatically sent to the server +on every connection, including any reconnections. + +## v0.5.6 - February 22, 2011 + +Fix bug in ready check with `return_buffers` set to `true`. + +Thanks to Dean Mao and Austin Chau. + +## v0.5.5 - February 16, 2011 + +Add probe for server readiness. + +When a Redis server starts up, it might take a while to load the dataset into memory. +During this time, the server will accept connections, but will return errors for all non-INFO +commands. Now node_redis will send an INFO command whenever it connects to a server. +If the info command indicates that the server is not ready, the client will keep trying until +the server is ready. Once it is ready, the client will emit a "ready" event as well as the +"connect" event. The client will queue up all commands sent before the server is ready, just +like it did before. When the server is ready, all offline/non-ready commands will be replayed. +This should be backward compatible with previous versions. + +To disable this ready check behavior, set `options.no_ready_check` when creating the client. + +As a side effect of this change, the key/val params from the info command are available as +`client.server_options`. Further, the version string is decomposed into individual elements +in `client.server_options.versions`. + +## v0.5.4 - February 11, 2011 + +Fix excess memory consumption from Queue backing store. + +Thanks to Gustaf Sjöberg. + +## v0.5.3 - February 5, 2011 + +Fix multi/exec error reply callback logic. + +Thanks to Stella Laurenzo. + +## v0.5.2 - January 18, 2011 + +Fix bug where unhandled error replies confuse the parser. + +## v0.5.1 - January 18, 2011 + +Fix bug where subscribe commands would not handle redis-server startup error properly. + +## v0.5.0 - December 29, 2010 + +Some bug fixes: + +* An important bug fix in reconnection logic. Previously, reply callbacks would be invoked twice after + a reconnect. +* Changed error callback argument to be an actual Error object. + +New feature: + +* Add friendly syntax for HMSET using an object. + +## v0.4.1 - December 8, 2010 + +Remove warning about missing hiredis. You probably do want it though. + +## v0.4.0 - December 5, 2010 + +Support for multiple response parsers and hiredis C library from Pieter Noordhuis. +Return Strings instead of Buffers by default. +Empty nested mb reply bug fix. + +## v0.3.9 - November 30, 2010 + +Fix parser bug on failed EXECs. + +## v0.3.8 - November 10, 2010 + +Fix for null MULTI response when WATCH condition fails. + +## v0.3.7 - November 9, 2010 + +Add "drain" and "idle" events. + +## v0.3.6 - November 3, 2010 + +Add all known Redis commands from Redis master, even ones that are coming in 2.2 and beyond. + +Send a friendlier "error" event message on stream errors like connection refused / reset. + +## v0.3.5 - October 21, 2010 + +A few bug fixes. + +* Fixed bug with `nil` multi-bulk reply lengths that showed up with `BLPOP` timeouts. +* Only emit `end` once when connection goes away. +* Fixed bug in `test.js` where driver finished before all tests completed. + +## unversioned wasteland + +See the git history for what happened before. diff --git a/coder-base/node_modules_orig/redis/diff_multi_bench_output.js b/coder-base/node_modules_orig/redis/diff_multi_bench_output.js new file mode 100755 index 00000000..99fdf4df --- /dev/null +++ b/coder-base/node_modules_orig/redis/diff_multi_bench_output.js @@ -0,0 +1,87 @@ +#!/usr/bin/env node + +var colors = require('colors'), + fs = require('fs'), + _ = require('underscore'), + metrics = require('metrics'), + + // `node diff_multi_bench_output.js before.txt after.txt` + before = process.argv[2], + after = process.argv[3]; + +if (!before || !after) { + console.log('Please supply two file arguments:'); + var n = __filename; + n = n.substring(n.lastIndexOf('/', n.length)); + console.log(' ./' + n + ' multiBenchBefore.txt multiBenchAfter.txt'); + console.log('To generate multiBenchBefore.txt, run'); + console.log(' node multi_bench.js > multiBenchBefore.txt'); + console.log('Thank you for benchmarking responsibly.'); + return; +} + +var before_lines = fs.readFileSync(before, 'utf8').split('\n'), + after_lines = fs.readFileSync(after, 'utf8').split('\n'); + +console.log('Comparing before,', before.green, '(', before_lines.length, + 'lines)', 'to after,', after.green, '(', after_lines.length, 'lines)'); + +var total_ops = new metrics.Histogram.createUniformHistogram(); + +before_lines.forEach(function(b, i) { + var a = after_lines[i]; + if (!a || !b || !b.trim() || !a.trim()) { + // console.log('#ignored#', '>'+a+'<', '>'+b+'<'); + return; + } + + b_words = b.split(' ').filter(is_whitespace); + a_words = a.split(' ').filter(is_whitespace); + + var ops = + [b_words, a_words] + .map(function(words) { + // console.log(words); + return parseInt10(words.slice(-2, -1)); + }).filter(function(num) { + var isNaN = !num && num !== 0; + return !isNaN; + }); + if (ops.length != 2) return + + var delta = ops[1] - ops[0]; + + total_ops.update(delta); + + delta = humanize_diff(delta); + console.log( + // name of test + command_name(a_words) == command_name(b_words) + ? command_name(a_words) + ':' + : '404:', + // results of test + ops.join(' -> '), 'ops/sec (∆', delta, ')'); +}); + +console.log('Mean difference in ops/sec:', humanize_diff(total_ops.mean())); + +function is_whitespace(s) { + return !!s.trim(); +} + +function parseInt10(s) { + return parseInt(s, 10); +} + +// green if greater than 0, red otherwise +function humanize_diff(num) { + if (num > 0) { + return ('+' + num).green; + } + return ('' + num).red; +} + +function command_name(words) { + var line = words.join(' '); + return line.substr(0, line.indexOf(',')); +} diff --git a/coder-base/node_modules_orig/redis/examples/auth.js b/coder-base/node_modules_orig/redis/examples/auth.js new file mode 100755 index 00000000..6c0a563c --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/auth.js @@ -0,0 +1,5 @@ +var redis = require("redis"), + client = redis.createClient(); + +// This command is magical. Client stashes the password and will issue on every connect. +client.auth("somepass"); diff --git a/coder-base/node_modules_orig/redis/examples/backpressure_drain.js b/coder-base/node_modules_orig/redis/examples/backpressure_drain.js new file mode 100755 index 00000000..3488ef4d --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/backpressure_drain.js @@ -0,0 +1,33 @@ +var redis = require("../index"), + client = redis.createClient(null, null, { + command_queue_high_water: 5, + command_queue_low_water: 1 + }), + remaining_ops = 100000, paused = false; + +function op() { + if (remaining_ops <= 0) { + console.error("Finished."); + process.exit(0); + } + + remaining_ops--; + if (client.hset("test hash", "val " + remaining_ops, remaining_ops) === false) { + console.log("Pausing at " + remaining_ops); + paused = true; + } else { + process.nextTick(op); + } +} + +client.on("drain", function () { + if (paused) { + console.log("Resuming at " + remaining_ops); + paused = false; + process.nextTick(op); + } else { + console.log("Got drain while not paused at " + remaining_ops); + } +}); + +op(); diff --git a/coder-base/node_modules_orig/redis/examples/eval.js b/coder-base/node_modules_orig/redis/examples/eval.js new file mode 100755 index 00000000..c1fbf8a5 --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/eval.js @@ -0,0 +1,9 @@ +var redis = require("./index"), + client = redis.createClient(); + +redis.debug_mode = true; + +client.eval("return 100.5", 0, function (err, res) { + console.dir(err); + console.dir(res); +}); diff --git a/coder-base/node_modules_orig/redis/examples/extend.js b/coder-base/node_modules_orig/redis/examples/extend.js new file mode 100755 index 00000000..488b8c2d --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/extend.js @@ -0,0 +1,24 @@ +var redis = require("redis"), + client = redis.createClient(); + +// Extend the RedisClient prototype to add a custom method +// This one converts the results from "INFO" into a JavaScript Object + +redis.RedisClient.prototype.parse_info = function (callback) { + this.info(function (err, res) { + var lines = res.toString().split("\r\n").sort(); + var obj = {}; + lines.forEach(function (line) { + var parts = line.split(':'); + if (parts[1]) { + obj[parts[0]] = parts[1]; + } + }); + callback(obj) + }); +}; + +client.parse_info(function (info) { + console.dir(info); + client.quit(); +}); diff --git a/coder-base/node_modules_orig/redis/examples/file.js b/coder-base/node_modules_orig/redis/examples/file.js new file mode 100755 index 00000000..4d2b5d1c --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/file.js @@ -0,0 +1,32 @@ +// Read a file from disk, store it in Redis, then read it back from Redis. + +var redis = require("redis"), + client = redis.createClient(), + fs = require("fs"), + filename = "kids_in_cart.jpg"; + +// Get the file I use for testing like this: +// curl http://ranney.com/kids_in_cart.jpg -o kids_in_cart.jpg +// or just use your own file. + +// Read a file from fs, store it in Redis, get it back from Redis, write it back to fs. +fs.readFile(filename, function (err, data) { + if (err) throw err + console.log("Read " + data.length + " bytes from filesystem."); + + client.set(filename, data, redis.print); // set entire file + client.get(filename, function (err, reply) { // get entire file + if (err) { + console.log("Get error: " + err); + } else { + fs.writeFile("duplicate_" + filename, reply, function (err) { + if (err) { + console.log("Error on write: " + err) + } else { + console.log("File written."); + } + client.end(); + }); + } + }); +}); diff --git a/coder-base/node_modules_orig/redis/examples/mget.js b/coder-base/node_modules_orig/redis/examples/mget.js new file mode 100755 index 00000000..936740d3 --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/mget.js @@ -0,0 +1,5 @@ +var client = require("redis").createClient(); + +client.mget(["sessions started", "sessions started", "foo"], function (err, res) { + console.dir(res); +}); \ No newline at end of file diff --git a/coder-base/node_modules_orig/redis/examples/monitor.js b/coder-base/node_modules_orig/redis/examples/monitor.js new file mode 100755 index 00000000..2cb6a4e1 --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/monitor.js @@ -0,0 +1,10 @@ +var client = require("../index").createClient(), + util = require("util"); + +client.monitor(function (err, res) { + console.log("Entering monitoring mode."); +}); + +client.on("monitor", function (time, args) { + console.log(time + ": " + util.inspect(args)); +}); diff --git a/coder-base/node_modules_orig/redis/examples/multi.js b/coder-base/node_modules_orig/redis/examples/multi.js new file mode 100755 index 00000000..35c08e18 --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/multi.js @@ -0,0 +1,46 @@ +var redis = require("redis"), + client = redis.createClient(), set_size = 20; + +client.sadd("bigset", "a member"); +client.sadd("bigset", "another member"); + +while (set_size > 0) { + client.sadd("bigset", "member " + set_size); + set_size -= 1; +} + +// multi chain with an individual callback +client.multi() + .scard("bigset") + .smembers("bigset") + .keys("*", function (err, replies) { + client.mget(replies, redis.print); + }) + .dbsize() + .exec(function (err, replies) { + console.log("MULTI got " + replies.length + " replies"); + replies.forEach(function (reply, index) { + console.log("Reply " + index + ": " + reply.toString()); + }); + }); + +client.mset("incr thing", 100, "incr other thing", 1, redis.print); + +// start a separate multi command queue +var multi = client.multi(); +multi.incr("incr thing", redis.print); +multi.incr("incr other thing", redis.print); + +// runs immediately +client.get("incr thing", redis.print); // 100 + +// drains multi queue and runs atomically +multi.exec(function (err, replies) { + console.log(replies); // 101, 2 +}); + +// you can re-run the same transaction if you like +multi.exec(function (err, replies) { + console.log(replies); // 102, 3 + client.quit(); +}); diff --git a/coder-base/node_modules_orig/redis/examples/multi2.js b/coder-base/node_modules_orig/redis/examples/multi2.js new file mode 100755 index 00000000..8be4d731 --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/multi2.js @@ -0,0 +1,29 @@ +var redis = require("redis"), + client = redis.createClient(), multi; + +// start a separate command queue for multi +multi = client.multi(); +multi.incr("incr thing", redis.print); +multi.incr("incr other thing", redis.print); + +// runs immediately +client.mset("incr thing", 100, "incr other thing", 1, redis.print); + +// drains multi queue and runs atomically +multi.exec(function (err, replies) { + console.log(replies); // 101, 2 +}); + +// you can re-run the same transaction if you like +multi.exec(function (err, replies) { + console.log(replies); // 102, 3 + client.quit(); +}); + +client.multi([ + ["mget", "multifoo", "multibar", redis.print], + ["incr", "multifoo"], + ["incr", "multibar"] +]).exec(function (err, replies) { + console.log(replies.toString()); +}); diff --git a/coder-base/node_modules_orig/redis/examples/psubscribe.js b/coder-base/node_modules_orig/redis/examples/psubscribe.js new file mode 100755 index 00000000..c57117b8 --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/psubscribe.js @@ -0,0 +1,33 @@ +var redis = require("redis"), + client1 = redis.createClient(), + client2 = redis.createClient(), + client3 = redis.createClient(), + client4 = redis.createClient(), + msg_count = 0; + +redis.debug_mode = false; + +client1.on("psubscribe", function (pattern, count) { + console.log("client1 psubscribed to " + pattern + ", " + count + " total subscriptions"); + client2.publish("channeltwo", "Me!"); + client3.publish("channelthree", "Me too!"); + client4.publish("channelfour", "And me too!"); +}); + +client1.on("punsubscribe", function (pattern, count) { + console.log("client1 punsubscribed from " + pattern + ", " + count + " total subscriptions"); + client4.end(); + client3.end(); + client2.end(); + client1.end(); +}); + +client1.on("pmessage", function (pattern, channel, message) { + console.log("("+ pattern +")" + " client1 received message on " + channel + ": " + message); + msg_count += 1; + if (msg_count === 3) { + client1.punsubscribe(); + } +}); + +client1.psubscribe("channel*"); diff --git a/coder-base/node_modules_orig/redis/examples/pub_sub.js b/coder-base/node_modules_orig/redis/examples/pub_sub.js new file mode 100755 index 00000000..aa508d6c --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/pub_sub.js @@ -0,0 +1,41 @@ +var redis = require("redis"), + client1 = redis.createClient(), msg_count = 0, + client2 = redis.createClient(); + +redis.debug_mode = false; + +// Most clients probably don't do much on "subscribe". This example uses it to coordinate things within one program. +client1.on("subscribe", function (channel, count) { + console.log("client1 subscribed to " + channel + ", " + count + " total subscriptions"); + if (count === 2) { + client2.publish("a nice channel", "I am sending a message."); + client2.publish("another one", "I am sending a second message."); + client2.publish("a nice channel", "I am sending my last message."); + } +}); + +client1.on("unsubscribe", function (channel, count) { + console.log("client1 unsubscribed from " + channel + ", " + count + " total subscriptions"); + if (count === 0) { + client2.end(); + client1.end(); + } +}); + +client1.on("message", function (channel, message) { + console.log("client1 channel " + channel + ": " + message); + msg_count += 1; + if (msg_count === 3) { + client1.unsubscribe(); + } +}); + +client1.on("ready", function () { + // if you need auth, do it here + client1.incr("did a thing"); + client1.subscribe("a nice channel", "another one"); +}); + +client2.on("ready", function () { + // if you need auth, do it here +}); diff --git a/coder-base/node_modules_orig/redis/examples/simple.js b/coder-base/node_modules_orig/redis/examples/simple.js new file mode 100755 index 00000000..f1f2e320 --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/simple.js @@ -0,0 +1,24 @@ +var redis = require("redis"), + client = redis.createClient(); + +client.on("error", function (err) { + console.log("error event - " + client.host + ":" + client.port + " - " + err); +}); + +client.set("string key", "string val", redis.print); +client.hset("hash key", "hashtest 1", "some value", redis.print); +client.hset(["hash key", "hashtest 2", "some other value"], redis.print); +client.hkeys("hash key", function (err, replies) { + if (err) { + return console.error("error response - " + err); + } + + console.log(replies.length + " replies:"); + replies.forEach(function (reply, i) { + console.log(" " + i + ": " + reply); + }); +}); + +client.quit(function (err, res) { + console.log("Exiting from quit command."); +}); diff --git a/coder-base/node_modules_orig/redis/examples/sort.js b/coder-base/node_modules_orig/redis/examples/sort.js new file mode 100755 index 00000000..e7c6249e --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/sort.js @@ -0,0 +1,17 @@ +var redis = require("redis"), + client = redis.createClient(); + +client.sadd("mylist", 1); +client.sadd("mylist", 2); +client.sadd("mylist", 3); + +client.set("weight_1", 5); +client.set("weight_2", 500); +client.set("weight_3", 1); + +client.set("object_1", "foo"); +client.set("object_2", "bar"); +client.set("object_3", "qux"); + +client.sort("mylist", "by", "weight_*", "get", "object_*", redis.print); +// Prints Reply: qux,foo,bar \ No newline at end of file diff --git a/coder-base/node_modules_orig/redis/examples/subqueries.js b/coder-base/node_modules_orig/redis/examples/subqueries.js new file mode 100755 index 00000000..560db240 --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/subqueries.js @@ -0,0 +1,15 @@ +// Sending commands in response to other commands. +// This example runs "type" against every key in the database +// +var client = require("redis").createClient(); + +client.keys("*", function (err, keys) { + keys.forEach(function (key, pos) { + client.type(key, function (err, keytype) { + console.log(key + " is " + keytype); + if (pos === (keys.length - 1)) { + client.quit(); + } + }); + }); +}); diff --git a/coder-base/node_modules_orig/redis/examples/subquery.js b/coder-base/node_modules_orig/redis/examples/subquery.js new file mode 100755 index 00000000..861657e1 --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/subquery.js @@ -0,0 +1,19 @@ +var client = require("redis").createClient(); + +function print_results(obj) { + console.dir(obj); +} + +// build a map of all keys and their types +client.keys("*", function (err, all_keys) { + var key_types = {}; + + all_keys.forEach(function (key, pos) { // use second arg of forEach to get pos + client.type(key, function (err, type) { + key_types[key] = type; + if (pos === all_keys.length - 1) { // callbacks all run in order + print_results(key_types); + } + }); + }); +}); diff --git a/coder-base/node_modules_orig/redis/examples/unix_socket.js b/coder-base/node_modules_orig/redis/examples/unix_socket.js new file mode 100755 index 00000000..4a5e0bb0 --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/unix_socket.js @@ -0,0 +1,29 @@ +var redis = require("redis"), + client = redis.createClient("/tmp/redis.sock"), + profiler = require("v8-profiler"); + +client.on("connect", function () { + console.log("Got Unix socket connection.") +}); + +client.on("error", function (err) { + console.log(err.message); +}); + +client.set("space chars", "space value"); + +setInterval(function () { + client.get("space chars"); +}, 100); + +function done() { + client.info(function (err, reply) { + console.log(reply.toString()); + client.quit(); + }); +} + +setTimeout(function () { + console.log("Taking snapshot."); + var snap = profiler.takeSnapshot(); +}, 5000); diff --git a/coder-base/node_modules_orig/redis/examples/web_server.js b/coder-base/node_modules_orig/redis/examples/web_server.js new file mode 100755 index 00000000..9fd85923 --- /dev/null +++ b/coder-base/node_modules_orig/redis/examples/web_server.js @@ -0,0 +1,31 @@ +// A simple web server that generates dyanmic content based on responses from Redis + +var http = require("http"), server, + redis_client = require("redis").createClient(); + +server = http.createServer(function (request, response) { + response.writeHead(200, { + "Content-Type": "text/plain" + }); + + var redis_info, total_requests; + + redis_client.info(function (err, reply) { + redis_info = reply; // stash response in outer scope + }); + redis_client.incr("requests", function (err, reply) { + total_requests = reply; // stash response in outer scope + }); + redis_client.hincrby("ip", request.connection.remoteAddress, 1); + redis_client.hgetall("ip", function (err, reply) { + // This is the last reply, so all of the previous replies must have completed already + response.write("This page was generated after talking to redis.\n\n" + + "Redis info:\n" + redis_info + "\n" + + "Total requests: " + total_requests + "\n\n" + + "IP count: \n"); + Object.keys(reply).forEach(function (ip) { + response.write(" " + ip + ": " + reply[ip] + "\n"); + }); + response.end(); + }); +}).listen(80); diff --git a/coder-base/node_modules_orig/redis/generate_commands.js b/coder-base/node_modules_orig/redis/generate_commands.js new file mode 100755 index 00000000..e6949d3a --- /dev/null +++ b/coder-base/node_modules_orig/redis/generate_commands.js @@ -0,0 +1,39 @@ +var http = require("http"), + fs = require("fs"); + +function prettyCurrentTime() { + var date = new Date(); + return date.toLocaleString(); +} + +function write_file(commands, path) { + var file_contents, out_commands; + + console.log("Writing " + Object.keys(commands).length + " commands to " + path); + + file_contents = "// This file was generated by ./generate_commands.js on " + prettyCurrentTime() + "\n"; + + out_commands = Object.keys(commands).map(function (key) { + return key.toLowerCase(); + }); + + file_contents += "module.exports = " + JSON.stringify(out_commands, null, " ") + ";\n"; + + fs.writeFile(path, file_contents); +} + +http.get({host: "redis.io", path: "/commands.json"}, function (res) { + var body = ""; + + console.log("Response from redis.io/commands.json: " + res.statusCode); + + res.on('data', function (chunk) { + body += chunk; + }); + + res.on('end', function () { + write_file(JSON.parse(body), "lib/commands.js"); + }); +}).on('error', function (e) { + console.log("Error fetching command list from redis.io: " + e.message); +}); diff --git a/coder-base/node_modules_orig/redis/index.js b/coder-base/node_modules_orig/redis/index.js new file mode 100755 index 00000000..dd27dbdd --- /dev/null +++ b/coder-base/node_modules_orig/redis/index.js @@ -0,0 +1,1113 @@ +/*global Buffer require exports console setTimeout */ + +var net = require("net"), + util = require("./lib/util"), + Queue = require("./lib/queue"), + to_array = require("./lib/to_array"), + events = require("events"), + crypto = require("crypto"), + parsers = [], commands, + connection_id = 0, + default_port = 6379, + default_host = "127.0.0.1"; + +// can set this to true to enable for all connections +exports.debug_mode = false; + +// hiredis might not be installed +try { + require("./lib/parser/hiredis"); + parsers.push(require("./lib/parser/hiredis")); +} catch (err) { + if (exports.debug_mode) { + console.warn("hiredis parser not installed."); + } +} + +parsers.push(require("./lib/parser/javascript")); + +function RedisClient(stream, options) { + this.stream = stream; + this.options = options = options || {}; + + this.connection_id = ++connection_id; + this.connected = false; + this.ready = false; + this.connections = 0; + if (this.options.socket_nodelay === undefined) { + this.options.socket_nodelay = true; + } + this.should_buffer = false; + this.command_queue_high_water = this.options.command_queue_high_water || 1000; + this.command_queue_low_water = this.options.command_queue_low_water || 0; + this.max_attempts = null; + if (options.max_attempts && !isNaN(options.max_attempts) && options.max_attempts > 0) { + this.max_attempts = +options.max_attempts; + } + this.command_queue = new Queue(); // holds sent commands to de-pipeline them + this.offline_queue = new Queue(); // holds commands issued but not able to be sent + this.commands_sent = 0; + this.connect_timeout = false; + if (options.connect_timeout && !isNaN(options.connect_timeout) && options.connect_timeout > 0) { + this.connect_timeout = +options.connect_timeout; + } + + this.enable_offline_queue = true; + if (typeof this.options.enable_offline_queue === "boolean") { + this.enable_offline_queue = this.options.enable_offline_queue; + } + + this.initialize_retry_vars(); + this.pub_sub_mode = false; + this.subscription_set = {}; + this.monitoring = false; + this.closing = false; + this.server_info = {}; + this.auth_pass = null; + this.parser_module = null; + this.selected_db = null; // save the selected db here, used when reconnecting + + this.old_state = null; + + var self = this; + + this.stream.on("connect", function () { + self.on_connect(); + }); + + this.stream.on("data", function (buffer_from_socket) { + self.on_data(buffer_from_socket); + }); + + this.stream.on("error", function (msg) { + self.on_error(msg.message); + }); + + this.stream.on("close", function () { + self.connection_gone("close"); + }); + + this.stream.on("end", function () { + self.connection_gone("end"); + }); + + this.stream.on("drain", function () { + self.should_buffer = false; + self.emit("drain"); + }); + + events.EventEmitter.call(this); +} +util.inherits(RedisClient, events.EventEmitter); +exports.RedisClient = RedisClient; + +RedisClient.prototype.initialize_retry_vars = function () { + this.retry_timer = null; + this.retry_totaltime = 0; + this.retry_delay = 150; + this.retry_backoff = 1.7; + this.attempts = 1; +}; + +// flush offline_queue and command_queue, erroring any items with a callback first +RedisClient.prototype.flush_and_error = function (message) { + var command_obj; + while (this.offline_queue.length > 0) { + command_obj = this.offline_queue.shift(); + if (typeof command_obj.callback === "function") { + command_obj.callback(message); + } + } + this.offline_queue = new Queue(); + + while (this.command_queue.length > 0) { + command_obj = this.command_queue.shift(); + if (typeof command_obj.callback === "function") { + command_obj.callback(message); + } + } + this.command_queue = new Queue(); +}; + +RedisClient.prototype.on_error = function (msg) { + var message = "Redis connection to " + this.host + ":" + this.port + " failed - " + msg; + + if (this.closing) { + return; + } + + if (exports.debug_mode) { + console.warn(message); + } + + this.flush_and_error(message); + + this.connected = false; + this.ready = false; + + this.emit("error", new Error(message)); + // "error" events get turned into exceptions if they aren't listened for. If the user handled this error + // then we should try to reconnect. + this.connection_gone("error"); +}; + +RedisClient.prototype.do_auth = function () { + var self = this; + + if (exports.debug_mode) { + console.log("Sending auth to " + self.host + ":" + self.port + " id " + self.connection_id); + } + self.send_anyway = true; + self.send_command("auth", [this.auth_pass], function (err, res) { + if (err) { + if (err.toString().match("LOADING")) { + // if redis is still loading the db, it will not authenticate and everything else will fail + console.log("Redis still loading, trying to authenticate later"); + setTimeout(function () { + self.do_auth(); + }, 2000); // TODO - magic number alert + return; + } else { + return self.emit("error", new Error("Auth error: " + err.message)); + } + } + if (res.toString() !== "OK") { + return self.emit("error", new Error("Auth failed: " + res.toString())); + } + if (exports.debug_mode) { + console.log("Auth succeeded " + self.host + ":" + self.port + " id " + self.connection_id); + } + if (self.auth_callback) { + self.auth_callback(err, res); + self.auth_callback = null; + } + + // now we are really connected + self.emit("connect"); + if (self.options.no_ready_check) { + self.on_ready(); + } else { + self.ready_check(); + } + }); + self.send_anyway = false; +}; + +RedisClient.prototype.on_connect = function () { + if (exports.debug_mode) { + console.log("Stream connected " + this.host + ":" + this.port + " id " + this.connection_id); + } + + this.connected = true; + this.ready = false; + this.attempts = 0; + this.connections += 1; + this.command_queue = new Queue(); + this.emitted_end = false; + this.initialize_retry_vars(); + if (this.options.socket_nodelay) { + this.stream.setNoDelay(); + } + this.stream.setTimeout(0); + + this.init_parser(); + + if (this.auth_pass) { + this.do_auth(); + } else { + this.emit("connect"); + + if (this.options.no_ready_check) { + this.on_ready(); + } else { + this.ready_check(); + } + } +}; + +RedisClient.prototype.init_parser = function () { + var self = this; + + if (this.options.parser) { + if (! parsers.some(function (parser) { + if (parser.name === self.options.parser) { + self.parser_module = parser; + if (exports.debug_mode) { + console.log("Using parser module: " + self.parser_module.name); + } + return true; + } + })) { + throw new Error("Couldn't find named parser " + self.options.parser + " on this system"); + } + } else { + if (exports.debug_mode) { + console.log("Using default parser module: " + parsers[0].name); + } + this.parser_module = parsers[0]; + } + + this.parser_module.debug_mode = exports.debug_mode; + + // return_buffers sends back Buffers from parser to callback. detect_buffers sends back Buffers from parser, but + // converts to Strings if the input arguments are not Buffers. + this.reply_parser = new this.parser_module.Parser({ + return_buffers: self.options.return_buffers || self.options.detect_buffers || false + }); + + // "reply error" is an error sent back by Redis + this.reply_parser.on("reply error", function (reply) { + self.return_error(new Error(reply)); + }); + this.reply_parser.on("reply", function (reply) { + self.return_reply(reply); + }); + // "error" is bad. Somehow the parser got confused. It'll try to reset and continue. + this.reply_parser.on("error", function (err) { + self.emit("error", new Error("Redis reply parser error: " + err.stack)); + }); +}; + +RedisClient.prototype.on_ready = function () { + var self = this; + + this.ready = true; + + if (this.old_state !== null) { + this.monitoring = this.old_state.monitoring; + this.pub_sub_mode = this.old_state.pub_sub_mode; + this.selected_db = this.old_state.selected_db; + this.old_state = null; + } + + // magically restore any modal commands from a previous connection + if (this.selected_db !== null) { + this.send_command('select', [this.selected_db]); + } + if (this.pub_sub_mode === true) { + // only emit "ready" when all subscriptions were made again + var callback_count = 0; + var callback = function () { + callback_count--; + if (callback_count === 0) { + self.emit("ready"); + } + }; + Object.keys(this.subscription_set).forEach(function (key) { + var parts = key.split(" "); + if (exports.debug_mode) { + console.warn("sending pub/sub on_ready " + parts[0] + ", " + parts[1]); + } + callback_count++; + self.send_command(parts[0] + "scribe", [parts[1]], callback); + }); + return; + } else if (this.monitoring) { + this.send_command("monitor"); + } else { + this.send_offline_queue(); + } + this.emit("ready"); +}; + +RedisClient.prototype.on_info_cmd = function (err, res) { + var self = this, obj = {}, lines, retry_time; + + if (err) { + return self.emit("error", new Error("Ready check failed: " + err.message)); + } + + lines = res.toString().split("\r\n"); + + lines.forEach(function (line) { + var parts = line.split(':'); + if (parts[1]) { + obj[parts[0]] = parts[1]; + } + }); + + obj.versions = []; + obj.redis_version.split('.').forEach(function (num) { + obj.versions.push(+num); + }); + + // expose info key/vals to users + this.server_info = obj; + + if (!obj.loading || (obj.loading && obj.loading === "0")) { + if (exports.debug_mode) { + console.log("Redis server ready."); + } + this.on_ready(); + } else { + retry_time = obj.loading_eta_seconds * 1000; + if (retry_time > 1000) { + retry_time = 1000; + } + if (exports.debug_mode) { + console.log("Redis server still loading, trying again in " + retry_time); + } + setTimeout(function () { + self.ready_check(); + }, retry_time); + } +}; + +RedisClient.prototype.ready_check = function () { + var self = this; + + if (exports.debug_mode) { + console.log("checking server ready state..."); + } + + this.send_anyway = true; // secret flag to send_command to send something even if not "ready" + this.info(function (err, res) { + self.on_info_cmd(err, res); + }); + this.send_anyway = false; +}; + +RedisClient.prototype.send_offline_queue = function () { + var command_obj, buffered_writes = 0; + + while (this.offline_queue.length > 0) { + command_obj = this.offline_queue.shift(); + if (exports.debug_mode) { + console.log("Sending offline command: " + command_obj.command); + } + buffered_writes += !this.send_command(command_obj.command, command_obj.args, command_obj.callback); + } + this.offline_queue = new Queue(); + // Even though items were shifted off, Queue backing store still uses memory until next add, so just get a new Queue + + if (!buffered_writes) { + this.should_buffer = false; + this.emit("drain"); + } +}; + +RedisClient.prototype.connection_gone = function (why) { + var self = this; + + // If a retry is already in progress, just let that happen + if (this.retry_timer) { + return; + } + + if (exports.debug_mode) { + console.warn("Redis connection is gone from " + why + " event."); + } + this.connected = false; + this.ready = false; + + if (this.old_state === null) { + var state = { + monitoring: this.monitoring, + pub_sub_mode: this.pub_sub_mode, + selected_db: this.selected_db + }; + this.old_state = state; + this.monitoring = false; + this.pub_sub_mode = false; + this.selected_db = null; + } + + // since we are collapsing end and close, users don't expect to be called twice + if (! this.emitted_end) { + this.emit("end"); + this.emitted_end = true; + } + + this.flush_and_error("Redis connection gone from " + why + " event."); + + // If this is a requested shutdown, then don't retry + if (this.closing) { + this.retry_timer = null; + if (exports.debug_mode) { + console.warn("connection ended from quit command, not retrying."); + } + return; + } + + this.retry_delay = Math.floor(this.retry_delay * this.retry_backoff); + + if (exports.debug_mode) { + console.log("Retry connection in " + this.retry_delay + " ms"); + } + + if (this.max_attempts && this.attempts >= this.max_attempts) { + this.retry_timer = null; + // TODO - some people need a "Redis is Broken mode" for future commands that errors immediately, and others + // want the program to exit. Right now, we just log, which doesn't really help in either case. + console.error("node_redis: Couldn't get Redis connection after " + this.max_attempts + " attempts."); + return; + } + + this.attempts += 1; + this.emit("reconnecting", { + delay: self.retry_delay, + attempt: self.attempts + }); + this.retry_timer = setTimeout(function () { + if (exports.debug_mode) { + console.log("Retrying connection..."); + } + + self.retry_totaltime += self.retry_delay; + + if (self.connect_timeout && self.retry_totaltime >= self.connect_timeout) { + self.retry_timer = null; + // TODO - engage Redis is Broken mode for future commands, or whatever + console.error("node_redis: Couldn't get Redis connection after " + self.retry_totaltime + "ms."); + return; + } + + self.stream.connect(self.port, self.host); + self.retry_timer = null; + }, this.retry_delay); +}; + +RedisClient.prototype.on_data = function (data) { + if (exports.debug_mode) { + console.log("net read " + this.host + ":" + this.port + " id " + this.connection_id + ": " + data.toString()); + } + + try { + this.reply_parser.execute(data); + } catch (err) { + // This is an unexpected parser problem, an exception that came from the parser code itself. + // Parser should emit "error" events if it notices things are out of whack. + // Callbacks that throw exceptions will land in return_reply(), below. + // TODO - it might be nice to have a different "error" event for different types of errors + this.emit("error", err); + } +}; + +RedisClient.prototype.return_error = function (err) { + var command_obj = this.command_queue.shift(), queue_len = this.command_queue.getLength(); + + if (this.pub_sub_mode === false && queue_len === 0) { + this.emit("idle"); + this.command_queue = new Queue(); + } + if (this.should_buffer && queue_len <= this.command_queue_low_water) { + this.emit("drain"); + this.should_buffer = false; + } + + if (command_obj && typeof command_obj.callback === "function") { + try { + command_obj.callback(err); + } catch (callback_err) { + // if a callback throws an exception, re-throw it on a new stack so the parser can keep going + process.nextTick(function () { + throw callback_err; + }); + } + } else { + console.log("node_redis: no callback to send error: " + err.message); + // this will probably not make it anywhere useful, but we might as well throw + process.nextTick(function () { + throw err; + }); + } +}; + +// if a callback throws an exception, re-throw it on a new stack so the parser can keep going. +// put this try/catch in its own function because V8 doesn't optimize this well yet. +function try_callback(callback, reply) { + try { + callback(null, reply); + } catch (err) { + process.nextTick(function () { + throw err; + }); + } +} + +// hgetall converts its replies to an Object. If the reply is empty, null is returned. +function reply_to_object(reply) { + var obj = {}, j, jl, key, val; + + if (reply.length === 0) { + return null; + } + + for (j = 0, jl = reply.length; j < jl; j += 2) { + key = reply[j].toString(); + val = reply[j + 1]; + obj[key] = val; + } + + return obj; +} + +function reply_to_strings(reply) { + var i; + + if (Buffer.isBuffer(reply)) { + return reply.toString(); + } + + if (Array.isArray(reply)) { + for (i = 0; i < reply.length; i++) { + reply[i] = reply[i].toString(); + } + return reply; + } + + return reply; +} + +RedisClient.prototype.return_reply = function (reply) { + var command_obj, len, type, timestamp, argindex, args, queue_len; + + command_obj = this.command_queue.shift(), + queue_len = this.command_queue.getLength(); + + if (this.pub_sub_mode === false && queue_len === 0) { + this.emit("idle"); + this.command_queue = new Queue(); // explicitly reclaim storage from old Queue + } + if (this.should_buffer && queue_len <= this.command_queue_low_water) { + this.emit("drain"); + this.should_buffer = false; + } + + if (command_obj && !command_obj.sub_command) { + if (typeof command_obj.callback === "function") { + if (this.options.detect_buffers && command_obj.buffer_args === false) { + // If detect_buffers option was specified, then the reply from the parser will be Buffers. + // If this command did not use Buffer arguments, then convert the reply to Strings here. + reply = reply_to_strings(reply); + } + + // TODO - confusing and error-prone that hgetall is special cased in two places + if (reply && 'hgetall' === command_obj.command.toLowerCase()) { + reply = reply_to_object(reply); + } + + try_callback(command_obj.callback, reply); + } else if (exports.debug_mode) { + console.log("no callback for reply: " + (reply && reply.toString && reply.toString())); + } + } else if (this.pub_sub_mode || (command_obj && command_obj.sub_command)) { + if (Array.isArray(reply)) { + type = reply[0].toString(); + + if (type === "message") { + this.emit("message", reply[1].toString(), reply[2]); // channel, message + } else if (type === "pmessage") { + this.emit("pmessage", reply[1].toString(), reply[2].toString(), reply[3]); // pattern, channel, message + } else if (type === "subscribe" || type === "unsubscribe" || type === "psubscribe" || type === "punsubscribe") { + if (reply[2] === 0) { + this.pub_sub_mode = false; + if (this.debug_mode) { + console.log("All subscriptions removed, exiting pub/sub mode"); + } + } else { + this.pub_sub_mode = true; + } + // subscribe commands take an optional callback and also emit an event, but only the first response is included in the callback + // TODO - document this or fix it so it works in a more obvious way + if (command_obj && typeof command_obj.callback === "function") { + try_callback(command_obj.callback, reply[1].toString()); + } + this.emit(type, reply[1].toString(), reply[2]); // channel, count + } else { + throw new Error("subscriptions are active but got unknown reply type " + type); + } + } else if (! this.closing) { + throw new Error("subscriptions are active but got an invalid reply: " + reply); + } + } else if (this.monitoring) { + len = reply.indexOf(" "); + timestamp = reply.slice(0, len); + argindex = reply.indexOf('"'); + args = reply.slice(argindex + 1, -1).split('" "').map(function (elem) { + return elem.replace(/\\"/g, '"'); + }); + this.emit("monitor", timestamp, args); + } else { + throw new Error("node_redis command queue state error. If you can reproduce this, please report it."); + } +}; + +// This Command constructor is ever so slightly faster than using an object literal, but more importantly, using +// a named constructor helps it show up meaningfully in the V8 CPU profiler and in heap snapshots. +function Command(command, args, sub_command, buffer_args, callback) { + this.command = command; + this.args = args; + this.sub_command = sub_command; + this.buffer_args = buffer_args; + this.callback = callback; +} + +RedisClient.prototype.send_command = function (command, args, callback) { + var arg, command_obj, i, il, elem_count, buffer_args, stream = this.stream, command_str = "", buffered_writes = 0, last_arg_type; + + if (typeof command !== "string") { + throw new Error("First argument to send_command must be the command name string, not " + typeof command); + } + + if (Array.isArray(args)) { + if (typeof callback === "function") { + // probably the fastest way: + // client.command([arg1, arg2], cb); (straight passthrough) + // send_command(command, [arg1, arg2], cb); + } else if (! callback) { + // most people find this variable argument length form more convenient, but it uses arguments, which is slower + // client.command(arg1, arg2, cb); (wraps up arguments into an array) + // send_command(command, [arg1, arg2, cb]); + // client.command(arg1, arg2); (callback is optional) + // send_command(command, [arg1, arg2]); + // client.command(arg1, arg2, undefined); (callback is undefined) + // send_command(command, [arg1, arg2, undefined]); + last_arg_type = typeof args[args.length - 1]; + if (last_arg_type === "function" || last_arg_type === "undefined") { + callback = args.pop(); + } + } else { + throw new Error("send_command: last argument must be a callback or undefined"); + } + } else { + throw new Error("send_command: second argument must be an array"); + } + + // if the last argument is an array and command is sadd, expand it out: + // client.sadd(arg1, [arg2, arg3, arg4], cb); + // converts to: + // client.sadd(arg1, arg2, arg3, arg4, cb); + if ((command === 'sadd' || command === 'SADD') && args.length > 0 && Array.isArray(args[args.length - 1])) { + args = args.slice(0, -1).concat(args[args.length - 1]); + } + + buffer_args = false; + for (i = 0, il = args.length, arg; i < il; i += 1) { + if (Buffer.isBuffer(args[i])) { + buffer_args = true; + } + } + + command_obj = new Command(command, args, false, buffer_args, callback); + + if ((!this.ready && !this.send_anyway) || !stream.writable) { + if (exports.debug_mode) { + if (!stream.writable) { + console.log("send command: stream is not writeable."); + } + } + + if (this.enable_offline_queue) { + if (exports.debug_mode) { + console.log("Queueing " + command + " for next server connection."); + } + this.offline_queue.push(command_obj); + this.should_buffer = true; + } else { + var not_writeable_error = new Error('send_command: stream not writeable. enable_offline_queue is false'); + if (command_obj.callback) { + command_obj.callback(not_writeable_error); + } else { + throw not_writeable_error; + } + } + + return false; + } + + if (command === "subscribe" || command === "psubscribe" || command === "unsubscribe" || command === "punsubscribe") { + this.pub_sub_command(command_obj); + } else if (command === "monitor") { + this.monitoring = true; + } else if (command === "quit") { + this.closing = true; + } else if (this.pub_sub_mode === true) { + throw new Error("Connection in pub/sub mode, only pub/sub commands may be used"); + } + this.command_queue.push(command_obj); + this.commands_sent += 1; + + elem_count = args.length + 1; + + // Always use "Multi bulk commands", but if passed any Buffer args, then do multiple writes, one for each arg. + // This means that using Buffers in commands is going to be slower, so use Strings if you don't already have a Buffer. + + command_str = "*" + elem_count + "\r\n$" + command.length + "\r\n" + command + "\r\n"; + + if (! buffer_args) { // Build up a string and send entire command in one write + for (i = 0, il = args.length, arg; i < il; i += 1) { + arg = args[i]; + if (typeof arg !== "string") { + arg = String(arg); + } + command_str += "$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n"; + } + if (exports.debug_mode) { + console.log("send " + this.host + ":" + this.port + " id " + this.connection_id + ": " + command_str); + } + buffered_writes += !stream.write(command_str); + } else { + if (exports.debug_mode) { + console.log("send command (" + command_str + ") has Buffer arguments"); + } + buffered_writes += !stream.write(command_str); + + for (i = 0, il = args.length, arg; i < il; i += 1) { + arg = args[i]; + if (!(Buffer.isBuffer(arg) || arg instanceof String)) { + arg = String(arg); + } + + if (Buffer.isBuffer(arg)) { + if (arg.length === 0) { + if (exports.debug_mode) { + console.log("send_command: using empty string for 0 length buffer"); + } + buffered_writes += !stream.write("$0\r\n\r\n"); + } else { + buffered_writes += !stream.write("$" + arg.length + "\r\n"); + buffered_writes += !stream.write(arg); + buffered_writes += !stream.write("\r\n"); + if (exports.debug_mode) { + console.log("send_command: buffer send " + arg.length + " bytes"); + } + } + } else { + if (exports.debug_mode) { + console.log("send_command: string send " + Buffer.byteLength(arg) + " bytes: " + arg); + } + buffered_writes += !stream.write("$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n"); + } + } + } + if (exports.debug_mode) { + console.log("send_command buffered_writes: " + buffered_writes, " should_buffer: " + this.should_buffer); + } + if (buffered_writes || this.command_queue.getLength() >= this.command_queue_high_water) { + this.should_buffer = true; + } + return !this.should_buffer; +}; + +RedisClient.prototype.pub_sub_command = function (command_obj) { + var i, key, command, args; + + if (this.pub_sub_mode === false && exports.debug_mode) { + console.log("Entering pub/sub mode from " + command_obj.command); + } + this.pub_sub_mode = true; + command_obj.sub_command = true; + + command = command_obj.command; + args = command_obj.args; + if (command === "subscribe" || command === "psubscribe") { + if (command === "subscribe") { + key = "sub"; + } else { + key = "psub"; + } + for (i = 0; i < args.length; i++) { + this.subscription_set[key + " " + args[i]] = true; + } + } else { + if (command === "unsubscribe") { + key = "sub"; + } else { + key = "psub"; + } + for (i = 0; i < args.length; i++) { + delete this.subscription_set[key + " " + args[i]]; + } + } +}; + +RedisClient.prototype.end = function () { + this.stream._events = {}; + this.connected = false; + this.ready = false; + return this.stream.end(); +}; + +function Multi(client, args) { + this.client = client; + this.queue = [["MULTI"]]; + if (Array.isArray(args)) { + this.queue = this.queue.concat(args); + } +} + +exports.Multi = Multi; + +// take 2 arrays and return the union of their elements +function set_union(seta, setb) { + var obj = {}; + + seta.forEach(function (val) { + obj[val] = true; + }); + setb.forEach(function (val) { + obj[val] = true; + }); + return Object.keys(obj); +} + +// This static list of commands is updated from time to time. ./lib/commands.js can be updated with generate_commands.js +commands = set_union(["get", "set", "setnx", "setex", "append", "strlen", "del", "exists", "setbit", "getbit", "setrange", "getrange", "substr", + "incr", "decr", "mget", "rpush", "lpush", "rpushx", "lpushx", "linsert", "rpop", "lpop", "brpop", "brpoplpush", "blpop", "llen", "lindex", + "lset", "lrange", "ltrim", "lrem", "rpoplpush", "sadd", "srem", "smove", "sismember", "scard", "spop", "srandmember", "sinter", "sinterstore", + "sunion", "sunionstore", "sdiff", "sdiffstore", "smembers", "zadd", "zincrby", "zrem", "zremrangebyscore", "zremrangebyrank", "zunionstore", + "zinterstore", "zrange", "zrangebyscore", "zrevrangebyscore", "zcount", "zrevrange", "zcard", "zscore", "zrank", "zrevrank", "hset", "hsetnx", + "hget", "hmset", "hmget", "hincrby", "hdel", "hlen", "hkeys", "hvals", "hgetall", "hexists", "incrby", "decrby", "getset", "mset", "msetnx", + "randomkey", "select", "move", "rename", "renamenx", "expire", "expireat", "keys", "dbsize", "auth", "ping", "echo", "save", "bgsave", + "bgrewriteaof", "shutdown", "lastsave", "type", "multi", "exec", "discard", "sync", "flushdb", "flushall", "sort", "info", "monitor", "ttl", + "persist", "slaveof", "debug", "config", "subscribe", "unsubscribe", "psubscribe", "punsubscribe", "publish", "watch", "unwatch", "cluster", + "restore", "migrate", "dump", "object", "client", "eval", "evalsha"], require("./lib/commands")); + +commands.forEach(function (command) { + RedisClient.prototype[command] = function (args, callback) { + if (Array.isArray(args) && typeof callback === "function") { + return this.send_command(command, args, callback); + } else { + return this.send_command(command, to_array(arguments)); + } + }; + RedisClient.prototype[command.toUpperCase()] = RedisClient.prototype[command]; + + Multi.prototype[command] = function () { + this.queue.push([command].concat(to_array(arguments))); + return this; + }; + Multi.prototype[command.toUpperCase()] = Multi.prototype[command]; +}); + +// store db in this.select_db to restore it on reconnect +RedisClient.prototype.select = function (db, callback) { + var self = this; + + this.send_command('select', [db], function (err, res) { + if (err === null) { + self.selected_db = db; + } + if (typeof(callback) === 'function') { + callback(err, res); + } + }); +}; +RedisClient.prototype.SELECT = RedisClient.prototype.select; + +// Stash auth for connect and reconnect. Send immediately if already connected. +RedisClient.prototype.auth = function () { + var args = to_array(arguments); + this.auth_pass = args[0]; + this.auth_callback = args[1]; + if (exports.debug_mode) { + console.log("Saving auth as " + this.auth_pass); + } + + if (this.connected) { + this.send_command("auth", args); + } +}; +RedisClient.prototype.AUTH = RedisClient.prototype.auth; + +RedisClient.prototype.hmget = function (arg1, arg2, arg3) { + if (Array.isArray(arg2) && typeof arg3 === "function") { + return this.send_command("hmget", [arg1].concat(arg2), arg3); + } else if (Array.isArray(arg1) && typeof arg2 === "function") { + return this.send_command("hmget", arg1, arg2); + } else { + return this.send_command("hmget", to_array(arguments)); + } +}; +RedisClient.prototype.HMGET = RedisClient.prototype.hmget; + +RedisClient.prototype.hmset = function (args, callback) { + var tmp_args, tmp_keys, i, il, key; + + if (Array.isArray(args) && typeof callback === "function") { + return this.send_command("hmset", args, callback); + } + + args = to_array(arguments); + if (typeof args[args.length - 1] === "function") { + callback = args[args.length - 1]; + args.length -= 1; + } else { + callback = null; + } + + if (args.length === 2 && typeof args[0] === "string" && typeof args[1] === "object") { + // User does: client.hmset(key, {key1: val1, key2: val2}) + tmp_args = [ args[0] ]; + tmp_keys = Object.keys(args[1]); + for (i = 0, il = tmp_keys.length; i < il ; i++) { + key = tmp_keys[i]; + tmp_args.push(key); + if (typeof args[1][key] !== "string") { + var err = new Error("hmset expected value to be a string", key, ":", args[1][key]); + if (callback) { + return callback(err); + } else { + throw err; + } + } + tmp_args.push(args[1][key]); + } + args = tmp_args; + } + + return this.send_command("hmset", args, callback); +}; +RedisClient.prototype.HMSET = RedisClient.prototype.hmset; + +Multi.prototype.hmset = function () { + var args = to_array(arguments), tmp_args; + if (args.length >= 2 && typeof args[0] === "string" && typeof args[1] === "object") { + tmp_args = [ "hmset", args[0] ]; + Object.keys(args[1]).map(function (key) { + tmp_args.push(key); + tmp_args.push(args[1][key]); + }); + if (args[2]) { + tmp_args.push(args[2]); + } + args = tmp_args; + } else { + args.unshift("hmset"); + } + + this.queue.push(args); + return this; +}; +Multi.prototype.HMSET = Multi.prototype.hmset; + +Multi.prototype.exec = function (callback) { + var self = this; + + // drain queue, callback will catch "QUEUED" or error + // TODO - get rid of all of these anonymous functions which are elegant but slow + this.queue.forEach(function (args, index) { + var command = args[0], obj; + if (typeof args[args.length - 1] === "function") { + args = args.slice(1, -1); + } else { + args = args.slice(1); + } + if (args.length === 1 && Array.isArray(args[0])) { + args = args[0]; + } + if (command.toLowerCase() === 'hmset' && typeof args[1] === 'object') { + obj = args.pop(); + Object.keys(obj).forEach(function (key) { + args.push(key); + args.push(obj[key]); + }); + } + this.client.send_command(command, args, function (err, reply) { + if (err) { + var cur = self.queue[index]; + if (typeof cur[cur.length - 1] === "function") { + cur[cur.length - 1](err); + } else { + throw new Error(err); + } + self.queue.splice(index, 1); + } + }); + }, this); + + // TODO - make this callback part of Multi.prototype instead of creating it each time + return this.client.send_command("EXEC", [], function (err, replies) { + if (err) { + if (callback) { + callback(new Error(err)); + return; + } else { + throw new Error(err); + } + } + + var i, il, reply, args; + + if (replies) { + for (i = 1, il = self.queue.length; i < il; i += 1) { + reply = replies[i - 1]; + args = self.queue[i]; + + // TODO - confusing and error-prone that hgetall is special cased in two places + if (reply && args[0].toLowerCase() === "hgetall") { + replies[i - 1] = reply = reply_to_object(reply); + } + + if (typeof args[args.length - 1] === "function") { + args[args.length - 1](null, reply); + } + } + } + + if (callback) { + callback(null, replies); + } + }); +}; +Multi.prototype.EXEC = Multi.prototype.exec; + +RedisClient.prototype.multi = function (args) { + return new Multi(this, args); +}; +RedisClient.prototype.MULTI = function (args) { + return new Multi(this, args); +}; + + +// stash original eval method +var eval_orig = RedisClient.prototype.eval; +// hook eval with an attempt to evalsha for cached scripts +RedisClient.prototype.eval = RedisClient.prototype.EVAL = function () { + var self = this, + args = to_array(arguments), + callback; + + if (typeof args[args.length - 1] === "function") { + callback = args.pop(); + } + + // replace script source with sha value + var source = args[0]; + args[0] = crypto.createHash("sha1").update(source).digest("hex"); + + self.evalsha(args, function (err, reply) { + if (err && /NOSCRIPT/.test(err.message)) { + args[0] = source; + eval_orig.call(self, args, callback); + + } else if (callback) { + callback(err, reply); + } + }); +}; + + +exports.createClient = function (port_arg, host_arg, options) { + var port = port_arg || default_port, + host = host_arg || default_host, + redis_client, net_client; + + net_client = net.createConnection(port, host); + + redis_client = new RedisClient(net_client, options); + + redis_client.port = port; + redis_client.host = host; + + return redis_client; +}; + +exports.print = function (err, reply) { + if (err) { + console.log("Error: " + err); + } else { + console.log("Reply: " + reply); + } +}; diff --git a/coder-base/node_modules_orig/redis/lib/commands.js b/coder-base/node_modules_orig/redis/lib/commands.js new file mode 100755 index 00000000..f57cca96 --- /dev/null +++ b/coder-base/node_modules_orig/redis/lib/commands.js @@ -0,0 +1,147 @@ +// This file was generated by ./generate_commands.js on Mon Aug 06 2012 15:04:06 GMT-0700 (PDT) +module.exports = [ + "append", + "auth", + "bgrewriteaof", + "bgsave", + "bitcount", + "bitop", + "blpop", + "brpop", + "brpoplpush", + "client kill", + "client list", + "config get", + "config set", + "config resetstat", + "dbsize", + "debug object", + "debug segfault", + "decr", + "decrby", + "del", + "discard", + "dump", + "echo", + "eval", + "evalsha", + "exec", + "exists", + "expire", + "expireat", + "flushall", + "flushdb", + "get", + "getbit", + "getrange", + "getset", + "hdel", + "hexists", + "hget", + "hgetall", + "hincrby", + "hincrbyfloat", + "hkeys", + "hlen", + "hmget", + "hmset", + "hset", + "hsetnx", + "hvals", + "incr", + "incrby", + "incrbyfloat", + "info", + "keys", + "lastsave", + "lindex", + "linsert", + "llen", + "lpop", + "lpush", + "lpushx", + "lrange", + "lrem", + "lset", + "ltrim", + "mget", + "migrate", + "monitor", + "move", + "mset", + "msetnx", + "multi", + "object", + "persist", + "pexpire", + "pexpireat", + "ping", + "psetex", + "psubscribe", + "pttl", + "publish", + "punsubscribe", + "quit", + "randomkey", + "rename", + "renamenx", + "restore", + "rpop", + "rpoplpush", + "rpush", + "rpushx", + "sadd", + "save", + "scard", + "script exists", + "script flush", + "script kill", + "script load", + "sdiff", + "sdiffstore", + "select", + "set", + "setbit", + "setex", + "setnx", + "setrange", + "shutdown", + "sinter", + "sinterstore", + "sismember", + "slaveof", + "slowlog", + "smembers", + "smove", + "sort", + "spop", + "srandmember", + "srem", + "strlen", + "subscribe", + "sunion", + "sunionstore", + "sync", + "time", + "ttl", + "type", + "unsubscribe", + "unwatch", + "watch", + "zadd", + "zcard", + "zcount", + "zincrby", + "zinterstore", + "zrange", + "zrangebyscore", + "zrank", + "zrem", + "zremrangebyrank", + "zremrangebyscore", + "zrevrange", + "zrevrangebyscore", + "zrevrank", + "zscore", + "zunionstore" +]; diff --git a/coder-base/node_modules_orig/redis/lib/parser/hiredis.js b/coder-base/node_modules_orig/redis/lib/parser/hiredis.js new file mode 100755 index 00000000..940bfeeb --- /dev/null +++ b/coder-base/node_modules_orig/redis/lib/parser/hiredis.js @@ -0,0 +1,46 @@ +var events = require("events"), + util = require("../util"), + hiredis = require("hiredis"); + +exports.debug_mode = false; +exports.name = "hiredis"; + +function HiredisReplyParser(options) { + this.name = exports.name; + this.options = options || {}; + this.reset(); + events.EventEmitter.call(this); +} + +util.inherits(HiredisReplyParser, events.EventEmitter); + +exports.Parser = HiredisReplyParser; + +HiredisReplyParser.prototype.reset = function () { + this.reader = new hiredis.Reader({ + return_buffers: this.options.return_buffers || false + }); +}; + +HiredisReplyParser.prototype.execute = function (data) { + var reply; + this.reader.feed(data); + while (true) { + try { + reply = this.reader.get(); + } catch (err) { + this.emit("error", err); + break; + } + + if (reply === undefined) { + break; + } + + if (reply && reply.constructor === Error) { + this.emit("reply error", reply); + } else { + this.emit("reply", reply); + } + } +}; diff --git a/coder-base/node_modules_orig/redis/lib/parser/javascript.js b/coder-base/node_modules_orig/redis/lib/parser/javascript.js new file mode 100755 index 00000000..256c3ea9 --- /dev/null +++ b/coder-base/node_modules_orig/redis/lib/parser/javascript.js @@ -0,0 +1,298 @@ +var events = require("events"), + util = require("../util"); + +function Packet(type, size) { + this.type = type; + this.size = +size; +} + +exports.name = "javascript"; +exports.debug_mode = false; + +function ReplyParser(options) { + this.name = exports.name; + this.options = options || { }; + + this._buffer = null; + this._offset = 0; + this._encoding = "utf-8"; + this._debug_mode = options.debug_mode; + this._reply_type = null; +} + +util.inherits(ReplyParser, events.EventEmitter); + +exports.Parser = ReplyParser; + +// Buffer.toString() is quite slow for small strings +function small_toString(buf, start, end) { + var tmp = "", i; + + for (i = start; i < end; i++) { + tmp += String.fromCharCode(buf[i]); + } + + return tmp; +} + +ReplyParser.prototype._parseResult = function (type) { + var start, end, offset, packetHeader; + + if (type === 43 || type === 45) { // + or - + // up to the delimiter + end = this._packetEndOffset() - 1; + start = this._offset; + + // include the delimiter + this._offset = end + 2; + + if (end > this._buffer.length) { + this._offset = start; + throw new Error("too far"); + } + + if (this.options.return_buffers) { + return this._buffer.slice(start, end); + } else { + if (end - start < 65536) { // completely arbitrary + return small_toString(this._buffer, start, end); + } else { + return this._buffer.toString(this._encoding, start, end); + } + } + } else if (type === 58) { // : + // up to the delimiter + end = this._packetEndOffset() - 1; + start = this._offset; + + // include the delimiter + this._offset = end + 2; + + if (end > this._buffer.length) { + this._offset = start; + throw new Error("too far"); + } + + if (this.options.return_buffers) { + return this._buffer.slice(start, end); + } + + // return the coerced numeric value + return +small_toString(this._buffer, start, end); + } else if (type === 36) { // $ + // set a rewind point, as the packet could be larger than the + // buffer in memory + offset = this._offset - 1; + + packetHeader = new Packet(type, this.parseHeader()); + + // packets with a size of -1 are considered null + if (packetHeader.size === -1) { + return undefined; + } + + end = this._offset + packetHeader.size; + start = this._offset; + + // set the offset to after the delimiter + this._offset = end + 2; + + if (end > this._buffer.length) { + this._offset = offset; + throw new Error("too far"); + } + + if (this.options.return_buffers) { + return this._buffer.slice(start, end); + } else { + return this._buffer.toString(this._encoding, start, end); + } + } else if (type === 42) { // * + offset = this._offset; + packetHeader = new Packet(type, this.parseHeader()); + + if (packetHeader.size > this._bytesRemaining()) { + this._offset = offset - 1; + return -1; + } + + if (packetHeader.size < 0) { + this._offset += 2; + return null; + } + + var reply = [ ]; + var ntype, i, res; + + offset = this._offset - 1; + + for (i = 0; i < packetHeader.size; i++) { + ntype = this._buffer[this._offset++]; + + if (this._offset > this._buffer.length) { + throw new Error("too far"); + } + res = this._parseResult(ntype); + if (res === undefined) { + res = null; + } + reply.push(res); + } + + return reply; + } +}; + +ReplyParser.prototype.execute = function (buffer) { + this.append(buffer); + + var type, ret, offset; + + while (true) { + offset = this._offset; + try { + // at least 4 bytes: :1\r\n + if (this._bytesRemaining() < 4) { + break; + } + + type = this._buffer[this._offset++]; + + if (type === 43) { // + + ret = this._parseResult(type); + + if (ret === null) { + break; + } + + this.send_reply(ret); + } else if (type === 45) { // - + ret = this._parseResult(type); + + if (ret === null) { + break; + } + + this.send_error(ret); + } else if (type === 58) { // : + ret = this._parseResult(type); + + if (ret === null) { + break; + } + + this.send_reply(ret); + } else if (type === 36) { // $ + ret = this._parseResult(type); + + if (ret === null) { + break; + } + + // check the state for what is the result of + // a -1, set it back up for a null reply + if (ret === undefined) { + ret = null; + } + + this.send_reply(ret); + } else if (type === 42) { // * + // set a rewind point. if a failure occurs, + // wait for the next execute()/append() and try again + offset = this._offset - 1; + + ret = this._parseResult(type); + + if (ret === -1) { + this._offset = offset; + break; + } + + this.send_reply(ret); + } + } catch (err) { + // catch the error (not enough data), rewind, and wait + // for the next packet to appear + this._offset = offset; + break; + } + } +}; + +ReplyParser.prototype.append = function (newBuffer) { + if (!newBuffer) { + return; + } + + // first run + if (this._buffer === null) { + this._buffer = newBuffer; + + return; + } + + // out of data + if (this._offset >= this._buffer.length) { + this._buffer = newBuffer; + this._offset = 0; + + return; + } + + // very large packet + // check for concat, if we have it, use it + if (Buffer.concat !== undefined) { + this._buffer = Buffer.concat([this._buffer.slice(this._offset), newBuffer]); + } else { + var remaining = this._bytesRemaining(), + newLength = remaining + newBuffer.length, + tmpBuffer = new Buffer(newLength); + + this._buffer.copy(tmpBuffer, 0, this._offset); + newBuffer.copy(tmpBuffer, remaining, 0); + + this._buffer = tmpBuffer; + } + + this._offset = 0; +}; + +ReplyParser.prototype.parseHeader = function () { + var end = this._packetEndOffset(), + value = small_toString(this._buffer, this._offset, end - 1); + + this._offset = end + 1; + + return value; +}; + +ReplyParser.prototype._packetEndOffset = function () { + var offset = this._offset; + + while (this._buffer[offset] !== 0x0d && this._buffer[offset + 1] !== 0x0a) { + offset++; + + if (offset >= this._buffer.length) { + throw new Error("didn't see LF after NL reading multi bulk count (" + offset + " => " + this._buffer.length + ", " + this._offset + ")"); + } + } + + offset++; + return offset; +}; + +ReplyParser.prototype._bytesRemaining = function () { + return (this._buffer.length - this._offset) < 0 ? 0 : (this._buffer.length - this._offset); +}; + +ReplyParser.prototype.parser_error = function (message) { + this.emit("error", message); +}; + +ReplyParser.prototype.send_error = function (reply) { + this.emit("reply error", reply); +}; + +ReplyParser.prototype.send_reply = function (reply) { + this.emit("reply", reply); +}; \ No newline at end of file diff --git a/coder-base/node_modules_orig/redis/lib/queue.js b/coder-base/node_modules_orig/redis/lib/queue.js new file mode 100755 index 00000000..3fc87ab1 --- /dev/null +++ b/coder-base/node_modules_orig/redis/lib/queue.js @@ -0,0 +1,59 @@ +// Queue class adapted from Tim Caswell's pattern library +// http://github.com/creationix/pattern/blob/master/lib/pattern/queue.js + +function Queue() { + this.tail = []; + this.head = []; + this.offset = 0; +} + +Queue.prototype.shift = function () { + if (this.offset === this.head.length) { + var tmp = this.head; + tmp.length = 0; + this.head = this.tail; + this.tail = tmp; + this.offset = 0; + if (this.head.length === 0) { + return; + } + } + return this.head[this.offset++]; // sorry, JSLint +}; + +Queue.prototype.push = function (item) { + return this.tail.push(item); +}; + +Queue.prototype.forEach = function (fn, thisv) { + var array = this.head.slice(this.offset), i, il; + + array.push.apply(array, this.tail); + + if (thisv) { + for (i = 0, il = array.length; i < il; i += 1) { + fn.call(thisv, array[i], i, array); + } + } else { + for (i = 0, il = array.length; i < il; i += 1) { + fn(array[i], i, array); + } + } + + return array; +}; + +Queue.prototype.getLength = function () { + return this.head.length - this.offset + this.tail.length; +}; + +Object.defineProperty(Queue.prototype, "length", { + get: function () { + return this.getLength(); + } +}); + + +if (typeof module !== "undefined" && module.exports) { + module.exports = Queue; +} diff --git a/coder-base/node_modules_orig/redis/lib/to_array.js b/coder-base/node_modules_orig/redis/lib/to_array.js new file mode 100755 index 00000000..88a57e18 --- /dev/null +++ b/coder-base/node_modules_orig/redis/lib/to_array.js @@ -0,0 +1,12 @@ +function to_array(args) { + var len = args.length, + arr = new Array(len), i; + + for (i = 0; i < len; i += 1) { + arr[i] = args[i]; + } + + return arr; +} + +module.exports = to_array; diff --git a/coder-base/node_modules_orig/redis/lib/util.js b/coder-base/node_modules_orig/redis/lib/util.js new file mode 100755 index 00000000..fc255ae9 --- /dev/null +++ b/coder-base/node_modules_orig/redis/lib/util.js @@ -0,0 +1,11 @@ +// Support for very old versions of node where the module was called "sys". At some point, we should abandon this. + +var util; + +try { + util = require("util"); +} catch (err) { + util = require("sys"); +} + +module.exports = util; diff --git a/coder-base/node_modules_orig/redis/multi_bench.js b/coder-base/node_modules_orig/redis/multi_bench.js new file mode 100755 index 00000000..3a0d92da --- /dev/null +++ b/coder-base/node_modules_orig/redis/multi_bench.js @@ -0,0 +1,222 @@ +var redis = require("./index"), + metrics = require("metrics"), + num_clients = parseInt(process.argv[2], 10) || 5, + num_requests = 20000, + tests = [], + versions_logged = false, + client_options = { + return_buffers: false + }, + small_str, large_str, small_buf, large_buf; + +redis.debug_mode = false; + +function lpad(input, len, chr) { + var str = input.toString(); + chr = chr || " "; + + while (str.length < len) { + str = chr + str; + } + return str; +} + +metrics.Histogram.prototype.print_line = function () { + var obj = this.printObj(); + + return lpad(obj.min, 4) + "/" + lpad(obj.max, 4) + "/" + lpad(obj.mean.toFixed(2), 7) + "/" + lpad(obj.p95.toFixed(2), 7); +}; + +function Test(args) { + this.args = args; + + this.callback = null; + this.clients = []; + this.clients_ready = 0; + this.commands_sent = 0; + this.commands_completed = 0; + this.max_pipeline = this.args.pipeline || num_requests; + this.client_options = args.client_options || client_options; + + this.connect_latency = new metrics.Histogram(); + this.ready_latency = new metrics.Histogram(); + this.command_latency = new metrics.Histogram(); +} + +Test.prototype.run = function (callback) { + var i; + + this.callback = callback; + + for (i = 0; i < num_clients ; i++) { + this.new_client(i); + } +}; + +Test.prototype.new_client = function (id) { + var self = this, new_client; + + new_client = redis.createClient(6379, "127.0.0.1", this.client_options); + new_client.create_time = Date.now(); + + new_client.on("connect", function () { + self.connect_latency.update(Date.now() - new_client.create_time); + }); + + new_client.on("ready", function () { + if (! versions_logged) { + console.log("Client count: " + num_clients + ", node version: " + process.versions.node + ", server version: " + + new_client.server_info.redis_version + ", parser: " + new_client.reply_parser.name); + versions_logged = true; + } + self.ready_latency.update(Date.now() - new_client.create_time); + self.clients_ready++; + if (self.clients_ready === self.clients.length) { + self.on_clients_ready(); + } + }); + + self.clients[id] = new_client; +}; + +Test.prototype.on_clients_ready = function () { + process.stdout.write(lpad(this.args.descr, 13) + ", " + lpad(this.args.pipeline, 5) + "/" + this.clients_ready + " "); + this.test_start = Date.now(); + + this.fill_pipeline(); +}; + +Test.prototype.fill_pipeline = function () { + var pipeline = this.commands_sent - this.commands_completed; + + while (this.commands_sent < num_requests && pipeline < this.max_pipeline) { + this.commands_sent++; + pipeline++; + this.send_next(); + } + + if (this.commands_completed === num_requests) { + this.print_stats(); + this.stop_clients(); + } +}; + +Test.prototype.stop_clients = function () { + var self = this; + + this.clients.forEach(function (client, pos) { + if (pos === self.clients.length - 1) { + client.quit(function (err, res) { + self.callback(); + }); + } else { + client.quit(); + } + }); +}; + +Test.prototype.send_next = function () { + var self = this, + cur_client = this.commands_sent % this.clients.length, + start = Date.now(); + + this.clients[cur_client][this.args.command](this.args.args, function (err, res) { + if (err) { + throw err; + } + self.commands_completed++; + self.command_latency.update(Date.now() - start); + self.fill_pipeline(); + }); +}; + +Test.prototype.print_stats = function () { + var duration = Date.now() - this.test_start; + + console.log("min/max/avg/p95: " + this.command_latency.print_line() + " " + lpad(duration, 6) + "ms total, " + + lpad((num_requests / (duration / 1000)).toFixed(2), 8) + " ops/sec"); +}; + +small_str = "1234"; +small_buf = new Buffer(small_str); +large_str = (new Array(4097).join("-")); +large_buf = new Buffer(large_str); + +tests.push(new Test({descr: "PING", command: "ping", args: [], pipeline: 1})); +tests.push(new Test({descr: "PING", command: "ping", args: [], pipeline: 50})); +tests.push(new Test({descr: "PING", command: "ping", args: [], pipeline: 200})); +tests.push(new Test({descr: "PING", command: "ping", args: [], pipeline: 20000})); + +tests.push(new Test({descr: "SET small str", command: "set", args: ["foo_rand000000000000", small_str], pipeline: 1})); +tests.push(new Test({descr: "SET small str", command: "set", args: ["foo_rand000000000000", small_str], pipeline: 50})); +tests.push(new Test({descr: "SET small str", command: "set", args: ["foo_rand000000000000", small_str], pipeline: 200})); +tests.push(new Test({descr: "SET small str", command: "set", args: ["foo_rand000000000000", small_str], pipeline: 20000})); + +tests.push(new Test({descr: "SET small buf", command: "set", args: ["foo_rand000000000000", small_buf], pipeline: 1})); +tests.push(new Test({descr: "SET small buf", command: "set", args: ["foo_rand000000000000", small_buf], pipeline: 50})); +tests.push(new Test({descr: "SET small buf", command: "set", args: ["foo_rand000000000000", small_buf], pipeline: 200})); +tests.push(new Test({descr: "SET small buf", command: "set", args: ["foo_rand000000000000", small_buf], pipeline: 20000})); + +tests.push(new Test({descr: "GET small str", command: "get", args: ["foo_rand000000000000"], pipeline: 1})); +tests.push(new Test({descr: "GET small str", command: "get", args: ["foo_rand000000000000"], pipeline: 50})); +tests.push(new Test({descr: "GET small str", command: "get", args: ["foo_rand000000000000"], pipeline: 200})); +tests.push(new Test({descr: "GET small str", command: "get", args: ["foo_rand000000000000"], pipeline: 20000})); + +tests.push(new Test({descr: "GET small buf", command: "get", args: ["foo_rand000000000000"], pipeline: 1, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET small buf", command: "get", args: ["foo_rand000000000000"], pipeline: 50, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET small buf", command: "get", args: ["foo_rand000000000000"], pipeline: 200, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET small buf", command: "get", args: ["foo_rand000000000000"], pipeline: 20000, client_opts: { return_buffers: true} })); + +tests.push(new Test({descr: "SET large str", command: "set", args: ["foo_rand000000000001", large_str], pipeline: 1})); +tests.push(new Test({descr: "SET large str", command: "set", args: ["foo_rand000000000001", large_str], pipeline: 50})); +tests.push(new Test({descr: "SET large str", command: "set", args: ["foo_rand000000000001", large_str], pipeline: 200})); +tests.push(new Test({descr: "SET large str", command: "set", args: ["foo_rand000000000001", large_str], pipeline: 20000})); + +tests.push(new Test({descr: "SET large buf", command: "set", args: ["foo_rand000000000001", large_buf], pipeline: 1})); +tests.push(new Test({descr: "SET large buf", command: "set", args: ["foo_rand000000000001", large_buf], pipeline: 50})); +tests.push(new Test({descr: "SET large buf", command: "set", args: ["foo_rand000000000001", large_buf], pipeline: 200})); +tests.push(new Test({descr: "SET large buf", command: "set", args: ["foo_rand000000000001", large_buf], pipeline: 20000})); + +tests.push(new Test({descr: "GET large str", command: "get", args: ["foo_rand000000000001"], pipeline: 1})); +tests.push(new Test({descr: "GET large str", command: "get", args: ["foo_rand000000000001"], pipeline: 50})); +tests.push(new Test({descr: "GET large str", command: "get", args: ["foo_rand000000000001"], pipeline: 200})); +tests.push(new Test({descr: "GET large str", command: "get", args: ["foo_rand000000000001"], pipeline: 20000})); + +tests.push(new Test({descr: "GET large buf", command: "get", args: ["foo_rand000000000001"], pipeline: 1, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET large buf", command: "get", args: ["foo_rand000000000001"], pipeline: 50, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET large buf", command: "get", args: ["foo_rand000000000001"], pipeline: 200, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET large buf", command: "get", args: ["foo_rand000000000001"], pipeline: 20000, client_opts: { return_buffers: true} })); + +tests.push(new Test({descr: "INCR", command: "incr", args: ["counter_rand000000000000"], pipeline: 1})); +tests.push(new Test({descr: "INCR", command: "incr", args: ["counter_rand000000000000"], pipeline: 50})); +tests.push(new Test({descr: "INCR", command: "incr", args: ["counter_rand000000000000"], pipeline: 200})); +tests.push(new Test({descr: "INCR", command: "incr", args: ["counter_rand000000000000"], pipeline: 20000})); + +tests.push(new Test({descr: "LPUSH", command: "lpush", args: ["mylist", small_str], pipeline: 1})); +tests.push(new Test({descr: "LPUSH", command: "lpush", args: ["mylist", small_str], pipeline: 50})); +tests.push(new Test({descr: "LPUSH", command: "lpush", args: ["mylist", small_str], pipeline: 200})); +tests.push(new Test({descr: "LPUSH", command: "lpush", args: ["mylist", small_str], pipeline: 20000})); + +tests.push(new Test({descr: "LRANGE 10", command: "lrange", args: ["mylist", "0", "9"], pipeline: 1})); +tests.push(new Test({descr: "LRANGE 10", command: "lrange", args: ["mylist", "0", "9"], pipeline: 50})); +tests.push(new Test({descr: "LRANGE 10", command: "lrange", args: ["mylist", "0", "9"], pipeline: 200})); +tests.push(new Test({descr: "LRANGE 10", command: "lrange", args: ["mylist", "0", "9"], pipeline: 20000})); + +tests.push(new Test({descr: "LRANGE 100", command: "lrange", args: ["mylist", "0", "99"], pipeline: 1})); +tests.push(new Test({descr: "LRANGE 100", command: "lrange", args: ["mylist", "0", "99"], pipeline: 50})); +tests.push(new Test({descr: "LRANGE 100", command: "lrange", args: ["mylist", "0", "99"], pipeline: 200})); +tests.push(new Test({descr: "LRANGE 100", command: "lrange", args: ["mylist", "0", "99"], pipeline: 20000})); + +function next() { + var test = tests.shift(); + if (test) { + test.run(function () { + next(); + }); + } else { + console.log("End of tests."); + process.exit(0); + } +} + +next(); diff --git a/coder-base/node_modules_orig/redis/package.json b/coder-base/node_modules_orig/redis/package.json new file mode 100755 index 00000000..03f5917b --- /dev/null +++ b/coder-base/node_modules_orig/redis/package.json @@ -0,0 +1,38 @@ +{ + "name": "redis", + "version": "0.8.2", + "description": "Redis client library", + "keywords": [ + "redis", + "database" + ], + "author": { + "name": "Matt Ranney", + "email": "mjr@ranney.com" + }, + "main": "./index.js", + "scripts": { + "test": "node ./test.js" + }, + "devDependencies": { + "metrics": ">=0.1.5" + }, + "repository": { + "type": "git", + "url": "git://github.com/mranney/node_redis.git" + }, + "_id": "redis@0.8.2", + "dependencies": {}, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "_engineSupported": true, + "_npmVersion": "1.1.4", + "_nodeVersion": "v0.6.19", + "_defaultsLoaded": true, + "dist": { + "shasum": "681387aab7b9bc8915f1f25c2e12aa7b0a96516e" + }, + "_from": "redis@*" +} diff --git a/coder-base/node_modules_orig/redis/test.js b/coder-base/node_modules_orig/redis/test.js new file mode 100755 index 00000000..94bd19d6 --- /dev/null +++ b/coder-base/node_modules_orig/redis/test.js @@ -0,0 +1,1675 @@ +/*global require console setTimeout process Buffer */ +var PORT = 6379; +var HOST = '127.0.0.1'; + +var redis = require("./index"), + client = redis.createClient(PORT, HOST), + client2 = redis.createClient(PORT, HOST), + client3 = redis.createClient(PORT, HOST), + bclient = redis.createClient(PORT, HOST, { return_buffers: true }), + assert = require("assert"), + crypto = require("crypto"), + util = require("./lib/util"), + test_db_num = 15, // this DB will be flushed and used for testing + tests = {}, + connected = false, + ended = false, + next, cur_start, run_next_test, all_tests, all_start, test_count; + +// Set this to truthy to see the wire protocol and other debugging info +redis.debug_mode = process.argv[2]; + +function buffers_to_strings(arr) { + return arr.map(function (val) { + return val.toString(); + }); +} + +function require_number(expected, label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected " + expected + ", got error: " + err); + assert.strictEqual(expected, results, label + " " + expected + " !== " + results); + assert.strictEqual(typeof results, "number", label); + return true; + }; +} + +function require_number_any(label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected any number, got error: " + err); + assert.strictEqual(typeof results, "number", label + " " + results + " is not a number"); + return true; + }; +} + +function require_number_pos(label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected positive number, got error: " + err); + assert.strictEqual(true, (results > 0), label + " " + results + " is not a positive number"); + return true; + }; +} + +function require_string(str, label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected string '" + str + "', got error: " + err); + assert.equal(str, results, label + " " + str + " does not match " + results); + return true; + }; +} + +function require_null(label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected null, got error: " + err); + assert.strictEqual(null, results, label + ": " + results + " is not null"); + return true; + }; +} + +function require_error(label) { + return function (err, results) { + assert.notEqual(err, null, label + " err is null, but an error is expected here."); + return true; + }; +} + +function is_empty_array(obj) { + return Array.isArray(obj) && obj.length === 0; +} + +function last(name, fn) { + return function (err, results) { + fn(err, results); + next(name); + }; +} + +next = function next(name) { + console.log(" \x1b[33m" + (Date.now() - cur_start) + "\x1b[0m ms"); + run_next_test(); +}; + +// Tests are run in the order they are defined, so FLUSHDB should always be first. + +tests.FLUSHDB = function () { + var name = "FLUSHDB"; + client.select(test_db_num, require_string("OK", name)); + client2.select(test_db_num, require_string("OK", name)); + client3.select(test_db_num, require_string("OK", name)); + client.mset("flush keys 1", "flush val 1", "flush keys 2", "flush val 2", require_string("OK", name)); + client.FLUSHDB(require_string("OK", name)); + client.dbsize(last(name, require_number(0, name))); +}; + +tests.INCR = function () { + var name = "INCR"; + + // Test incr with the maximum JavaScript number value. Since we are + // returning buffers we should get back one more as a Buffer. + bclient.set("seq", "9007199254740992", function (err, result) { + assert.strictEqual(result.toString(), "OK"); + bclient.incr("seq", function (err, result) { + assert.strictEqual("9007199254740993", result.toString()); + next(name); + }); + }); +}; + +tests.MULTI_1 = function () { + var name = "MULTI_1", multi1, multi2; + + // Provoke an error at queue time + multi1 = client.multi(); + multi1.mset("multifoo", "10", "multibar", "20", require_string("OK", name)); + multi1.set("foo2", require_error(name)); + multi1.incr("multifoo", require_number(11, name)); + multi1.incr("multibar", require_number(21, name)); + multi1.exec(); + + // Confirm that the previous command, while containing an error, still worked. + multi2 = client.multi(); + multi2.incr("multibar", require_number(22, name)); + multi2.incr("multifoo", require_number(12, name)); + multi2.exec(function (err, replies) { + assert.strictEqual(22, replies[0]); + assert.strictEqual(12, replies[1]); + next(name); + }); +}; + +tests.MULTI_2 = function () { + var name = "MULTI_2"; + + // test nested multi-bulk replies + client.multi([ + ["mget", "multifoo", "multibar", function (err, res) { + assert.strictEqual(2, res.length, name); + assert.strictEqual("12", res[0].toString(), name); + assert.strictEqual("22", res[1].toString(), name); + }], + ["set", "foo2", require_error(name)], + ["incr", "multifoo", require_number(13, name)], + ["incr", "multibar", require_number(23, name)] + ]).exec(function (err, replies) { + assert.strictEqual(2, replies[0].length, name); + assert.strictEqual("12", replies[0][0].toString(), name); + assert.strictEqual("22", replies[0][1].toString(), name); + + assert.strictEqual("13", replies[1].toString()); + assert.strictEqual("23", replies[2].toString()); + next(name); + }); +}; + +tests.MULTI_3 = function () { + var name = "MULTI_3"; + + client.sadd("some set", "mem 1"); + client.sadd("some set", "mem 2"); + client.sadd("some set", "mem 3"); + client.sadd("some set", "mem 4"); + + // make sure empty mb reply works + client.del("some missing set"); + client.smembers("some missing set", function (err, reply) { + // make sure empty mb reply works + assert.strictEqual(true, is_empty_array(reply), name); + }); + + // test nested multi-bulk replies with empty mb elements. + client.multi([ + ["smembers", "some set"], + ["del", "some set"], + ["smembers", "some set"] + ]) + .scard("some set") + .exec(function (err, replies) { + assert.strictEqual(true, is_empty_array(replies[2]), name); + next(name); + }); +}; + +tests.MULTI_4 = function () { + var name = "MULTI_4"; + + client.multi() + .mset('some', '10', 'keys', '20') + .incr('some') + .incr('keys') + .mget('some', 'keys') + .exec(function (err, replies) { + assert.strictEqual(null, err); + assert.equal('OK', replies[0]); + assert.equal(11, replies[1]); + assert.equal(21, replies[2]); + assert.equal(11, replies[3][0].toString()); + assert.equal(21, replies[3][1].toString()); + next(name); + }); +}; + +tests.MULTI_5 = function () { + var name = "MULTI_5"; + + // test nested multi-bulk replies with nulls. + client.multi([ + ["mget", ["multifoo", "some", "random value", "keys"]], + ["incr", "multifoo"] + ]) + .exec(function (err, replies) { + assert.strictEqual(replies.length, 2, name); + assert.strictEqual(replies[0].length, 4, name); + next(name); + }); +}; + +tests.MULTI_6 = function () { + var name = "MULTI_6"; + + client.multi() + .hmset("multihash", "a", "foo", "b", 1) + .hmset("multihash", { + extra: "fancy", + things: "here" + }) + .hgetall("multihash") + .exec(function (err, replies) { + assert.strictEqual(null, err); + assert.equal("OK", replies[0]); + assert.equal(Object.keys(replies[2]).length, 4); + assert.equal("foo", replies[2].a); + assert.equal("1", replies[2].b); + assert.equal("fancy", replies[2].extra); + assert.equal("here", replies[2].things); + next(name); + }); +}; + +tests.EVAL_1 = function () { + var name = "EVAL_1"; + + if (client.server_info.versions[0] >= 2 && client.server_info.versions[1] >= 5) { + // test {EVAL - Lua integer -> Redis protocol type conversion} + client.eval("return 100.5", 0, require_number(100, name)); + // test {EVAL - Lua string -> Redis protocol type conversion} + client.eval("return 'hello world'", 0, require_string("hello world", name)); + // test {EVAL - Lua true boolean -> Redis protocol type conversion} + client.eval("return true", 0, require_number(1, name)); + // test {EVAL - Lua false boolean -> Redis protocol type conversion} + client.eval("return false", 0, require_null(name)); + // test {EVAL - Lua status code reply -> Redis protocol type conversion} + client.eval("return {ok='fine'}", 0, require_string("fine", name)); + // test {EVAL - Lua error reply -> Redis protocol type conversion} + client.eval("return {err='this is an error'}", 0, require_error(name)); + // test {EVAL - Lua table -> Redis protocol type conversion} + client.eval("return {1,2,3,'ciao',{1,2}}", 0, function (err, res) { + assert.strictEqual(5, res.length, name); + assert.strictEqual(1, res[0], name); + assert.strictEqual(2, res[1], name); + assert.strictEqual(3, res[2], name); + assert.strictEqual("ciao", res[3], name); + assert.strictEqual(2, res[4].length, name); + assert.strictEqual(1, res[4][0], name); + assert.strictEqual(2, res[4][1], name); + }); + // test {EVAL - Are the KEYS and ARGS arrays populated correctly?} + client.eval("return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}", 2, "a", "b", "c", "d", function (err, res) { + assert.strictEqual(4, res.length, name); + assert.strictEqual("a", res[0], name); + assert.strictEqual("b", res[1], name); + assert.strictEqual("c", res[2], name); + assert.strictEqual("d", res[3], name); + }); + + // prepare sha sum for evalsha cache test + var source = "return redis.call('get', 'sha test')", + sha = crypto.createHash('sha1').update(source).digest('hex'); + + client.set("sha test", "eval get sha test", function (err, res) { + if (err) throw err; + // test {EVAL - is Lua able to call Redis API?} + client.eval(source, 0, function (err, res) { + require_string("eval get sha test", name)(err, res); + // test {EVALSHA - Can we call a SHA1 if already defined?} + client.evalsha(sha, 0, require_string("eval get sha test", name)); + // test {EVALSHA - Do we get an error on non defined SHA1?} + client.evalsha("ffffffffffffffffffffffffffffffffffffffff", 0, require_error(name)); + }); + }); + + // test {EVAL - Redis integer -> Lua type conversion} + client.set("incr key", 0, function (err, reply) { + if (err) throw err; + client.eval("local foo = redis.call('incr','incr key')\n" + "return {type(foo),foo}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("number", res[0], name); + assert.strictEqual(1, res[1], name); + }); + }); + + client.set("bulk reply key", "bulk reply value", function (err, res) { + // test {EVAL - Redis bulk -> Lua type conversion} + client.eval("local foo = redis.call('get','bulk reply key'); return {type(foo),foo}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("string", res[0], name); + assert.strictEqual("bulk reply value", res[1], name); + }); + }); + + // test {EVAL - Redis multi bulk -> Lua type conversion} + client.multi() + .del("mylist") + .rpush("mylist", "a") + .rpush("mylist", "b") + .rpush("mylist", "c") + .exec(function (err, replies) { + if (err) throw err; + client.eval("local foo = redis.call('lrange','mylist',0,-1); return {type(foo),foo[1],foo[2],foo[3],# foo}", 0, function (err, res) { + assert.strictEqual(5, res.length, name); + assert.strictEqual("table", res[0], name); + assert.strictEqual("a", res[1], name); + assert.strictEqual("b", res[2], name); + assert.strictEqual("c", res[3], name); + assert.strictEqual(3, res[4], name); + }); + }); + // test {EVAL - Redis status reply -> Lua type conversion} + client.eval("local foo = redis.call('set','mykey','myval'); return {type(foo),foo['ok']}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("table", res[0], name); + assert.strictEqual("OK", res[1], name); + }); + // test {EVAL - Redis error reply -> Lua type conversion} + client.set("error reply key", "error reply value", function (err, res) { + if (err) throw err; + client.eval("local foo = redis.pcall('incr','error reply key'); return {type(foo),foo['err']}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("table", res[0], name); + assert.strictEqual("ERR value is not an integer or out of range", res[1], name); + }); + }); + // test {EVAL - Redis nil bulk reply -> Lua type conversion} + client.del("nil reply key", function (err, res) { + if (err) throw err; + client.eval("local foo = redis.call('get','nil reply key'); return {type(foo),foo == false}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("boolean", res[0], name); + assert.strictEqual(1, res[1], name); + next(name); + }); + }); + } else { + console.log("Skipping " + name + " because server version isn't new enough."); + next(name); + } +}; + +tests.WATCH_MULTI = function () { + var name = 'WATCH_MULTI', multi; + + if (client.server_info.versions[0] >= 2 && client.server_info.versions[1] >= 1) { + client.watch(name); + client.incr(name); + multi = client.multi(); + multi.incr(name); + multi.exec(last(name, require_null(name))); + } else { + console.log("Skipping " + name + " because server version isn't new enough."); + next(name); + } +}; + +tests.detect_buffers = function () { + var name = "detect_buffers", detect_client = redis.createClient(null, null, {detect_buffers: true}); + + detect_client.on("ready", function () { + // single Buffer or String + detect_client.set("string key 1", "string value"); + detect_client.get("string key 1", require_string("string value", name)); + detect_client.get(new Buffer("string key 1"), function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual(true, Buffer.isBuffer(reply), name); + assert.strictEqual("", reply.inspect(), name); + }); + + detect_client.hmset("hash key 2", "key 1", "val 1", "key 2", "val 2"); + // array of Buffers or Strings + detect_client.hmget("hash key 2", "key 1", "key 2", function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual(true, Array.isArray(reply), name); + assert.strictEqual(2, reply.length, name); + assert.strictEqual("val 1", reply[0], name); + assert.strictEqual("val 2", reply[1], name); + }); + detect_client.hmget(new Buffer("hash key 2"), "key 1", "key 2", function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual(true, Array.isArray(reply)); + assert.strictEqual(2, reply.length, name); + assert.strictEqual(true, Buffer.isBuffer(reply[0])); + assert.strictEqual(true, Buffer.isBuffer(reply[1])); + assert.strictEqual("", reply[0].inspect(), name); + assert.strictEqual("", reply[1].inspect(), name); + }); + + // Object of Buffers or Strings + detect_client.hgetall("hash key 2", function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual("object", typeof reply, name); + assert.strictEqual(2, Object.keys(reply).length, name); + assert.strictEqual("val 1", reply["key 1"], name); + assert.strictEqual("val 2", reply["key 2"], name); + }); + detect_client.hgetall(new Buffer("hash key 2"), function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual("object", typeof reply, name); + assert.strictEqual(2, Object.keys(reply).length, name); + assert.strictEqual(true, Buffer.isBuffer(reply["key 1"])); + assert.strictEqual(true, Buffer.isBuffer(reply["key 2"])); + assert.strictEqual("", reply["key 1"].inspect(), name); + assert.strictEqual("", reply["key 2"].inspect(), name); + }); + + detect_client.quit(function (err, res) { + next(name); + }); + }); +}; + +tests.socket_nodelay = function () { + var name = "socket_nodelay", c1, c2, c3, ready_count = 0, quit_count = 0; + + c1 = redis.createClient(null, null, {socket_nodelay: true}); + c2 = redis.createClient(null, null, {socket_nodelay: false}); + c3 = redis.createClient(null, null); + + function quit_check() { + quit_count++; + + if (quit_count === 3) { + next(name); + } + } + + function run() { + assert.strictEqual(true, c1.options.socket_nodelay, name); + assert.strictEqual(false, c2.options.socket_nodelay, name); + assert.strictEqual(true, c3.options.socket_nodelay, name); + + c1.set(["set key 1", "set val"], require_string("OK", name)); + c1.set(["set key 2", "set val"], require_string("OK", name)); + c1.get(["set key 1"], require_string("set val", name)); + c1.get(["set key 2"], require_string("set val", name)); + + c2.set(["set key 3", "set val"], require_string("OK", name)); + c2.set(["set key 4", "set val"], require_string("OK", name)); + c2.get(["set key 3"], require_string("set val", name)); + c2.get(["set key 4"], require_string("set val", name)); + + c3.set(["set key 5", "set val"], require_string("OK", name)); + c3.set(["set key 6", "set val"], require_string("OK", name)); + c3.get(["set key 5"], require_string("set val", name)); + c3.get(["set key 6"], require_string("set val", name)); + + c1.quit(quit_check); + c2.quit(quit_check); + c3.quit(quit_check); + } + + function ready_check() { + ready_count++; + if (ready_count === 3) { + run(); + } + } + + c1.on("ready", ready_check); + c2.on("ready", ready_check); + c3.on("ready", ready_check); +}; + +tests.reconnect = function () { + var name = "reconnect"; + + client.set("recon 1", "one"); + client.set("recon 2", "two", function (err, res) { + // Do not do this in normal programs. This is to simulate the server closing on us. + // For orderly shutdown in normal programs, do client.quit() + client.stream.destroy(); + }); + + client.on("reconnecting", function on_recon(params) { + client.on("connect", function on_connect() { + client.select(test_db_num, require_string("OK", name)); + client.get("recon 1", require_string("one", name)); + client.get("recon 1", require_string("one", name)); + client.get("recon 2", require_string("two", name)); + client.get("recon 2", require_string("two", name)); + client.removeListener("connect", on_connect); + client.removeListener("reconnecting", on_recon); + next(name); + }); + }); +}; + +tests.idle = function () { + var name = "idle"; + + client.on("idle", function on_idle() { + client.removeListener("idle", on_idle); + next(name); + }); + + client.set("idle", "test"); +}; + +tests.HSET = function () { + var key = "test hash", + field1 = new Buffer("0123456789"), + value1 = new Buffer("abcdefghij"), + field2 = new Buffer(0), + value2 = new Buffer(0), + name = "HSET"; + + client.HSET(key, field1, value1, require_number(1, name)); + client.HGET(key, field1, require_string(value1.toString(), name)); + + // Empty value + client.HSET(key, field1, value2, require_number(0, name)); + client.HGET([key, field1], require_string("", name)); + + // Empty key, empty value + client.HSET([key, field2, value1], require_number(1, name)); + client.HSET(key, field2, value2, last(name, require_number(0, name))); +}; + +tests.HLEN = function () { + var key = "test hash", + field1 = new Buffer("0123456789"), + value1 = new Buffer("abcdefghij"), + field2 = new Buffer(0), + value2 = new Buffer(0), + name = "HSET", + timeout = 1000; + + client.HSET(key, field1, value1, function (err, results) { + client.HLEN(key, function (err, len) { + assert.ok(2 === +len); + next(name); + }); + }); +} + +tests.HMSET_BUFFER_AND_ARRAY = function () { + // Saving a buffer and an array to the same key should not error + var key = "test hash", + field1 = "buffer", + value1 = new Buffer("abcdefghij"), + field2 = "array", + value2 = ["array contents"], + name = "HSET"; + + client.HMSET(key, field1, value1, field2, value2, last(name, require_string("OK", name))); +}; + +// TODO - add test for HMSET with optional callbacks + +tests.HMGET = function () { + var key1 = "test hash 1", key2 = "test hash 2", name = "HMGET"; + + // redis-like hmset syntax + client.HMSET(key1, "0123456789", "abcdefghij", "some manner of key", "a type of value", require_string("OK", name)); + + // fancy hmset syntax + client.HMSET(key2, { + "0123456789": "abcdefghij", + "some manner of key": "a type of value" + }, require_string("OK", name)); + + client.HMGET(key1, "0123456789", "some manner of key", function (err, reply) { + assert.strictEqual("abcdefghij", reply[0].toString(), name); + assert.strictEqual("a type of value", reply[1].toString(), name); + }); + + client.HMGET(key2, "0123456789", "some manner of key", function (err, reply) { + assert.strictEqual("abcdefghij", reply[0].toString(), name); + assert.strictEqual("a type of value", reply[1].toString(), name); + }); + + client.HMGET(key1, ["0123456789"], function (err, reply) { + assert.strictEqual("abcdefghij", reply[0], name); + }); + + client.HMGET(key1, ["0123456789", "some manner of key"], function (err, reply) { + assert.strictEqual("abcdefghij", reply[0], name); + assert.strictEqual("a type of value", reply[1], name); + }); + + client.HMGET(key1, "missing thing", "another missing thing", function (err, reply) { + assert.strictEqual(null, reply[0], name); + assert.strictEqual(null, reply[1], name); + next(name); + }); +}; + +tests.HINCRBY = function () { + var name = "HINCRBY"; + client.hset("hash incr", "value", 10, require_number(1, name)); + client.HINCRBY("hash incr", "value", 1, require_number(11, name)); + client.HINCRBY("hash incr", "value 2", 1, last(name, require_number(1, name))); +}; + +tests.SUBSCRIBE = function () { + var client1 = client, msg_count = 0, name = "SUBSCRIBE"; + + client1.on("subscribe", function (channel, count) { + if (channel === "chan1") { + client2.publish("chan1", "message 1", require_number(1, name)); + client2.publish("chan2", "message 2", require_number(1, name)); + client2.publish("chan1", "message 3", require_number(1, name)); + } + }); + + client1.on("unsubscribe", function (channel, count) { + if (count === 0) { + // make sure this connection can go into and out of pub/sub mode + client1.incr("did a thing", last(name, require_number(2, name))); + } + }); + + client1.on("message", function (channel, message) { + msg_count += 1; + assert.strictEqual("message " + msg_count, message.toString()); + if (msg_count === 3) { + client1.unsubscribe("chan1", "chan2"); + } + }); + + client1.set("did a thing", 1, require_string("OK", name)); + client1.subscribe("chan1", "chan2", function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual("chan1", results.toString(), name); + }); +}; + +tests.SUB_UNSUB_SUB = function () { + var name = "SUB_UNSUB_SUB"; + client3.subscribe('chan3'); + client3.unsubscribe('chan3'); + client3.subscribe('chan3', function (err, results) { + assert.strictEqual(null, err, "unexpected error: " + err); + client2.publish('chan3', 'foo'); + }); + client3.on('message', function (channel, message) { + assert.strictEqual(channel, 'chan3'); + assert.strictEqual(message, 'foo'); + next(name); + }); +}; + +tests.SUBSCRIBE_QUIT = function () { + var name = "SUBSCRIBE_QUIT"; + client3.on("end", function () { + next(name); + }); + client3.on("subscribe", function (channel, count) { + client3.quit(); + }); + client3.subscribe("chan3"); +}; + +tests.SUBSCRIBE_CLOSE_RESUBSCRIBE = function () { + var name = "SUBSCRIBE_CLOSE_RESUBSCRIBE"; + var c1 = redis.createClient(); + var c2 = redis.createClient(); + var count = 0; + + /* Create two clients. c1 subscribes to two channels, c2 will publish to them. + c2 publishes the first message. + c1 gets the message and drops its connection. It must resubscribe itself. + When it resubscribes, c2 publishes the second message, on the same channel + c1 gets the message and drops its connection. It must resubscribe itself, again. + When it resubscribes, c2 publishes the third message, on the second channel + c1 gets the message and drops its connection. When it reconnects, the test ends. + */ + + c1.on("message", function(channel, message) { + if (channel === "chan1") { + assert.strictEqual(message, "hi on channel 1"); + c1.stream.end(); + + } else if (channel === "chan2") { + assert.strictEqual(message, "hi on channel 2"); + c1.stream.end(); + + } else { + c1.quit(); + c2.quit(); + assert.fail("test failed"); + } + }) + + c1.subscribe("chan1", "chan2"); + + c2.once("ready", function() { + console.log("c2 is ready"); + c1.on("ready", function(err, results) { + console.log("c1 is ready", count); + + count++; + if (count == 1) { + c2.publish("chan1", "hi on channel 1"); + return; + + } else if (count == 2) { + c2.publish("chan2", "hi on channel 2"); + + } else { + c1.quit(function() { + c2.quit(function() { + next(name); + }); + }); + } + }); + + c2.publish("chan1", "hi on channel 1"); + + }); +}; + +tests.EXISTS = function () { + var name = "EXISTS"; + client.del("foo", "foo2", require_number_any(name)); + client.set("foo", "bar", require_string("OK", name)); + client.EXISTS("foo", require_number(1, name)); + client.EXISTS("foo2", last(name, require_number(0, name))); +}; + +tests.DEL = function () { + var name = "DEL"; + client.DEL("delkey", require_number_any(name)); + client.set("delkey", "delvalue", require_string("OK", name)); + client.DEL("delkey", require_number(1, name)); + client.exists("delkey", require_number(0, name)); + client.DEL("delkey", require_number(0, name)); + client.mset("delkey", "delvalue", "delkey2", "delvalue2", require_string("OK", name)); + client.DEL("delkey", "delkey2", last(name, require_number(2, name))); +}; + +tests.TYPE = function () { + var name = "TYPE"; + client.set(["string key", "should be a string"], require_string("OK", name)); + client.rpush(["list key", "should be a list"], require_number_pos(name)); + client.sadd(["set key", "should be a set"], require_number_any(name)); + client.zadd(["zset key", "10.0", "should be a zset"], require_number_any(name)); + client.hset(["hash key", "hashtest", "should be a hash"], require_number_any(0, name)); + + client.TYPE(["string key"], require_string("string", name)); + client.TYPE(["list key"], require_string("list", name)); + client.TYPE(["set key"], require_string("set", name)); + client.TYPE(["zset key"], require_string("zset", name)); + client.TYPE("not here yet", require_string("none", name)); + client.TYPE(["hash key"], last(name, require_string("hash", name))); +}; + +tests.KEYS = function () { + var name = "KEYS"; + client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], require_string("OK", name)); + client.KEYS(["test keys*"], function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual(2, results.length, name); + assert.strictEqual("test keys 1", results[0].toString(), name); + assert.strictEqual("test keys 2", results[1].toString(), name); + next(name); + }); +}; + +tests.MULTIBULK = function() { + var name = "MULTIBULK", + keys_values = []; + + for (var i = 0; i < 200; i++) { + var key_value = [ + "multibulk:" + crypto.randomBytes(256).toString("hex"), // use long strings as keys to ensure generation of large packet + "test val " + i + ]; + keys_values.push(key_value); + } + + client.mset(keys_values.reduce(function(a, b) { + return a.concat(b); + }), require_string("OK", name)); + + client.KEYS("multibulk:*", function(err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.deepEqual(keys_values.map(function(val) { + return val[0]; + }).sort(), results.sort(), name); + }); + + next(name); +}; + +tests.MULTIBULK_ZERO_LENGTH = function () { + var name = "MULTIBULK_ZERO_LENGTH"; + client.KEYS(['users:*'], function (err, results) { + assert.strictEqual(null, err, 'error on empty multibulk reply'); + assert.strictEqual(true, is_empty_array(results), "not an empty array"); + next(name); + }); +}; + +tests.RANDOMKEY = function () { + var name = "RANDOMKEY"; + client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], require_string("OK", name)); + client.RANDOMKEY([], function (err, results) { + assert.strictEqual(null, err, name + " result sent back unexpected error: " + err); + assert.strictEqual(true, /\w+/.test(results), name); + next(name); + }); +}; + +tests.RENAME = function () { + var name = "RENAME"; + client.set(['foo', 'bar'], require_string("OK", name)); + client.RENAME(["foo", "new foo"], require_string("OK", name)); + client.exists(["foo"], require_number(0, name)); + client.exists(["new foo"], last(name, require_number(1, name))); +}; + +tests.RENAMENX = function () { + var name = "RENAMENX"; + client.set(['foo', 'bar'], require_string("OK", name)); + client.set(['foo2', 'bar2'], require_string("OK", name)); + client.RENAMENX(["foo", "foo2"], require_number(0, name)); + client.exists(["foo"], require_number(1, name)); + client.exists(["foo2"], require_number(1, name)); + client.del(["foo2"], require_number(1, name)); + client.RENAMENX(["foo", "foo2"], require_number(1, name)); + client.exists(["foo"], require_number(0, name)); + client.exists(["foo2"], last(name, require_number(1, name))); +}; + +tests.DBSIZE = function () { + var name = "DBSIZE"; + client.set(['foo', 'bar'], require_string("OK", name)); + client.DBSIZE([], last(name, require_number_pos("DBSIZE"))); +}; + +tests.GET_1 = function () { + var name = "GET_1"; + client.set(["get key", "get val"], require_string("OK", name)); + client.GET(["get key"], last(name, require_string("get val", name))); +}; + +tests.GET_2 = function() { + var name = "GET_2"; + + // tests handling of non-existent keys + client.GET('this_key_shouldnt_exist', last(name, require_null(name))); +}; + +tests.SET = function () { + var name = "SET"; + client.SET(["set key", "set val"], require_string("OK", name)); + client.get(["set key"], last(name, require_string("set val", name))); +}; + +tests.GETSET = function () { + var name = "GETSET"; + client.set(["getset key", "getset val"], require_string("OK", name)); + client.GETSET(["getset key", "new getset val"], require_string("getset val", name)); + client.get(["getset key"], last(name, require_string("new getset val", name))); +}; + +tests.MGET = function () { + var name = "MGET"; + client.mset(["mget keys 1", "mget val 1", "mget keys 2", "mget val 2", "mget keys 3", "mget val 3"], require_string("OK", name)); + client.MGET("mget keys 1", "mget keys 2", "mget keys 3", function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual(3, results.length, name); + assert.strictEqual("mget val 1", results[0].toString(), name); + assert.strictEqual("mget val 2", results[1].toString(), name); + assert.strictEqual("mget val 3", results[2].toString(), name); + }); + client.MGET(["mget keys 1", "mget keys 2", "mget keys 3"], function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual(3, results.length, name); + assert.strictEqual("mget val 1", results[0].toString(), name); + assert.strictEqual("mget val 2", results[1].toString(), name); + assert.strictEqual("mget val 3", results[2].toString(), name); + }); + client.MGET(["mget keys 1", "some random shit", "mget keys 2", "mget keys 3"], function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual(4, results.length, name); + assert.strictEqual("mget val 1", results[0].toString(), name); + assert.strictEqual(null, results[1], name); + assert.strictEqual("mget val 2", results[2].toString(), name); + assert.strictEqual("mget val 3", results[3].toString(), name); + next(name); + }); +}; + +tests.SETNX = function () { + var name = "SETNX"; + client.set(["setnx key", "setnx value"], require_string("OK", name)); + client.SETNX(["setnx key", "new setnx value"], require_number(0, name)); + client.del(["setnx key"], require_number(1, name)); + client.exists(["setnx key"], require_number(0, name)); + client.SETNX(["setnx key", "new setnx value"], require_number(1, name)); + client.exists(["setnx key"], last(name, require_number(1, name))); +}; + +tests.SETEX = function () { + var name = "SETEX"; + client.SETEX(["setex key", "100", "setex val"], require_string("OK", name)); + client.exists(["setex key"], require_number(1, name)); + client.ttl(["setex key"], last(name, require_number_pos(name))); +}; + +tests.MSETNX = function () { + var name = "MSETNX"; + client.mset(["mset1", "val1", "mset2", "val2", "mset3", "val3"], require_string("OK", name)); + client.MSETNX(["mset3", "val3", "mset4", "val4"], require_number(0, name)); + client.del(["mset3"], require_number(1, name)); + client.MSETNX(["mset3", "val3", "mset4", "val4"], require_number(1, name)); + client.exists(["mset3"], require_number(1, name)); + client.exists(["mset4"], last(name, require_number(1, name))); +}; + +tests.HGETALL = function () { + var name = "HGETALL"; + client.hmset(["hosts", "mjr", "1", "another", "23", "home", "1234"], require_string("OK", name)); + client.HGETALL(["hosts"], function (err, obj) { + assert.strictEqual(null, err, name + " result sent back unexpected error: " + err); + assert.strictEqual(3, Object.keys(obj).length, name); + assert.strictEqual("1", obj.mjr.toString(), name); + assert.strictEqual("23", obj.another.toString(), name); + assert.strictEqual("1234", obj.home.toString(), name); + next(name); + }); +}; + +tests.HGETALL_NULL = function () { + var name = "HGETALL_NULL"; + + client.hgetall("missing", function (err, obj) { + assert.strictEqual(null, err); + assert.strictEqual(null, obj); + next(name); + }); +}; + +tests.UTF8 = function () { + var name = "UTF8", + utf8_sample = "ಠ_ಠ"; + + client.set(["utf8test", utf8_sample], require_string("OK", name)); + client.get(["utf8test"], function (err, obj) { + assert.strictEqual(null, err); + assert.strictEqual(utf8_sample, obj); + next(name); + }); +}; + +// Set tests were adapted from Brian Hammond's redis-node-client.js, which has a comprehensive test suite + +tests.SADD = function () { + var name = "SADD"; + + client.del('set0'); + client.SADD('set0', 'member0', require_number(1, name)); + client.sadd('set0', 'member0', last(name, require_number(0, name))); +}; + +tests.SADD2 = function () { + var name = "SADD2"; + + client.del("set0"); + client.sadd("set0", ["member0", "member1", "member2"], require_number(3, name)); + client.smembers("set0", function (err, res) { + assert.strictEqual(res.length, 3); + assert.strictEqual(res[0], "member0"); + assert.strictEqual(res[1], "member1"); + assert.strictEqual(res[2], "member2"); + }); + client.SADD("set1", ["member0", "member1", "member2"], require_number(3, name)); + client.smembers("set1", function (err, res) { + assert.strictEqual(res.length, 3); + assert.strictEqual(res[0], "member0"); + assert.strictEqual(res[1], "member1"); + assert.strictEqual(res[2], "member2"); + next(name); + }); +}; + +tests.SISMEMBER = function () { + var name = "SISMEMBER"; + + client.del('set0'); + client.sadd('set0', 'member0', require_number(1, name)); + client.sismember('set0', 'member0', require_number(1, name)); + client.sismember('set0', 'member1', last(name, require_number(0, name))); +}; + +tests.SCARD = function () { + var name = "SCARD"; + + client.del('set0'); + client.sadd('set0', 'member0', require_number(1, name)); + client.scard('set0', require_number(1, name)); + client.sadd('set0', 'member1', require_number(1, name)); + client.scard('set0', last(name, require_number(2, name))); +}; + +tests.SREM = function () { + var name = "SREM"; + + client.del('set0'); + client.sadd('set0', 'member0', require_number(1, name)); + client.srem('set0', 'foobar', require_number(0, name)); + client.srem('set0', 'member0', require_number(1, name)); + client.scard('set0', last(name, require_number(0, name))); +}; + +tests.SPOP = function () { + var name = "SPOP"; + + client.del('zzz'); + client.sadd('zzz', 'member0', require_number(1, name)); + client.scard('zzz', require_number(1, name)); + + client.spop('zzz', function (err, value) { + if (err) { + assert.fail(err); + } + assert.equal(value, 'member0', name); + }); + + client.scard('zzz', last(name, require_number(0, name))); +}; + +tests.SDIFF = function () { + var name = "SDIFF"; + + client.del('foo'); + client.sadd('foo', 'x', require_number(1, name)); + client.sadd('foo', 'a', require_number(1, name)); + client.sadd('foo', 'b', require_number(1, name)); + client.sadd('foo', 'c', require_number(1, name)); + + client.sadd('bar', 'c', require_number(1, name)); + + client.sadd('baz', 'a', require_number(1, name)); + client.sadd('baz', 'd', require_number(1, name)); + + client.sdiff('foo', 'bar', 'baz', function (err, values) { + if (err) { + assert.fail(err, name); + } + values.sort(); + assert.equal(values.length, 2, name); + assert.equal(values[0], 'b', name); + assert.equal(values[1], 'x', name); + next(name); + }); +}; + +tests.SDIFFSTORE = function () { + var name = "SDIFFSTORE"; + + client.del('foo'); + client.del('bar'); + client.del('baz'); + client.del('quux'); + + client.sadd('foo', 'x', require_number(1, name)); + client.sadd('foo', 'a', require_number(1, name)); + client.sadd('foo', 'b', require_number(1, name)); + client.sadd('foo', 'c', require_number(1, name)); + + client.sadd('bar', 'c', require_number(1, name)); + + client.sadd('baz', 'a', require_number(1, name)); + client.sadd('baz', 'd', require_number(1, name)); + + // NB: SDIFFSTORE returns the number of elements in the dstkey + + client.sdiffstore('quux', 'foo', 'bar', 'baz', require_number(2, name)); + + client.smembers('quux', function (err, values) { + if (err) { + assert.fail(err, name); + } + var members = buffers_to_strings(values).sort(); + + assert.deepEqual(members, [ 'b', 'x' ], name); + next(name); + }); +}; + +tests.SMEMBERS = function () { + var name = "SMEMBERS"; + + client.del('foo'); + client.sadd('foo', 'x', require_number(1, name)); + + client.smembers('foo', function (err, members) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(members), [ 'x' ], name); + }); + + client.sadd('foo', 'y', require_number(1, name)); + + client.smembers('foo', function (err, values) { + if (err) { + assert.fail(err, name); + } + assert.equal(values.length, 2, name); + var members = buffers_to_strings(values).sort(); + + assert.deepEqual(members, [ 'x', 'y' ], name); + next(name); + }); +}; + +tests.SMOVE = function () { + var name = "SMOVE"; + + client.del('foo'); + client.del('bar'); + + client.sadd('foo', 'x', require_number(1, name)); + client.smove('foo', 'bar', 'x', require_number(1, name)); + client.sismember('foo', 'x', require_number(0, name)); + client.sismember('bar', 'x', require_number(1, name)); + client.smove('foo', 'bar', 'x', last(name, require_number(0, name))); +}; + +tests.SINTER = function () { + var name = "SINTER"; + + client.del('sa'); + client.del('sb'); + client.del('sc'); + + client.sadd('sa', 'a', require_number(1, name)); + client.sadd('sa', 'b', require_number(1, name)); + client.sadd('sa', 'c', require_number(1, name)); + + client.sadd('sb', 'b', require_number(1, name)); + client.sadd('sb', 'c', require_number(1, name)); + client.sadd('sb', 'd', require_number(1, name)); + + client.sadd('sc', 'c', require_number(1, name)); + client.sadd('sc', 'd', require_number(1, name)); + client.sadd('sc', 'e', require_number(1, name)); + + client.sinter('sa', 'sb', function (err, intersection) { + if (err) { + assert.fail(err, name); + } + assert.equal(intersection.length, 2, name); + assert.deepEqual(buffers_to_strings(intersection).sort(), [ 'b', 'c' ], name); + }); + + client.sinter('sb', 'sc', function (err, intersection) { + if (err) { + assert.fail(err, name); + } + assert.equal(intersection.length, 2, name); + assert.deepEqual(buffers_to_strings(intersection).sort(), [ 'c', 'd' ], name); + }); + + client.sinter('sa', 'sc', function (err, intersection) { + if (err) { + assert.fail(err, name); + } + assert.equal(intersection.length, 1, name); + assert.equal(intersection[0], 'c', name); + }); + + // 3-way + + client.sinter('sa', 'sb', 'sc', function (err, intersection) { + if (err) { + assert.fail(err, name); + } + assert.equal(intersection.length, 1, name); + assert.equal(intersection[0], 'c', name); + next(name); + }); +}; + +tests.SINTERSTORE = function () { + var name = "SINTERSTORE"; + + client.del('sa'); + client.del('sb'); + client.del('sc'); + client.del('foo'); + + client.sadd('sa', 'a', require_number(1, name)); + client.sadd('sa', 'b', require_number(1, name)); + client.sadd('sa', 'c', require_number(1, name)); + + client.sadd('sb', 'b', require_number(1, name)); + client.sadd('sb', 'c', require_number(1, name)); + client.sadd('sb', 'd', require_number(1, name)); + + client.sadd('sc', 'c', require_number(1, name)); + client.sadd('sc', 'd', require_number(1, name)); + client.sadd('sc', 'e', require_number(1, name)); + + client.sinterstore('foo', 'sa', 'sb', 'sc', require_number(1, name)); + + client.smembers('foo', function (err, members) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(members), [ 'c' ], name); + next(name); + }); +}; + +tests.SUNION = function () { + var name = "SUNION"; + + client.del('sa'); + client.del('sb'); + client.del('sc'); + + client.sadd('sa', 'a', require_number(1, name)); + client.sadd('sa', 'b', require_number(1, name)); + client.sadd('sa', 'c', require_number(1, name)); + + client.sadd('sb', 'b', require_number(1, name)); + client.sadd('sb', 'c', require_number(1, name)); + client.sadd('sb', 'd', require_number(1, name)); + + client.sadd('sc', 'c', require_number(1, name)); + client.sadd('sc', 'd', require_number(1, name)); + client.sadd('sc', 'e', require_number(1, name)); + + client.sunion('sa', 'sb', 'sc', function (err, union) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(union).sort(), ['a', 'b', 'c', 'd', 'e'], name); + next(name); + }); +}; + +tests.SUNIONSTORE = function () { + var name = "SUNIONSTORE"; + + client.del('sa'); + client.del('sb'); + client.del('sc'); + client.del('foo'); + + client.sadd('sa', 'a', require_number(1, name)); + client.sadd('sa', 'b', require_number(1, name)); + client.sadd('sa', 'c', require_number(1, name)); + + client.sadd('sb', 'b', require_number(1, name)); + client.sadd('sb', 'c', require_number(1, name)); + client.sadd('sb', 'd', require_number(1, name)); + + client.sadd('sc', 'c', require_number(1, name)); + client.sadd('sc', 'd', require_number(1, name)); + client.sadd('sc', 'e', require_number(1, name)); + + client.sunionstore('foo', 'sa', 'sb', 'sc', function (err, cardinality) { + if (err) { + assert.fail(err, name); + } + assert.equal(cardinality, 5, name); + }); + + client.smembers('foo', function (err, members) { + if (err) { + assert.fail(err, name); + } + assert.equal(members.length, 5, name); + assert.deepEqual(buffers_to_strings(members).sort(), ['a', 'b', 'c', 'd', 'e'], name); + next(name); + }); +}; + +// SORT test adapted from Brian Hammond's redis-node-client.js, which has a comprehensive test suite + +tests.SORT = function () { + var name = "SORT"; + + client.del('y'); + client.del('x'); + + client.rpush('y', 'd', require_number(1, name)); + client.rpush('y', 'b', require_number(2, name)); + client.rpush('y', 'a', require_number(3, name)); + client.rpush('y', 'c', require_number(4, name)); + + client.rpush('x', '3', require_number(1, name)); + client.rpush('x', '9', require_number(2, name)); + client.rpush('x', '2', require_number(3, name)); + client.rpush('x', '4', require_number(4, name)); + + client.set('w3', '4', require_string("OK", name)); + client.set('w9', '5', require_string("OK", name)); + client.set('w2', '12', require_string("OK", name)); + client.set('w4', '6', require_string("OK", name)); + + client.set('o2', 'buz', require_string("OK", name)); + client.set('o3', 'foo', require_string("OK", name)); + client.set('o4', 'baz', require_string("OK", name)); + client.set('o9', 'bar', require_string("OK", name)); + + client.set('p2', 'qux', require_string("OK", name)); + client.set('p3', 'bux', require_string("OK", name)); + client.set('p4', 'lux', require_string("OK", name)); + client.set('p9', 'tux', require_string("OK", name)); + + // Now the data has been setup, we can test. + + // But first, test basic sorting. + + // y = [ d b a c ] + // sort y ascending = [ a b c d ] + // sort y descending = [ d c b a ] + + client.sort('y', 'asc', 'alpha', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), ['a', 'b', 'c', 'd'], name); + }); + + client.sort('y', 'desc', 'alpha', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), ['d', 'c', 'b', 'a'], name); + }); + + // Now try sorting numbers in a list. + // x = [ 3, 9, 2, 4 ] + + client.sort('x', 'asc', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), [2, 3, 4, 9], name); + }); + + client.sort('x', 'desc', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), [9, 4, 3, 2], name); + }); + + // Try sorting with a 'by' pattern. + + client.sort('x', 'by', 'w*', 'asc', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), [3, 9, 4, 2], name); + }); + + // Try sorting with a 'by' pattern and 1 'get' pattern. + + client.sort('x', 'by', 'w*', 'asc', 'get', 'o*', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), ['foo', 'bar', 'baz', 'buz'], name); + }); + + // Try sorting with a 'by' pattern and 2 'get' patterns. + + client.sort('x', 'by', 'w*', 'asc', 'get', 'o*', 'get', 'p*', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), ['foo', 'bux', 'bar', 'tux', 'baz', 'lux', 'buz', 'qux'], name); + }); + + // Try sorting with a 'by' pattern and 2 'get' patterns. + // Instead of getting back the sorted set/list, store the values to a list. + // Then check that the values are there in the expected order. + + client.sort('x', 'by', 'w*', 'asc', 'get', 'o*', 'get', 'p*', 'store', 'bacon', function (err) { + if (err) { + assert.fail(err, name); + } + }); + + client.lrange('bacon', 0, -1, function (err, values) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(values), ['foo', 'bux', 'bar', 'tux', 'baz', 'lux', 'buz', 'qux'], name); + next(name); + }); + + // TODO - sort by hash value +}; + +tests.MONITOR = function () { + var name = "MONITOR", responses = [], monitor_client; + + monitor_client = redis.createClient(); + monitor_client.monitor(function (err, res) { + client.mget("some", "keys", "foo", "bar"); + client.set("json", JSON.stringify({ + foo: "123", + bar: "sdflkdfsjk", + another: false + })); + }); + monitor_client.on("monitor", function (time, args) { + // skip monitor command for Redis <= 2.4.16 + if (args[0] === "monitor") return; + + responses.push(args); + if (responses.length === 2) { + assert.strictEqual(5, responses[0].length); + assert.strictEqual("mget", responses[0][0]); + assert.strictEqual("some", responses[0][1]); + assert.strictEqual("keys", responses[0][2]); + assert.strictEqual("foo", responses[0][3]); + assert.strictEqual("bar", responses[0][4]); + assert.strictEqual(3, responses[1].length); + assert.strictEqual("set", responses[1][0]); + assert.strictEqual("json", responses[1][1]); + assert.strictEqual('{"foo":"123","bar":"sdflkdfsjk","another":false}', responses[1][2]); + monitor_client.quit(function (err, res) { + next(name); + }); + } + }); +}; + +tests.BLPOP = function () { + var name = "BLPOP"; + + client.rpush("blocking list", "initial value", function (err, res) { + client2.BLPOP("blocking list", 0, function (err, res) { + assert.strictEqual("blocking list", res[0].toString()); + assert.strictEqual("initial value", res[1].toString()); + + client.rpush("blocking list", "wait for this value"); + }); + client2.BLPOP("blocking list", 0, function (err, res) { + assert.strictEqual("blocking list", res[0].toString()); + assert.strictEqual("wait for this value", res[1].toString()); + next(name); + }); + }); +}; + +tests.BLPOP_TIMEOUT = function () { + var name = "BLPOP_TIMEOUT"; + + // try to BLPOP the list again, which should be empty. This should timeout and return null. + client2.BLPOP("blocking list", 1, function (err, res) { + if (err) { + throw err; + } + + assert.strictEqual(res, null); + next(name); + }); +}; + +tests.EXPIRE = function () { + var name = "EXPIRE"; + client.set(['expiry key', 'bar'], require_string("OK", name)); + client.EXPIRE(["expiry key", "1"], require_number_pos(name)); + setTimeout(function () { + client.exists(["expiry key"], last(name, require_number(0, name))); + }, 2000); +}; + +tests.TTL = function () { + var name = "TTL"; + client.set(["ttl key", "ttl val"], require_string("OK", name)); + client.expire(["ttl key", "100"], require_number_pos(name)); + setTimeout(function () { + client.TTL(["ttl key"], last(name, require_number_pos(0, name))); + }, 500); +}; + +tests.OPTIONAL_CALLBACK = function () { + var name = "OPTIONAL_CALLBACK"; + client.del("op_cb1"); + client.set("op_cb1", "x"); + client.get("op_cb1", last(name, require_string("x", name))); +}; + +tests.OPTIONAL_CALLBACK_UNDEFINED = function () { + var name = "OPTIONAL_CALLBACK_UNDEFINED"; + client.del("op_cb2"); + client.set("op_cb2", "y", undefined); + client.get("op_cb2", last(name, require_string("y", name))); +}; + +tests.HMSET_THROWS_ON_NON_STRINGS = function () { + var name = "HMSET_THROWS_ON_NON_STRINGS"; + var hash = name; + var data = { "a": [ "this is not a string" ] }; + + client.hmset(hash, data, cb); + function cb(e, r) { + assert(e); // should be an error! + } + + // alternative way it throws + function thrower() { + client.hmset(hash, data); + } + assert.throws(thrower); + next(name); +}; + +tests.ENABLE_OFFLINE_QUEUE_TRUE = function () { + var name = "ENABLE_OFFLINE_QUEUE_TRUE"; + var cli = redis.createClient(9999, null, { + max_attempts: 1 + // default :) + // enable_offline_queue: true + }); + cli.on('error', function(e) { + // ignore, b/c expecting a "can't connect" error + }); + return setTimeout(function() { + cli.set(name, name, function(err, result) { + assert.ifError(err); + }); + + return setTimeout(function(){ + assert.strictEqual(cli.offline_queue.length, 1); + return next(name); + }, 25); + }, 50); +}; + +tests.ENABLE_OFFLINE_QUEUE_FALSE = function () { + var name = "ENABLE_OFFLINE_QUEUE_FALSE"; + var cli = redis.createClient(9999, null, { + max_attempts: 1, + enable_offline_queue: false + }); + cli.on('error', function() { + // ignore, see above + }); + assert.throws(function () { + cli.set(name, name) + }) + assert.doesNotThrow(function () { + cli.set(name, name, function (err) { + // should callback with an error + assert.ok(err); + setTimeout(function () { + next(name); + }, 50); + }); + }); +}; + +// TODO - need a better way to test auth, maybe auto-config a local Redis server or something. +// Yes, this is the real password. Please be nice, thanks. +tests.auth = function () { + var name = "AUTH", client4, ready_count = 0; + + client4 = redis.createClient(9006, "filefish.redistogo.com"); + client4.auth("664b1b6aaf134e1ec281945a8de702a9", function (err, res) { + assert.strictEqual(null, err, name); + assert.strictEqual("OK", res.toString(), name); + }); + + // test auth, then kill the connection so it'll auto-reconnect and auto-re-auth + client4.on("ready", function () { + ready_count++; + if (ready_count === 1) { + client4.stream.destroy(); + } else { + client4.quit(function (err, res) { + next(name); + }); + } + }); +}; + +all_tests = Object.keys(tests); +all_start = new Date(); +test_count = 0; + +run_next_test = function run_next_test() { + var test_name = all_tests.shift(); + if (typeof tests[test_name] === "function") { + util.print('- \x1b[1m' + test_name.toLowerCase() + '\x1b[0m:'); + cur_start = new Date(); + test_count += 1; + tests[test_name](); + } else { + console.log('\n completed \x1b[32m%d\x1b[0m tests in \x1b[33m%d\x1b[0m ms\n', test_count, new Date() - all_start); + client.quit(); + client2.quit(); + bclient.quit(); + } +}; + +client.once("ready", function start_tests() { + console.log("Connected to " + client.host + ":" + client.port + ", Redis server version " + client.server_info.redis_version + "\n"); + console.log("Using reply parser " + client.reply_parser.name); + + run_next_test(); + + connected = true; +}); + +client.on('end', function () { + ended = true; +}); + +// Exit immediately on connection failure, which triggers "exit", below, which fails the test +client.on("error", function (err) { + console.error("client: " + err.stack); + process.exit(); +}); +client2.on("error", function (err) { + console.error("client2: " + err.stack); + process.exit(); +}); +client3.on("error", function (err) { + console.error("client3: " + err.stack); + process.exit(); +}); +bclient.on("error", function (err) { + console.error("bclient: " + err.stack); + process.exit(); +}); + +client.on("reconnecting", function (params) { + console.log("reconnecting: " + util.inspect(params)); +}); + +process.on('uncaughtException', function (err) { + console.error("Uncaught exception: " + err.stack); + process.exit(1); +}); + +process.on('exit', function (code) { + assert.equal(true, connected); + assert.equal(true, ended); +}); diff --git a/coder-base/node_modules_orig/redis/test3.js b/coder-base/node_modules_orig/redis/test3.js new file mode 100755 index 00000000..3ce06649 --- /dev/null +++ b/coder-base/node_modules_orig/redis/test3.js @@ -0,0 +1,18 @@ +var redis = require('redis'); + +rc = redis.createClient(); + +rc.on('error', function (err) { + console.log('Redis error ' + err); +}); + +var jsonStr = '{\"glossary\":{\"title\":\"example glossary\",\"GlossDiv\":{\"title\":\"S\",\"GlossList\":{\"GlossEntry\":{\"ID\":\"SGML\",\"SortAs\":\"SGML\",\"GlossTerm\":\"Standard Generalized Markup Language\",\"Acronym\":\"SGML\",\"Abbrev\":\"ISO 8879:1986\",\"GlossDef\":{\"para\":\"A meta-markup language, used to create markup languages such as DocBook.\",\"GlossSeeAlso\":[\"GML\",\"XML\"]},\"GlossSee\":\"markup\"}}}}}'; + +for (var i = 0, len = 100; i < len; i++) { + rc.rpush('test:case', jsonStr); +} + +rc.lrange('test:case', 0, -1, function (err, data) { + console.log(data); // it will return 100 elements, but the last ones will be null's instead of the actual value + rc.end(); +}); diff --git a/coder-base/node_modules_orig/socket.io/.npmignore b/coder-base/node_modules_orig/socket.io/.npmignore new file mode 100755 index 00000000..39e9864f --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/.npmignore @@ -0,0 +1,3 @@ +support +test +examples diff --git a/coder-base/node_modules_orig/socket.io/.travis.yml b/coder-base/node_modules_orig/socket.io/.travis.yml new file mode 100755 index 00000000..56eca033 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - 0.6 + +notifications: + irc: "irc.freenode.org#socket.io" diff --git a/coder-base/node_modules_orig/socket.io/History.md b/coder-base/node_modules_orig/socket.io/History.md new file mode 100755 index 00000000..e51c7e60 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/History.md @@ -0,0 +1,310 @@ + +0.9.13 / 2012-12-13 +=================== + + * package: fixed `base64id` requirement + +0.9.12 / 2012-12-13 +=================== + + * manager: fix for latest node which is returning a clone with `listeners` [viirya] + +0.9.11 / 2012-11-02 +=================== + + * package: move redis to optionalDependenices [3rd-Eden] + * bumped client + +0.9.10 / 2012-08-10 +=================== + + * Don't lowercase log messages + * Always set the HTTP response in case an error should be returned to the client + * Create or destroy the flash policy server on configuration change + * Honour configuration to disable flash policy server + * Add express 3.0 instructions on Readme.md + * Bump client + +0.9.9 / 2012-08-01 +================== + + * Fixed sync disconnect xhrs handling + * Put license text in its own file (#965) + * Add warning to .listen() to ease the migration to Express 3.x + * Restored compatibility with node 0.4.x + +0.9.8 / 2012-07-24 +================== + + * Bumped client. + +0.9.7 / 2012-07-24 +================== + + * Prevent crash when socket leaves a room twice. + * Corrects unsafe usage of for..in + * Fix for node 0.8 with `gzip compression` [vadimi] + * Update redis to support Node 0.8.x + * Made ID generation securely random + * Fix Redis Store race condition in manager onOpen unsubscribe callback + * Fix for EventEmitters always reusing the same Array instance for listeners + +0.9.6 / 2012-04-17 +================== + + * Fixed XSS in jsonp-polling. + +0.9.5 / 2012-04-05 +================== + + * Added test for polling and socket close. + * Ensure close upon request close. + * Fix disconnection reason being lost for polling transports. + * Ensure that polling transports work with Connection: close. + * Log disconnection reason. + +0.9.4 / 2012-04-01 +================== + + * Disconnecting from namespace improvement (#795) [DanielBaulig] + * Bumped client with polling reconnection loop (#438) + +0.9.3 / 2012-03-28 +================== + + * Fix "Syntax error" on FF Web Console with XHR Polling [mikito] + +0.9.2 / 2012-03-13 +================== + + * More sensible close `timeout default` (fixes disconnect issue) + +0.9.1-1 / 2012-03-02 +==================== + + * Bumped client with NPM dependency fix. + +0.9.1 / 2012-03-02 +================== + + * Changed heartbeat timeout and interval defaults (60 and 25 seconds) + * Make tests work both on 0.4 and 0.6 + * Updated client (improvements + bug fixes). + +0.9.0 / 2012-02-26 +================== + + * Make it possible to use a regexp to match the socket.io resource URL. + We need this because we have to prefix the socket.io URL with a variable ID. + * Supplemental fix to gavinuhma/authfix, it looks like the same Access-Control-Origin logic is needed in the http and xhr-polling transports + * Updated express dep for windows compatibility. + * Combine two substr calls into one in decodePayload to improve performance + * Minor documentation fix + * Minor. Conform to style of other files. + * Switching setting to 'match origin protocol' + * Revert "Fixes leaking Redis subscriptions for #663. The local flag was not getting passed through onClientDisconnect()." + * Revert "Handle leaked dispatch:[id] subscription." + * Merge pull request #667 from dshaw/patch/redis-disconnect + * Handle leaked dispatch:[id] subscription. + * Fixes leaking Redis subscriptions for #663. The local flag was not getting passed through onClientDisconnect(). + * Prevent memory leaking on uncompleted requests & add max post size limitation + * Fix for testcase + * Set Access-Control-Allow-Credentials true, regardless of cookie + * Remove assertvarnish from package as it breaks on 0.6 + * Correct irc channel + * Added proper return after reserved field error + * Fixes manager.js failure to close connection after transport error has happened + * Added implicit port 80 for origin checks. fixes #638 + * Fixed bug #432 in 0.8.7 + * Set Access-Control-Allow-Origin header to origin to enable withCredentials + * Adding configuration variable matchOriginProtocol + * Fixes location mismatch error in Safari. + * Use tty to detect if we should add colors or not by default. + * Updated the package location. + +0.8.7 / 2011-11-05 +================== + + * Fixed memory leaks in closed clients. + * Fixed memory leaks in namespaces. + * Fixed websocket handling for malformed requests from proxies. [einaros] + * Node 0.6 compatibility. [einaros] [3rd-Eden] + * Adapted tests and examples. + +0.8.6 / 2011-10-27 +================== + + * Added JSON decoding on jsonp-polling transport. + * Fixed README example. + * Major speed optimizations [3rd-Eden] [einaros] [visionmedia] + * Added decode/encode benchmarks [visionmedia] + * Added support for black-listing client sent events. + * Fixed logging options, closes #540 [3rd-Eden] + * Added vary header for gzip [3rd-Eden] + * Properly cleaned up async websocket / flashsocket tests, after patching node-websocket-client + * Patched to properly shut down when a finishClose call is made during connection establishment + * Added support for socket.io version on url and far-future Expires [3rd-Eden] [getify] + * Began IE10 compatibility [einaros] [tbranyen] + * Misc WebSocket fixes [einaros] + * Added UTF8 to respone headers for htmlfile [3rd-Eden] + +0.8.5 / 2011-10-07 +================== + + * Added websocket draft HyBi-16 support. [einaros] + * Fixed websocket continuation bugs. [einaros] + * Fixed flashsocket transport name. + * Fixed websocket tests. + * Ensured `parser#decodePayload` doesn't choke. + * Added http referrer verification to manager verifyOrigin. + * Added access control for cross domain xhr handshakes [3rd-Eden] + * Added support for automatic generation of socket.io files [3rd-Eden] + * Added websocket binary support [einaros] + * Added gzip support for socket.io.js [3rd-Eden] + * Expose socket.transport [3rd-Eden] + * Updated client. + +0.8.4 / 2011-09-06 +================== + + * Client build + +0.8.3 / 2011-09-03 +================== + + * Fixed `\n` parsing for non-JSON packets (fixes #479). + * Fixed parsing of certain unicode characters (fixes #451). + * Fixed transport message packet logging. + * Fixed emission of `error` event resulting in an uncaught exception if unhandled (fixes #476). + * Fixed; allow for falsy values as the configuration value of `log level` (fixes #491). + * Fixed repository URI in `package.json`. Fixes #504. + * Added text/plain content-type to handshake responses [einaros] + * Improved single byte writes [einaros] + * Updated socket.io-flashsocket default port from 843 to 10843 [3rd-Eden] + * Updated client. + +0.8.2 / 2011-08-29 +================== + + * Updated client. + +0.8.1 / 2011-08-29 +================== + + * Fixed utf8 bug in send framing in websocket [einaros] + * Fixed typo in docs [Znarkus] + * Fixed bug in send framing for over 64kB of data in websocket [einaros] + * Corrected ping handling in websocket transport [einaros] + +0.8.0 / 2011-08-28 +================== + + * Updated to work with two-level websocket versioning. [einaros] + * Added hybi07 support. [einaros] + * Added hybi10 support. [einaros] + * Added http referrer verification to manager.js verifyOrigin. [einaors] + +0.7.11 / 2011-08-27 +=================== + + * Updated socket.io-client. + +0.7.10 / 2011-08-27 +=================== + + * Updated socket.io-client. + +0.7.9 / 2011-08-12 +================== + + * Updated socket.io-client. + * Make sure we only do garbage collection when the server we receive is actually run. + +0.7.8 / 2011-08-08 +================== + + * Changed; make sure sio#listen passes options to both HTTP server and socket.io manager. + * Added docs for sio#listen. + * Added options parameter support for Manager constructor. + * Added memory leaks tests and test-leaks Makefile task. + * Removed auto npm-linking from make test. + * Make sure that you can disable heartbeats. [3rd-Eden] + * Fixed rooms memory leak [3rd-Eden] + * Send response once we got all POST data, not immediately [Pita] + * Fixed onLeave behavior with missing clientsk [3rd-Eden] + * Prevent duplicate references in rooms. + * Added alias for `to` to `in` and `in` to `to`. + * Fixed roomClients definition. + * Removed dependency on redis for installation without npm [3rd-Eden] + * Expose path and querystring in handshakeData [3rd-Eden] + +0.7.7 / 2011-07-12 +================== + + * Fixed double dispatch handling with emit to closed clients. + * Added test for emitting to closed clients to prevent regression. + * Fixed race condition in redis test. + * Changed Transport#end instrumentation. + * Leveraged $emit instead of emit internally. + * Made tests faster. + * Fixed double disconnect events. + * Fixed disconnect logic + * Simplified remote events handling in Socket. + * Increased testcase timeout. + * Fixed unknown room emitting (GH-291). [3rd-Eden] + * Fixed `address` in handshakeData. [3rd-Eden] + * Removed transports definition in chat example. + * Fixed room cleanup + * Fixed; make sure the client is cleaned up after booting. + * Make sure to mark the client as non-open if the connection is closed. + * Removed unneeded `buffer` declarations. + * Fixed; make sure to clear socket handlers and subscriptions upon transport close. + +0.7.6 / 2011-06-30 +================== + + * Fixed general dispatching when a client has closed. + +0.7.5 / 2011-06-30 +================== + + * Fixed dispatching to clients that are disconnected. + +0.7.4 / 2011-06-30 +================== + + * Fixed; only clear handlers if they were set. [level09] + +0.7.3 / 2011-06-30 +================== + + * Exposed handshake data to clients. + * Refactored dispatcher interface. + * Changed; Moved id generation method into the manager. + * Added sub-namespace authorization. [3rd-Eden] + * Changed; normalized SocketNamespace local eventing [dvv] + * Changed; Use packet.reason or default to 'packet' [3rd-Eden] + * Changed console.error to console.log. + * Fixed; bind both servers at the same time do that the test never times out. + * Added 304 support. + * Removed `Transport#name` for abstract interface. + * Changed; lazily require http and https module only when needed. [3rd-Eden] + +0.7.2 / 2011-06-22 +================== + + * Make sure to write a packet (of type `noop`) when closing a poll. + This solves a problem with cross-domain requests being flagged as aborted and + reconnection being triggered. + * Added `noop` message type. + +0.7.1 / 2011-06-21 +================== + + * Fixed cross-domain XHR. + * Added CORS test to xhr-polling suite. + +0.7.0 / 2010-06-21 +================== + + * http://socket.io/announcement.html diff --git a/coder-base/node_modules_orig/socket.io/LICENSE b/coder-base/node_modules_orig/socket.io/LICENSE new file mode 100755 index 00000000..0f4acd44 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2011 Guillermo Rauch + +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/coder-base/node_modules_orig/socket.io/Makefile b/coder-base/node_modules_orig/socket.io/Makefile new file mode 100755 index 00000000..832cba8b --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/Makefile @@ -0,0 +1,31 @@ + +ALL_TESTS = $(shell find test/ -name '*.test.js') +ALL_BENCH = $(shell find benchmarks -name '*.bench.js') + +run-tests: + @./node_modules/.bin/expresso \ + -t 3000 \ + -I support \ + --serial \ + $(TESTFLAGS) \ + $(TESTS) + +test: + @$(MAKE) NODE_PATH=lib TESTS="$(ALL_TESTS)" run-tests + +test-cov: + @TESTFLAGS=--cov $(MAKE) test + +test-leaks: + @ls test/leaks/* | xargs node --expose_debug_as=debug --expose_gc + +run-bench: + @node $(PROFILEFLAGS) benchmarks/runner.js + +bench: + @$(MAKE) BENCHMARKS="$(ALL_BENCH)" run-bench + +profile: + @PROFILEFLAGS='--prof --trace-opt --trace-bailout --trace-deopt' $(MAKE) bench + +.PHONY: test bench profile diff --git a/coder-base/node_modules_orig/socket.io/Readme.md b/coder-base/node_modules_orig/socket.io/Readme.md new file mode 100755 index 00000000..41f21f68 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/Readme.md @@ -0,0 +1,364 @@ +# Socket.IO + +Socket.IO is a Node.JS project that makes WebSockets and realtime possible in +all browsers. It also enhances WebSockets by providing built-in multiplexing, +horizontal scalability, automatic JSON encoding/decoding, and more. + +## How to Install + +```bash +npm install socket.io +``` + +## How to use + +First, require `socket.io`: + +```js +var io = require('socket.io'); +``` + +Next, attach it to a HTTP/HTTPS server. If you're using the fantastic `express` +web framework: + +#### Express 3.x + +```js +var app = express() + , server = require('http').createServer(app) + , io = io.listen(server); + +server.listen(80); + +io.sockets.on('connection', function (socket) { + socket.emit('news', { hello: 'world' }); + socket.on('my other event', function (data) { + console.log(data); + }); +}); +``` + +#### Express 2.x + +```js +var app = express.createServer() + , io = io.listen(app); + +app.listen(80); + +io.sockets.on('connection', function (socket) { + socket.emit('news', { hello: 'world' }); + socket.on('my other event', function (data) { + console.log(data); + }); +}); +``` + +Finally, load it from the client side code: + +```html + + +``` + +For more thorough examples, look at the `examples/` directory. + +## Short recipes + +### Sending and receiving events. + +Socket.IO allows you to emit and receive custom events. +Besides `connect`, `message` and `disconnect`, you can emit custom events: + +```js +// note, io.listen() will create a http server for you +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + io.sockets.emit('this', { will: 'be received by everyone' }); + + socket.on('private message', function (from, msg) { + console.log('I received a private message by ', from, ' saying ', msg); + }); + + socket.on('disconnect', function () { + io.sockets.emit('user disconnected'); + }); +}); +``` + +### Storing data associated to a client + +Sometimes it's necessary to store data associated with a client that's +necessary for the duration of the session. + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.on('set nickname', function (name) { + socket.set('nickname', name, function () { socket.emit('ready'); }); + }); + + socket.on('msg', function () { + socket.get('nickname', function (err, name) { + console.log('Chat message by ', name); + }); + }); +}); +``` + +#### Client side + +```html + +``` + +### Restricting yourself to a namespace + +If you have control over all the messages and events emitted for a particular +application, using the default `/` namespace works. + +If you want to leverage 3rd-party code, or produce code to share with others, +socket.io provides a way of namespacing a `socket`. + +This has the benefit of `multiplexing` a single connection. Instead of +socket.io using two `WebSocket` connections, it'll use one. + +The following example defines a socket that listens on '/chat' and one for +'/news': + +#### Server side + +```js +var io = require('socket.io').listen(80); + +var chat = io + .of('/chat') + .on('connection', function (socket) { + socket.emit('a message', { that: 'only', '/chat': 'will get' }); + chat.emit('a message', { everyone: 'in', '/chat': 'will get' }); + }); + +var news = io + .of('/news'); + .on('connection', function (socket) { + socket.emit('item', { news: 'item' }); + }); +``` + +#### Client side: + +```html + +``` + +### Sending volatile messages. + +Sometimes certain messages can be dropped. Let's say you have an app that +shows realtime tweets for the keyword `bieber`. + +If a certain client is not ready to receive messages (because of network slowness +or other issues, or because he's connected through long polling and is in the +middle of a request-response cycle), if he doesn't receive ALL the tweets related +to bieber your application won't suffer. + +In that case, you might want to send those messages as volatile messages. + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + var tweets = setInterval(function () { + getBieberTweet(function (tweet) { + socket.volatile.emit('bieber tweet', tweet); + }); + }, 100); + + socket.on('disconnect', function () { + clearInterval(tweets); + }); +}); +``` + +#### Client side + +In the client side, messages are received the same way whether they're volatile +or not. + +### Getting acknowledgements + +Sometimes, you might want to get a callback when the client confirmed the message +reception. + +To do this, simply pass a function as the last parameter of `.send` or `.emit`. +What's more, when you use `.emit`, the acknowledgement is done by you, which +means you can also pass data along: + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.on('ferret', function (name, fn) { + fn('woot'); + }); +}); +``` + +#### Client side + +```html + +``` + +### Broadcasting messages + +To broadcast, simply add a `broadcast` flag to `emit` and `send` method calls. +Broadcasting means sending a message to everyone else except for the socket +that starts it. + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.broadcast.emit('user connected'); + socket.broadcast.json.send({ a: 'message' }); +}); +``` + +### Rooms + +Sometimes you want to put certain sockets in the same room, so that it's easy +to broadcast to all of them together. + +Think of this as built-in channels for sockets. Sockets `join` and `leave` +rooms in each socket. + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.join('justin bieber fans'); + socket.broadcast.to('justin bieber fans').emit('new fan'); + io.sockets.in('rammstein fans').emit('new non-fan'); +}); +``` + +### Using it just as a cross-browser WebSocket + +If you just want the WebSocket semantics, you can do that too. +Simply leverage `send` and listen on the `message` event: + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.on('message', function () { }); + socket.on('disconnect', function () { }); +}); +``` + +#### Client side + +```html + +``` + +### Changing configuration + +Configuration in socket.io is TJ-style: + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.configure(function () { + io.set('transports', ['websocket', 'flashsocket', 'xhr-polling']); +}); + +io.configure('development', function () { + io.set('transports', ['websocket', 'xhr-polling']); + io.enable('log'); +}); +``` + +## License + +(The MIT License) + +Copyright (c) 2011 Guillermo Rauch <guillermo@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. diff --git a/coder-base/node_modules_orig/socket.io/benchmarks/decode.bench.js b/coder-base/node_modules_orig/socket.io/benchmarks/decode.bench.js new file mode 100755 index 00000000..4855d805 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/benchmarks/decode.bench.js @@ -0,0 +1,64 @@ + +/** + * Module dependencies. + */ + +var benchmark = require('benchmark') + , colors = require('colors') + , io = require('../') + , parser = io.parser + , suite = new benchmark.Suite('Decode packet'); + +suite.add('string', function () { + parser.decodePacket('4:::"2"'); +}); + +suite.add('event', function () { + parser.decodePacket('5:::{"name":"woot"}'); +}); + +suite.add('event+ack', function () { + parser.decodePacket('5:1+::{"name":"tobi"}'); +}); + +suite.add('event+data', function () { + parser.decodePacket('5:::{"name":"edwald","args":[{"a": "b"},2,"3"]}'); +}); + +suite.add('heartbeat', function () { + parser.decodePacket('2:::'); +}); + +suite.add('error', function () { + parser.decodePacket('7:::2+0'); +}); + +var payload = parser.encodePayload([ + parser.encodePacket({ type: 'message', data: '5', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: '53d', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbazfoobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' }) +]); + +suite.add('payload', function () { + parser.decodePayload(payload); +}); + +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)); +}); + +if (!module.parent) { + suite.run(); +} else { + module.exports = suite; +} diff --git a/coder-base/node_modules_orig/socket.io/benchmarks/encode.bench.js b/coder-base/node_modules_orig/socket.io/benchmarks/encode.bench.js new file mode 100755 index 00000000..5037702d --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/benchmarks/encode.bench.js @@ -0,0 +1,90 @@ + +/** + * Module dependencies. + */ + +var benchmark = require('benchmark') + , colors = require('colors') + , io = require('../') + , parser = io.parser + , suite = new benchmark.Suite('Encode packet'); + +suite.add('string', function () { + parser.encodePacket({ + type: 'json' + , endpoint: '' + , data: '2' + }); +}); + +suite.add('event', function () { + parser.encodePacket({ + type: 'event' + , name: 'woot' + , endpoint: '' + , args: [] + }); +}); + +suite.add('event+ack', function () { + parser.encodePacket({ + type: 'json' + , id: 1 + , ack: 'data' + , endpoint: '' + , data: { a: 'b' } + }); +}); + +suite.add('event+data', function () { + parser.encodePacket({ + type: 'event' + , name: 'edwald' + , endpoint: '' + , args: [{a: 'b'}, 2, '3'] + }); +}); + +suite.add('heartbeat', function () { + parser.encodePacket({ + type: 'heartbeat' + , endpoint: '' + }) +}); + +suite.add('error', function () { + parser.encodePacket({ + type: 'error' + , reason: 'unauthorized' + , advice: 'reconnect' + , endpoint: '' + }) +}) + +suite.add('payload', function () { + parser.encodePayload([ + parser.encodePacket({ type: 'message', data: '5', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: '53d', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbazfoobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' }) + ]); +}); + +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)); +}); + +if (!module.parent) { + suite.run(); +} else { + module.exports = suite; +} diff --git a/coder-base/node_modules_orig/socket.io/benchmarks/runner.js b/coder-base/node_modules_orig/socket.io/benchmarks/runner.js new file mode 100755 index 00000000..81e55cae --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/benchmarks/runner.js @@ -0,0 +1,55 @@ +/** + * Benchmark runner dependencies + */ + +var colors = require('colors') + , path = require('path'); + +/** + * Find all the benchmarks + */ + +var benchmarks_files = process.env.BENCHMARKS.split(' ') + , all = [].concat(benchmarks_files) + , first = all.shift() + , benchmarks = {}; + +// find the benchmarks and load them all in our obj +benchmarks_files.forEach(function (file) { + benchmarks[file] = require(path.join(__dirname, '..', file)); +}); + +// setup the complete listeners +benchmarks_files.forEach(function (file) { + var benchmark = benchmarks[file] + , next_file = all.shift() + , next = benchmarks[next_file]; + + /** + * Generate a oncomplete function for the tests, either we are done or we + * have more benchmarks to process. + */ + + function complete () { + if (!next) { + console.log( + '\n\nBenchmark completed in'.grey + , (Date.now() - start).toString().green + ' ms'.grey + ); + } else { + console.log('\nStarting benchmark '.grey + next_file.yellow); + next.run(); + } + } + + // attach the listener + benchmark.on('complete', complete); +}); + +/** + * Start the benchmark + */ + +var start = Date.now(); +console.log('Starting benchmark '.grey + first.yellow); +benchmarks[first].run(); diff --git a/coder-base/node_modules_orig/socket.io/index.js b/coder-base/node_modules_orig/socket.io/index.js new file mode 100755 index 00000000..cc00c103 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/index.js @@ -0,0 +1,8 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +module.exports = require('./lib/socket.io'); diff --git a/coder-base/node_modules_orig/socket.io/lib/index.js b/coder-base/node_modules_orig/socket.io/lib/index.js new file mode 100755 index 00000000..d19bf850 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/index.js @@ -0,0 +1,131 @@ + +/** + * Module dependencies. + */ + +var http = require('http') + , engine = require('engine.io') + , Client = require('./client') + , Namespace = require('./namespace') + , debug = require('debug')('socket.io:server'); + +/** + * Read client + */ + +var client = { + source: require('socket.io-client').source, + version: require('socket.io-client/package').version +}; + +/** + * Server constructor. + * + * @param {http.Server|Number|Object} http server, port or options + * @param {Object} options + * @api public + */ + +function Server(srv, opts){ + if (!(this instanceof Server)) return new Server(srv, opts); + if ('object' == typeof srv && !srv.listen) { + opts = srv; + srv = null; + } + opts = opts || {}; + if (srv) this.attach(srv, opts); + this.sockets = this.of('/'); + this.client(true); +} + +/** + * Serve client code. + * + * @api public + */ + + + +/** + * Attaches socket.io to a server or port. + * + * @param {http.Server|Number} server or port + * @param {Object} options + * @api public + */ + +Server.prototype.attach = function(srv, opts){ + if ('number' == typeof srv) { + debug('creating engine.io on port %d', srv); + srv = engine.listen(srv, opts); + } else { + debug('creating engine.io instance', opts); + srv = engine.attach(srv, opts); + } + this.bind(srv); +}; + +/** + * Binds socket.io to an engine.io instance. + * + * @param {engine.Server} engine.io (or compatible) server + * @api public + */ + +Server.prototype.bind = function(engine){ + this.engine = engine; + this.engine.on('connection', this.onconnection.bind(this)); +}; + +/** + * Called with each incoming transport connection. + * + * @api public + */ + +Server.prototype.onconnection = function(conn){ + debug('incoming connection with id %s', conn.id); + var client = new Client(this, conn); + client.connect('/'); + this.emit('client', client); +}; + +/** + * Looks up a namespace. + * + * @param {String} nsp name + * @api public + */ + +Server.prototype.of = function(name){ + if (!this.nsps[name]) { + debug('initializing namespace %s', name); + var nsp = new Namespace(this, name); + this.nsps[name] = nsp; + } + return this.nsps[name]; +}; + +/** + * Expose main namespace (/). + */ + +['use', 'to', 'in', 'emit', 'send', 'write'].forEach(function(name){ + Server.prototype[name] = function(){ + var nsp = this.sockets[name]; + return nsp.apply(this.sockets, arguments); + }; +}); + +Namespace.flags.forEach(function(flag){ + Server.prototype.__defineGetter__(flag, function(name){ + this.flags.push(name); + return this; + }); +}); + +/** + * BC with `io.listen` + */ + +Server.listen = Server; diff --git a/coder-base/node_modules_orig/socket.io/lib/logger.js b/coder-base/node_modules_orig/socket.io/lib/logger.js new file mode 100755 index 00000000..49d02c98 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/logger.js @@ -0,0 +1,97 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var util = require('./util') + , toArray = util.toArray; + +/** + * Log levels. + */ + +var levels = [ + 'error' + , 'warn' + , 'info' + , 'debug' +]; + +/** + * Colors for log levels. + */ + +var colors = [ + 31 + , 33 + , 36 + , 90 +]; + +/** + * Pads the nice output to the longest log level. + */ + +function pad (str) { + var max = 0; + + for (var i = 0, l = levels.length; i < l; i++) + max = Math.max(max, levels[i].length); + + if (str.length < max) + return str + new Array(max - str.length + 1).join(' '); + + return str; +}; + +/** + * Logger (console). + * + * @api public + */ + +var Logger = module.exports = function (opts) { + opts = opts || {} + this.colors = false !== opts.colors; + this.level = 3; + this.enabled = true; +}; + +/** + * Log method. + * + * @api public + */ + +Logger.prototype.log = function (type) { + var index = levels.indexOf(type); + + if (index > this.level || !this.enabled) + return this; + + console.log.apply( + console + , [this.colors + ? ' \033[' + colors[index] + 'm' + pad(type) + ' -\033[39m' + : type + ':' + ].concat(toArray(arguments).slice(1)) + ); + + return this; +}; + +/** + * Generate methods. + */ + +levels.forEach(function (name) { + Logger.prototype[name] = function () { + this.log.apply(this, [name].concat(toArray(arguments))); + }; +}); diff --git a/coder-base/node_modules_orig/socket.io/lib/manager.js b/coder-base/node_modules_orig/socket.io/lib/manager.js new file mode 100755 index 00000000..b3ea7d92 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/manager.js @@ -0,0 +1,1026 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var fs = require('fs') + , url = require('url') + , tty = require('tty') + , crypto = require('crypto') + , util = require('./util') + , store = require('./store') + , client = require('socket.io-client') + , transports = require('./transports') + , Logger = require('./logger') + , Socket = require('./socket') + , MemoryStore = require('./stores/memory') + , SocketNamespace = require('./namespace') + , Static = require('./static') + , EventEmitter = process.EventEmitter; + +/** + * Export the constructor. + */ + +exports = module.exports = Manager; + +/** + * Default transports. + */ + +var defaultTransports = exports.defaultTransports = [ + 'websocket' + , 'htmlfile' + , 'xhr-polling' + , 'jsonp-polling' +]; + +/** + * Inherited defaults. + */ + +var parent = module.parent.exports + , protocol = parent.protocol + , jsonpolling_re = /^\d+$/; + +/** + * Manager constructor. + * + * @param {HTTPServer} server + * @param {Object} options, optional + * @api public + */ + +function Manager (server, options) { + this.server = server; + this.namespaces = {}; + this.sockets = this.of(''); + this.settings = { + origins: '*:*' + , log: true + , store: new MemoryStore + , logger: new Logger + , static: new Static(this) + , heartbeats: true + , resource: '/socket.io' + , transports: defaultTransports + , authorization: false + , blacklist: ['disconnect'] + , 'log level': 3 + , 'log colors': tty.isatty(process.stdout.fd) + , 'close timeout': 60 + , 'heartbeat interval': 25 + , 'heartbeat timeout': 60 + , 'polling duration': 20 + , 'flash policy server': true + , 'flash policy port': 10843 + , 'destroy upgrade': true + , 'destroy buffer size': 10E7 + , 'browser client': true + , 'browser client cache': true + , 'browser client minification': false + , 'browser client etag': false + , 'browser client expires': 315360000 + , 'browser client gzip': false + , 'browser client handler': false + , 'client store expiration': 15 + , 'match origin protocol': false + }; + + for (var i in options) { + if (options.hasOwnProperty(i)) { + this.settings[i] = options[i]; + } + } + + var self = this; + + // default error handler + server.on('error', function(err) { + self.log.warn('error raised: ' + err); + }); + + this.initStore(); + + this.on('set:store', function() { + self.initStore(); + }); + + // reset listeners + this.oldListeners = server.listeners('request').splice(0); + server.removeAllListeners('request'); + + server.on('request', function (req, res) { + self.handleRequest(req, res); + }); + + server.on('upgrade', function (req, socket, head) { + self.handleUpgrade(req, socket, head); + }); + + server.on('close', function () { + clearInterval(self.gc); + }); + + server.once('listening', function () { + self.gc = setInterval(self.garbageCollection.bind(self), 10000); + }); + + for (var i in transports) { + if (transports.hasOwnProperty(i)) { + if (transports[i].init) { + transports[i].init(this); + } + } + } + + // forward-compatibility with 1.0 + var self = this; + this.sockets.on('connection', function (conn) { + self.emit('connection', conn); + }); + + this.sequenceNumber = Date.now() | 0; + + this.log.info('socket.io started'); +}; + +Manager.prototype.__proto__ = EventEmitter.prototype + +/** + * Store accessor shortcut. + * + * @api public + */ + +Manager.prototype.__defineGetter__('store', function () { + var store = this.get('store'); + store.manager = this; + return store; +}); + +/** + * Logger accessor. + * + * @api public + */ + +Manager.prototype.__defineGetter__('log', function () { + var logger = this.get('logger'); + + logger.level = this.get('log level') || -1; + logger.colors = this.get('log colors'); + logger.enabled = this.enabled('log'); + + return logger; +}); + +/** + * Static accessor. + * + * @api public + */ + +Manager.prototype.__defineGetter__('static', function () { + return this.get('static'); +}); + +/** + * Get settings. + * + * @api public + */ + +Manager.prototype.get = function (key) { + return this.settings[key]; +}; + +/** + * Set settings + * + * @api public + */ + +Manager.prototype.set = function (key, value) { + if (arguments.length == 1) return this.get(key); + this.settings[key] = value; + this.emit('set:' + key, this.settings[key], key); + return this; +}; + +/** + * Enable a setting + * + * @api public + */ + +Manager.prototype.enable = function (key) { + this.settings[key] = true; + this.emit('set:' + key, this.settings[key], key); + return this; +}; + +/** + * Disable a setting + * + * @api public + */ + +Manager.prototype.disable = function (key) { + this.settings[key] = false; + this.emit('set:' + key, this.settings[key], key); + return this; +}; + +/** + * Checks if a setting is enabled + * + * @api public + */ + +Manager.prototype.enabled = function (key) { + return !!this.settings[key]; +}; + +/** + * Checks if a setting is disabled + * + * @api public + */ + +Manager.prototype.disabled = function (key) { + return !this.settings[key]; +}; + +/** + * Configure callbacks. + * + * @api public + */ + +Manager.prototype.configure = function (env, fn) { + if ('function' == typeof env) { + env.call(this); + } else if (env == (process.env.NODE_ENV || 'development')) { + fn.call(this); + } + + return this; +}; + +/** + * Initializes everything related to the message dispatcher. + * + * @api private + */ + +Manager.prototype.initStore = function () { + this.handshaken = {}; + this.connected = {}; + this.open = {}; + this.closed = {}; + this.rooms = {}; + this.roomClients = {}; + + var self = this; + + this.store.subscribe('handshake', function (id, data) { + self.onHandshake(id, data); + }); + + this.store.subscribe('connect', function (id) { + self.onConnect(id); + }); + + this.store.subscribe('open', function (id) { + self.onOpen(id); + }); + + this.store.subscribe('join', function (id, room) { + self.onJoin(id, room); + }); + + this.store.subscribe('leave', function (id, room) { + self.onLeave(id, room); + }); + + this.store.subscribe('close', function (id) { + self.onClose(id); + }); + + this.store.subscribe('dispatch', function (room, packet, volatile, exceptions) { + self.onDispatch(room, packet, volatile, exceptions); + }); + + this.store.subscribe('disconnect', function (id) { + self.onDisconnect(id); + }); +}; + +/** + * Called when a client handshakes. + * + * @param text + */ + +Manager.prototype.onHandshake = function (id, data) { + this.handshaken[id] = data; +}; + +/** + * Called when a client connects (ie: transport first opens) + * + * @api private + */ + +Manager.prototype.onConnect = function (id) { + this.connected[id] = true; +}; + +/** + * Called when a client opens a request in a different node. + * + * @api private + */ + +Manager.prototype.onOpen = function (id) { + this.open[id] = true; + + if (this.closed[id]) { + var self = this; + + this.store.unsubscribe('dispatch:' + id, function () { + var transport = self.transports[id]; + if (self.closed[id] && self.closed[id].length && transport) { + + // if we have buffered messages that accumulate between calling + // onOpen an this async callback, send them if the transport is + // still open, otherwise leave them buffered + if (transport.open) { + transport.payload(self.closed[id]); + self.closed[id] = []; + } + } + }); + } + + // clear the current transport + if (this.transports[id]) { + this.transports[id].discard(); + this.transports[id] = null; + } +}; + +/** + * Called when a message is sent to a namespace and/or room. + * + * @api private + */ + +Manager.prototype.onDispatch = function (room, packet, volatile, exceptions) { + if (this.rooms[room]) { + for (var i = 0, l = this.rooms[room].length; i < l; i++) { + var id = this.rooms[room][i]; + + if (!~exceptions.indexOf(id)) { + if (this.transports[id] && this.transports[id].open) { + this.transports[id].onDispatch(packet, volatile); + } else if (!volatile) { + this.onClientDispatch(id, packet); + } + } + } + } +}; + +/** + * Called when a client joins a nsp / room. + * + * @api private + */ + +Manager.prototype.onJoin = function (id, name) { + if (!this.roomClients[id]) { + this.roomClients[id] = {}; + } + + if (!this.rooms[name]) { + this.rooms[name] = []; + } + + if (!~this.rooms[name].indexOf(id)) { + this.rooms[name].push(id); + this.roomClients[id][name] = true; + } +}; + +/** + * Called when a client leaves a nsp / room. + * + * @param private + */ + +Manager.prototype.onLeave = function (id, room) { + if (this.rooms[room]) { + var index = this.rooms[room].indexOf(id); + + if (index >= 0) { + this.rooms[room].splice(index, 1); + } + + if (!this.rooms[room].length) { + delete this.rooms[room]; + } + + if (this.roomClients[id]) { + delete this.roomClients[id][room]; + } + } +}; + +/** + * Called when a client closes a request in different node. + * + * @api private + */ + +Manager.prototype.onClose = function (id) { + if (this.open[id]) { + delete this.open[id]; + } + + this.closed[id] = []; + + var self = this; + + this.store.subscribe('dispatch:' + id, function (packet, volatile) { + if (!volatile) { + self.onClientDispatch(id, packet); + } + }); +}; + +/** + * Dispatches a message for a closed client. + * + * @api private + */ + +Manager.prototype.onClientDispatch = function (id, packet) { + if (this.closed[id]) { + this.closed[id].push(packet); + } +}; + +/** + * Receives a message for a client. + * + * @api private + */ + +Manager.prototype.onClientMessage = function (id, packet) { + if (this.namespaces[packet.endpoint]) { + this.namespaces[packet.endpoint].handlePacket(id, packet); + } +}; + +/** + * Fired when a client disconnects (not triggered). + * + * @api private + */ + +Manager.prototype.onClientDisconnect = function (id, reason) { + for (var name in this.namespaces) { + if (this.namespaces.hasOwnProperty(name)) { + this.namespaces[name].handleDisconnect(id, reason, typeof this.roomClients[id] !== 'undefined' && + typeof this.roomClients[id][name] !== 'undefined'); + } + } + + this.onDisconnect(id); +}; + +/** + * Called when a client disconnects. + * + * @param text + */ + +Manager.prototype.onDisconnect = function (id, local) { + delete this.handshaken[id]; + + if (this.open[id]) { + delete this.open[id]; + } + + if (this.connected[id]) { + delete this.connected[id]; + } + + if (this.transports[id]) { + this.transports[id].discard(); + delete this.transports[id]; + } + + if (this.closed[id]) { + delete this.closed[id]; + } + + if (this.roomClients[id]) { + for (var room in this.roomClients[id]) { + if (this.roomClients[id].hasOwnProperty(room)) { + this.onLeave(id, room); + } + } + delete this.roomClients[id] + } + + this.store.destroyClient(id, this.get('client store expiration')); + + this.store.unsubscribe('dispatch:' + id); + + if (local) { + this.store.unsubscribe('message:' + id); + this.store.unsubscribe('disconnect:' + id); + } +}; + +/** + * Handles an HTTP request. + * + * @api private + */ + +Manager.prototype.handleRequest = function (req, res) { + var data = this.checkRequest(req); + + if (!data) { + for (var i = 0, l = this.oldListeners.length; i < l; i++) { + this.oldListeners[i].call(this.server, req, res); + } + + return; + } + + if (data.static || !data.transport && !data.protocol) { + if (data.static && this.enabled('browser client')) { + this.static.write(data.path, req, res); + } else { + res.writeHead(200); + res.end('Welcome to socket.io.'); + + this.log.info('unhandled socket.io url'); + } + + return; + } + + if (data.protocol != protocol) { + res.writeHead(500); + res.end('Protocol version not supported.'); + + this.log.info('client protocol version unsupported'); + } else { + if (data.id) { + this.handleHTTPRequest(data, req, res); + } else { + this.handleHandshake(data, req, res); + } + } +}; + +/** + * Handles an HTTP Upgrade. + * + * @api private + */ + +Manager.prototype.handleUpgrade = function (req, socket, head) { + var data = this.checkRequest(req) + , self = this; + + if (!data) { + if (this.enabled('destroy upgrade')) { + socket.end(); + this.log.debug('destroying non-socket.io upgrade'); + } + + return; + } + + req.head = head; + this.handleClient(data, req); +}; + +/** + * Handles a normal handshaken HTTP request (eg: long-polling) + * + * @api private + */ + +Manager.prototype.handleHTTPRequest = function (data, req, res) { + req.res = res; + this.handleClient(data, req); +}; + +/** + * Intantiantes a new client. + * + * @api private + */ + +Manager.prototype.handleClient = function (data, req) { + var socket = req.socket + , store = this.store + , self = this; + + // handle sync disconnect xhrs + if (undefined != data.query.disconnect) { + if (this.transports[data.id] && this.transports[data.id].open) { + this.transports[data.id].onForcedDisconnect(); + } else { + this.store.publish('disconnect-force:' + data.id); + } + req.res.writeHead(200); + req.res.end(); + return; + } + + if (!~this.get('transports').indexOf(data.transport)) { + this.log.warn('unknown transport: "' + data.transport + '"'); + req.connection.end(); + return; + } + + var transport = new transports[data.transport](this, data, req) + , handshaken = this.handshaken[data.id]; + + if (transport.disconnected) { + // failed during transport setup + req.connection.end(); + return; + } + if (handshaken) { + if (transport.open) { + if (this.closed[data.id] && this.closed[data.id].length) { + transport.payload(this.closed[data.id]); + this.closed[data.id] = []; + } + + this.onOpen(data.id); + this.store.publish('open', data.id); + this.transports[data.id] = transport; + } + + if (!this.connected[data.id]) { + this.onConnect(data.id); + this.store.publish('connect', data.id); + + // flag as used + delete handshaken.issued; + this.onHandshake(data.id, handshaken); + this.store.publish('handshake', data.id, handshaken); + + // initialize the socket for all namespaces + for (var i in this.namespaces) { + if (this.namespaces.hasOwnProperty(i)) { + var socket = this.namespaces[i].socket(data.id, true); + + // echo back connect packet and fire connection event + if (i === '') { + this.namespaces[i].handlePacket(data.id, { type: 'connect' }); + } + } + } + + this.store.subscribe('message:' + data.id, function (packet) { + self.onClientMessage(data.id, packet); + }); + + this.store.subscribe('disconnect:' + data.id, function (reason) { + self.onClientDisconnect(data.id, reason); + }); + } + } else { + if (transport.open) { + transport.error('client not handshaken', 'reconnect'); + } + + transport.discard(); + } +}; + +/** + * Generates a session id. + * + * @api private + */ + +Manager.prototype.generateId = function () { + var rand = new Buffer(15); // multiple of 3 for base64 + if (!rand.writeInt32BE) { + return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString() + + Math.abs(Math.random() * Math.random() * Date.now() | 0).toString(); + } + this.sequenceNumber = (this.sequenceNumber + 1) | 0; + rand.writeInt32BE(this.sequenceNumber, 11); + if (crypto.randomBytes) { + crypto.randomBytes(12).copy(rand); + } else { + // not secure for node 0.4 + [0, 4, 8].forEach(function(i) { + rand.writeInt32BE(Math.random() * Math.pow(2, 32) | 0, i); + }); + } + return rand.toString('base64').replace(/\//g, '_').replace(/\+/g, '-'); +}; + +/** + * Handles a handshake request. + * + * @api private + */ + +Manager.prototype.handleHandshake = function (data, req, res) { + var self = this + , origin = req.headers.origin + , headers = { + 'Content-Type': 'text/plain' + }; + + function writeErr (status, message) { + if (data.query.jsonp && jsonpolling_re.test(data.query.jsonp)) { + res.writeHead(200, { 'Content-Type': 'application/javascript' }); + res.end('io.j[' + data.query.jsonp + '](new Error("' + message + '"));'); + } else { + res.writeHead(status, headers); + res.end(message); + } + }; + + function error (err) { + writeErr(500, 'handshake error'); + self.log.warn('handshake error ' + err); + }; + + if (!this.verifyOrigin(req)) { + writeErr(403, 'handshake bad origin'); + return; + } + + var handshakeData = this.handshakeData(data); + + if (origin) { + // https://developer.mozilla.org/En/HTTP_Access_Control + headers['Access-Control-Allow-Origin'] = origin; + headers['Access-Control-Allow-Credentials'] = 'true'; + } + + this.authorize(handshakeData, function (err, authorized, newData) { + if (err) return error(err); + + if (authorized) { + var id = self.generateId() + , hs = [ + id + , self.enabled('heartbeats') ? self.get('heartbeat timeout') || '' : '' + , self.get('close timeout') || '' + , self.transports(data).join(',') + ].join(':'); + + if (data.query.jsonp && jsonpolling_re.test(data.query.jsonp)) { + hs = 'io.j[' + data.query.jsonp + '](' + JSON.stringify(hs) + ');'; + res.writeHead(200, { 'Content-Type': 'application/javascript' }); + } else { + res.writeHead(200, headers); + } + + res.end(hs); + + self.onHandshake(id, newData || handshakeData); + self.store.publish('handshake', id, newData || handshakeData); + + self.log.info('handshake authorized', id); + } else { + writeErr(403, 'handshake unauthorized'); + self.log.info('handshake unauthorized'); + } + }) +}; + +/** + * Gets normalized handshake data + * + * @api private + */ + +Manager.prototype.handshakeData = function (data) { + var connection = data.request.connection + , connectionAddress + , date = new Date; + + if (connection.remoteAddress) { + connectionAddress = { + address: connection.remoteAddress + , port: connection.remotePort + }; + } else if (connection.socket && connection.socket.remoteAddress) { + connectionAddress = { + address: connection.socket.remoteAddress + , port: connection.socket.remotePort + }; + } + + return { + headers: data.headers + , address: connectionAddress + , time: date.toString() + , query: data.query + , url: data.request.url + , xdomain: !!data.request.headers.origin + , secure: data.request.connection.secure + , issued: +date + }; +}; + +/** + * Verifies the origin of a request. + * + * @api private + */ + +Manager.prototype.verifyOrigin = function (request) { + var origin = request.headers.origin || request.headers.referer + , origins = this.get('origins'); + + if (origin === 'null') origin = '*'; + + if (origins.indexOf('*:*') !== -1) { + return true; + } + + if (origin) { + try { + var parts = url.parse(origin); + parts.port = parts.port || 80; + var ok = + ~origins.indexOf(parts.hostname + ':' + parts.port) || + ~origins.indexOf(parts.hostname + ':*') || + ~origins.indexOf('*:' + parts.port); + if (!ok) this.log.warn('illegal origin: ' + origin); + return ok; + } catch (ex) { + this.log.warn('error parsing origin'); + } + } + else { + this.log.warn('origin missing from handshake, yet required by config'); + } + return false; +}; + +/** + * Handles an incoming packet. + * + * @api private + */ + +Manager.prototype.handlePacket = function (sessid, packet) { + this.of(packet.endpoint || '').handlePacket(sessid, packet); +}; + +/** + * Performs authentication. + * + * @param Object client request data + * @api private + */ + +Manager.prototype.authorize = function (data, fn) { + if (this.get('authorization')) { + var self = this; + + this.get('authorization').call(this, data, function (err, authorized) { + self.log.debug('client ' + authorized ? 'authorized' : 'unauthorized'); + fn(err, authorized); + }); + } else { + this.log.debug('client authorized'); + fn(null, true); + } + + return this; +}; + +/** + * Retrieves the transports adviced to the user. + * + * @api private + */ + +Manager.prototype.transports = function (data) { + var transp = this.get('transports') + , ret = []; + + for (var i = 0, l = transp.length; i < l; i++) { + var transport = transp[i]; + + if (transport) { + if (!transport.checkClient || transport.checkClient(data)) { + ret.push(transport); + } + } + } + + return ret; +}; + +/** + * Checks whether a request is a socket.io one. + * + * @return {Object} a client request data object or `false` + * @api private + */ + +var regexp = /^\/([^\/]+)\/?([^\/]+)?\/?([^\/]+)?\/?$/ + +Manager.prototype.checkRequest = function (req) { + var resource = this.get('resource'); + + var match; + if (typeof resource === 'string') { + match = req.url.substr(0, resource.length); + if (match !== resource) match = null; + } else { + match = resource.exec(req.url); + if (match) match = match[0]; + } + + if (match) { + var uri = url.parse(req.url.substr(match.length), true) + , path = uri.pathname || '' + , pieces = path.match(regexp); + + // client request data + var data = { + query: uri.query || {} + , headers: req.headers + , request: req + , path: path + }; + + if (pieces) { + data.protocol = Number(pieces[1]); + data.transport = pieces[2]; + data.id = pieces[3]; + data.static = !!this.static.has(path); + }; + + return data; + } + + return false; +}; + +/** + * Declares a socket namespace + * + * @api public + */ + +Manager.prototype.of = function (nsp) { + if (this.namespaces[nsp]) { + return this.namespaces[nsp]; + } + + return this.namespaces[nsp] = new SocketNamespace(this, nsp); +}; + +/** + * Perform garbage collection on long living objects and properties that cannot + * be removed automatically. + * + * @api private + */ + +Manager.prototype.garbageCollection = function () { + // clean up unused handshakes + var ids = Object.keys(this.handshaken) + , i = ids.length + , now = Date.now() + , handshake; + + while (i--) { + handshake = this.handshaken[ids[i]]; + + if ('issued' in handshake && (now - handshake.issued) >= 3E4) { + this.onDisconnect(ids[i]); + } + } +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/namespace.js b/coder-base/node_modules_orig/socket.io/lib/namespace.js new file mode 100755 index 00000000..6e1e1c92 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/namespace.js @@ -0,0 +1,355 @@ +/** + * Module dependencies. + */ + +var Socket = require('./socket') + , EventEmitter = process.EventEmitter + , parser = require('./parser') + , util = require('./util'); + +/** + * Exports the constructor. + */ + +exports = module.exports = SocketNamespace; + +/** + * Constructor. + * + * @api public. + */ + +function SocketNamespace (mgr, name) { + this.manager = mgr; + this.name = name || ''; + this.sockets = {}; + this.auth = false; + this.setFlags(); +}; + +/** + * Inherits from EventEmitter. + */ + +SocketNamespace.prototype.__proto__ = EventEmitter.prototype; + +/** + * Copies emit since we override it. + * + * @api private + */ + +SocketNamespace.prototype.$emit = EventEmitter.prototype.emit; + +/** + * Retrieves all clients as Socket instances as an array. + * + * @api public + */ + +SocketNamespace.prototype.clients = function (room) { + var room = this.name + (room !== undefined ? + '/' + room : ''); + + if (!this.manager.rooms[room]) { + return []; + } + + return this.manager.rooms[room].map(function (id) { + return this.socket(id); + }, this); +}; + +/** + * Access logger interface. + * + * @api public + */ + +SocketNamespace.prototype.__defineGetter__('log', function () { + return this.manager.log; +}); + +/** + * Access store. + * + * @api public + */ + +SocketNamespace.prototype.__defineGetter__('store', function () { + return this.manager.store; +}); + +/** + * JSON message flag. + * + * @api public + */ + +SocketNamespace.prototype.__defineGetter__('json', function () { + this.flags.json = true; + return this; +}); + +/** + * Volatile message flag. + * + * @api public + */ + +SocketNamespace.prototype.__defineGetter__('volatile', function () { + this.flags.volatile = true; + return this; +}); + +/** + * Overrides the room to relay messages to (flag). + * + * @api public + */ + +SocketNamespace.prototype.in = SocketNamespace.prototype.to = function (room) { + this.flags.endpoint = this.name + (room ? '/' + room : ''); + return this; +}; + +/** + * Adds a session id we should prevent relaying messages to (flag). + * + * @api public + */ + +SocketNamespace.prototype.except = function (id) { + this.flags.exceptions.push(id); + return this; +}; + +/** + * Sets the default flags. + * + * @api private + */ + +SocketNamespace.prototype.setFlags = function () { + this.flags = { + endpoint: this.name + , exceptions: [] + }; + return this; +}; + +/** + * Sends out a packet. + * + * @api private + */ + +SocketNamespace.prototype.packet = function (packet) { + packet.endpoint = this.name; + + var store = this.store + , log = this.log + , volatile = this.flags.volatile + , exceptions = this.flags.exceptions + , packet = parser.encodePacket(packet); + + this.manager.onDispatch(this.flags.endpoint, packet, volatile, exceptions); + this.store.publish('dispatch', this.flags.endpoint, packet, volatile, exceptions); + + this.setFlags(); + + return this; +}; + +/** + * Sends to everyone. + * + * @api public + */ + +SocketNamespace.prototype.send = function (data) { + return this.packet({ + type: this.flags.json ? 'json' : 'message' + , data: data + }); +}; + +/** + * Emits to everyone (override). + * + * @api public + */ + +SocketNamespace.prototype.emit = function (name) { + if (name == 'newListener') { + return this.$emit.apply(this, arguments); + } + + return this.packet({ + type: 'event' + , name: name + , args: util.toArray(arguments).slice(1) + }); +}; + +/** + * Retrieves or creates a write-only socket for a client, unless specified. + * + * @param {Boolean} whether the socket will be readable when initialized + * @api public + */ + +SocketNamespace.prototype.socket = function (sid, readable) { + if (!this.sockets[sid]) { + this.sockets[sid] = new Socket(this.manager, sid, this, readable); + } + + return this.sockets[sid]; +}; + +/** + * Sets authorization for this namespace. + * + * @api public + */ + +SocketNamespace.prototype.authorization = function (fn) { + this.auth = fn; + return this; +}; + +/** + * Called when a socket disconnects entirely. + * + * @api private + */ + +SocketNamespace.prototype.handleDisconnect = function (sid, reason, raiseOnDisconnect) { + if (this.sockets[sid] && this.sockets[sid].readable) { + if (raiseOnDisconnect) this.sockets[sid].onDisconnect(reason); + delete this.sockets[sid]; + } +}; + +/** + * Performs authentication. + * + * @param Object client request data + * @api private + */ + +SocketNamespace.prototype.authorize = function (data, fn) { + if (this.auth) { + var self = this; + + this.auth.call(this, data, function (err, authorized) { + self.log.debug('client ' + + (authorized ? '' : 'un') + 'authorized for ' + self.name); + fn(err, authorized); + }); + } else { + this.log.debug('client authorized for ' + this.name); + fn(null, true); + } + + return this; +}; + +/** + * Handles a packet. + * + * @api private + */ + +SocketNamespace.prototype.handlePacket = function (sessid, packet) { + var socket = this.socket(sessid) + , dataAck = packet.ack == 'data' + , manager = this.manager + , self = this; + + function ack () { + self.log.debug('sending data ack packet'); + socket.packet({ + type: 'ack' + , args: util.toArray(arguments) + , ackId: packet.id + }); + }; + + function error (err) { + self.log.warn('handshake error ' + err + ' for ' + self.name); + socket.packet({ type: 'error', reason: err }); + }; + + function connect () { + self.manager.onJoin(sessid, self.name); + self.store.publish('join', sessid, self.name); + + // packet echo + socket.packet({ type: 'connect' }); + + // emit connection event + self.$emit('connection', socket); + }; + + switch (packet.type) { + case 'connect': + if (packet.endpoint == '') { + connect(); + } else { + var handshakeData = manager.handshaken[sessid]; + + this.authorize(handshakeData, function (err, authorized, newData) { + if (err) return error(err); + + if (authorized) { + manager.onHandshake(sessid, newData || handshakeData); + self.store.publish('handshake', sessid, newData || handshakeData); + connect(); + } else { + error('unauthorized'); + } + }); + } + break; + + case 'ack': + if (socket.acks[packet.ackId]) { + socket.acks[packet.ackId].apply(socket, packet.args); + } else { + this.log.info('unknown ack packet'); + } + break; + + case 'event': + // check if the emitted event is not blacklisted + if (-~manager.get('blacklist').indexOf(packet.name)) { + this.log.debug('ignoring blacklisted event `' + packet.name + '`'); + } else { + var params = [packet.name].concat(packet.args); + + if (dataAck) { + params.push(ack); + } + + socket.$emit.apply(socket, params); + } + break; + + case 'disconnect': + this.manager.onLeave(sessid, this.name); + this.store.publish('leave', sessid, this.name); + + socket.$emit('disconnect', packet.reason || 'packet'); + break; + + case 'json': + case 'message': + var params = ['message', packet.data]; + + if (dataAck) + params.push(ack); + + socket.$emit.apply(socket, params); + }; +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/parser.js b/coder-base/node_modules_orig/socket.io/lib/parser.js new file mode 100755 index 00000000..d56b5500 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/parser.js @@ -0,0 +1,249 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +/** + * Packet types. + */ + +var packets = exports.packets = { + 'disconnect': 0 + , 'connect': 1 + , 'heartbeat': 2 + , 'message': 3 + , 'json': 4 + , 'event': 5 + , 'ack': 6 + , 'error': 7 + , 'noop': 8 + } + , packetslist = Object.keys(packets); + +/** + * Errors reasons. + */ + +var reasons = exports.reasons = { + 'transport not supported': 0 + , 'client not handshaken': 1 + , 'unauthorized': 2 + } + , reasonslist = Object.keys(reasons); + +/** + * Errors advice. + */ + +var advice = exports.advice = { + 'reconnect': 0 + } + , advicelist = Object.keys(advice); + +/** + * Encodes a packet. + * + * @api private + */ + +exports.encodePacket = function (packet) { + var type = packets[packet.type] + , id = packet.id || '' + , endpoint = packet.endpoint || '' + , ack = packet.ack + , data = null; + + switch (packet.type) { + case 'message': + if (packet.data !== '') + data = packet.data; + break; + + case 'event': + var ev = { name: packet.name }; + + if (packet.args && packet.args.length) { + ev.args = packet.args; + } + + data = JSON.stringify(ev); + break; + + case 'json': + data = JSON.stringify(packet.data); + break; + + case 'ack': + data = packet.ackId + + (packet.args && packet.args.length + ? '+' + JSON.stringify(packet.args) : ''); + break; + + case 'connect': + if (packet.qs) + data = packet.qs; + break; + + case 'error': + var reason = packet.reason ? reasons[packet.reason] : '' + , adv = packet.advice ? advice[packet.advice] : '' + + if (reason !== '' || adv !== '') + data = reason + (adv !== '' ? ('+' + adv) : '') + + break; + } + + // construct packet with required fragments + var encoded = type + ':' + id + (ack == 'data' ? '+' : '') + ':' + endpoint; + + // data fragment is optional + if (data !== null && data !== undefined) + encoded += ':' + data; + + return encoded; +}; + +/** + * Encodes multiple messages (payload). + * + * @param {Array} messages + * @api private + */ + +exports.encodePayload = function (packets) { + var decoded = ''; + + if (packets.length == 1) + return packets[0]; + + for (var i = 0, l = packets.length; i < l; i++) { + var packet = packets[i]; + decoded += '\ufffd' + packet.length + '\ufffd' + packets[i] + } + + return decoded; +}; + +/** + * Decodes a packet + * + * @api private + */ + +var regexp = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/; + +/** + * Wrap the JSON.parse in a seperate function the crankshaft optimizer will + * only punish this function for the usage for try catch + * + * @api private + */ + +function parse (data) { + try { return JSON.parse(data) } + catch (e) { return false } +} + +exports.decodePacket = function (data) { + var pieces = data.match(regexp); + + if (!pieces) return {}; + + var id = pieces[2] || '' + , data = pieces[5] || '' + , packet = { + type: packetslist[pieces[1]] + , endpoint: pieces[4] || '' + }; + + // whether we need to acknowledge the packet + if (id) { + packet.id = id; + if (pieces[3]) + packet.ack = 'data'; + else + packet.ack = true; + } + + // handle different packet types + switch (packet.type) { + case 'message': + packet.data = data || ''; + break; + + case 'event': + pieces = parse(data); + if (pieces) { + packet.name = pieces.name; + packet.args = pieces.args; + } + + packet.args = packet.args || []; + break; + + case 'json': + packet.data = parse(data); + break; + + case 'connect': + packet.qs = data || ''; + break; + + case 'ack': + pieces = data.match(/^([0-9]+)(\+)?(.*)/); + if (pieces) { + packet.ackId = pieces[1]; + packet.args = []; + + if (pieces[3]) { + packet.args = parse(pieces[3]) || []; + } + } + break; + + case 'error': + pieces = data.split('+'); + packet.reason = reasonslist[pieces[0]] || ''; + packet.advice = advicelist[pieces[1]] || ''; + } + + return packet; +}; + +/** + * Decodes data payload. Detects multiple messages + * + * @return {Array} messages + * @api public + */ + +exports.decodePayload = function (data) { + if (undefined == data || null == data) { + return []; + } + + if (data[0] == '\ufffd') { + var ret = []; + + for (var i = 1, length = ''; i < data.length; i++) { + if (data[i] == '\ufffd') { + ret.push(exports.decodePacket(data.substr(i + 1, length))); + i += Number(length) + 1; + length = ''; + } else { + length += data[i]; + } + } + + return ret; + } else { + return [exports.decodePacket(data)]; + } +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/socket.io.js b/coder-base/node_modules_orig/socket.io/lib/socket.io.js new file mode 100755 index 00000000..bf590364 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/socket.io.js @@ -0,0 +1,143 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var client = require('socket.io-client'); + +/** + * Version. + */ + +exports.version = '0.9.11'; + +/** + * Supported protocol version. + */ + +exports.protocol = 1; + +/** + * Client that we serve. + */ + +exports.clientVersion = client.version; + +/** + * Attaches a manager + * + * @param {HTTPServer/Number} a HTTP/S server or a port number to listen on. + * @param {Object} opts to be passed to Manager and/or http server + * @param {Function} callback if a port is supplied + * @api public + */ + +exports.listen = function (server, options, fn) { + if ('function' == typeof server) { + console.warn('Socket.IO\'s `listen()` method expects an `http.Server` instance\n' + + 'as its first parameter. Are you migrating from Express 2.x to 3.x?\n' + + 'If so, check out the "Socket.IO compatibility" section at:\n' + + 'https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x'); + } + + if ('function' == typeof options) { + fn = options; + options = {}; + } + + if ('undefined' == typeof server) { + // create a server that listens on port 80 + server = 80; + } + + if ('number' == typeof server) { + // if a port number is passed + var port = server; + + if (options && options.key) + server = require('https').createServer(options); + else + server = require('http').createServer(); + + // default response + server.on('request', function (req, res) { + res.writeHead(200); + res.end('Welcome to socket.io.'); + }); + + server.listen(port, fn); + } + + // otherwise assume a http/s server + return new exports.Manager(server, options); +}; + +/** + * Manager constructor. + * + * @api public + */ + +exports.Manager = require('./manager'); + +/** + * Transport constructor. + * + * @api public + */ + +exports.Transport = require('./transport'); + +/** + * Socket constructor. + * + * @api public + */ + +exports.Socket = require('./socket'); + +/** + * Static constructor. + * + * @api public + */ + +exports.Static = require('./static'); + +/** + * Store constructor. + * + * @api public + */ + +exports.Store = require('./store'); + +/** + * Memory Store constructor. + * + * @api public + */ + +exports.MemoryStore = require('./stores/memory'); + +/** + * Redis Store constructor. + * + * @api public + */ + +exports.RedisStore = require('./stores/redis'); + +/** + * Parser. + * + * @api public + */ + +exports.parser = require('./parser'); diff --git a/coder-base/node_modules_orig/socket.io/lib/socket.js b/coder-base/node_modules_orig/socket.io/lib/socket.js new file mode 100755 index 00000000..d9807f6d --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/socket.js @@ -0,0 +1,369 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var parser = require('./parser') + , util = require('./util') + , EventEmitter = process.EventEmitter + +/** + * Export the constructor. + */ + +exports = module.exports = Socket; + +/** + * Default error event listener to prevent uncaught exceptions. + */ + +var defaultError = function () {}; + +/** + * Socket constructor. + * + * @param {Manager} manager instance + * @param {String} session id + * @param {Namespace} namespace the socket belongs to + * @param {Boolean} whether the + * @api public + */ + +function Socket (manager, id, nsp, readable) { + this.id = id; + this.namespace = nsp; + this.manager = manager; + this.disconnected = false; + this.ackPackets = 0; + this.acks = {}; + this.setFlags(); + this.readable = readable; + this.store = this.manager.store.client(this.id); + this.on('error', defaultError); +}; + +/** + * Inherits from EventEmitter. + */ + +Socket.prototype.__proto__ = EventEmitter.prototype; + +/** + * Accessor shortcut for the handshake data + * + * @api private + */ + +Socket.prototype.__defineGetter__('handshake', function () { + return this.manager.handshaken[this.id]; +}); + +/** + * Accessor shortcut for the transport type + * + * @api private + */ + +Socket.prototype.__defineGetter__('transport', function () { + return this.manager.transports[this.id].name; +}); + +/** + * Accessor shortcut for the logger. + * + * @api private + */ + +Socket.prototype.__defineGetter__('log', function () { + return this.manager.log; +}); + +/** + * JSON message flag. + * + * @api public + */ + +Socket.prototype.__defineGetter__('json', function () { + this.flags.json = true; + return this; +}); + +/** + * Volatile message flag. + * + * @api public + */ + +Socket.prototype.__defineGetter__('volatile', function () { + this.flags.volatile = true; + return this; +}); + +/** + * Broadcast message flag. + * + * @api public + */ + +Socket.prototype.__defineGetter__('broadcast', function () { + this.flags.broadcast = true; + return this; +}); + +/** + * Overrides the room to broadcast messages to (flag) + * + * @api public + */ + +Socket.prototype.to = Socket.prototype.in = function (room) { + this.flags.room = room; + return this; +}; + +/** + * Resets flags + * + * @api private + */ + +Socket.prototype.setFlags = function () { + this.flags = { + endpoint: this.namespace.name + , room: '' + }; + return this; +}; + +/** + * Triggered on disconnect + * + * @api private + */ + +Socket.prototype.onDisconnect = function (reason) { + if (!this.disconnected) { + this.$emit('disconnect', reason); + this.disconnected = true; + } +}; + +/** + * Joins a user to a room. + * + * @api public + */ + +Socket.prototype.join = function (name, fn) { + var nsp = this.namespace.name + , name = (nsp + '/') + name; + + this.manager.onJoin(this.id, name); + this.manager.store.publish('join', this.id, name); + + if (fn) { + this.log.warn('Client#join callback is deprecated'); + fn(); + } + + return this; +}; + +/** + * Un-joins a user from a room. + * + * @api public + */ + +Socket.prototype.leave = function (name, fn) { + var nsp = this.namespace.name + , name = (nsp + '/') + name; + + this.manager.onLeave(this.id, name); + this.manager.store.publish('leave', this.id, name); + + if (fn) { + this.log.warn('Client#leave callback is deprecated'); + fn(); + } + + return this; +}; + +/** + * Transmits a packet. + * + * @api private + */ + +Socket.prototype.packet = function (packet) { + if (this.flags.broadcast) { + this.log.debug('broadcasting packet'); + this.namespace.in(this.flags.room).except(this.id).packet(packet); + } else { + packet.endpoint = this.flags.endpoint; + packet = parser.encodePacket(packet); + + this.dispatch(packet, this.flags.volatile); + } + + this.setFlags(); + + return this; +}; + +/** + * Dispatches a packet + * + * @api private + */ + +Socket.prototype.dispatch = function (packet, volatile) { + if (this.manager.transports[this.id] && this.manager.transports[this.id].open) { + this.manager.transports[this.id].onDispatch(packet, volatile); + } else { + if (!volatile) { + this.manager.onClientDispatch(this.id, packet, volatile); + } + + this.manager.store.publish('dispatch:' + this.id, packet, volatile); + } +}; + +/** + * Stores data for the client. + * + * @api public + */ + +Socket.prototype.set = function (key, value, fn) { + this.store.set(key, value, fn); + return this; +}; + +/** + * Retrieves data for the client + * + * @api public + */ + +Socket.prototype.get = function (key, fn) { + this.store.get(key, fn); + return this; +}; + +/** + * Checks data for the client + * + * @api public + */ + +Socket.prototype.has = function (key, fn) { + this.store.has(key, fn); + return this; +}; + +/** + * Deletes data for the client + * + * @api public + */ + +Socket.prototype.del = function (key, fn) { + this.store.del(key, fn); + return this; +}; + +/** + * Kicks client + * + * @api public + */ + +Socket.prototype.disconnect = function () { + if (!this.disconnected) { + this.log.info('booting client'); + + if ('' === this.namespace.name) { + if (this.manager.transports[this.id] && this.manager.transports[this.id].open) { + this.manager.transports[this.id].onForcedDisconnect(); + } else { + this.manager.onClientDisconnect(this.id); + this.manager.store.publish('disconnect:' + this.id); + } + } else { + this.packet({type: 'disconnect'}); + this.manager.onLeave(this.id, this.namespace.name); + this.$emit('disconnect', 'booted'); + } + + } + + return this; +}; + +/** + * Send a message. + * + * @api public + */ + +Socket.prototype.send = function (data, fn) { + var packet = { + type: this.flags.json ? 'json' : 'message' + , data: data + }; + + if (fn) { + packet.id = ++this.ackPackets; + packet.ack = true; + this.acks[packet.id] = fn; + } + + return this.packet(packet); +}; + +/** + * Original emit function. + * + * @api private + */ + +Socket.prototype.$emit = EventEmitter.prototype.emit; + +/** + * Emit override for custom events. + * + * @api public + */ + +Socket.prototype.emit = function (ev) { + if (ev == 'newListener') { + return this.$emit.apply(this, arguments); + } + + var args = util.toArray(arguments).slice(1) + , lastArg = args[args.length - 1] + , packet = { + type: 'event' + , name: ev + }; + + if ('function' == typeof lastArg) { + packet.id = ++this.ackPackets; + packet.ack = lastArg.length ? 'data' : true; + this.acks[packet.id] = lastArg; + args = args.slice(0, args.length - 1); + } + + packet.args = args; + + return this.packet(packet); +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/static.js b/coder-base/node_modules_orig/socket.io/lib/static.js new file mode 100755 index 00000000..fe505937 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/static.js @@ -0,0 +1,395 @@ + +/*! +* socket.io-node +* Copyright(c) 2011 LearnBoost +* MIT Licensed +*/ + +/** + * Module dependencies. + */ + +var client = require('socket.io-client') + , cp = require('child_process') + , fs = require('fs') + , util = require('./util'); + +/** + * File type details. + * + * @api private + */ + +var mime = { + js: { + type: 'application/javascript' + , encoding: 'utf8' + , gzip: true + } + , swf: { + type: 'application/x-shockwave-flash' + , encoding: 'binary' + , gzip: false + } +}; + +/** + * Regexp for matching custom transport patterns. Users can configure their own + * socket.io bundle based on the url structure. Different transport names are + * concatinated using the `+` char. /socket.io/socket.io+websocket.js should + * create a bundle that only contains support for the websocket. + * + * @api private + */ + +var bundle = /\+((?:\+)?[\w\-]+)*(?:\.v\d+\.\d+\.\d+)?(?:\.js)$/ + , versioning = /\.v\d+\.\d+\.\d+(?:\.js)$/; + +/** + * Export the constructor + */ + +exports = module.exports = Static; + +/** + * Static constructor + * + * @api public + */ + +function Static (manager) { + this.manager = manager; + this.cache = {}; + this.paths = {}; + + this.init(); +} + +/** + * Initialize the Static by adding default file paths. + * + * @api public + */ + +Static.prototype.init = function () { + /** + * Generates a unique id based the supplied transports array + * + * @param {Array} transports The array with transport types + * @api private + */ + function id (transports) { + var id = transports.join('').split('').map(function (char) { + return ('' + char.charCodeAt(0)).split('').pop(); + }).reduce(function (char, id) { + return char +id; + }); + + return client.version + ':' + id; + } + + /** + * Generates a socket.io-client file based on the supplied transports. + * + * @param {Array} transports The array with transport types + * @param {Function} callback Callback for the static.write + * @api private + */ + + function build (transports, callback) { + client.builder(transports, { + minify: self.manager.enabled('browser client minification') + }, function (err, content) { + callback(err, content ? new Buffer(content) : null, id(transports)); + } + ); + } + + var self = this; + + // add our default static files + this.add('/static/flashsocket/WebSocketMain.swf', { + file: client.dist + '/WebSocketMain.swf' + }); + + this.add('/static/flashsocket/WebSocketMainInsecure.swf', { + file: client.dist + '/WebSocketMainInsecure.swf' + }); + + // generates dedicated build based on the available transports + this.add('/socket.io.js', function (path, callback) { + build(self.manager.get('transports'), callback); + }); + + this.add('/socket.io.v', { mime: mime.js }, function (path, callback) { + build(self.manager.get('transports'), callback); + }); + + // allow custom builds based on url paths + this.add('/socket.io+', { mime: mime.js }, function (path, callback) { + var available = self.manager.get('transports') + , matches = path.match(bundle) + , transports = []; + + if (!matches) return callback('No valid transports'); + + // make sure they valid transports + matches[0].split('.')[0].split('+').slice(1).forEach(function (transport) { + if (!!~available.indexOf(transport)) { + transports.push(transport); + } + }); + + if (!transports.length) return callback('No valid transports'); + build(transports, callback); + }); + + // clear cache when transports change + this.manager.on('set:transports', function (key, value) { + delete self.cache['/socket.io.js']; + Object.keys(self.cache).forEach(function (key) { + if (bundle.test(key)) { + delete self.cache[key]; + } + }); + }); +}; + +/** + * Gzip compress buffers. + * + * @param {Buffer} data The buffer that needs gzip compression + * @param {Function} callback + * @api public + */ + +Static.prototype.gzip = function (data, callback) { + var gzip = cp.spawn('gzip', ['-9', '-c', '-f', '-n']) + , encoding = Buffer.isBuffer(data) ? 'binary' : 'utf8' + , buffer = [] + , err; + + gzip.stdout.on('data', function (data) { + buffer.push(data); + }); + + gzip.stderr.on('data', function (data) { + err = data +''; + buffer.length = 0; + }); + + gzip.on('close', function () { + if (err) return callback(err); + + var size = 0 + , index = 0 + , i = buffer.length + , content; + + while (i--) { + size += buffer[i].length; + } + + content = new Buffer(size); + i = buffer.length; + + buffer.forEach(function (buffer) { + var length = buffer.length; + + buffer.copy(content, index, 0, length); + index += length; + }); + + buffer.length = 0; + callback(null, content); + }); + + gzip.stdin.end(data, encoding); +}; + +/** + * Is the path a static file? + * + * @param {String} path The path that needs to be checked + * @api public + */ + +Static.prototype.has = function (path) { + // fast case + if (this.paths[path]) return this.paths[path]; + + var keys = Object.keys(this.paths) + , i = keys.length; + + while (i--) { + if (-~path.indexOf(keys[i])) return this.paths[keys[i]]; + } + + return false; +}; + +/** + * Add new paths new paths that can be served using the static provider. + * + * @param {String} path The path to respond to + * @param {Options} options Options for writing out the response + * @param {Function} [callback] Optional callback if no options.file is + * supplied this would be called instead. + * @api public + */ + +Static.prototype.add = function (path, options, callback) { + var extension = /(?:\.(\w{1,4}))$/.exec(path); + + if (!callback && typeof options == 'function') { + callback = options; + options = {}; + } + + options.mime = options.mime || (extension ? mime[extension[1]] : false); + + if (callback) options.callback = callback; + if (!(options.file || options.callback) || !options.mime) return false; + + this.paths[path] = options; + + return true; +}; + +/** + * Writes a static response. + * + * @param {String} path The path for the static content + * @param {HTTPRequest} req The request object + * @param {HTTPResponse} res The response object + * @api public + */ + +Static.prototype.write = function (path, req, res) { + /** + * Write a response without throwing errors because can throw error if the + * response is no longer writable etc. + * + * @api private + */ + + function write (status, headers, content, encoding) { + try { + res.writeHead(status, headers || undefined); + + // only write content if it's not a HEAD request and we actually have + // some content to write (304's doesn't have content). + res.end( + req.method !== 'HEAD' && content ? content : '' + , encoding || undefined + ); + } catch (e) {} + } + + /** + * Answers requests depending on the request properties and the reply object. + * + * @param {Object} reply The details and content to reply the response with + * @api private + */ + + function answer (reply) { + var cached = req.headers['if-none-match'] === reply.etag; + if (cached && self.manager.enabled('browser client etag')) { + return write(304); + } + + var accept = req.headers['accept-encoding'] || '' + , gzip = !!~accept.toLowerCase().indexOf('gzip') + , mime = reply.mime + , versioned = reply.versioned + , headers = { + 'Content-Type': mime.type + }; + + // check if we can add a etag + if (self.manager.enabled('browser client etag') && reply.etag && !versioned) { + headers['Etag'] = reply.etag; + } + + // see if we need to set Expire headers because the path is versioned + if (versioned) { + var expires = self.manager.get('browser client expires'); + headers['Cache-Control'] = 'private, x-gzip-ok="", max-age=' + expires; + headers['Date'] = new Date().toUTCString(); + headers['Expires'] = new Date(Date.now() + (expires * 1000)).toUTCString(); + } + + if (gzip && reply.gzip) { + headers['Content-Length'] = reply.gzip.length; + headers['Content-Encoding'] = 'gzip'; + headers['Vary'] = 'Accept-Encoding'; + write(200, headers, reply.gzip.content, mime.encoding); + } else { + headers['Content-Length'] = reply.length; + write(200, headers, reply.content, mime.encoding); + } + + self.manager.log.debug('served static content ' + path); + } + + var self = this + , details; + + // most common case first + if (this.manager.enabled('browser client cache') && this.cache[path]) { + return answer(this.cache[path]); + } else if (this.manager.get('browser client handler')) { + return this.manager.get('browser client handler').call(this, req, res); + } else if ((details = this.has(path))) { + /** + * A small helper function that will let us deal with fs and dynamic files + * + * @param {Object} err Optional error + * @param {Buffer} content The data + * @api private + */ + + function ready (err, content, etag) { + if (err) { + self.manager.log.warn('Unable to serve file. ' + (err.message || err)); + return write(500, null, 'Error serving static ' + path); + } + + // store the result in the cache + var reply = self.cache[path] = { + content: content + , length: content.length + , mime: details.mime + , etag: etag || client.version + , versioned: versioning.test(path) + }; + + // check if gzip is enabled + if (details.mime.gzip && self.manager.enabled('browser client gzip')) { + self.gzip(content, function (err, content) { + if (!err) { + reply.gzip = { + content: content + , length: content.length + } + } + + answer(reply); + }); + } else { + answer(reply); + } + } + + if (details.file) { + fs.readFile(details.file, ready); + } else if(details.callback) { + details.callback.call(this, path, ready); + } else { + write(404, null, 'File handle not found'); + } + } else { + write(404, null, 'File not found'); + } +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/store.js b/coder-base/node_modules_orig/socket.io/lib/store.js new file mode 100755 index 00000000..06c0389a --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/store.js @@ -0,0 +1,98 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Expose the constructor. + */ + +exports = module.exports = Store; + +/** + * Module dependencies. + */ + +var EventEmitter = process.EventEmitter; + +/** + * Store interface + * + * @api public + */ + +function Store (options) { + this.options = options; + this.clients = {}; +}; + +/** + * Inherit from EventEmitter. + */ + +Store.prototype.__proto__ = EventEmitter.prototype; + +/** + * Initializes a client store + * + * @param {String} id + * @api public + */ + +Store.prototype.client = function (id) { + if (!this.clients[id]) { + this.clients[id] = new (this.constructor.Client)(this, id); + } + + return this.clients[id]; +}; + +/** + * Destroys a client + * + * @api {String} sid + * @param {Number} number of seconds to expire client data + * @api private + */ + +Store.prototype.destroyClient = function (id, expiration) { + if (this.clients[id]) { + this.clients[id].destroy(expiration); + delete this.clients[id]; + } + + return this; +}; + +/** + * Destroys the store + * + * @param {Number} number of seconds to expire client data + * @api private + */ + +Store.prototype.destroy = function (clientExpiration) { + var keys = Object.keys(this.clients) + , count = keys.length; + + for (var i = 0, l = count; i < l; i++) { + this.destroyClient(keys[i], clientExpiration); + } + + this.clients = {}; + + return this; +}; + +/** + * Client. + * + * @api public + */ + +Store.Client = function (store, id) { + this.store = store; + this.id = id; +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/stores/memory.js b/coder-base/node_modules_orig/socket.io/lib/stores/memory.js new file mode 100755 index 00000000..8b731a79 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/stores/memory.js @@ -0,0 +1,143 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var crypto = require('crypto') + , Store = require('../store'); + +/** + * Exports the constructor. + */ + +exports = module.exports = Memory; +Memory.Client = Client; + +/** + * Memory store + * + * @api public + */ + +function Memory (opts) { + Store.call(this, opts); +}; + +/** + * Inherits from Store. + */ + +Memory.prototype.__proto__ = Store.prototype; + +/** + * Publishes a message. + * + * @api private + */ + +Memory.prototype.publish = function () { }; + +/** + * Subscribes to a channel + * + * @api private + */ + +Memory.prototype.subscribe = function () { }; + +/** + * Unsubscribes + * + * @api private + */ + +Memory.prototype.unsubscribe = function () { }; + +/** + * Client constructor + * + * @api private + */ + +function Client () { + Store.Client.apply(this, arguments); + this.data = {}; +}; + +/** + * Inherits from Store.Client + */ + +Client.prototype.__proto__ = Store.Client; + +/** + * Gets a key + * + * @api public + */ + +Client.prototype.get = function (key, fn) { + fn(null, this.data[key] === undefined ? null : this.data[key]); + return this; +}; + +/** + * Sets a key + * + * @api public + */ + +Client.prototype.set = function (key, value, fn) { + this.data[key] = value; + fn && fn(null); + return this; +}; + +/** + * Has a key + * + * @api public + */ + +Client.prototype.has = function (key, fn) { + fn(null, key in this.data); +}; + +/** + * Deletes a key + * + * @api public + */ + +Client.prototype.del = function (key, fn) { + delete this.data[key]; + fn && fn(null); + return this; +}; + +/** + * Destroys the client. + * + * @param {Number} number of seconds to expire data + * @api private + */ + +Client.prototype.destroy = function (expiration) { + if ('number' != typeof expiration) { + this.data = {}; + } else { + var self = this; + + setTimeout(function () { + self.data = {}; + }, expiration * 1000); + } + + return this; +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/stores/redis.js b/coder-base/node_modules_orig/socket.io/lib/stores/redis.js new file mode 100755 index 00000000..8fea235f --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/stores/redis.js @@ -0,0 +1,269 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var crypto = require('crypto') + , Store = require('../store') + , assert = require('assert'); + +/** + * Exports the constructor. + */ + +exports = module.exports = Redis; +Redis.Client = Client; + +/** + * Redis store. + * Options: + * - nodeId (fn) gets an id that uniquely identifies this node + * - redis (fn) redis constructor, defaults to redis + * - redisPub (object) options to pass to the pub redis client + * - redisSub (object) options to pass to the sub redis client + * - redisClient (object) options to pass to the general redis client + * - pack (fn) custom packing, defaults to JSON or msgpack if installed + * - unpack (fn) custom packing, defaults to JSON or msgpack if installed + * + * @api public + */ + +function Redis (opts) { + opts = opts || {}; + + // node id to uniquely identify this node + var nodeId = opts.nodeId || function () { + // by default, we generate a random id + return Math.abs(Math.random() * Math.random() * Date.now() | 0); + }; + + this.nodeId = nodeId(); + + // packing / unpacking mechanism + if (opts.pack) { + this.pack = opts.pack; + this.unpack = opts.unpack; + } else { + try { + var msgpack = require('msgpack'); + this.pack = msgpack.pack; + this.unpack = msgpack.unpack; + } catch (e) { + this.pack = JSON.stringify; + this.unpack = JSON.parse; + } + } + + var redis = opts.redis || require('redis') + , RedisClient = redis.RedisClient; + + // initialize a pubsub client and a regular client + if (opts.redisPub instanceof RedisClient) { + this.pub = opts.redisPub; + } else { + opts.redisPub || (opts.redisPub = {}); + this.pub = redis.createClient(opts.redisPub.port, opts.redisPub.host, opts.redisPub); + } + if (opts.redisSub instanceof RedisClient) { + this.sub = opts.redisSub; + } else { + opts.redisSub || (opts.redisSub = {}); + this.sub = redis.createClient(opts.redisSub.port, opts.redisSub.host, opts.redisSub); + } + if (opts.redisClient instanceof RedisClient) { + this.cmd = opts.redisClient; + } else { + opts.redisClient || (opts.redisClient = {}); + this.cmd = redis.createClient(opts.redisClient.port, opts.redisClient.host, opts.redisClient); + } + + Store.call(this, opts); + + this.sub.setMaxListeners(0); + this.setMaxListeners(0); +}; + +/** + * Inherits from Store. + */ + +Redis.prototype.__proto__ = Store.prototype; + +/** + * Publishes a message. + * + * @api private + */ + +Redis.prototype.publish = function (name) { + var args = Array.prototype.slice.call(arguments, 1); + this.pub.publish(name, this.pack({ nodeId: this.nodeId, args: args })); + this.emit.apply(this, ['publish', name].concat(args)); +}; + +/** + * Subscribes to a channel + * + * @api private + */ + +Redis.prototype.subscribe = function (name, consumer, fn) { + this.sub.subscribe(name); + + if (consumer || fn) { + var self = this; + + self.sub.on('subscribe', function subscribe (ch) { + if (name == ch) { + function message (ch, msg) { + if (name == ch) { + msg = self.unpack(msg); + + // we check that the message consumed wasnt emitted by this node + if (self.nodeId != msg.nodeId) { + consumer.apply(null, msg.args); + } + } + }; + + self.sub.on('message', message); + + self.on('unsubscribe', function unsubscribe (ch) { + if (name == ch) { + self.sub.removeListener('message', message); + self.removeListener('unsubscribe', unsubscribe); + } + }); + + self.sub.removeListener('subscribe', subscribe); + + fn && fn(); + } + }); + } + + this.emit('subscribe', name, consumer, fn); +}; + +/** + * Unsubscribes + * + * @api private + */ + +Redis.prototype.unsubscribe = function (name, fn) { + this.sub.unsubscribe(name); + + if (fn) { + var client = this.sub; + + client.on('unsubscribe', function unsubscribe (ch) { + if (name == ch) { + fn(); + client.removeListener('unsubscribe', unsubscribe); + } + }); + } + + this.emit('unsubscribe', name, fn); +}; + +/** + * Destroys the store + * + * @api public + */ + +Redis.prototype.destroy = function () { + Store.prototype.destroy.call(this); + + this.pub.end(); + this.sub.end(); + this.cmd.end(); +}; + +/** + * Client constructor + * + * @api private + */ + +function Client (store, id) { + Store.Client.call(this, store, id); +}; + +/** + * Inherits from Store.Client + */ + +Client.prototype.__proto__ = Store.Client; + +/** + * Redis hash get + * + * @api private + */ + +Client.prototype.get = function (key, fn) { + this.store.cmd.hget(this.id, key, fn); + return this; +}; + +/** + * Redis hash set + * + * @api private + */ + +Client.prototype.set = function (key, value, fn) { + this.store.cmd.hset(this.id, key, value, fn); + return this; +}; + +/** + * Redis hash del + * + * @api private + */ + +Client.prototype.del = function (key, fn) { + this.store.cmd.hdel(this.id, key, fn); + return this; +}; + +/** + * Redis hash has + * + * @api private + */ + +Client.prototype.has = function (key, fn) { + this.store.cmd.hexists(this.id, key, function (err, has) { + if (err) return fn(err); + fn(null, !!has); + }); + return this; +}; + +/** + * Destroys client + * + * @param {Number} number of seconds to expire data + * @api private + */ + +Client.prototype.destroy = function (expiration) { + if ('number' != typeof expiration) { + this.store.cmd.del(this.id); + } else { + this.store.cmd.expire(this.id, expiration); + } + + return this; +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/transport.js b/coder-base/node_modules_orig/socket.io/lib/transport.js new file mode 100755 index 00000000..2e4c08bd --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/transport.js @@ -0,0 +1,534 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var parser = require('./parser'); + +/** + * Expose the constructor. + */ + +exports = module.exports = Transport; + +/** + * Transport constructor. + * + * @api public + */ + +function Transport (mng, data, req) { + this.manager = mng; + this.id = data.id; + this.disconnected = false; + this.drained = true; + this.handleRequest(req); +}; + +/** + * Access the logger. + * + * @api public + */ + +Transport.prototype.__defineGetter__('log', function () { + return this.manager.log; +}); + +/** + * Access the store. + * + * @api public + */ + +Transport.prototype.__defineGetter__('store', function () { + return this.manager.store; +}); + +/** + * Handles a request when it's set. + * + * @api private + */ + +Transport.prototype.handleRequest = function (req) { + this.log.debug('setting request', req.method, req.url); + this.req = req; + + if (req.method == 'GET') { + this.socket = req.socket; + this.open = true; + this.drained = true; + this.setHeartbeatInterval(); + + this.setHandlers(); + this.onSocketConnect(); + } +}; + +/** + * Called when a connection is first set. + * + * @api private + */ + +Transport.prototype.onSocketConnect = function () { }; + +/** + * Sets transport handlers + * + * @api private + */ + +Transport.prototype.setHandlers = function () { + var self = this; + + // we need to do this in a pub/sub way since the client can POST the message + // over a different socket (ie: different Transport instance) + this.store.subscribe('heartbeat-clear:' + this.id, function () { + self.onHeartbeatClear(); + }); + + this.store.subscribe('disconnect-force:' + this.id, function () { + self.onForcedDisconnect(); + }); + + this.store.subscribe('dispatch:' + this.id, function (packet, volatile) { + self.onDispatch(packet, volatile); + }); + + this.bound = { + end: this.onSocketEnd.bind(this) + , close: this.onSocketClose.bind(this) + , error: this.onSocketError.bind(this) + , drain: this.onSocketDrain.bind(this) + }; + + this.socket.on('end', this.bound.end); + this.socket.on('close', this.bound.close); + this.socket.on('error', this.bound.error); + this.socket.on('drain', this.bound.drain); + + this.handlersSet = true; +}; + +/** + * Removes transport handlers + * + * @api private + */ + +Transport.prototype.clearHandlers = function () { + if (this.handlersSet) { + this.store.unsubscribe('disconnect-force:' + this.id); + this.store.unsubscribe('heartbeat-clear:' + this.id); + this.store.unsubscribe('dispatch:' + this.id); + + this.socket.removeListener('end', this.bound.end); + this.socket.removeListener('close', this.bound.close); + this.socket.removeListener('error', this.bound.error); + this.socket.removeListener('drain', this.bound.drain); + } +}; + +/** + * Called when the connection dies + * + * @api private + */ + +Transport.prototype.onSocketEnd = function () { + this.end('socket end'); +}; + +/** + * Called when the connection dies + * + * @api private + */ + +Transport.prototype.onSocketClose = function (error) { + this.end(error ? 'socket error' : 'socket close'); +}; + +/** + * Called when the connection has an error. + * + * @api private + */ + +Transport.prototype.onSocketError = function (err) { + if (this.open) { + this.socket.destroy(); + this.onClose(); + } + + this.log.info('socket error ' + err.stack); +}; + +/** + * Called when the connection is drained. + * + * @api private + */ + +Transport.prototype.onSocketDrain = function () { + this.drained = true; +}; + +/** + * Called upon receiving a heartbeat packet. + * + * @api private + */ + +Transport.prototype.onHeartbeatClear = function () { + this.clearHeartbeatTimeout(); + this.setHeartbeatInterval(); +}; + +/** + * Called upon a forced disconnection. + * + * @api private + */ + +Transport.prototype.onForcedDisconnect = function () { + if (!this.disconnected) { + this.log.info('transport end by forced client disconnection'); + if (this.open) { + this.packet({ type: 'disconnect' }); + } + this.end('booted'); + } +}; + +/** + * Dispatches a packet. + * + * @api private + */ + +Transport.prototype.onDispatch = function (packet, volatile) { + if (volatile) { + this.writeVolatile(packet); + } else { + this.write(packet); + } +}; + +/** + * Sets the close timeout. + */ + +Transport.prototype.setCloseTimeout = function () { + if (!this.closeTimeout) { + var self = this; + + this.closeTimeout = setTimeout(function () { + self.log.debug('fired close timeout for client', self.id); + self.closeTimeout = null; + self.end('close timeout'); + }, this.manager.get('close timeout') * 1000); + + this.log.debug('set close timeout for client', this.id); + } +}; + +/** + * Clears the close timeout. + */ + +Transport.prototype.clearCloseTimeout = function () { + if (this.closeTimeout) { + clearTimeout(this.closeTimeout); + this.closeTimeout = null; + + this.log.debug('cleared close timeout for client', this.id); + } +}; + +/** + * Sets the heartbeat timeout + */ + +Transport.prototype.setHeartbeatTimeout = function () { + if (!this.heartbeatTimeout && this.manager.enabled('heartbeats')) { + var self = this; + + this.heartbeatTimeout = setTimeout(function () { + self.log.debug('fired heartbeat timeout for client', self.id); + self.heartbeatTimeout = null; + self.end('heartbeat timeout'); + }, this.manager.get('heartbeat timeout') * 1000); + + this.log.debug('set heartbeat timeout for client', this.id); + } +}; + +/** + * Clears the heartbeat timeout + * + * @param text + */ + +Transport.prototype.clearHeartbeatTimeout = function () { + if (this.heartbeatTimeout && this.manager.enabled('heartbeats')) { + clearTimeout(this.heartbeatTimeout); + this.heartbeatTimeout = null; + this.log.debug('cleared heartbeat timeout for client', this.id); + } +}; + +/** + * Sets the heartbeat interval. To be called when a connection opens and when + * a heartbeat is received. + * + * @api private + */ + +Transport.prototype.setHeartbeatInterval = function () { + if (!this.heartbeatInterval && this.manager.enabled('heartbeats')) { + var self = this; + + this.heartbeatInterval = setTimeout(function () { + self.heartbeat(); + self.heartbeatInterval = null; + }, this.manager.get('heartbeat interval') * 1000); + + this.log.debug('set heartbeat interval for client', this.id); + } +}; + +/** + * Clears all timeouts. + * + * @api private + */ + +Transport.prototype.clearTimeouts = function () { + this.clearCloseTimeout(); + this.clearHeartbeatTimeout(); + this.clearHeartbeatInterval(); +}; + +/** + * Sends a heartbeat + * + * @api private + */ + +Transport.prototype.heartbeat = function () { + if (this.open) { + this.log.debug('emitting heartbeat for client', this.id); + this.packet({ type: 'heartbeat' }); + this.setHeartbeatTimeout(); + } + + return this; +}; + +/** + * Handles a message. + * + * @param {Object} packet object + * @api private + */ + +Transport.prototype.onMessage = function (packet) { + var current = this.manager.transports[this.id]; + + if ('heartbeat' == packet.type) { + this.log.debug('got heartbeat packet'); + + if (current && current.open) { + current.onHeartbeatClear(); + } else { + this.store.publish('heartbeat-clear:' + this.id); + } + } else { + if ('disconnect' == packet.type && packet.endpoint == '') { + this.log.debug('got disconnection packet'); + + if (current) { + current.onForcedDisconnect(); + } else { + this.store.publish('disconnect-force:' + this.id); + } + + return; + } + + if (packet.id && packet.ack != 'data') { + this.log.debug('acknowledging packet automatically'); + + var ack = parser.encodePacket({ + type: 'ack' + , ackId: packet.id + , endpoint: packet.endpoint || '' + }); + + if (current && current.open) { + current.onDispatch(ack); + } else { + this.manager.onClientDispatch(this.id, ack); + this.store.publish('dispatch:' + this.id, ack); + } + } + + // handle packet locally or publish it + if (current) { + this.manager.onClientMessage(this.id, packet); + } else { + this.store.publish('message:' + this.id, packet); + } + } +}; + +/** + * Clears the heartbeat interval + * + * @api private + */ + +Transport.prototype.clearHeartbeatInterval = function () { + if (this.heartbeatInterval && this.manager.enabled('heartbeats')) { + clearTimeout(this.heartbeatInterval); + this.heartbeatInterval = null; + this.log.debug('cleared heartbeat interval for client', this.id); + } +}; + +/** + * Finishes the connection and makes sure client doesn't reopen + * + * @api private + */ + +Transport.prototype.disconnect = function (reason) { + this.packet({ type: 'disconnect' }); + this.end(reason); + + return this; +}; + +/** + * Closes the connection. + * + * @api private + */ + +Transport.prototype.close = function () { + if (this.open) { + this.doClose(); + this.onClose(); + } +}; + +/** + * Called upon a connection close. + * + * @api private + */ + +Transport.prototype.onClose = function () { + if (this.open) { + this.setCloseTimeout(); + this.clearHandlers(); + this.open = false; + this.manager.onClose(this.id); + this.store.publish('close', this.id); + } +}; + +/** + * Cleans up the connection, considers the client disconnected. + * + * @api private + */ + +Transport.prototype.end = function (reason) { + if (!this.disconnected) { + this.log.info('transport end (' + reason + ')'); + + var local = this.manager.transports[this.id]; + + this.close(); + this.clearTimeouts(); + this.disconnected = true; + + if (local) { + this.manager.onClientDisconnect(this.id, reason, true); + } else { + this.store.publish('disconnect:' + this.id, reason); + } + } +}; + +/** + * Signals that the transport should pause and buffer data. + * + * @api public + */ + +Transport.prototype.discard = function () { + this.log.debug('discarding transport'); + this.discarded = true; + this.clearTimeouts(); + this.clearHandlers(); + + return this; +}; + +/** + * Writes an error packet with the specified reason and advice. + * + * @param {Number} advice + * @param {Number} reason + * @api public + */ + +Transport.prototype.error = function (reason, advice) { + this.packet({ + type: 'error' + , reason: reason + , advice: advice + }); + + this.log.warn(reason, advice ? ('client should ' + advice) : ''); + this.end('error'); +}; + +/** + * Write a packet. + * + * @api public + */ + +Transport.prototype.packet = function (obj) { + return this.write(parser.encodePacket(obj)); +}; + +/** + * Writes a volatile message. + * + * @api private + */ + +Transport.prototype.writeVolatile = function (msg) { + if (this.open) { + if (this.drained) { + this.write(msg); + } else { + this.log.debug('ignoring volatile packet, buffer not drained'); + } + } else { + this.log.debug('ignoring volatile packet, transport not open'); + } +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/transports/flashsocket.js b/coder-base/node_modules_orig/socket.io/lib/transports/flashsocket.js new file mode 100755 index 00000000..dc2d78b4 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/transports/flashsocket.js @@ -0,0 +1,129 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ +var WebSocket = require('./websocket'); + +/** + * Export the constructor. + */ + +exports = module.exports = FlashSocket; + +/** + * The FlashSocket transport is just a proxy + * for WebSocket connections. + * + * @api public + */ + +function FlashSocket (mng, data, req) { + return WebSocket.call(this, mng, data, req); +} + +/** + * Inherits from WebSocket. + */ + +FlashSocket.prototype.__proto__ = WebSocket.prototype; + +/** + * Transport name + * + * @api public + */ + +FlashSocket.prototype.name = 'flashsocket'; + +/** + * Listens for new configuration changes of the Manager + * this way we can enable and disable the flash server. + * + * @param {Manager} Manager instance. + * @api private + */ + + +FlashSocket.init = function (manager) { + var server; + function create () { + + // Drop out immediately if the user has + // disabled the flash policy server + if (!manager.get('flash policy server')) { + return; + } + + server = require('policyfile').createServer({ + log: function(msg){ + manager.log.info(msg); + } + }, manager.get('origins')); + + server.on('close', function (e) { + server = null; + }); + + server.listen(manager.get('flash policy port'), manager.server); + + manager.flashPolicyServer = server; + } + + // listen for origin changes, so we can update the server + manager.on('set:origins', function (value, key) { + if (!server) return; + + // update the origins and compile a new response buffer + server.origins = Array.isArray(value) ? value : [value]; + server.compile(); + }); + + // destory the server and create a new server + manager.on('set:flash policy port', function (value, key) { + var transports = manager.get('transports'); + if (~transports.indexOf('flashsocket')) { + if (server) { + if (server.port === value) return; + // destroy the server and rebuild it on a new port + try { + server.close(); + } + catch (e) { /* ignore exception. could e.g. be that the server isn't started yet */ } + } + create(); + } + }); + + // create or destroy the server + manager.on('set:flash policy server', function (value, key) { + var transports = manager.get('transports'); + if (~transports.indexOf('flashsocket')) { + if (server && !value) { + // destroy the server + try { + server.close(); + } + catch (e) { /* ignore exception. could e.g. be that the server isn't started yet */ } + } + } else if (!server && value) { + // create the server + create(); + } + }); + + // only start the server + manager.on('set:transports', function (value, key){ + if (!server && ~manager.get('transports').indexOf('flashsocket')) { + create(); + } + }); + // check if we need to initialize at start + if (~manager.get('transports').indexOf('flashsocket')){ + create(); + } +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/transports/htmlfile.js b/coder-base/node_modules_orig/socket.io/lib/transports/htmlfile.js new file mode 100755 index 00000000..e8709a31 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/transports/htmlfile.js @@ -0,0 +1,82 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var HTTPTransport = require('./http'); + +/** + * Export the constructor. + */ + +exports = module.exports = HTMLFile; + +/** + * HTMLFile transport constructor. + * + * @api public + */ + +function HTMLFile (mng, data, req) { + HTTPTransport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +HTMLFile.prototype.__proto__ = HTTPTransport.prototype; + +/** + * Transport name + * + * @api public + */ + +HTMLFile.prototype.name = 'htmlfile'; + +/** + * Handles the request. + * + * @api private + */ + +HTMLFile.prototype.handleRequest = function (req) { + HTTPTransport.prototype.handleRequest.call(this, req); + + if (req.method == 'GET') { + req.res.writeHead(200, { + 'Content-Type': 'text/html; charset=UTF-8' + , 'Connection': 'keep-alive' + , 'Transfer-Encoding': 'chunked' + }); + + req.res.write( + '' + + '' + + new Array(174).join(' ') + ); + } +}; + +/** + * Performs the write. + * + * @api private + */ + +HTMLFile.prototype.write = function (data) { + data = ''; + + if (this.response.write(data)) { + this.drained = true; + } + + this.log.debug(this.name + ' writing', data); +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/transports/http-polling.js b/coder-base/node_modules_orig/socket.io/lib/transports/http-polling.js new file mode 100755 index 00000000..89b7e042 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/transports/http-polling.js @@ -0,0 +1,147 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var HTTPTransport = require('./http'); + +/** + * Exports the constructor. + */ + +exports = module.exports = HTTPPolling; + +/** + * HTTP polling constructor. + * + * @api public. + */ + +function HTTPPolling (mng, data, req) { + HTTPTransport.call(this, mng, data, req); +}; + +/** + * Inherits from HTTPTransport. + * + * @api public. + */ + +HTTPPolling.prototype.__proto__ = HTTPTransport.prototype; + +/** + * Transport name + * + * @api public + */ + +HTTPPolling.prototype.name = 'httppolling'; + +/** + * Override setHandlers + * + * @api private + */ + +HTTPPolling.prototype.setHandlers = function () { + HTTPTransport.prototype.setHandlers.call(this); + this.socket.removeListener('end', this.bound.end); + this.socket.removeListener('close', this.bound.close); +}; + +/** + * Removes heartbeat timeouts for polling. + */ + +HTTPPolling.prototype.setHeartbeatInterval = function () { + return this; +}; + +/** + * Handles a request + * + * @api private + */ + +HTTPPolling.prototype.handleRequest = function (req) { + HTTPTransport.prototype.handleRequest.call(this, req); + + if (req.method == 'GET') { + var self = this; + + this.pollTimeout = setTimeout(function () { + self.packet({ type: 'noop' }); + self.log.debug(self.name + ' closed due to exceeded duration'); + }, this.manager.get('polling duration') * 1000); + + this.log.debug('setting poll timeout'); + } +}; + +/** + * Clears polling timeout + * + * @api private + */ + +HTTPPolling.prototype.clearPollTimeout = function () { + if (this.pollTimeout) { + clearTimeout(this.pollTimeout); + this.pollTimeout = null; + this.log.debug('clearing poll timeout'); + } + + return this; +}; + +/** + * Override clear timeouts to clear the poll timeout + * + * @api private + */ + +HTTPPolling.prototype.clearTimeouts = function () { + HTTPTransport.prototype.clearTimeouts.call(this); + + this.clearPollTimeout(); +}; + +/** + * doWrite to clear poll timeout + * + * @api private + */ + +HTTPPolling.prototype.doWrite = function () { + this.clearPollTimeout(); +}; + +/** + * Performs a write. + * + * @api private. + */ + +HTTPPolling.prototype.write = function (data, close) { + this.doWrite(data); + this.response.end(); + this.onClose(); +}; + +/** + * Override end. + * + * @api private + */ + +HTTPPolling.prototype.end = function (reason) { + this.clearPollTimeout(); + return HTTPTransport.prototype.end.call(this, reason); +}; + diff --git a/coder-base/node_modules_orig/socket.io/lib/transports/http.js b/coder-base/node_modules_orig/socket.io/lib/transports/http.js new file mode 100755 index 00000000..28db794d --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/transports/http.js @@ -0,0 +1,121 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var Transport = require('../transport') + , parser = require('../parser') + , qs = require('querystring'); + +/** + * Export the constructor. + */ + +exports = module.exports = HTTPTransport; + +/** + * HTTP interface constructor. For all non-websocket transports. + * + * @api public + */ + +function HTTPTransport (mng, data, req) { + Transport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +HTTPTransport.prototype.__proto__ = Transport.prototype; + +/** + * Handles a request. + * + * @api private + */ + +HTTPTransport.prototype.handleRequest = function (req) { + + // Always set the response in case an error is returned to the client + this.response = req.res; + + if (req.method == 'POST') { + var buffer = '' + , res = req.res + , origin = req.headers.origin + , headers = { 'Content-Length': 1, 'Content-Type': 'text/plain; charset=UTF-8' } + , self = this; + + req.on('data', function (data) { + buffer += data; + + if (Buffer.byteLength(buffer) >= self.manager.get('destroy buffer size')) { + buffer = ''; + req.connection.destroy(); + } + }); + + req.on('end', function () { + res.writeHead(200, headers); + res.end('1'); + + self.onData(self.postEncoded ? qs.parse(buffer).d : buffer); + }); + + // prevent memory leaks for uncompleted requests + req.on('close', function () { + buffer = ''; + self.onClose(); + }); + + if (origin) { + // https://developer.mozilla.org/En/HTTP_Access_Control + headers['Access-Control-Allow-Origin'] = origin; + headers['Access-Control-Allow-Credentials'] = 'true'; + } + } else { + Transport.prototype.handleRequest.call(this, req); + } +}; + +/** + * Handles data payload. + * + * @api private + */ + +HTTPTransport.prototype.onData = function (data) { + var messages = parser.decodePayload(data); + this.log.debug(this.name + ' received data packet', data); + + for (var i = 0, l = messages.length; i < l; i++) { + this.onMessage(messages[i]); + } +}; + +/** + * Closes the request-response cycle + * + * @api private + */ + +HTTPTransport.prototype.doClose = function () { + this.response.end(); +}; + +/** + * Writes a payload of messages + * + * @api private + */ + +HTTPTransport.prototype.payload = function (msgs) { + this.write(parser.encodePayload(msgs)); +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/transports/index.js b/coder-base/node_modules_orig/socket.io/lib/transports/index.js new file mode 100755 index 00000000..b8655594 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/transports/index.js @@ -0,0 +1,12 @@ + +/** + * Export transports. + */ + +module.exports = { + websocket: require('./websocket') + , flashsocket: require('./flashsocket') + , htmlfile: require('./htmlfile') + , 'xhr-polling': require('./xhr-polling') + , 'jsonp-polling': require('./jsonp-polling') +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/transports/jsonp-polling.js b/coder-base/node_modules_orig/socket.io/lib/transports/jsonp-polling.js new file mode 100755 index 00000000..ad7d5aff --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/transports/jsonp-polling.js @@ -0,0 +1,97 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var HTTPPolling = require('./http-polling'); +var jsonpolling_re = /^\d+$/ + +/** + * Export the constructor. + */ + +exports = module.exports = JSONPPolling; + +/** + * JSON-P polling transport. + * + * @api public + */ + +function JSONPPolling (mng, data, req) { + HTTPPolling.call(this, mng, data, req); + + this.head = 'io.j[0]('; + this.foot = ');'; + + if (data.query.i && jsonpolling_re.test(data.query.i)) { + this.head = 'io.j[' + data.query.i + ']('; + } +}; + +/** + * Inherits from Transport. + */ + +JSONPPolling.prototype.__proto__ = HTTPPolling.prototype; + +/** + * Transport name + * + * @api public + */ + +JSONPPolling.prototype.name = 'jsonppolling'; + +/** + * Make sure POST are decoded. + */ + +JSONPPolling.prototype.postEncoded = true; + +/** + * Handles incoming data. + * Due to a bug in \n handling by browsers, we expect a JSONified string. + * + * @api private + */ + +JSONPPolling.prototype.onData = function (data) { + try { + data = JSON.parse(data); + } catch (e) { + this.error('parse', 'reconnect'); + return; + } + + HTTPPolling.prototype.onData.call(this, data); +}; + +/** + * Performs the write. + * + * @api private + */ + +JSONPPolling.prototype.doWrite = function (data) { + HTTPPolling.prototype.doWrite.call(this); + + var data = data === undefined + ? '' : this.head + JSON.stringify(data) + this.foot; + + this.response.writeHead(200, { + 'Content-Type': 'text/javascript; charset=UTF-8' + , 'Content-Length': Buffer.byteLength(data) + , 'Connection': 'Keep-Alive' + , 'X-XSS-Protection': '0' + }); + + this.response.write(data); + this.log.debug(this.name + ' writing', data); +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/transports/websocket.js b/coder-base/node_modules_orig/socket.io/lib/transports/websocket.js new file mode 100755 index 00000000..78a43043 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/transports/websocket.js @@ -0,0 +1,36 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var protocolVersions = require('./websocket/'); + +/** + * Export the constructor. + */ + +exports = module.exports = WebSocket; + +/** + * HTTP interface constructor. Interface compatible with all transports that + * depend on request-response cycles. + * + * @api public + */ + +function WebSocket (mng, data, req) { + var transport + , version = req.headers['sec-websocket-version']; + if (typeof version !== 'undefined' && typeof protocolVersions[version] !== 'undefined') { + transport = new protocolVersions[version](mng, data, req); + } + else transport = new protocolVersions['default'](mng, data, req); + if (typeof this.name !== 'undefined') transport.name = this.name; + return transport; +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/transports/websocket/default.js b/coder-base/node_modules_orig/socket.io/lib/transports/websocket/default.js new file mode 100755 index 00000000..091fdd44 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/transports/websocket/default.js @@ -0,0 +1,362 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var Transport = require('../../transport') + , EventEmitter = process.EventEmitter + , crypto = require('crypto') + , parser = require('../../parser'); + +/** + * Export the constructor. + */ + +exports = module.exports = WebSocket; + +/** + * HTTP interface constructor. Interface compatible with all transports that + * depend on request-response cycles. + * + * @api public + */ + +function WebSocket (mng, data, req) { + // parser + var self = this; + + this.parser = new Parser(); + this.parser.on('data', function (packet) { + self.log.debug(self.name + ' received data packet', packet); + self.onMessage(parser.decodePacket(packet)); + }); + this.parser.on('close', function () { + self.end(); + }); + this.parser.on('error', function () { + self.end(); + }); + + Transport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +WebSocket.prototype.__proto__ = Transport.prototype; + +/** + * Transport name + * + * @api public + */ + +WebSocket.prototype.name = 'websocket'; + +/** + * Websocket draft version + * + * @api public + */ + +WebSocket.prototype.protocolVersion = 'hixie-76'; + +/** + * Called when the socket connects. + * + * @api private + */ + +WebSocket.prototype.onSocketConnect = function () { + var self = this; + + this.socket.setNoDelay(true); + + this.buffer = true; + this.buffered = []; + + if (this.req.headers.upgrade !== 'WebSocket') { + this.log.warn(this.name + ' connection invalid'); + this.end(); + return; + } + + var origin = this.req.headers['origin'] + , waitingForNonce = false; + if(this.manager.settings['match origin protocol']){ + location = (origin.indexOf('https')>-1 ? 'wss' : 'ws') + '://' + this.req.headers.host + this.req.url; + }else if(this.socket.encrypted){ + location = 'wss://' + this.req.headers.host + this.req.url; + }else{ + location = 'ws://' + this.req.headers.host + this.req.url; + } + + if (this.req.headers['sec-websocket-key1']) { + // If we don't have the nonce yet, wait for it (HAProxy compatibility). + if (! (this.req.head && this.req.head.length >= 8)) { + waitingForNonce = true; + } + + var headers = [ + 'HTTP/1.1 101 WebSocket Protocol Handshake' + , 'Upgrade: WebSocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Origin: ' + origin + , 'Sec-WebSocket-Location: ' + location + ]; + + if (this.req.headers['sec-websocket-protocol']){ + headers.push('Sec-WebSocket-Protocol: ' + + this.req.headers['sec-websocket-protocol']); + } + } else { + var headers = [ + 'HTTP/1.1 101 Web Socket Protocol Handshake' + , 'Upgrade: WebSocket' + , 'Connection: Upgrade' + , 'WebSocket-Origin: ' + origin + , 'WebSocket-Location: ' + location + ]; + } + + try { + this.socket.write(headers.concat('', '').join('\r\n')); + this.socket.setTimeout(0); + this.socket.setNoDelay(true); + this.socket.setEncoding('utf8'); + } catch (e) { + this.end(); + return; + } + + if (waitingForNonce) { + this.socket.setEncoding('binary'); + } else if (this.proveReception(headers)) { + self.flush(); + } + + var headBuffer = ''; + + this.socket.on('data', function (data) { + if (waitingForNonce) { + headBuffer += data; + + if (headBuffer.length < 8) { + return; + } + + // Restore the connection to utf8 encoding after receiving the nonce + self.socket.setEncoding('utf8'); + waitingForNonce = false; + + // Stuff the nonce into the location where it's expected to be + self.req.head = headBuffer.substr(0, 8); + headBuffer = ''; + + if (self.proveReception(headers)) { + self.flush(); + } + + return; + } + + self.parser.add(data); + }); +}; + +/** + * Writes to the socket. + * + * @api private + */ + +WebSocket.prototype.write = function (data) { + if (this.open) { + this.drained = false; + + if (this.buffer) { + this.buffered.push(data); + return this; + } + + var length = Buffer.byteLength(data) + , buffer = new Buffer(2 + length); + + buffer.write('\x00', 'binary'); + buffer.write(data, 1, 'utf8'); + buffer.write('\xff', 1 + length, 'binary'); + + try { + if (this.socket.write(buffer)) { + this.drained = true; + } + } catch (e) { + this.end(); + } + + this.log.debug(this.name + ' writing', data); + } +}; + +/** + * Flushes the internal buffer + * + * @api private + */ + +WebSocket.prototype.flush = function () { + this.buffer = false; + + for (var i = 0, l = this.buffered.length; i < l; i++) { + this.write(this.buffered.splice(0, 1)[0]); + } +}; + +/** + * Finishes the handshake. + * + * @api private + */ + +WebSocket.prototype.proveReception = function (headers) { + var self = this + , k1 = this.req.headers['sec-websocket-key1'] + , k2 = this.req.headers['sec-websocket-key2']; + + if (k1 && k2){ + var 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){ + self.log.warn('Invalid ' + self.name + ' key: "' + k + '".'); + self.end(); + return false; + } + + n /= spaces; + + md5.update(String.fromCharCode( + n >> 24 & 0xFF, + n >> 16 & 0xFF, + n >> 8 & 0xFF, + n & 0xFF)); + }); + + md5.update(this.req.head.toString('binary')); + + try { + this.socket.write(md5.digest('binary'), 'binary'); + } catch (e) { + this.end(); + } + } + + return true; +}; + +/** + * Writes a payload. + * + * @api private + */ + +WebSocket.prototype.payload = function (msgs) { + for (var i = 0, l = msgs.length; i < l; i++) { + this.write(msgs[i]); + } + + return this; +}; + +/** + * Closes the connection. + * + * @api private + */ + +WebSocket.prototype.doClose = function () { + this.socket.end(); +}; + +/** + * WebSocket parser + * + * @api public + */ + +function Parser () { + this.buffer = ''; + this.i = 0; +}; + +/** + * Inherits from EventEmitter. + */ + +Parser.prototype.__proto__ = EventEmitter.prototype; + +/** + * Adds data to the buffer. + * + * @api public + */ + +Parser.prototype.add = function (data) { + this.buffer += data; + this.parse(); +}; + +/** + * Parses the buffer. + * + * @api private + */ + +Parser.prototype.parse = function () { + for (var i = this.i, chr, l = this.buffer.length; i < l; i++){ + chr = this.buffer[i]; + + if (this.buffer.length == 2 && this.buffer[1] == '\u0000') { + this.emit('close'); + this.buffer = ''; + this.i = 0; + return; + } + + if (i === 0){ + if (chr != '\u0000') + this.error('Bad framing. Expected null byte as first frame'); + else + continue; + } + + if (chr == '\ufffd'){ + this.emit('data', this.buffer.substr(1, i - 1)); + this.buffer = this.buffer.substr(i + 1); + this.i = 0; + return this.parse(); + } + } +}; + +/** + * Handles an error + * + * @api private + */ + +Parser.prototype.error = function (reason) { + this.buffer = ''; + this.i = 0; + this.emit('error', reason); + return this; +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/transports/websocket/hybi-07-12.js b/coder-base/node_modules_orig/socket.io/lib/transports/websocket/hybi-07-12.js new file mode 100755 index 00000000..44f666a5 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/transports/websocket/hybi-07-12.js @@ -0,0 +1,622 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var Transport = require('../../transport') + , EventEmitter = process.EventEmitter + , crypto = require('crypto') + , url = require('url') + , parser = require('../../parser') + , util = require('../../util'); + +/** + * Export the constructor. + */ + +exports = module.exports = WebSocket; +exports.Parser = Parser; + +/** + * HTTP interface constructor. Interface compatible with all transports that + * depend on request-response cycles. + * + * @api public + */ + +function WebSocket (mng, data, req) { + // parser + var self = this; + + this.manager = mng; + this.parser = new Parser(); + this.parser.on('data', function (packet) { + self.onMessage(parser.decodePacket(packet)); + }); + this.parser.on('ping', function () { + // version 8 ping => pong + try { + self.socket.write('\u008a\u0000'); + } + catch (e) { + self.end(); + return; + } + }); + this.parser.on('close', function () { + self.end(); + }); + this.parser.on('error', function (reason) { + self.log.warn(self.name + ' parser error: ' + reason); + self.end(); + }); + + Transport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +WebSocket.prototype.__proto__ = Transport.prototype; + +/** + * Transport name + * + * @api public + */ + +WebSocket.prototype.name = 'websocket'; + +/** + * Websocket draft version + * + * @api public + */ + +WebSocket.prototype.protocolVersion = '07-12'; + +/** + * Called when the socket connects. + * + * @api private + */ + +WebSocket.prototype.onSocketConnect = function () { + var self = this; + + if (typeof this.req.headers.upgrade === 'undefined' || + this.req.headers.upgrade.toLowerCase() !== 'websocket') { + this.log.warn(this.name + ' connection invalid'); + this.end(); + return; + } + + var origin = this.req.headers['sec-websocket-origin'] + , location = ((this.manager.settings['match origin protocol'] ? + origin.match(/^https/) : this.socket.encrypted) ? + 'wss' : 'ws') + + '://' + this.req.headers.host + this.req.url; + + if (!this.verifyOrigin(origin)) { + this.log.warn(this.name + ' connection invalid: origin mismatch'); + this.end(); + return; + } + + if (!this.req.headers['sec-websocket-key']) { + this.log.warn(this.name + ' connection invalid: received no key'); + this.end(); + return; + } + + // calc key + var key = this.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 + ]; + + try { + this.socket.write(headers.concat('', '').join('\r\n')); + this.socket.setTimeout(0); + this.socket.setNoDelay(true); + } catch (e) { + this.end(); + return; + } + + this.socket.on('data', function (data) { + self.parser.add(data); + }); +}; + +/** + * Verifies the origin of a request. + * + * @api private + */ + +WebSocket.prototype.verifyOrigin = function (origin) { + var origins = this.manager.get('origins'); + + if (origin === 'null') origin = '*'; + + if (origins.indexOf('*:*') !== -1) { + return true; + } + + if (origin) { + try { + var parts = url.parse(origin); + parts.port = parts.port || 80; + var ok = + ~origins.indexOf(parts.hostname + ':' + parts.port) || + ~origins.indexOf(parts.hostname + ':*') || + ~origins.indexOf('*:' + parts.port); + if (!ok) this.log.warn('illegal origin: ' + origin); + return ok; + } catch (ex) { + this.log.warn('error parsing origin'); + } + } + else { + this.log.warn('origin missing from websocket call, yet required by config'); + } + return false; +}; + +/** + * Writes to the socket. + * + * @api private + */ + +WebSocket.prototype.write = function (data) { + if (this.open) { + var buf = this.frame(0x81, data); + try { + this.socket.write(buf, 'binary'); + } + catch (e) { + this.end(); + return; + } + this.log.debug(this.name + ' writing', data); + } +}; + +/** + * Writes a payload. + * + * @api private + */ + +WebSocket.prototype.payload = function (msgs) { + for (var i = 0, l = msgs.length; i < l; i++) { + this.write(msgs[i]); + } + + return this; +}; + +/** + * Frame server-to-client output as a text packet. + * + * @api private + */ + +WebSocket.prototype.frame = function (opcode, str) { + var dataBuffer = new Buffer(str) + , dataLength = dataBuffer.length + , startOffset = 2 + , secondByte = dataLength; + if (dataLength > 65536) { + startOffset = 10; + secondByte = 127; + } + else if (dataLength > 125) { + startOffset = 4; + secondByte = 126; + } + var outputBuffer = new Buffer(dataLength + startOffset); + outputBuffer[0] = opcode; + outputBuffer[1] = secondByte; + dataBuffer.copy(outputBuffer, startOffset); + switch (secondByte) { + case 126: + outputBuffer[2] = dataLength >>> 8; + outputBuffer[3] = dataLength % 256; + break; + case 127: + var l = dataLength; + for (var i = 1; i <= 8; ++i) { + outputBuffer[startOffset - i] = l & 0xff; + l >>>= 8; + } + } + return outputBuffer; +}; + +/** + * Closes the connection. + * + * @api private + */ + +WebSocket.prototype.doClose = function () { + this.socket.end(); +}; + +/** + * WebSocket parser + * + * @api public + */ + +function Parser () { + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0 + }; + this.overflow = null; + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.currentMessage = ''; + + var self = this; + this.opcodeHandlers = { + // text + '1': function(data) { + var finish = function(mask, data) { + self.currentMessage += self.unmask(mask, data); + if (self.state.lastFragment) { + self.emit('data', self.currentMessage); + self.currentMessage = ''; + } + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + if (util.unpack(data.slice(0, 4)) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported'); + return; + } + var lengthBytes = data.slice(4); // note: cap to 32 bit length + expectData(util.unpack(data)); + }); + } + }, + // binary + '2': function(data) { + var finish = function(mask, data) { + if (typeof self.currentMessage == 'string') self.currentMessage = []; // build a buffer list + self.currentMessage.push(self.unmask(mask, data, true)); + if (self.state.lastFragment) { + self.emit('binary', self.concatBuffers(self.currentMessage)); + self.currentMessage = ''; + } + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + if (util.unpack(data.slice(0, 4)) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported'); + return; + } + var lengthBytes = data.slice(4); // note: cap to 32 bit length + expectData(util.unpack(data)); + }); + } + }, + // close + '8': function(data) { + self.emit('close'); + self.reset(); + }, + // ping + '9': function(data) { + if (self.state.lastFragment == false) { + self.error('fragmented ping is not supported'); + return; + } + + var finish = function(mask, data) { + self.emit('ping', self.unmask(mask, data)); + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength == 0) { + finish(null, null); + } + else if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + expectData(util.unpack(data)); + }); + } + } + } + + this.expect('Opcode', 2, this.processPacket); +}; + +/** + * Inherits from EventEmitter. + */ + +Parser.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add new data to the parser. + * + * @api public + */ + +Parser.prototype.add = function(data) { + if (this.expectBuffer == null) { + this.addToOverflow(data); + return; + } + var toRead = Math.min(data.length, this.expectBuffer.length - this.expectOffset); + data.copy(this.expectBuffer, this.expectOffset, 0, toRead); + this.expectOffset += toRead; + if (toRead < data.length) { + // at this point the overflow buffer shouldn't at all exist + this.overflow = new Buffer(data.length - toRead); + data.copy(this.overflow, 0, toRead, toRead + this.overflow.length); + } + if (this.expectOffset == this.expectBuffer.length) { + var bufferForHandler = this.expectBuffer; + this.expectBuffer = null; + this.expectOffset = 0; + this.expectHandler.call(this, bufferForHandler); + } +} + +/** + * Adds a piece of data to the overflow. + * + * @api private + */ + +Parser.prototype.addToOverflow = function(data) { + if (this.overflow == null) this.overflow = data; + else { + var prevOverflow = this.overflow; + this.overflow = new Buffer(this.overflow.length + data.length); + prevOverflow.copy(this.overflow, 0); + data.copy(this.overflow, prevOverflow.length); + } +} + +/** + * Waits for a certain amount of bytes to be available, then fires a callback. + * + * @api private + */ + +Parser.prototype.expect = function(what, length, handler) { + this.expectBuffer = new Buffer(length); + this.expectOffset = 0; + this.expectHandler = handler; + if (this.overflow != null) { + var toOverflow = this.overflow; + this.overflow = null; + this.add(toOverflow); + } +} + +/** + * Start processing a new packet. + * + * @api private + */ + +Parser.prototype.processPacket = function (data) { + if ((data[0] & 0x70) != 0) { + this.error('reserved fields must be empty'); + } + 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.opcode = this.state.activeFragmentedOperation; + if (!(this.state.opcode == 1 || this.state.opcode == 2)) { + this.error('continuation frame cannot follow current opcode') + return; + } + } + else { + this.state.opcode = opcode; + if (this.state.lastFragment === false) { + this.state.activeFragmentedOperation = opcode; + } + } + var handler = this.opcodeHandlers[this.state.opcode]; + if (typeof handler == 'undefined') this.error('no handler for opcode ' + this.state.opcode); + else handler(data); +} + +/** + * Endprocessing a packet. + * + * @api private + */ + +Parser.prototype.endPacket = function() { + 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.expect('Opcode', 2, this.processPacket); +} + +/** + * Reset the parser state. + * + * @api private + */ + +Parser.prototype.reset = function() { + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0 + }; + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.overflow = null; + this.currentMessage = ''; +} + +/** + * Unmask received data. + * + * @api private + */ + +Parser.prototype.unmask = function (mask, buf, binary) { + if (mask != null) { + for (var i = 0, ll = buf.length; i < ll; i++) { + buf[i] ^= mask[i % 4]; + } + } + if (binary) return buf; + return buf != null ? buf.toString('utf8') : ''; +} + +/** + * Concatenates a list of buffers. + * + * @api private + */ + +Parser.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); + var offset = 0; + for (var i = 0, l = buffers.length; i < l; ++i) { + buffers[i].copy(mergedBuffer, offset); + offset += buffers[i].length; + } + return mergedBuffer; +} + +/** + * Handles an error + * + * @api private + */ + +Parser.prototype.error = function (reason) { + this.reset(); + this.emit('error', reason); + return this; +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/transports/websocket/hybi-16.js b/coder-base/node_modules_orig/socket.io/lib/transports/websocket/hybi-16.js new file mode 100755 index 00000000..69967dad --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/transports/websocket/hybi-16.js @@ -0,0 +1,622 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var Transport = require('../../transport') + , EventEmitter = process.EventEmitter + , crypto = require('crypto') + , url = require('url') + , parser = require('../../parser') + , util = require('../../util'); + +/** + * Export the constructor. + */ + +exports = module.exports = WebSocket; +exports.Parser = Parser; + +/** + * HTTP interface constructor. Interface compatible with all transports that + * depend on request-response cycles. + * + * @api public + */ + +function WebSocket (mng, data, req) { + // parser + var self = this; + + this.manager = mng; + this.parser = new Parser(); + this.parser.on('data', function (packet) { + self.onMessage(parser.decodePacket(packet)); + }); + this.parser.on('ping', function () { + // version 8 ping => pong + try { + self.socket.write('\u008a\u0000'); + } + catch (e) { + self.end(); + return; + } + }); + this.parser.on('close', function () { + self.end(); + }); + this.parser.on('error', function (reason) { + self.log.warn(self.name + ' parser error: ' + reason); + self.end(); + }); + + Transport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +WebSocket.prototype.__proto__ = Transport.prototype; + +/** + * Transport name + * + * @api public + */ + +WebSocket.prototype.name = 'websocket'; + +/** + * Websocket draft version + * + * @api public + */ + +WebSocket.prototype.protocolVersion = '16'; + +/** + * Called when the socket connects. + * + * @api private + */ + +WebSocket.prototype.onSocketConnect = function () { + var self = this; + + if (typeof this.req.headers.upgrade === 'undefined' || + this.req.headers.upgrade.toLowerCase() !== 'websocket') { + this.log.warn(this.name + ' connection invalid'); + this.end(); + return; + } + + var origin = this.req.headers['origin'] || '' + , location = ((this.manager.settings['match origin protocol'] ? + origin.match(/^https/) : this.socket.encrypted) ? + 'wss' : 'ws') + + '://' + this.req.headers.host + this.req.url; + + if (!this.verifyOrigin(origin)) { + this.log.warn(this.name + ' connection invalid: origin mismatch'); + this.end(); + return; + } + + if (!this.req.headers['sec-websocket-key']) { + this.log.warn(this.name + ' connection invalid: received no key'); + this.end(); + return; + } + + // calc key + var key = this.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 + ]; + + try { + this.socket.write(headers.concat('', '').join('\r\n')); + this.socket.setTimeout(0); + this.socket.setNoDelay(true); + } catch (e) { + this.end(); + return; + } + + this.socket.on('data', function (data) { + self.parser.add(data); + }); +}; + +/** + * Verifies the origin of a request. + * + * @api private + */ + +WebSocket.prototype.verifyOrigin = function (origin) { + var origins = this.manager.get('origins'); + + if (origin === 'null') origin = '*'; + + if (origins.indexOf('*:*') !== -1) { + return true; + } + + if (origin) { + try { + var parts = url.parse(origin); + parts.port = parts.port || 80; + var ok = + ~origins.indexOf(parts.hostname + ':' + parts.port) || + ~origins.indexOf(parts.hostname + ':*') || + ~origins.indexOf('*:' + parts.port); + if (!ok) this.log.warn('illegal origin: ' + origin); + return ok; + } catch (ex) { + this.log.warn('error parsing origin'); + } + } + else { + this.log.warn('origin missing from websocket call, yet required by config'); + } + return false; +}; + +/** + * Writes to the socket. + * + * @api private + */ + +WebSocket.prototype.write = function (data) { + if (this.open) { + var buf = this.frame(0x81, data); + try { + this.socket.write(buf, 'binary'); + } + catch (e) { + this.end(); + return; + } + this.log.debug(this.name + ' writing', data); + } +}; + +/** + * Writes a payload. + * + * @api private + */ + +WebSocket.prototype.payload = function (msgs) { + for (var i = 0, l = msgs.length; i < l; i++) { + this.write(msgs[i]); + } + + return this; +}; + +/** + * Frame server-to-client output as a text packet. + * + * @api private + */ + +WebSocket.prototype.frame = function (opcode, str) { + var dataBuffer = new Buffer(str) + , dataLength = dataBuffer.length + , startOffset = 2 + , secondByte = dataLength; + if (dataLength > 65536) { + startOffset = 10; + secondByte = 127; + } + else if (dataLength > 125) { + startOffset = 4; + secondByte = 126; + } + var outputBuffer = new Buffer(dataLength + startOffset); + outputBuffer[0] = opcode; + outputBuffer[1] = secondByte; + dataBuffer.copy(outputBuffer, startOffset); + switch (secondByte) { + case 126: + outputBuffer[2] = dataLength >>> 8; + outputBuffer[3] = dataLength % 256; + break; + case 127: + var l = dataLength; + for (var i = 1; i <= 8; ++i) { + outputBuffer[startOffset - i] = l & 0xff; + l >>>= 8; + } + } + return outputBuffer; +}; + +/** + * Closes the connection. + * + * @api private + */ + +WebSocket.prototype.doClose = function () { + this.socket.end(); +}; + +/** + * WebSocket parser + * + * @api public + */ + +function Parser () { + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0 + }; + this.overflow = null; + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.currentMessage = ''; + + var self = this; + this.opcodeHandlers = { + // text + '1': function(data) { + var finish = function(mask, data) { + self.currentMessage += self.unmask(mask, data); + if (self.state.lastFragment) { + self.emit('data', self.currentMessage); + self.currentMessage = ''; + } + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + if (util.unpack(data.slice(0, 4)) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported'); + return; + } + var lengthBytes = data.slice(4); // note: cap to 32 bit length + expectData(util.unpack(data)); + }); + } + }, + // binary + '2': function(data) { + var finish = function(mask, data) { + if (typeof self.currentMessage == 'string') self.currentMessage = []; // build a buffer list + self.currentMessage.push(self.unmask(mask, data, true)); + if (self.state.lastFragment) { + self.emit('binary', self.concatBuffers(self.currentMessage)); + self.currentMessage = ''; + } + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + if (util.unpack(data.slice(0, 4)) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported'); + return; + } + var lengthBytes = data.slice(4); // note: cap to 32 bit length + expectData(util.unpack(data)); + }); + } + }, + // close + '8': function(data) { + self.emit('close'); + self.reset(); + }, + // ping + '9': function(data) { + if (self.state.lastFragment == false) { + self.error('fragmented ping is not supported'); + return; + } + + var finish = function(mask, data) { + self.emit('ping', self.unmask(mask, data)); + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength == 0) { + finish(null, null); + } + else if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + expectData(util.unpack(data)); + }); + } + } + } + + this.expect('Opcode', 2, this.processPacket); +}; + +/** + * Inherits from EventEmitter. + */ + +Parser.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add new data to the parser. + * + * @api public + */ + +Parser.prototype.add = function(data) { + if (this.expectBuffer == null) { + this.addToOverflow(data); + return; + } + var toRead = Math.min(data.length, this.expectBuffer.length - this.expectOffset); + data.copy(this.expectBuffer, this.expectOffset, 0, toRead); + this.expectOffset += toRead; + if (toRead < data.length) { + // at this point the overflow buffer shouldn't at all exist + this.overflow = new Buffer(data.length - toRead); + data.copy(this.overflow, 0, toRead, toRead + this.overflow.length); + } + if (this.expectOffset == this.expectBuffer.length) { + var bufferForHandler = this.expectBuffer; + this.expectBuffer = null; + this.expectOffset = 0; + this.expectHandler.call(this, bufferForHandler); + } +} + +/** + * Adds a piece of data to the overflow. + * + * @api private + */ + +Parser.prototype.addToOverflow = function(data) { + if (this.overflow == null) this.overflow = data; + else { + var prevOverflow = this.overflow; + this.overflow = new Buffer(this.overflow.length + data.length); + prevOverflow.copy(this.overflow, 0); + data.copy(this.overflow, prevOverflow.length); + } +} + +/** + * Waits for a certain amount of bytes to be available, then fires a callback. + * + * @api private + */ + +Parser.prototype.expect = function(what, length, handler) { + this.expectBuffer = new Buffer(length); + this.expectOffset = 0; + this.expectHandler = handler; + if (this.overflow != null) { + var toOverflow = this.overflow; + this.overflow = null; + this.add(toOverflow); + } +} + +/** + * Start processing a new packet. + * + * @api private + */ + +Parser.prototype.processPacket = function (data) { + if ((data[0] & 0x70) != 0) { + this.error('reserved fields must be empty'); + 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.opcode = this.state.activeFragmentedOperation; + if (!(this.state.opcode == 1 || this.state.opcode == 2)) { + this.error('continuation frame cannot follow current opcode') + return; + } + } + else { + this.state.opcode = opcode; + if (this.state.lastFragment === false) { + this.state.activeFragmentedOperation = opcode; + } + } + var handler = this.opcodeHandlers[this.state.opcode]; + if (typeof handler == 'undefined') this.error('no handler for opcode ' + this.state.opcode); + else handler(data); +} + +/** + * Endprocessing a packet. + * + * @api private + */ + +Parser.prototype.endPacket = function() { + 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.expect('Opcode', 2, this.processPacket); +} + +/** + * Reset the parser state. + * + * @api private + */ + +Parser.prototype.reset = function() { + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0 + }; + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.overflow = null; + this.currentMessage = ''; +} + +/** + * Unmask received data. + * + * @api private + */ + +Parser.prototype.unmask = function (mask, buf, binary) { + if (mask != null) { + for (var i = 0, ll = buf.length; i < ll; i++) { + buf[i] ^= mask[i % 4]; + } + } + if (binary) return buf; + return buf != null ? buf.toString('utf8') : ''; +} + +/** + * Concatenates a list of buffers. + * + * @api private + */ + +Parser.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); + var offset = 0; + for (var i = 0, l = buffers.length; i < l; ++i) { + buffers[i].copy(mergedBuffer, offset); + offset += buffers[i].length; + } + return mergedBuffer; +} + +/** + * Handles an error + * + * @api private + */ + +Parser.prototype.error = function (reason) { + this.reset(); + this.emit('error', reason); + return this; +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/transports/websocket/index.js b/coder-base/node_modules_orig/socket.io/lib/transports/websocket/index.js new file mode 100755 index 00000000..3a952b75 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/transports/websocket/index.js @@ -0,0 +1,11 @@ + +/** + * Export websocket versions. + */ + +module.exports = { + 7: require('./hybi-07-12'), + 8: require('./hybi-07-12'), + 13: require('./hybi-16'), + default: require('./default') +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/transports/xhr-polling.js b/coder-base/node_modules_orig/socket.io/lib/transports/xhr-polling.js new file mode 100755 index 00000000..1db5aeee --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/transports/xhr-polling.js @@ -0,0 +1,69 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var HTTPPolling = require('./http-polling'); + +/** + * Export the constructor. + */ + +exports = module.exports = XHRPolling; + +/** + * Ajax polling transport. + * + * @api public + */ + +function XHRPolling (mng, data, req) { + HTTPPolling.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +XHRPolling.prototype.__proto__ = HTTPPolling.prototype; + +/** + * Transport name + * + * @api public + */ + +XHRPolling.prototype.name = 'xhr-polling'; + +/** + * Frames data prior to write. + * + * @api private + */ + +XHRPolling.prototype.doWrite = function (data) { + HTTPPolling.prototype.doWrite.call(this); + + var origin = this.req.headers.origin + , headers = { + 'Content-Type': 'text/plain; charset=UTF-8' + , 'Content-Length': data === undefined ? 0 : Buffer.byteLength(data) + , 'Connection': 'Keep-Alive' + }; + + if (origin) { + // https://developer.mozilla.org/En/HTTP_Access_Control + headers['Access-Control-Allow-Origin'] = origin; + headers['Access-Control-Allow-Credentials'] = 'true'; + } + + this.response.writeHead(200, headers); + this.response.write(data); + this.log.debug(this.name + ' writing', data); +}; diff --git a/coder-base/node_modules_orig/socket.io/lib/util.js b/coder-base/node_modules_orig/socket.io/lib/util.js new file mode 100755 index 00000000..f7d9f2b4 --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/lib/util.js @@ -0,0 +1,50 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +/** + * Converts an enumerable to an array. + * + * @api public + */ + +exports.toArray = function (enu) { + var arr = []; + + for (var i = 0, l = enu.length; i < l; i++) + arr.push(enu[i]); + + return arr; +}; + +/** + * Unpacks a buffer to a number. + * + * @api public + */ + +exports.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; +} + +/** + * Left pads a string. + * + * @api public + */ + +exports.padl = function (s,n,c) { + return new Array(1 + n - s.length).join(c) + s; +} + diff --git a/coder-base/node_modules_orig/socket.io/package.json b/coder-base/node_modules_orig/socket.io/package.json new file mode 100755 index 00000000..50416d5d --- /dev/null +++ b/coder-base/node_modules_orig/socket.io/package.json @@ -0,0 +1,72 @@ +{ + "name": "socket.io", + "version": "0.9.13", + "description": "Real-time apps made cross-browser & easy with a WebSocket-like API", + "homepage": "http://socket.io/", + "keywords": [ + "websocket", + "socket", + "realtime", + "socket.io", + "comet", + "ajax" + ], + "author": { + "name": "Guillermo Rauch", + "email": "guillermo@learnboost.com" + }, + "contributors": [ + { + "name": "Guillermo Rauch", + "email": "rauchg@gmail.com" + }, + { + "name": "Arnout Kazemier", + "email": "info@3rd-eden.com" + }, + { + "name": "Vladimir Dronnikov", + "email": "dronnikov@gmail.com" + }, + { + "name": "Einar Otto Stangvik", + "email": "einaros@gmail.com" + } + ], + "repository": { + "type": "git", + "url": "git://github.com/LearnBoost/socket.io.git" + }, + "dependencies": { + "socket.io-client": "0.9.11", + "policyfile": "0.0.4", + "base64id": "0.1.0", + "redis": "0.7.3" + }, + "devDependencies": { + "expresso": "0.9.2", + "should": "*", + "benchmark": "0.2.2", + "microtime": "0.1.3-1", + "colors": "0.5.1" + }, + "optionalDependencies": { + "redis": "0.7.3" + }, + "main": "index", + "engines": { + "node": ">= 0.4.0" + }, + "scripts": { + "test": "make test" + }, + "_id": "socket.io@0.9.13", + "_engineSupported": true, + "_npmVersion": "1.1.4", + "_nodeVersion": "v0.6.19", + "_defaultsLoaded": true, + "dist": { + "shasum": "35141dd603295ca2e754b7b14f67c473c30eb2ad" + }, + "_from": "socket.io@0.x" +} diff --git a/coder-base/package.json b/coder-base/package.json old mode 100644 new mode 100755 index a107a3d6..1e0e9b71 --- a/coder-base/package.json +++ b/coder-base/package.json @@ -1,15 +1,15 @@ { - "name": "coder-base", - "description": "kid-friendly web programming environment for pi", - "version": "0.0.1", - "private": true, - "dependencies": { - "express": "3.1.0", - "redis": "0.8.2", - "mustache": "0.7.2", - "consolidate": "0.8.0", - "socket.io": "0.9.13", - "express-params": "0.0.3", - "bcrypt": "0.7.4" - } + "name": "coder-base", + "description": "kid-friendly web programming environment for pi", + "version": "0.0.1", + "private": true, + "dependencies": { + "express": "3.4.0", + "redis": "0.8.6", + "mustache": "0.7.2", + "consolidate": "0.9.1", + "socket.io": "0.9.16", + "express-params": "0.0.3", + "bcrypt": "0.7.7" + } } diff --git a/coder-base/server.js b/coder-base/server.js old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/auth/css/index.css b/coder-base/static/apps/auth/css/index.css old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/auth/js/index.js b/coder-base/static/apps/auth/js/index.js old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/boilerplate/css/index.css b/coder-base/static/apps/boilerplate/css/index.css old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/boilerplate/js/index.js b/coder-base/static/apps/boilerplate/js/index.js old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/coder/css/index.css b/coder-base/static/apps/coder/css/index.css old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/coder/js/index.js b/coder-base/static/apps/coder/js/index.js old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/coder/media/myapps_tip.png b/coder-base/static/apps/coder/media/myapps_tip.png old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/coder/media/newapp_tip.png b/coder-base/static/apps/coder/media/newapp_tip.png old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/coder/media/settings_tip.png b/coder-base/static/apps/coder/media/settings_tip.png old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/coderlib/css/index.css b/coder-base/static/apps/coderlib/css/index.css old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/coderlib/js/index.js b/coder-base/static/apps/coderlib/js/index.js old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/editor/css/index.css b/coder-base/static/apps/editor/css/index.css old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/editor/js/index.js b/coder-base/static/apps/editor/js/index.js old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/eyeball/css/index.css b/coder-base/static/apps/eyeball/css/index.css old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/eyeball/js/index.js b/coder-base/static/apps/eyeball/js/index.js old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/game2d/css/index.css b/coder-base/static/apps/game2d/css/index.css old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/game2d/js/index.js b/coder-base/static/apps/game2d/js/index.js old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/hello_coder/css/index.css b/coder-base/static/apps/hello_coder/css/index.css old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/hello_coder/js/index.js b/coder-base/static/apps/hello_coder/js/index.js old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/node_js_tests/css/index.css b/coder-base/static/apps/node_js_tests/css/index.css new file mode 100755 index 00000000..408ef623 --- /dev/null +++ b/coder-base/static/apps/node_js_tests/css/index.css @@ -0,0 +1,4 @@ + +.pagecontent { + padding: 24px; +} \ No newline at end of file diff --git a/coder-base/static/apps/node_js_tests/js/index.js b/coder-base/static/apps/node_js_tests/js/index.js new file mode 100755 index 00000000..89508e79 --- /dev/null +++ b/coder-base/static/apps/node_js_tests/js/index.js @@ -0,0 +1,6 @@ + +$(document).ready( function() { + + //This code will run after your page loads + +}); \ No newline at end of file diff --git a/coder-base/static/apps/space_rocks_/css/index.css b/coder-base/static/apps/space_rocks_/css/index.css old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/space_rocks_/js/index.js b/coder-base/static/apps/space_rocks_/js/index.js old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/space_rocks_/media/die_ship.mp3 b/coder-base/static/apps/space_rocks_/media/die_ship.mp3 old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/space_rocks_/media/die_ship.ogg b/coder-base/static/apps/space_rocks_/media/die_ship.ogg old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/space_rocks_/media/die_ship.wav b/coder-base/static/apps/space_rocks_/media/die_ship.wav old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/space_rocks_/media/die_spacerock.mp3 b/coder-base/static/apps/space_rocks_/media/die_spacerock.mp3 old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/space_rocks_/media/die_spacerock.ogg b/coder-base/static/apps/space_rocks_/media/die_spacerock.ogg old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/space_rocks_/media/die_spacerock.wav b/coder-base/static/apps/space_rocks_/media/die_spacerock.wav old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/space_rocks_/media/spacerocks_shoot.mp3 b/coder-base/static/apps/space_rocks_/media/spacerocks_shoot.mp3 old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/space_rocks_/media/spacerocks_shoot.ogg b/coder-base/static/apps/space_rocks_/media/spacerocks_shoot.ogg old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/space_rocks_/media/spacerocks_shoot.wav b/coder-base/static/apps/space_rocks_/media/spacerocks_shoot.wav old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/space_rocks_/media/thrust.mp3 b/coder-base/static/apps/space_rocks_/media/thrust.mp3 old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/space_rocks_/media/thrust.ogg b/coder-base/static/apps/space_rocks_/media/thrust.ogg old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/space_rocks_/media/thrust.wav b/coder-base/static/apps/space_rocks_/media/thrust.wav old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/wifi/css/index.css b/coder-base/static/apps/wifi/css/index.css old mode 100644 new mode 100755 diff --git a/coder-base/static/apps/wifi/js/index.js b/coder-base/static/apps/wifi/js/index.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/LICENSE b/coder-base/static/common/ace-min/LICENSE old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/ace.js b/coder-base/static/common/ace-min/ace.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/ext-static_highlight.js b/coder-base/static/common/ace-min/ext-static_highlight.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/ext-textarea.js b/coder-base/static/common/ace-min/ext-textarea.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/keybinding-emacs.js b/coder-base/static/common/ace-min/keybinding-emacs.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/keybinding-vim.js b/coder-base/static/common/ace-min/keybinding-vim.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-asciidoc.js b/coder-base/static/common/ace-min/mode-asciidoc.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-c9search.js b/coder-base/static/common/ace-min/mode-c9search.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-c_cpp.js b/coder-base/static/common/ace-min/mode-c_cpp.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-clojure.js b/coder-base/static/common/ace-min/mode-clojure.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-coffee.js b/coder-base/static/common/ace-min/mode-coffee.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-coldfusion.js b/coder-base/static/common/ace-min/mode-coldfusion.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-csharp.js b/coder-base/static/common/ace-min/mode-csharp.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-css.js b/coder-base/static/common/ace-min/mode-css.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-diff.js b/coder-base/static/common/ace-min/mode-diff.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-glsl.js b/coder-base/static/common/ace-min/mode-glsl.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-golang.js b/coder-base/static/common/ace-min/mode-golang.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-groovy.js b/coder-base/static/common/ace-min/mode-groovy.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-haxe.js b/coder-base/static/common/ace-min/mode-haxe.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-html.js b/coder-base/static/common/ace-min/mode-html.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-jade.js b/coder-base/static/common/ace-min/mode-jade.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-java.js b/coder-base/static/common/ace-min/mode-java.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-javascript.js b/coder-base/static/common/ace-min/mode-javascript.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-json.js b/coder-base/static/common/ace-min/mode-json.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-jsp.js b/coder-base/static/common/ace-min/mode-jsp.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-jsx.js b/coder-base/static/common/ace-min/mode-jsx.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-latex.js b/coder-base/static/common/ace-min/mode-latex.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-less.js b/coder-base/static/common/ace-min/mode-less.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-liquid.js b/coder-base/static/common/ace-min/mode-liquid.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-lua.js b/coder-base/static/common/ace-min/mode-lua.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-luapage.js b/coder-base/static/common/ace-min/mode-luapage.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-markdown.js b/coder-base/static/common/ace-min/mode-markdown.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-ocaml.js b/coder-base/static/common/ace-min/mode-ocaml.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-perl.js b/coder-base/static/common/ace-min/mode-perl.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-pgsql.js b/coder-base/static/common/ace-min/mode-pgsql.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-php.js b/coder-base/static/common/ace-min/mode-php.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-powershell.js b/coder-base/static/common/ace-min/mode-powershell.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-python.js b/coder-base/static/common/ace-min/mode-python.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-ruby.js b/coder-base/static/common/ace-min/mode-ruby.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-scad.js b/coder-base/static/common/ace-min/mode-scad.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-scala.js b/coder-base/static/common/ace-min/mode-scala.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-scss.js b/coder-base/static/common/ace-min/mode-scss.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-sh.js b/coder-base/static/common/ace-min/mode-sh.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-sql.js b/coder-base/static/common/ace-min/mode-sql.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-svg.js b/coder-base/static/common/ace-min/mode-svg.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-tcl.js b/coder-base/static/common/ace-min/mode-tcl.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-text.js b/coder-base/static/common/ace-min/mode-text.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-textile.js b/coder-base/static/common/ace-min/mode-textile.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-typescript.js b/coder-base/static/common/ace-min/mode-typescript.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-xml.js b/coder-base/static/common/ace-min/mode-xml.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-xquery.js b/coder-base/static/common/ace-min/mode-xquery.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/mode-yaml.js b/coder-base/static/common/ace-min/mode-yaml.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-ambiance.js b/coder-base/static/common/ace-min/theme-ambiance.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-chrome.js b/coder-base/static/common/ace-min/theme-chrome.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-clouds.js b/coder-base/static/common/ace-min/theme-clouds.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-clouds_midnight.js b/coder-base/static/common/ace-min/theme-clouds_midnight.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-cobalt.js b/coder-base/static/common/ace-min/theme-cobalt.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-coder.js b/coder-base/static/common/ace-min/theme-coder.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-crimson_editor.js b/coder-base/static/common/ace-min/theme-crimson_editor.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-dawn.js b/coder-base/static/common/ace-min/theme-dawn.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-dreamweaver.js b/coder-base/static/common/ace-min/theme-dreamweaver.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-eclipse.js b/coder-base/static/common/ace-min/theme-eclipse.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-github.js b/coder-base/static/common/ace-min/theme-github.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-idle_fingers.js b/coder-base/static/common/ace-min/theme-idle_fingers.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-kr.js b/coder-base/static/common/ace-min/theme-kr.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-merbivore.js b/coder-base/static/common/ace-min/theme-merbivore.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-merbivore_soft.js b/coder-base/static/common/ace-min/theme-merbivore_soft.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-mono_industrial.js b/coder-base/static/common/ace-min/theme-mono_industrial.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-monokai.js b/coder-base/static/common/ace-min/theme-monokai.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-pastel_on_dark.js b/coder-base/static/common/ace-min/theme-pastel_on_dark.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-solarized_dark.js b/coder-base/static/common/ace-min/theme-solarized_dark.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-solarized_light.js b/coder-base/static/common/ace-min/theme-solarized_light.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-textmate.js b/coder-base/static/common/ace-min/theme-textmate.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-tomorrow.js b/coder-base/static/common/ace-min/theme-tomorrow.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-tomorrow_night.js b/coder-base/static/common/ace-min/theme-tomorrow_night.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-tomorrow_night_blue.js b/coder-base/static/common/ace-min/theme-tomorrow_night_blue.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-tomorrow_night_bright.js b/coder-base/static/common/ace-min/theme-tomorrow_night_bright.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-tomorrow_night_eighties.js b/coder-base/static/common/ace-min/theme-tomorrow_night_eighties.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-twilight.js b/coder-base/static/common/ace-min/theme-twilight.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-vibrant_ink.js b/coder-base/static/common/ace-min/theme-vibrant_ink.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/theme-xcode.js b/coder-base/static/common/ace-min/theme-xcode.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/worker-coffee.js b/coder-base/static/common/ace-min/worker-coffee.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/worker-css.js b/coder-base/static/common/ace-min/worker-css.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/worker-javascript.js b/coder-base/static/common/ace-min/worker-javascript.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/worker-json.js b/coder-base/static/common/ace-min/worker-json.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/ace-min/worker-xquery.js b/coder-base/static/common/ace-min/worker-xquery.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/js/jquery.fileupload.js b/coder-base/static/common/js/jquery.fileupload.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/js/jquery.iframe-transport.js b/coder-base/static/common/js/jquery.iframe-transport.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/js/jquery.min.js b/coder-base/static/common/js/jquery.min.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/js/jquery.ui.widget.js b/coder-base/static/common/js/jquery.ui.widget.js old mode 100644 new mode 100755 diff --git a/coder-base/static/common/media/coder_icons.png b/coder-base/static/common/media/coder_icons.png old mode 100644 new mode 100755 diff --git a/coder-base/tmp/.placeholder b/coder-base/tmp/.placeholder old mode 100644 new mode 100755 diff --git a/coder-base/views/404.html b/coder-base/views/404.html old mode 100644 new mode 100755 diff --git a/coder-base/views/apps/auth/index.html b/coder-base/views/apps/auth/index.html old mode 100644 new mode 100755 diff --git a/coder-base/views/apps/boilerplate/index.html b/coder-base/views/apps/boilerplate/index.html old mode 100644 new mode 100755 diff --git a/coder-base/views/apps/coder/index.html b/coder-base/views/apps/coder/index.html old mode 100644 new mode 100755 diff --git a/coder-base/views/apps/coderlib/index.html b/coder-base/views/apps/coderlib/index.html old mode 100644 new mode 100755 diff --git a/coder-base/views/apps/editor/index.html b/coder-base/views/apps/editor/index.html old mode 100644 new mode 100755 diff --git a/coder-base/views/apps/eyeball/index.html b/coder-base/views/apps/eyeball/index.html old mode 100644 new mode 100755 diff --git a/coder-base/views/apps/game2d/index.html b/coder-base/views/apps/game2d/index.html old mode 100644 new mode 100755 diff --git a/coder-base/views/apps/hello_coder/index.html b/coder-base/views/apps/hello_coder/index.html old mode 100644 new mode 100755 diff --git a/coder-base/views/apps/node_js_tests/index.html b/coder-base/views/apps/node_js_tests/index.html new file mode 100755 index 00000000..c62c2c7c --- /dev/null +++ b/coder-base/views/apps/node_js_tests/index.html @@ -0,0 +1,32 @@ + + + + Coder + + + + + + + + + + + + + + + + +
+

Hello World

+

Your html goes here.

+
+ + \ No newline at end of file diff --git a/coder-base/views/apps/space_rocks_/index.html b/coder-base/views/apps/space_rocks_/index.html old mode 100644 new mode 100755 diff --git a/coder-base/views/apps/wifi/index.html b/coder-base/views/apps/wifi/index.html old mode 100644 new mode 100755 diff --git a/coder-base/views/index.html b/coder-base/views/index.html old mode 100644 new mode 100755 diff --git a/findcoder-appengine/api/__init__.py b/findcoder-appengine/api/__init__.py old mode 100644 new mode 100755 diff --git a/findcoder-appengine/api/coder.py b/findcoder-appengine/api/coder.py old mode 100644 new mode 100755 diff --git a/findcoder-appengine/app.yaml b/findcoder-appengine/app.yaml old mode 100644 new mode 100755 diff --git a/findcoder-appengine/index.py b/findcoder-appengine/index.py old mode 100644 new mode 100755 diff --git a/findcoder-appengine/static/assets/css/index.css b/findcoder-appengine/static/assets/css/index.css old mode 100644 new mode 100755 diff --git a/findcoder-appengine/static/assets/js/index.js b/findcoder-appengine/static/assets/js/index.js old mode 100644 new mode 100755 diff --git a/findcoder-appengine/static/assets/js/jquery.min.js b/findcoder-appengine/static/assets/js/jquery.min.js old mode 100644 new mode 100755 diff --git a/findcoder-appengine/views/index.html b/findcoder-appengine/views/index.html old mode 100644 new mode 100755 diff --git a/installer/macosx/CoderSetup.py b/installer/macosx/CoderSetup.py old mode 100644 new mode 100755 diff --git a/installer/macosx/buildcmd.txt b/installer/macosx/buildcmd.txt old mode 100644 new mode 100755 diff --git a/installer/macosx/clonesdcard.txt b/installer/macosx/clonesdcard.txt old mode 100644 new mode 100755 diff --git a/installer/macosx/codersd.icns b/installer/macosx/codersd.icns old mode 100644 new mode 100755 diff --git a/installer/macosx/formatsdcard.py b/installer/macosx/formatsdcard.py old mode 100644 new mode 100755 diff --git a/installer/macosx/installerlogo.gif b/installer/macosx/installerlogo.gif old mode 100644 new mode 100755 diff --git a/installer/macosx/setup.py b/installer/macosx/setup.py old mode 100644 new mode 100755 diff --git a/raspbian-addons/etc/default/coder-daemon b/raspbian-addons/etc/default/coder-daemon old mode 100644 new mode 100755 diff --git a/raspbian-addons/etc/default/isc-dhcp-server b/raspbian-addons/etc/default/isc-dhcp-server old mode 100644 new mode 100755 diff --git a/raspbian-addons/etc/dhcp/dhcpd.conf b/raspbian-addons/etc/dhcp/dhcpd.conf old mode 100644 new mode 100755 diff --git a/raspbian-addons/etc/iptables.up.rules b/raspbian-addons/etc/iptables.up.rules old mode 100644 new mode 100755 diff --git a/raspbian-addons/etc/network/interfaces b/raspbian-addons/etc/network/interfaces old mode 100644 new mode 100755 diff --git a/raspbian-addons/etc/ssh/sshd_config b/raspbian-addons/etc/ssh/sshd_config old mode 100644 new mode 100755 diff --git a/raspbian-addons/etc/sudoers b/raspbian-addons/etc/sudoers old mode 100644 new mode 100755 diff --git a/raspbian-addons/etc/wpa_supplicant/wpa_supplicant.conf b/raspbian-addons/etc/wpa_supplicant/wpa_supplicant.conf old mode 100644 new mode 100755 diff --git a/raspbian-addons/etc/wpa_supplicant/wpa_supplicant.conf.reset b/raspbian-addons/etc/wpa_supplicant/wpa_supplicant.conf.reset old mode 100644 new mode 100755 From 37edee3e22b665d6bc41a09063ea9a2e3fbb723e Mon Sep 17 00:00:00 2001 From: Brannon Dorsey Date: Sun, 6 Oct 2013 19:38:25 +0000 Subject: [PATCH 2/2] test commit from coderrrrrr --- coder-base/apps/eyeball/app.js | 2 ++ coder-base/apps/eyeball/meta.json | 2 +- testCommit.txt | 0 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 testCommit.txt diff --git a/coder-base/apps/eyeball/app.js b/coder-base/apps/eyeball/app.js index 5e949e05..e67760f7 100755 --- a/coder-base/apps/eyeball/app.js +++ b/coder-base/apps/eyeball/app.js @@ -1,4 +1,5 @@ exports.settings={}; + //These are dynamically updated by the runtime //settings.appname - the app id (folder) where your app is installed //settings.viewpath - prefix to where your view html files are located @@ -17,6 +18,7 @@ exports.post_routes = [ exports.index_handler = function( req, res ) { + var tmplvars = {}; tmplvars['static_url'] = exports.settings.staticurl; tmplvars['app_name'] = exports.settings.appname; diff --git a/coder-base/apps/eyeball/meta.json b/coder-base/apps/eyeball/meta.json index 2013dda0..3c73545c 100755 --- a/coder-base/apps/eyeball/meta.json +++ b/coder-base/apps/eyeball/meta.json @@ -1,6 +1,6 @@ { "created": "2013-03-15", - "modified": "2013-07-08", + "modified": "2013-10-05", "color": "#f39c12", "author": "Justin Windle", "name": "Eyeball", diff --git a/testCommit.txt b/testCommit.txt new file mode 100644 index 00000000..e69de29b